[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