FAILED: patch "[PATCH] nfsd: fix handling of cached open files in nfsd4_open" failed to apply to 6.1-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.1-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
Possible dependencies:
0b3a551fa58b ("nfsd: fix handling of cached open files in nfsd4_open codepath") ac3a2585f018 ("nfsd: rework refcounting in filecache")d7064eaf688c ("NFSD: Add an nfsd_file_fsync tracepoint")
821411858988 ("nfsd: reorganize filecache.c")1f696e230ea5 ("nfsd: remove the pages_flushed statistic from filecache") 4d1ea8455716 ("NFSD: Add an NFSD_FILE_GC flag to enable nfsd_file garbage collection") dcf3f80965ca ("NFSD: Revert "NFSD: NFSv4 CLOSE should release an nfsd_file immediately"") c252849082ff ("NFSD: Pass the target nfsd_file to nfsd_commit()")
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 0b3a551fa58b4da941efeb209b3770868e2eddd7 Mon Sep 17 00:00:00 2001
From: Jeff Layton <[email protected]>
Date: Thu, 5 Jan 2023 14:55:56 -0500
Subject: [PATCH] nfsd: fix handling of cached open files in nfsd4_open
codepath
Commit fb70bf124b05 ("NFSD: Instantiate a struct file when creating a regular NFSv4 file") added the ability to cache an open fd over a compound. There are a couple of problems with the way this currently works:
It's racy, as a newly-created nfsd_file can end up with its PENDING bit cleared while the nf is hashed, and the nf_file pointer is still zeroed out. Other tasks can find it in this state and they expect to see a valid nf_file, and can oops if nf_file is NULL.
Also, there is no guarantee that we'll end up creating a new nfsd_file if one is already in the hash. If an extant entry is in the hash with a valid nf_file, nfs4_get_vfs_file will clobber its nf_file pointer with the value of op_file and the old nf_file will leak.
Fix both issues by making a new nfsd_file_acquirei_opened variant that takes an optional file pointer. If one is present when this is called, we'll take a new reference to it instead of trying to open the file. If the nfsd_file already has a valid nf_file, we'll just ignore the optional file and pass the nfsd_file back as-is.
Also rework the tracepoints a bit to allow for an "opened" variant and don't try to avoid counting acquisitions in the case where we already have a cached open file.
fs/nfsd/filecache.c +22 -18
@@ -1071,8 +1071,8 @@ nfsd_file_is_cached(struct inode *inode)static __be32 nfsd_file_do_acquire (struct svc_rqst *rqstp,struct svc_fh *fhp, -unsigned int may_flags,struct nfsd_file **pnf, -bool open,bool want_gc) +unsigned int may_flags,struct file *file, +struct nfsd_file **pnf,bool want_gc) {struct nfsd_file_lookup_key key = { .type =NFSD_FILE_KEY_FULL ,
@@ -1147,8 +1147,7 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp, status =nfserrno (nfsd_open_break_lease (file_inode (nf->nf_file), may_flags)); out:if (status == nfs_ok) { -if (open) -this_cpu_inc (nfsd_file_acquisitions); +this_cpu_inc (nfsd_file_acquisitions); *pnf = nf; }else {if (refcount_dec_and_test (&nf->nf_ref))
@@ -1158,20 +1157,23 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp, out_status:put_cred (key.cred); -if (open) -trace_nfsd_file_acquire (rqstp, key.inode, may_flags, nf, status); +trace_nfsd_file_acquire (rqstp, key.inode, may_flags, nf, status);return status; open_file:trace_nfsd_file_alloc (nf); nf->nf_mark =nfsd_file_mark_find_or_create (nf, key.inode);if (nf->nf_mark) { -if (open) { +if (file) { +get_file (file); + nf->nf_file = file; + status = nfs_ok; +trace_nfsd_file_opened (nf, status); + }else { status =nfsd_open_verified (rqstp, fhp, may_flags, &nf->nf_file);trace_nfsd_file_open (nf, status); - }else - status = nfs_ok; + } }else status = nfserr_jukebox;/*
@@ -1207,7 +1209,7 @@ __be32 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, fhp, may_flags, pnf, true, true); + return nfsd_file_do_acquire(rqstp, fhp, may_flags, NULL, pnf, true); }/**
@@ -1228,28 +1230,30 @@ __be32 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, fhp, may_flags, pnf, true, false); + return nfsd_file_do_acquire(rqstp, fhp, may_flags, NULL, pnf, false); }/** -* nfsd_file_create - Get a struct nfsd_file, do not open +* nfsd_file_acquire_opened - Get a struct nfsd_file using existing open file * @rqstp: the RPC transaction being executed * @fhp: the NFS filehandle of the file just created * @may_flags: NFSD_MAY_ settings for the file +* @file: cached, already-open file (may be NULL) * @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 released immediately -* one RCU grace period after the final nfsd_file_put(). +* Acquire a nfsd_file object that is not GC'ed. If one doesn't already exist, +* and @file is non-NULL, use it to instantiate a new nfsd_file instead of +* opening a new one. * * Returns nfs_ok and sets @pnf on success; otherwise an nfsstat in * network byte order is returned. */ __be32 -nfsd_file_create (struct svc_rqst *rqstp,struct svc_fh *fhp, -unsigned int may_flags,struct nfsd_file **pnf) +nfsd_file_acquire_opened (struct svc_rqst *rqstp,struct svc_fh *fhp, +unsigned int may_flags,struct file *file, +struct nfsd_file **pnf) { -return nfsd_file_do_acquire (rqstp, fhp, may_flags, pnf, false, false); +return nfsd_file_do_acquire (rqstp, fhp, may_flags, file, pnf, false); }/*
fs/nfsd/filecache.h +3 -2
@@ -60,7 +60,8 @@ __be32 nfsd_file_acquire_gc(struct svc_rqst *rqstp, struct svc_fh *fhp, unsigned int may_flags, struct nfsd_file **nfp);__be32 nfsd_file_acquire (struct svc_rqst *rqstp,struct svc_fh *fhp,unsigned int may_flags,struct nfsd_file **nfp); -__be32 nfsd_file_create (struct svc_rqst *rqstp,struct svc_fh *fhp, -unsigned int may_flags,struct nfsd_file **nfp); +__be32 nfsd_file_acquire_opened (struct svc_rqst *rqstp,struct svc_fh *fhp, +unsigned int may_flags,struct file *file, +struct nfsd_file **nfp);int nfsd_file_cache_stats_show (struct seq_file *m,void *v);#endif /* _FS_NFSD_FILECACHE_H */
fs/nfsd/nfs4state.c +4 -12
@@ -5262,18 +5262,10 @@ static __be32 nfs4_get_vfs_file(struct svc_rqst *rqstp, struct nfs4_file *fp,if (!fp->fi_fds[oflag]) {spin_unlock (&fp->fi_lock); -if (!open->op_filp) { - status =nfsd_file_acquire (rqstp, cur_fh, access, &nf); -if (status != nfs_ok) - goto out_put_access; - }else { - status =nfsd_file_create (rqstp, cur_fh, access, &nf); -if (status != nfs_ok) - goto out_put_access; - nf->nf_file = open->op_filp; - open->op_filp =NULL ; -trace_nfsd_file_create (rqstp, access, nf); - } + status =nfsd_file_acquire_opened (rqstp, cur_fh, access, + open->op_filp, &nf); +if (status != nfs_ok) + goto out_put_access;spin_lock (&fp->fi_lock);if (!fp->fi_fds[oflag]) {
fs/nfsd/trace.h +13 -39
70 lines not on this page · raw message