1 From 2665a88c9d8e81d1e9f47d56f9002bf2c1a6646f Mon Sep 17 00:00:00 2001
2 From: Sasha Levin <sashal@kernel.org>
3 Date: Tue, 26 Jul 2022 16:45:30 +1000
4 Subject: NFSD: introduce struct nfsd_attrs
6 From: NeilBrown <neilb@suse.de>
8 [ Upstream commit 7fe2a71dda349a1afa75781f0cc7975be9784d15 ]
10 The attributes that nfsd might want to set on a file include 'struct
11 iattr' as well as an ACL and security label.
12 The latter two are passed around quite separately from the first, in
13 part because they are only needed for NFSv4. This leads to some
14 clumsiness in the code, such as the attributes NOT being set in
15 nfsd_create_setattr().
17 We need to keep the directory locked until all attributes are set to
18 ensure the file is never visibile without all its attributes. This need
19 combined with the inconsistent handling of attributes leads to more
22 As a first step towards tidying this up, introduce 'struct nfsd_attrs'.
23 This is passed (by reference) to vfs.c functions that work with
24 attributes, and is assembled by the various nfs*proc functions which
25 call them. As yet only iattr is included, but future patches will
28 Signed-off-by: NeilBrown <neilb@suse.de>
29 Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
31 fs/nfsd/nfs3proc.c | 20 ++++++++++++++++----
32 fs/nfsd/nfs4proc.c | 23 ++++++++++++++++-------
33 fs/nfsd/nfs4state.c | 5 ++++-
34 fs/nfsd/nfsproc.c | 17 +++++++++++++----
35 fs/nfsd/vfs.c | 24 ++++++++++++++----------
36 fs/nfsd/vfs.h | 12 ++++++++----
37 6 files changed, 71 insertions(+), 30 deletions(-)
39 diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
40 index 57854ca022d18..113567b3a98a5 100644
41 --- a/fs/nfsd/nfs3proc.c
42 +++ b/fs/nfsd/nfs3proc.c
43 @@ -67,12 +67,15 @@ nfsd3_proc_setattr(struct svc_rqst *rqstp)
45 struct nfsd3_sattrargs *argp = rqstp->rq_argp;
46 struct nfsd3_attrstat *resp = rqstp->rq_resp;
47 + struct nfsd_attrs attrs = {
48 + .na_iattr = &argp->attrs,
51 dprintk("nfsd: SETATTR(3) %s\n",
52 SVCFH_fmt(&argp->fh));
54 fh_copy(&resp->fh, &argp->fh);
55 - resp->status = nfsd_setattr(rqstp, &resp->fh, &argp->attrs,
56 + resp->status = nfsd_setattr(rqstp, &resp->fh, &attrs,
57 argp->check_guard, argp->guardtime);
60 @@ -233,6 +236,9 @@ nfsd3_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
62 struct iattr *iap = &argp->attrs;
63 struct dentry *parent, *child;
64 + struct nfsd_attrs attrs = {
67 __u32 v_mtime, v_atime;
70 @@ -331,7 +337,7 @@ nfsd3_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
74 - status = nfsd_create_setattr(rqstp, fhp, resfhp, iap);
75 + status = nfsd_create_setattr(rqstp, fhp, resfhp, &attrs);
79 @@ -368,6 +374,9 @@ nfsd3_proc_mkdir(struct svc_rqst *rqstp)
81 struct nfsd3_createargs *argp = rqstp->rq_argp;
82 struct nfsd3_diropres *resp = rqstp->rq_resp;
83 + struct nfsd_attrs attrs = {
84 + .na_iattr = &argp->attrs,
87 dprintk("nfsd: MKDIR(3) %s %.*s\n",
89 @@ -378,7 +387,7 @@ nfsd3_proc_mkdir(struct svc_rqst *rqstp)
90 fh_copy(&resp->dirfh, &argp->fh);
91 fh_init(&resp->fh, NFS3_FHSIZE);
92 resp->status = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
93 - &argp->attrs, S_IFDIR, 0, &resp->fh);
94 + &attrs, S_IFDIR, 0, &resp->fh);
95 fh_unlock(&resp->dirfh);
98 @@ -428,6 +437,9 @@ nfsd3_proc_mknod(struct svc_rqst *rqstp)
100 struct nfsd3_mknodargs *argp = rqstp->rq_argp;
101 struct nfsd3_diropres *resp = rqstp->rq_resp;
102 + struct nfsd_attrs attrs = {
103 + .na_iattr = &argp->attrs,
108 @@ -453,7 +465,7 @@ nfsd3_proc_mknod(struct svc_rqst *rqstp)
110 type = nfs3_ftypes[argp->ftype];
111 resp->status = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
112 - &argp->attrs, type, rdev, &resp->fh);
113 + &attrs, type, rdev, &resp->fh);
114 fh_unlock(&resp->dirfh);
117 diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
118 index ae0948271da9c..9b04611a318d7 100644
119 --- a/fs/nfsd/nfs4proc.c
120 +++ b/fs/nfsd/nfs4proc.c
121 @@ -286,6 +286,9 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
122 struct svc_fh *resfhp, struct nfsd4_open *open)
124 struct iattr *iap = &open->op_iattr;
125 + struct nfsd_attrs attrs = {
128 struct dentry *parent, *child;
129 __u32 v_mtime, v_atime;
131 @@ -404,7 +407,7 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
135 - status = nfsd_create_setattr(rqstp, fhp, resfhp, iap);
136 + status = nfsd_create_setattr(rqstp, fhp, resfhp, &attrs);
140 @@ -787,6 +790,9 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
143 struct nfsd4_create *create = &u->create;
144 + struct nfsd_attrs attrs = {
145 + .na_iattr = &create->cr_iattr,
150 @@ -818,7 +824,7 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
152 status = nfsd_create(rqstp, &cstate->current_fh,
153 create->cr_name, create->cr_namelen,
154 - &create->cr_iattr, S_IFBLK, rdev, &resfh);
155 + &attrs, S_IFBLK, rdev, &resfh);
159 @@ -829,26 +835,26 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
161 status = nfsd_create(rqstp, &cstate->current_fh,
162 create->cr_name, create->cr_namelen,
163 - &create->cr_iattr, S_IFCHR, rdev, &resfh);
164 + &attrs, S_IFCHR, rdev, &resfh);
168 status = nfsd_create(rqstp, &cstate->current_fh,
169 create->cr_name, create->cr_namelen,
170 - &create->cr_iattr, S_IFSOCK, 0, &resfh);
171 + &attrs, S_IFSOCK, 0, &resfh);
175 status = nfsd_create(rqstp, &cstate->current_fh,
176 create->cr_name, create->cr_namelen,
177 - &create->cr_iattr, S_IFIFO, 0, &resfh);
178 + &attrs, S_IFIFO, 0, &resfh);
182 create->cr_iattr.ia_valid &= ~ATTR_SIZE;
183 status = nfsd_create(rqstp, &cstate->current_fh,
184 create->cr_name, create->cr_namelen,
185 - &create->cr_iattr, S_IFDIR, 0, &resfh);
186 + &attrs, S_IFDIR, 0, &resfh);
190 @@ -1142,6 +1148,9 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
193 struct nfsd4_setattr *setattr = &u->setattr;
194 + struct nfsd_attrs attrs = {
195 + .na_iattr = &setattr->sa_iattr,
197 __be32 status = nfs_ok;
200 @@ -1174,7 +1183,7 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
204 - status = nfsd_setattr(rqstp, &cstate->current_fh, &setattr->sa_iattr,
205 + status = nfsd_setattr(rqstp, &cstate->current_fh, &attrs,
208 fh_drop_write(&cstate->current_fh);
209 diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
210 index 7122ebc50a035..a299aeaa0de07 100644
211 --- a/fs/nfsd/nfs4state.c
212 +++ b/fs/nfsd/nfs4state.c
213 @@ -5077,11 +5077,14 @@ nfsd4_truncate(struct svc_rqst *rqstp, struct svc_fh *fh,
214 .ia_valid = ATTR_SIZE,
217 + struct nfsd_attrs attrs = {
218 + .na_iattr = &iattr,
220 if (!open->op_truncate)
222 if (!(open->op_share_access & NFS4_SHARE_ACCESS_WRITE))
224 - return nfsd_setattr(rqstp, fh, &iattr, 0, (time64_t)0);
225 + return nfsd_setattr(rqstp, fh, &attrs, 0, (time64_t)0);
228 static __be32 nfs4_get_vfs_file(struct svc_rqst *rqstp, struct nfs4_file *fp,
229 diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
230 index f65eba938a57d..c75d83bc3f21b 100644
231 --- a/fs/nfsd/nfsproc.c
232 +++ b/fs/nfsd/nfsproc.c
233 @@ -51,6 +51,9 @@ nfsd_proc_setattr(struct svc_rqst *rqstp)
234 struct nfsd_sattrargs *argp = rqstp->rq_argp;
235 struct nfsd_attrstat *resp = rqstp->rq_resp;
236 struct iattr *iap = &argp->attrs;
237 + struct nfsd_attrs attrs = {
242 dprintk("nfsd: SETATTR %s, valid=%x, size=%ld\n",
243 @@ -100,7 +103,7 @@ nfsd_proc_setattr(struct svc_rqst *rqstp)
247 - resp->status = nfsd_setattr(rqstp, fhp, iap, 0, (time64_t)0);
248 + resp->status = nfsd_setattr(rqstp, fhp, &attrs, 0, (time64_t)0);
249 if (resp->status != nfs_ok)
252 @@ -261,6 +264,9 @@ nfsd_proc_create(struct svc_rqst *rqstp)
253 svc_fh *dirfhp = &argp->fh;
254 svc_fh *newfhp = &resp->fh;
255 struct iattr *attr = &argp->attrs;
256 + struct nfsd_attrs attrs = {
260 struct dentry *dchild;
262 @@ -386,7 +392,7 @@ nfsd_proc_create(struct svc_rqst *rqstp)
264 /* File doesn't exist. Create it and set attrs */
265 resp->status = nfsd_create_locked(rqstp, dirfhp, argp->name,
266 - argp->len, attr, type, rdev,
267 + argp->len, &attrs, type, rdev,
269 } else if (type == S_IFREG) {
270 dprintk("nfsd: existing %s, valid=%x, size=%ld\n",
271 @@ -397,7 +403,7 @@ nfsd_proc_create(struct svc_rqst *rqstp)
273 attr->ia_valid &= ATTR_SIZE;
275 - resp->status = nfsd_setattr(rqstp, newfhp, attr, 0,
276 + resp->status = nfsd_setattr(rqstp, newfhp, &attrs, 0,
280 @@ -512,6 +518,9 @@ nfsd_proc_mkdir(struct svc_rqst *rqstp)
282 struct nfsd_createargs *argp = rqstp->rq_argp;
283 struct nfsd_diropres *resp = rqstp->rq_resp;
284 + struct nfsd_attrs attrs = {
285 + .na_iattr = &argp->attrs,
288 dprintk("nfsd: MKDIR %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name);
290 @@ -523,7 +532,7 @@ nfsd_proc_mkdir(struct svc_rqst *rqstp)
291 argp->attrs.ia_valid &= ~ATTR_SIZE;
292 fh_init(&resp->fh, NFS_FHSIZE);
293 resp->status = nfsd_create(rqstp, &argp->fh, argp->name, argp->len,
294 - &argp->attrs, S_IFDIR, 0, &resp->fh);
295 + &attrs, S_IFDIR, 0, &resp->fh);
297 if (resp->status != nfs_ok)
299 diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
300 index 6689ad5bb790d..489225de05a2a 100644
303 @@ -350,11 +350,13 @@ nfsd_get_write_access(struct svc_rqst *rqstp, struct svc_fh *fhp,
304 * Set various file attributes. After this call fhp needs an fh_put.
307 -nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
308 +nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,
309 + struct nfsd_attrs *attr,
310 int check_guard, time64_t guardtime)
312 struct dentry *dentry;
314 + struct iattr *iap = attr->na_iattr;
315 int accmode = NFSD_MAY_SATTR;
318 @@ -1203,14 +1205,15 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, u64 offset,
319 * @rqstp: RPC transaction being executed
320 * @fhp: NFS filehandle of parent directory
321 * @resfhp: NFS filehandle of new object
322 - * @iap: requested attributes of new object
323 + * @attrs: requested attributes of new object
325 * Returns nfs_ok on success, or an nfsstat in network byte order.
328 nfsd_create_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,
329 - struct svc_fh *resfhp, struct iattr *iap)
330 + struct svc_fh *resfhp, struct nfsd_attrs *attrs)
332 + struct iattr *iap = attrs->na_iattr;
336 @@ -1231,7 +1234,7 @@ nfsd_create_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,
337 * if the attributes have not changed.
340 - status = nfsd_setattr(rqstp, resfhp, iap, 0, (time64_t)0);
341 + status = nfsd_setattr(rqstp, resfhp, attrs, 0, (time64_t)0);
343 status = nfserrno(commit_metadata(resfhp));
345 @@ -1270,11 +1273,12 @@ nfsd_check_ignore_resizing(struct iattr *iap)
346 /* The parent directory should already be locked: */
348 nfsd_create_locked(struct svc_rqst *rqstp, struct svc_fh *fhp,
349 - char *fname, int flen, struct iattr *iap,
350 - int type, dev_t rdev, struct svc_fh *resfhp)
351 + char *fname, int flen, struct nfsd_attrs *attrs,
352 + int type, dev_t rdev, struct svc_fh *resfhp)
354 struct dentry *dentry, *dchild;
356 + struct iattr *iap = attrs->na_iattr;
360 @@ -1348,7 +1352,7 @@ nfsd_create_locked(struct svc_rqst *rqstp, struct svc_fh *fhp,
364 - err = nfsd_create_setattr(rqstp, fhp, resfhp, iap);
365 + err = nfsd_create_setattr(rqstp, fhp, resfhp, attrs);
369 @@ -1367,8 +1371,8 @@ nfsd_create_locked(struct svc_rqst *rqstp, struct svc_fh *fhp,
372 nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
373 - char *fname, int flen, struct iattr *iap,
374 - int type, dev_t rdev, struct svc_fh *resfhp)
375 + char *fname, int flen, struct nfsd_attrs *attrs,
376 + int type, dev_t rdev, struct svc_fh *resfhp)
378 struct dentry *dentry, *dchild = NULL;
380 @@ -1400,7 +1404,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
384 - return nfsd_create_locked(rqstp, fhp, fname, flen, iap, type,
385 + return nfsd_create_locked(rqstp, fhp, fname, flen, attrs, type,
389 diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h
390 index 26347d76f44a0..d8b1a36fca956 100644
393 @@ -42,6 +42,10 @@ struct nfsd_file;
394 typedef int (*nfsd_filldir_t)(void *, const char *, int, loff_t, u64, unsigned);
398 + struct iattr *na_iattr; /* input */
401 int nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
402 struct svc_export **expp);
403 __be32 nfsd_lookup(struct svc_rqst *, struct svc_fh *,
404 @@ -50,7 +54,7 @@ __be32 nfsd_lookup_dentry(struct svc_rqst *, struct svc_fh *,
405 const char *, unsigned int,
406 struct svc_export **, struct dentry **);
407 __be32 nfsd_setattr(struct svc_rqst *, struct svc_fh *,
408 - struct iattr *, int, time64_t);
409 + struct nfsd_attrs *, int, time64_t);
410 int nfsd_mountpoint(struct dentry *, struct svc_export *);
411 #ifdef CONFIG_NFSD_V4
412 __be32 nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *,
413 @@ -63,14 +67,14 @@ __be32 nfsd4_clone_file_range(struct svc_rqst *rqstp,
414 u64 count, bool sync);
415 #endif /* CONFIG_NFSD_V4 */
416 __be32 nfsd_create_locked(struct svc_rqst *, struct svc_fh *,
417 - char *name, int len, struct iattr *attrs,
418 + char *name, int len, struct nfsd_attrs *attrs,
419 int type, dev_t rdev, struct svc_fh *res);
420 __be32 nfsd_create(struct svc_rqst *, struct svc_fh *,
421 - char *name, int len, struct iattr *attrs,
422 + char *name, int len, struct nfsd_attrs *attrs,
423 int type, dev_t rdev, struct svc_fh *res);
424 __be32 nfsd_access(struct svc_rqst *, struct svc_fh *, u32 *, u32 *);
425 __be32 nfsd_create_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,
426 - struct svc_fh *resfhp, struct iattr *iap);
427 + struct svc_fh *resfhp, struct nfsd_attrs *iap);
428 __be32 nfsd_commit(struct svc_rqst *rqst, struct svc_fh *fhp,
429 u64 offset, u32 count, __be32 *verf);
430 #ifdef CONFIG_NFSD_V4