diff options
| author | NeilBrown <neil@brown.name> | 2026-07-17 19:28:03 +1000 |
|---|---|---|
| committer | Chuck Lever <cel@kernel.org> | 2026-09-13 20:36:54 -0400 |
| commit | 4c6e358eca2602d6cfbffa8f6606d4281f140108 (patch) | |
| tree | 61d1a58ecedb0cb0f0f9cb2e52d207d408d3b586 | |
| parent | 12911aba4f2b90f882ce185c4ce7274f0341ba3b (diff) | |
| download | linux-next-4c6e358eca2602d6cfbffa8f6606d4281f140108.tar.gz linux-next-4c6e358eca2602d6cfbffa8f6606d4281f140108.zip | |
nfsd: reduce want-write range in nfsd4_create_file()
nfsd4_create_file() needs write access to the mount for two purposes:
1/ to create/open the file.
2/ to set attributes on the newly created (or pre-existing) file.
Currently this is all handled by holding the write access across the
open and the setattr. A subsequent patch will necessarily change how
write access is gained for the open. So we reduce the range for the
first want_write, and add another one to cover setattr. If we failed to
get write access, it is only fatal if there were attrs to set.
We call nfsd_create_setattr() if at all possible, even when no attrs, as
it also calls commit_metadata and we need to be certain that the file
creation has been synced. If the mount became read-only since the
creation happened, we can safely assume that the sync happened as part
of that.
Signed-off-by: NeilBrown <neil@brown.name>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Link: https://patch.msgid.link/20260717093001.1972119-16-neilb@ownmail.net
Signed-off-by: Chuck Lever <cel@kernel.org>
| -rw-r--r-- | fs/nfsd/nfs4proc.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 6dff6013a068..5e047469ba78 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -343,6 +343,8 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp, &QSTR_LEN(open->op_fname, open->op_fnamelen)); if (IS_ERR(child)) { status = nfserrno(PTR_ERR(child)); + if (!want_write_err) + fh_drop_write(fhp); goto out; } path.dentry = child; @@ -377,6 +379,8 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp, } } end_creating(child); + if (!want_write_err) + fh_drop_write(fhp); if (status != nfs_ok) goto out; @@ -420,7 +424,16 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp, if ((iap->ia_valid & ATTR_SIZE) && (iap->ia_size == 0)) iap->ia_valid &= ~ATTR_SIZE; - status = nfsd_create_setattr(rqstp, fhp, resfhp, &attrs); + /* We will need write access to set the attrs */ + want_write_err = fh_want_write(fhp); + if (!want_write_err) { + status = nfsd_create_setattr(rqstp, fhp, + resfhp, &attrs); + fh_drop_write(fhp); + } else if (nfsd_attrs_valid(&attrs)) { + /* Needed write access */ + status = nfserrno(want_write_err); + } if (attrs.na_labelerr) open->op_bmval[2] &= ~FATTR4_WORD2_SECURITY_LABEL; @@ -431,8 +444,6 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp, if (attrs.na_paclerr) open->op_bmval[2] &= ~FATTR4_WORD2_POSIX_ACCESS_ACL; out: - if (!want_write_err) - fh_drop_write(fhp); nfsd_attrs_free(&attrs); return status; } |
