[PATCH 10/18] nfsd: in nfsd4_create_file() let VFS report if file was created.

NeilBrown <[email protected]>
Newsgroups gmane.linux.nfs,gmane.linux.file-systems
Message-ID <[email protected]>
From: NeilBrown <neil-+NVA1uvv1dVBDLzU/[email protected]>

nfsd4_create_file() currently assumes that if a lookup failed but then a
create succeeds, then the "create" created the file.  With atomic_open
this may not be the case - some other actor might have created the file
between the lookup and the create.

So we move the call to nfsd4_vfs_create() earlier and set ->op_created
based on that.  Then use "!  ->op_created" to trigger nfserr_exist
handling.

The switch statement is split up into two if() statements.
First we check for the possibility of a successful exclusive
create and set ->op_create to true if appropriate.
Then we check for NFS4_CREATE_UNCHECKED to decide if a
pre-existing file means an error or success.

This allows us to combine the two fh_compose() calls to one place.

With this rearrangement we now repeat the setattr when an exclusive
create is repeated.  This should be both rare and harmless, and it
simplifies the code.

Signed-off-by: NeilBrown <neil-+NVA1uvv1dVBDLzU/[email protected]>
---
 fs/nfsd/nfs4proc.c | 75 ++++++++++++++++++++--------------------------
 1 file changed, 33 insertions(+), 42 deletions(-)

diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 3446f9b43bf8..bce64e2061d7 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -337,58 +337,49 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
 			goto out;
 	}
 
-	if (d_really_is_positive(child)) {
-		/* NFSv4 protocol requires change attributes even though
-		 * no change happened.
-		 */
-		fh_fill_post_noop(fhp);
-
-		status = fh_compose(resfhp, fhp->fh_export, child, fhp);
+	if (d_really_is_negative(child)) {
+		status = nfsd4_vfs_create(fhp, &child, open);
 		if (status != nfs_ok)
 			goto out;
+		open->op_created = open->op_filp->f_mode & FMODE_CREATED;
+	}
 
-		switch (open->op_createmode) {
-		case NFS4_CREATE_UNCHECKED:
-			if (!d_is_reg(child))
-				break;
+	status = fh_compose(resfhp, fhp->fh_export, child, fhp);
+	if (status != nfs_ok)
+		goto out;
 
-			/*
-			 * In NFSv4, we don't want to truncate the file
-			 * now. This would be wrong if the OPEN fails for
-			 * some other reason. Furthermore, if the size is
-			 * nonzero, we should ignore it according to spec!
-			 */
-			open->op_truncate = (iap->ia_valid & ATTR_SIZE) &&
-						!iap->ia_size;
-			break;
-		case NFS4_CREATE_GUARDED:
-			status = nfserr_exist;
-			break;
-		case NFS4_CREATE_EXCLUSIVE:
-		case NFS4_CREATE_EXCLUSIVE4_1:
-			if (inode_get_mtime_sec(d_inode(child)) == v_mtime &&
-			    inode_get_atime_sec(d_inode(child)) == v_atime &&
-			    d_inode(child)->i_size == 0) {
-				open->op_created = true;
-				goto set_attr;
-			}
-			status = nfserr_exist;
-			break;
-		}
+	if (!open->op_created &&
+	    nfsd4_create_is_exclusive(open->op_createmode) &&
+	    inode_get_mtime_sec(d_inode(child)) == v_mtime &&
+	    inode_get_atime_sec(d_inode(child)) == v_atime &&
+	    d_inode(child)->i_size == 0)
+		open->op_created = true;
+
+	if (!open->op_created &&
+	    open->op_createmode == NFS4_CREATE_UNCHECKED) {
+		/* NFSv4 protocol requires change attributes
+		 * even though no change happened.
+		 */
+		fh_fill_post_noop(fhp);
+
+		/*
+		 * In NFSv4, we don't want to truncate the file
+		 * now. This would be wrong if the OPEN fails for
+		 * some other reason. Furthermore, if the size is
+		 * nonzero, we should ignore it according to spec!
+		 */
+		open->op_truncate = (d_is_reg(child) &&
+				     (iap->ia_valid & ATTR_SIZE) &&
+				     !iap->ia_size);
 		goto out;
 	}
 
-	status = nfsd4_vfs_create(fhp, &child, open);
-	if (status != nfs_ok)
+	if (!open->op_created) {
+		status = nfserr_exist;
 		goto out;
-	open->op_created = true;
+	}
 	fh_fill_post_attrs(fhp);
 
-	status = fh_compose(resfhp, fhp->fh_export, child, fhp);
-	if (status != nfs_ok)
-		goto out;
-
-set_attr:
 	if (is_create_with_attrs(open)) {
 		status = nfsd_create_setattr(rqstp, fhp, resfhp, &attrs);
 
-- 
2.50.0.107.gf914562f5916.dirty
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.