Re: [PATCH v2 09/11] nfsd: allow filecache to hold S_IFDIR files
Chuck Lever <[email protected]>
| Newsgroups | org.kernel.vger.ecryptfs,dev.linux.lists.netfs,org.kernel.vger.linux-cifs,org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-kernel,org.kernel.vger.linux-nfs,org.kernel.vger.linux-unionfs,org.kernel.vger.linux-xfs,org.kernel.vger.netdev |
|---|---|
| Message-ID | <[email protected]> |
On 10/17/25 7:32 AM, Jeff Layton wrote: > The filecache infrastructure will only handle S_IFREG files at the > moment. Directory delegations will require adding support for opening > S_IFDIR inodes. > > Plumb a "type" argument into nfsd_file_do_acquire() and have all of the > existing callers set it to S_IFREG. Add a new nfsd_file_acquire_dir() > wrapper that nfsd can call to request a nfsd_file that holds a directory > open. > > For now, there is no need for a fsnotify_mark for directories, as > CB_NOTIFY is not yet supported. Change nfsd_file_do_acquire() to avoid > allocating one for non-S_IFREG inodes. > > Signed-off-by: Jeff Layton <[email protected]> > --- > fs/nfsd/filecache.c | 57 ++++++++++++++++++++++++++++++++++++++++------------- > fs/nfsd/filecache.h | 2 ++ > fs/nfsd/vfs.c | 5 +++-- > fs/nfsd/vfs.h | 2 +- > 4 files changed, 49 insertions(+), 17 deletions(-) > > diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c > index a238b6725008a5c2988bd3da874d1f34ee778437..93798575b8075c63f95cd415b6d24df706ada0f6 100644 > --- a/fs/nfsd/filecache.c > +++ b/fs/nfsd/filecache.c > @@ -1086,7 +1086,7 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct net *net, > struct auth_domain *client, > struct svc_fh *fhp, > unsigned int may_flags, struct file *file, > - struct nfsd_file **pnf, bool want_gc) > + umode_t type, bool want_gc, struct nfsd_file **pnf) > { > unsigned char need = may_flags & NFSD_FILE_MAY_MASK; > struct nfsd_file *new, *nf; > @@ -1097,13 +1097,13 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct net *net, > int ret; > > retry: > - if (rqstp) { > - status = fh_verify(rqstp, fhp, S_IFREG, > + if (rqstp) > + status = fh_verify(rqstp, fhp, type, > may_flags|NFSD_MAY_OWNER_OVERRIDE); > - } else { > - status = fh_verify_local(net, cred, client, fhp, S_IFREG, > + else > + status = fh_verify_local(net, cred, client, fhp, type, > may_flags|NFSD_MAY_OWNER_OVERRIDE); > - } > + > if (status != nfs_ok) > return status; > inode = d_inode(fhp->fh_dentry); > @@ -1176,15 +1176,18 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct net *net, > > open_file: > trace_nfsd_file_alloc(nf); > - nf->nf_mark = nfsd_file_mark_find_or_create(inode); > - if (nf->nf_mark) { > + > + if (type == S_IFREG) > + nf->nf_mark = nfsd_file_mark_find_or_create(inode); > + > + if (type != S_IFREG || nf->nf_mark) { > if (file) { > get_file(file); > nf->nf_file = file; > status = nfs_ok; > trace_nfsd_file_opened(nf, status); > } else { > - ret = nfsd_open_verified(fhp, may_flags, &nf->nf_file); > + ret = nfsd_open_verified(fhp, type, may_flags, &nf->nf_file); > if (ret == -EOPENSTALE && stale_retry) { > stale_retry = false; > nfsd_file_unhash(nf); > @@ -1246,7 +1249,7 @@ nfsd_file_acquire_gc(struct svc_rqst *rqstp, struct svc_fh *fhp, > unsigned int may_flags, struct nfsd_file **pnf) > { > return nfsd_file_do_acquire(rqstp, SVC_NET(rqstp), NULL, NULL, > - fhp, may_flags, NULL, pnf, true); > + fhp, may_flags, NULL, S_IFREG, true, pnf); > } > > /** > @@ -1271,7 +1274,7 @@ nfsd_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp, > unsigned int may_flags, struct nfsd_file **pnf) > { > return nfsd_file_do_acquire(rqstp, SVC_NET(rqstp), NULL, NULL, > - fhp, may_flags, NULL, pnf, false); > + fhp, may_flags, NULL, S_IFREG, false, pnf); > } > > /** > @@ -1314,8 +1317,8 @@ nfsd_file_acquire_local(struct net *net, struct svc_cred *cred, > const struct cred *save_cred = get_current_cred(); > __be32 beres; > > - beres = nfsd_file_do_acquire(NULL, net, cred, client, > - fhp, may_flags, NULL, pnf, false); > + beres = nfsd_file_do_acquire(NULL, net, cred, client, fhp, may_flags, > + NULL, S_IFREG, false, pnf); > put_cred(revert_creds(save_cred)); > return beres; > } > @@ -1344,7 +1347,33 @@ nfsd_file_acquire_opened(struct svc_rqst *rqstp, struct svc_fh *fhp, > struct nfsd_file **pnf) > { > return nfsd_file_do_acquire(rqstp, SVC_NET(rqstp), NULL, NULL, > - fhp, may_flags, file, pnf, false); > + fhp, may_flags, file, S_IFREG, false, pnf); > +} > + > +/** > + * nfsd_file_acquire_dir - Get a struct nfsd_file with an open directory > + * @rqstp: the RPC transaction being executed > + * @fhp: the NFS filehandle of the file to be opened > + * @pnf: OUT: new or found "struct nfsd_file" object > + * > + * The nfsd_file_object returned by this API is reference-counted > + * but not garbage-collected. The object is unhashed after the > + * final nfsd_file_put(). This opens directories only, and only > + * in O_RDONLY mode. > + * > + * Return values: > + * %nfs_ok - @pnf points to an nfsd_file with its reference > + * count boosted. > + * > + * On error, an nfsstat value in network byte order is returned. > + */ > +__be32 > +nfsd_file_acquire_dir(struct svc_rqst *rqstp, struct svc_fh *fhp, > + struct nfsd_file **pnf) > +{ > + return nfsd_file_do_acquire(rqstp, SVC_NET(rqstp), NULL, NULL, fhp, > + NFSD_MAY_READ|NFSD_MAY_64BIT_COOKIE, > + NULL, S_IFDIR, false, pnf); > } > > /* > diff --git a/fs/nfsd/filecache.h b/fs/nfsd/filecache.h > index e3d6ca2b60308e5e91ba4bb32d935f54527d8bda..b383dbc5b9218d21a29b852572f80fab08de9fa9 100644 > --- a/fs/nfsd/filecache.h > +++ b/fs/nfsd/filecache.h > @@ -82,5 +82,7 @@ __be32 nfsd_file_acquire_opened(struct svc_rqst *rqstp, struct svc_fh *fhp, > __be32 nfsd_file_acquire_local(struct net *net, struct svc_cred *cred, > struct auth_domain *client, struct svc_fh *fhp, > unsigned int may_flags, struct nfsd_file **pnf); > +__be32 nfsd_file_acquire_dir(struct svc_rqst *rqstp, struct svc_fh *fhp, > + struct nfsd_file **pnf); > int nfsd_file_cache_stats_show(struct seq_file *m, void *v); > #endif /* _FS_NFSD_FILECACHE_H */ > diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c > index eeb138569eba5df6de361cf6ba29604722e14af9..12c33223b612664dbb3b18b591e97fc708165763 100644 > --- a/fs/nfsd/vfs.c > +++ b/fs/nfsd/vfs.c > @@ -959,15 +959,16 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, > /** > * nfsd_open_verified - Open a regular file for the filecache > * @fhp: NFS filehandle of the file to open > + * @type: S_IFMT inode type allowed (0 means any type is allowed) > * @may_flags: internal permission flags > * @filp: OUT: open "struct file *" > * > * Returns zero on success, or a negative errno value. > */ > int > -nfsd_open_verified(struct svc_fh *fhp, int may_flags, struct file **filp) > +nfsd_open_verified(struct svc_fh *fhp, umode_t type, int may_flags, struct file **filp) > { > - return __nfsd_open(fhp, S_IFREG, may_flags, filp); > + return __nfsd_open(fhp, type, may_flags, filp); > } > > /* > diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h > index fa46f8b5f132079e3a2c45e71ecf9cc43181f6b0..ded2900d423f80d33fb6c8b809bc5d9fc842ebfd 100644 > --- a/fs/nfsd/vfs.h > +++ b/fs/nfsd/vfs.h > @@ -114,7 +114,7 @@ __be32 nfsd_setxattr(struct svc_rqst *rqstp, struct svc_fh *fhp, > int nfsd_open_break_lease(struct inode *, int); > __be32 nfsd_open(struct svc_rqst *, struct svc_fh *, umode_t, > int, struct file **); > -int nfsd_open_verified(struct svc_fh *fhp, int may_flags, > +int nfsd_open_verified(struct svc_fh *fhp, umode_t type, int may_flags, > struct file **filp); > __be32 nfsd_splice_read(struct svc_rqst *rqstp, struct svc_fh *fhp, > struct file *file, loff_t offset, > Reviewed-by: Chuck Lever <[email protected]> These can probably go in via Christian's tree. I don't think there are going to be conflicts between these and what's in nfsd-testing now. -- Chuck Lever