Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a08a8cd3 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

NFS: Add attribute update barriers to NFS writebacks



Ensure that other operations that race with our write RPC calls
cannot revert the file size updates that were made on the server.

Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
Tested-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent f5062003
Loading
Loading
Loading
Loading
+22 −3
Original line number Diff line number Diff line
@@ -1491,7 +1491,7 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr)
EXPORT_SYMBOL_GPL(nfs_post_op_update_inode);

/**
 * nfs_post_op_update_inode_force_wcc - try to update the inode attribute cache
 * nfs_post_op_update_inode_force_wcc_locked - update the inode attribute cache
 * @inode - pointer to inode
 * @fattr - updated attributes
 *
@@ -1501,11 +1501,10 @@ EXPORT_SYMBOL_GPL(nfs_post_op_update_inode);
 *
 * This function is mainly designed to be used by the ->write_done() functions.
 */
int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr)
int nfs_post_op_update_inode_force_wcc_locked(struct inode *inode, struct nfs_fattr *fattr)
{
	int status;

	spin_lock(&inode->i_lock);
	/* Don't do a WCC update if these attributes are already stale */
	if ((fattr->valid & NFS_ATTR_FATTR) == 0 ||
			!nfs_inode_attrs_need_update(inode, fattr)) {
@@ -1537,6 +1536,26 @@ int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fa
	}
out_noforce:
	status = nfs_post_op_update_inode_locked(inode, fattr);
	return status;
}

/**
 * nfs_post_op_update_inode_force_wcc - try to update the inode attribute cache
 * @inode - pointer to inode
 * @fattr - updated attributes
 *
 * After an operation that has changed the inode metadata, mark the
 * attribute cache as being invalid, then try to update it. Fake up
 * weak cache consistency data, if none exist.
 *
 * This function is mainly designed to be used by the ->write_done() functions.
 */
int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr)
{
	int status;

	spin_lock(&inode->i_lock);
	status = nfs_post_op_update_inode_force_wcc_locked(inode, fattr);
	spin_unlock(&inode->i_lock);
	return status;
}
+1 −0
Original line number Diff line number Diff line
@@ -459,6 +459,7 @@ void nfs_mark_request_commit(struct nfs_page *req,
			     struct nfs_commit_info *cinfo,
			     u32 ds_commit_idx);
int nfs_write_need_commit(struct nfs_pgio_header *);
void nfs_writeback_update_inode(struct nfs_pgio_header *hdr);
int nfs_generic_commit_list(struct inode *inode, struct list_head *head,
			    int how, struct nfs_commit_info *cinfo);
void nfs_retry_commit(struct list_head *page_list,
+1 −1
Original line number Diff line number Diff line
@@ -834,7 +834,7 @@ static int nfs3_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
	if (nfs3_async_handle_jukebox(task, inode))
		return -EAGAIN;
	if (task->tk_status >= 0)
		nfs_post_op_update_inode_force_wcc(inode, hdr->res.fattr);
		nfs_writeback_update_inode(hdr);
	return 0;
}

+1 −1
Original line number Diff line number Diff line
@@ -4237,7 +4237,7 @@ static int nfs4_write_done_cb(struct rpc_task *task,
	}
	if (task->tk_status >= 0) {
		renew_lease(NFS_SERVER(inode), hdr->timestamp);
		nfs_post_op_update_inode_force_wcc(inode, &hdr->fattr);
		nfs_writeback_update_inode(hdr);
	}
	return 0;
}
+1 −3
Original line number Diff line number Diff line
@@ -609,10 +609,8 @@ static int nfs_proc_pgio_rpc_prepare(struct rpc_task *task,

static int nfs_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
{
	struct inode *inode = hdr->inode;

	if (task->tk_status >= 0)
		nfs_post_op_update_inode_force_wcc(inode, hdr->res.fattr);
		nfs_writeback_update_inode(hdr);
	return 0;
}

Loading