]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
NFSD: NFSv4 CLOSE should release an nfsd_file immediately
authorChuck Lever <chuck.lever@oracle.com>
Fri, 8 Jul 2022 18:27:02 +0000 (14:27 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 10 Apr 2024 14:19:11 +0000 (16:19 +0200)
[ Upstream commit 5e138c4a750dc140d881dab4a8804b094bbc08d2 ]

The last close of a file should enable other accessors to open and
use that file immediately. Leaving the file open in the filecache
prevents other users from accessing that file until the filecache
garbage-collects the file -- sometimes that takes several seconds.

Reported-by: Wang Yugui <wangyugui@e16-tech.com>
Link: https://bugzilla.linux-nfs.org/show_bug.cgi?387
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
fs/nfsd/filecache.c
fs/nfsd/filecache.h
fs/nfsd/nfs4state.c

index 26cfae138b9067e4ba96ceee9fbc6502750e654c..7ad27655db6993609c4d05c35aa188b5e908fe97 100644 (file)
@@ -451,6 +451,24 @@ nfsd_file_put(struct nfsd_file *nf)
                nfsd_file_put_noref(nf);
 }
 
+/**
+ * nfsd_file_close - Close an nfsd_file
+ * @nf: nfsd_file to close
+ *
+ * If this is the final reference for @nf, free it immediately.
+ * This reflects an on-the-wire CLOSE or DELEGRETURN into the
+ * VFS and exported filesystem.
+ */
+void nfsd_file_close(struct nfsd_file *nf)
+{
+       nfsd_file_put(nf);
+       if (refcount_dec_if_one(&nf->nf_ref)) {
+               nfsd_file_unhash(nf);
+               nfsd_file_lru_remove(nf);
+               nfsd_file_free(nf);
+       }
+}
+
 struct nfsd_file *
 nfsd_file_get(struct nfsd_file *nf)
 {
index ee9ed99d8b8fa63e80c4ec839e62df175c0038fd..28145f1628923cd4de0d8e1b5b915de00dbb3443 100644 (file)
@@ -52,6 +52,7 @@ void nfsd_file_cache_shutdown(void);
 int nfsd_file_cache_start_net(struct net *net);
 void nfsd_file_cache_shutdown_net(struct net *net);
 void nfsd_file_put(struct nfsd_file *nf);
+void nfsd_file_close(struct nfsd_file *nf);
 struct nfsd_file *nfsd_file_get(struct nfsd_file *nf);
 void nfsd_file_close_inode_sync(struct inode *inode);
 bool nfsd_file_is_cached(struct inode *inode);
index d349abf0821d6aa1fc5920e004c48c0bc46ba541..923eec2716d75f398349e320e1a6d38f862850d8 100644 (file)
@@ -831,9 +831,9 @@ static void __nfs4_file_put_access(struct nfs4_file *fp, int oflag)
                        swap(f2, fp->fi_fds[O_RDWR]);
                spin_unlock(&fp->fi_lock);
                if (f1)
-                       nfsd_file_put(f1);
+                       nfsd_file_close(f1);
                if (f2)
-                       nfsd_file_put(f2);
+                       nfsd_file_close(f2);
        }
 }