]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.11-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 19 Mar 2021 10:28:46 +0000 (11:28 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 19 Mar 2021 10:28:46 +0000 (11:28 +0100)
added patches:
revert-nfsd4-a-client-s-own-opens-needn-t-prevent-delegations.patch
revert-nfsd4-remove-check_conflicting_opens-warning.patch

queue-5.11/revert-nfsd4-a-client-s-own-opens-needn-t-prevent-delegations.patch [new file with mode: 0644]
queue-5.11/revert-nfsd4-remove-check_conflicting_opens-warning.patch [new file with mode: 0644]
queue-5.11/series

diff --git a/queue-5.11/revert-nfsd4-a-client-s-own-opens-needn-t-prevent-delegations.patch b/queue-5.11/revert-nfsd4-a-client-s-own-opens-needn-t-prevent-delegations.patch
new file mode 100644 (file)
index 0000000..46d0c12
--- /dev/null
@@ -0,0 +1,138 @@
+From 6ee65a773096ab3f39d9b00311ac983be5bdeb7c Mon Sep 17 00:00:00 2001
+From: "J. Bruce Fields" <bfields@redhat.com>
+Date: Mon, 8 Mar 2021 10:52:29 -0500
+Subject: Revert "nfsd4: a client's own opens needn't prevent delegations"
+
+From: J. Bruce Fields <bfields@redhat.com>
+
+commit 6ee65a773096ab3f39d9b00311ac983be5bdeb7c upstream.
+
+This reverts commit 94415b06eb8aed13481646026dc995f04a3a534a.
+
+That commit claimed to allow a client to get a read delegation when it
+was the only writer.  Actually it allowed a client to get a read
+delegation when *any* client has a write open!
+
+The main problem is that it's depending on nfs4_clnt_odstate structures
+that are actually only maintained for pnfs exports.
+
+This causes clients to miss writes performed by other clients, even when
+there have been intervening closes and opens, violating close-to-open
+cache consistency.
+
+We can do this a different way, but first we should just revert this.
+
+I've added pynfs 4.1 test DELEG19 to test for this, as I should have
+done originally!
+
+Cc: stable@vger.kernel.org
+Reported-by: Timo Rothenpieler <timo@rothenpieler.org>
+Signed-off-by: J. Bruce Fields <bfields@redhat.com>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/locks.c          |    3 --
+ fs/nfsd/nfs4state.c |   54 +++++++++++++---------------------------------------
+ 2 files changed, 14 insertions(+), 43 deletions(-)
+
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -1808,9 +1808,6 @@ check_conflicting_open(struct file *filp
+       if (flags & FL_LAYOUT)
+               return 0;
+-      if (flags & FL_DELEG)
+-              /* We leave these checks to the caller. */
+-              return 0;
+       if (arg == F_RDLCK)
+               return inode_is_open_for_write(inode) ? -EAGAIN : 0;
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -4945,32 +4945,6 @@ static struct file_lock *nfs4_alloc_init
+       return fl;
+ }
+-static int nfsd4_check_conflicting_opens(struct nfs4_client *clp,
+-                                              struct nfs4_file *fp)
+-{
+-      struct nfs4_clnt_odstate *co;
+-      struct file *f = fp->fi_deleg_file->nf_file;
+-      struct inode *ino = locks_inode(f);
+-      int writes = atomic_read(&ino->i_writecount);
+-
+-      if (fp->fi_fds[O_WRONLY])
+-              writes--;
+-      if (fp->fi_fds[O_RDWR])
+-              writes--;
+-      WARN_ON_ONCE(writes < 0);
+-      if (writes > 0)
+-              return -EAGAIN;
+-      spin_lock(&fp->fi_lock);
+-      list_for_each_entry(co, &fp->fi_clnt_odstate, co_perfile) {
+-              if (co->co_client != clp) {
+-                      spin_unlock(&fp->fi_lock);
+-                      return -EAGAIN;
+-              }
+-      }
+-      spin_unlock(&fp->fi_lock);
+-      return 0;
+-}
+-
+ static struct nfs4_delegation *
+ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,
+                   struct nfs4_file *fp, struct nfs4_clnt_odstate *odstate)
+@@ -4990,12 +4964,9 @@ nfs4_set_delegation(struct nfs4_client *
+       nf = find_readable_file(fp);
+       if (!nf) {
+-              /*
+-               * We probably could attempt another open and get a read
+-               * delegation, but for now, don't bother until the
+-               * client actually sends us one.
+-               */
+-              return ERR_PTR(-EAGAIN);
++              /* We should always have a readable file here */
++              WARN_ON_ONCE(1);
++              return ERR_PTR(-EBADF);
+       }
+       spin_lock(&state_lock);
+       spin_lock(&fp->fi_lock);
+@@ -5025,19 +4996,11 @@ nfs4_set_delegation(struct nfs4_client *
+       if (!fl)
+               goto out_clnt_odstate;
+-      status = nfsd4_check_conflicting_opens(clp, fp);
+-      if (status) {
+-              locks_free_lock(fl);
+-              goto out_clnt_odstate;
+-      }
+       status = vfs_setlease(fp->fi_deleg_file->nf_file, fl->fl_type, &fl, NULL);
+       if (fl)
+               locks_free_lock(fl);
+       if (status)
+               goto out_clnt_odstate;
+-      status = nfsd4_check_conflicting_opens(clp, fp);
+-      if (status)
+-              goto out_clnt_odstate;
+       spin_lock(&state_lock);
+       spin_lock(&fp->fi_lock);
+@@ -5119,6 +5082,17 @@ nfs4_open_delegation(struct svc_fh *fh,
+                               goto out_no_deleg;
+                       if (!cb_up || !(oo->oo_flags & NFS4_OO_CONFIRMED))
+                               goto out_no_deleg;
++                      /*
++                       * Also, if the file was opened for write or
++                       * create, there's a good chance the client's
++                       * about to write to it, resulting in an
++                       * immediate recall (since we don't support
++                       * write delegations):
++                       */
++                      if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
++                              goto out_no_deleg;
++                      if (open->op_create == NFS4_OPEN_CREATE)
++                              goto out_no_deleg;
+                       break;
+               default:
+                       goto out_no_deleg;
diff --git a/queue-5.11/revert-nfsd4-remove-check_conflicting_opens-warning.patch b/queue-5.11/revert-nfsd4-remove-check_conflicting_opens-warning.patch
new file mode 100644 (file)
index 0000000..4825fda
--- /dev/null
@@ -0,0 +1,31 @@
+From 4aa5e002034f0701c3335379fd6c22d7f3338cce Mon Sep 17 00:00:00 2001
+From: "J. Bruce Fields" <bfields@redhat.com>
+Date: Mon, 8 Mar 2021 10:51:51 -0500
+Subject: Revert "nfsd4: remove check_conflicting_opens warning"
+
+From: J. Bruce Fields <bfields@redhat.com>
+
+commit 4aa5e002034f0701c3335379fd6c22d7f3338cce upstream.
+
+This reverts commit 50747dd5e47b "nfsd4: remove check_conflicting_opens
+warning", as a prerequisite for reverting 94415b06eb8a, which has a
+serious bug.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: J. Bruce Fields <bfields@redhat.com>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4state.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -4957,6 +4957,7 @@ static int nfsd4_check_conflicting_opens
+               writes--;
+       if (fp->fi_fds[O_RDWR])
+               writes--;
++      WARN_ON_ONCE(writes < 0);
+       if (writes > 0)
+               return -EAGAIN;
+       spin_lock(&fp->fi_lock);
index 9482313ef524064b368245cbaeefb54a3b04f2ee..67fa5d0096994ba8f99b5164652e34467fcb061b 100644 (file)
@@ -25,3 +25,5 @@ bpf-selftests-fix-up-some-test_verifier-cases-for-unprivileged.patch
 arm64-unconditionally-set-virtual-cpu-id-registers.patch
 rdma-srp-fix-support-for-unpopulated-and-unbalanced-numa-nodes.patch
 fuse-fix-live-lock-in-fuse_iget.patch
+revert-nfsd4-remove-check_conflicting_opens-warning.patch
+revert-nfsd4-a-client-s-own-opens-needn-t-prevent-delegations.patch