nfsd: eliminate the NFSD_FILE_BREAK_* flags
authorJeff Layton <jlayton@kernel.org>
Fri, 29 Jul 2022 21:01:07 +0000 (17:01 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 17 Aug 2022 12:22:45 +0000 (14:22 +0200)
commit 23ba98de6dcec665e15c0ca19244379bb0d30932 upstream.

We had a report from the spring Bake-a-thon of data corruption in some
nfstest_interop tests. Looking at the traces showed the NFS server
allowing a v3 WRITE to proceed while a read delegation was still
outstanding.

Currently, we only set NFSD_FILE_BREAK_* flags if
NFSD_MAY_NOT_BREAK_LEASE was set when we call nfsd_file_alloc.
NFSD_MAY_NOT_BREAK_LEASE was intended to be set when finding files for
COMMIT ops, where we need a writeable filehandle but don't need to
break read leases.

It doesn't make any sense to consult that flag when allocating a file
since the file may be used on subsequent calls where we do want to break
the lease (and the usage of it here seems to be reverse from what it
should be anyway).

Also, after calling nfsd_open_break_lease, we don't want to clear the
BREAK_* bits. A lease could end up being set on it later (more than
once) and we need to be able to break those leases as well.

This means that the NFSD_FILE_BREAK_* flags now just mirror
NFSD_MAY_{READ,WRITE} flags, so there's no need for them at all. Just
drop those flags and unconditionally call nfsd_open_break_lease every
time.

Reported-by: Olga Kornieskaia <kolga@netapp.com>
Link: https://bugzilla.redhat.com/show_bug.cgi?id=2107360
Fixes: 65294c1f2c5e (nfsd: add a new struct file caching facility to nfsd)
Cc: <stable@vger.kernel.org> # 5.4.x : bb283ca18d1e NFSD: Clean up the show_nf_flags() macro
Cc: <stable@vger.kernel.org> # 5.4.x
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/nfsd/filecache.c
fs/nfsd/filecache.h
fs/nfsd/trace.h

index 87d984e0cdc0c9dce7e16bf7781f2e9c9116e685..1e8c31ed6c7c4d87a0f072e69001d5e6f6561782 100644 (file)
@@ -187,12 +187,6 @@ nfsd_file_alloc(struct inode *inode, unsigned int may, unsigned int hashval,
                nf->nf_hashval = hashval;
                refcount_set(&nf->nf_ref, 1);
                nf->nf_may = may & NFSD_FILE_MAY_MASK;
-               if (may & NFSD_MAY_NOT_BREAK_LEASE) {
-                       if (may & NFSD_MAY_WRITE)
-                               __set_bit(NFSD_FILE_BREAK_WRITE, &nf->nf_flags);
-                       if (may & NFSD_MAY_READ)
-                               __set_bit(NFSD_FILE_BREAK_READ, &nf->nf_flags);
-               }
                nf->nf_mark = NULL;
                trace_nfsd_file_alloc(nf);
        }
@@ -990,21 +984,7 @@ wait_for_construction:
 
        this_cpu_inc(nfsd_file_cache_hits);
 
-       if (!(may_flags & NFSD_MAY_NOT_BREAK_LEASE)) {
-               bool write = (may_flags & NFSD_MAY_WRITE);
-
-               if (test_bit(NFSD_FILE_BREAK_READ, &nf->nf_flags) ||
-                   (test_bit(NFSD_FILE_BREAK_WRITE, &nf->nf_flags) && write)) {
-                       status = nfserrno(nfsd_open_break_lease(
-                                       file_inode(nf->nf_file), may_flags));
-                       if (status == nfs_ok) {
-                               clear_bit(NFSD_FILE_BREAK_READ, &nf->nf_flags);
-                               if (write)
-                                       clear_bit(NFSD_FILE_BREAK_WRITE,
-                                                 &nf->nf_flags);
-                       }
-               }
-       }
+       status = nfserrno(nfsd_open_break_lease(file_inode(nf->nf_file), may_flags));
 out:
        if (status == nfs_ok) {
                *pnf = nf;
index 435ceab27897addb7a9cc5202be27ddc2f4ba419..63104be2865c585d44b9f5b1aab2ba99e4e58cc8 100644 (file)
@@ -37,9 +37,7 @@ struct nfsd_file {
        struct net              *nf_net;
 #define NFSD_FILE_HASHED       (0)
 #define NFSD_FILE_PENDING      (1)
-#define NFSD_FILE_BREAK_READ   (2)
-#define NFSD_FILE_BREAK_WRITE  (3)
-#define NFSD_FILE_REFERENCED   (4)
+#define NFSD_FILE_REFERENCED   (2)
        unsigned long           nf_flags;
        struct inode            *nf_inode;
        unsigned int            nf_hashval;
index 09638bc91ecf7ca3ee71474b395527b76433a4b7..0fc1fa6f28e0bc65b99e54a2762ef72b8d8eaa7b 100644 (file)
@@ -640,8 +640,6 @@ DEFINE_CLID_EVENT(confirmed_r);
        __print_flags(val, "|",                                         \
                { 1 << NFSD_FILE_HASHED,        "HASHED" },             \
                { 1 << NFSD_FILE_PENDING,       "PENDING" },            \
-               { 1 << NFSD_FILE_BREAK_READ,    "BREAK_READ" },         \
-               { 1 << NFSD_FILE_BREAK_WRITE,   "BREAK_WRITE" },        \
                { 1 << NFSD_FILE_REFERENCED,    "REFERENCED"})
 
 DECLARE_EVENT_CLASS(nfsd_file_class,