]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 18 Nov 2014 20:24:26 +0000 (12:24 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 18 Nov 2014 20:24:26 +0000 (12:24 -0800)
added patches:
nfs-don-t-try-to-reclaim-delegation-open-state-if-recovery-failed.patch
nfs-fix-use-of-uninitialized-variable-in-nfs_getattr.patch
nfsv4-ensure-that-we-remove-nfsv4.0-delegations-when-state-has-expired.patch
nfsv4-fix-races-between-nfs_remove_bad_delegation-and-delegation-return.patch

queue-3.10/nfs-don-t-try-to-reclaim-delegation-open-state-if-recovery-failed.patch [new file with mode: 0644]
queue-3.10/nfs-fix-use-of-uninitialized-variable-in-nfs_getattr.patch [new file with mode: 0644]
queue-3.10/nfsv4-ensure-that-we-remove-nfsv4.0-delegations-when-state-has-expired.patch [new file with mode: 0644]
queue-3.10/nfsv4-fix-races-between-nfs_remove_bad_delegation-and-delegation-return.patch [new file with mode: 0644]
queue-3.10/series

diff --git a/queue-3.10/nfs-don-t-try-to-reclaim-delegation-open-state-if-recovery-failed.patch b/queue-3.10/nfs-don-t-try-to-reclaim-delegation-open-state-if-recovery-failed.patch
new file mode 100644 (file)
index 0000000..6ad4dc1
--- /dev/null
@@ -0,0 +1,31 @@
+From f8ebf7a8ca35dde321f0cd385fee6f1950609367 Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+Date: Fri, 17 Oct 2014 23:02:52 +0300
+Subject: NFS: Don't try to reclaim delegation open state if recovery failed
+
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+
+commit f8ebf7a8ca35dde321f0cd385fee6f1950609367 upstream.
+
+If state recovery failed, then we should not attempt to reclaim delegated
+state.
+
+http://lkml.kernel.org/r/CAN-5tyHwG=Cn2Q9KsHWadewjpTTy_K26ee+UnSvHvG4192p-Xw@mail.gmail.com
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/delegation.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/nfs/delegation.c
++++ b/fs/nfs/delegation.c
+@@ -108,6 +108,8 @@ again:
+                       continue;
+               if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
+                       continue;
++              if (!nfs4_valid_open_stateid(state))
++                      continue;
+               if (!nfs4_stateid_match(&state->stateid, stateid))
+                       continue;
+               get_nfs_open_context(ctx);
diff --git a/queue-3.10/nfs-fix-use-of-uninitialized-variable-in-nfs_getattr.patch b/queue-3.10/nfs-fix-use-of-uninitialized-variable-in-nfs_getattr.patch
new file mode 100644 (file)
index 0000000..648601d
--- /dev/null
@@ -0,0 +1,32 @@
+From 16caf5b6101d03335b386e77e9e14136f989be87 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Thu, 23 Oct 2014 14:02:47 +0200
+Subject: nfs: Fix use of uninitialized variable in nfs_getattr()
+
+From: Jan Kara <jack@suse.cz>
+
+commit 16caf5b6101d03335b386e77e9e14136f989be87 upstream.
+
+Variable 'err' needn't be initialized when nfs_getattr() uses it to
+check whether it should call generic_fillattr() or not. That can result
+in spurious error returns. Initialize 'err' properly.
+
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/inode.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/nfs/inode.c
++++ b/fs/nfs/inode.c
+@@ -519,7 +519,7 @@ int nfs_getattr(struct vfsmount *mnt, st
+ {
+       struct inode *inode = dentry->d_inode;
+       int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME;
+-      int err;
++      int err = 0;
+       /* Flush out writes to the server in order to update c/mtime.  */
+       if (S_ISREG(inode->i_mode)) {
diff --git a/queue-3.10/nfsv4-ensure-that-we-remove-nfsv4.0-delegations-when-state-has-expired.patch b/queue-3.10/nfsv4-ensure-that-we-remove-nfsv4.0-delegations-when-state-has-expired.patch
new file mode 100644 (file)
index 0000000..65e2ac4
--- /dev/null
@@ -0,0 +1,61 @@
+From 4dfd4f7af0afd201706ad186352ca423b0f17d4b Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+Date: Fri, 17 Oct 2014 15:10:25 +0300
+Subject: NFSv4: Ensure that we remove NFSv4.0 delegations when state has expired
+
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+
+commit 4dfd4f7af0afd201706ad186352ca423b0f17d4b upstream.
+
+NFSv4.0 does not have TEST_STATEID/FREE_STATEID functionality, so
+unlike NFSv4.1, the recovery procedure when stateids have expired or
+have been revoked requires us to just forget the delegation.
+
+http://lkml.kernel.org/r/CAN-5tyHwG=Cn2Q9KsHWadewjpTTy_K26ee+UnSvHvG4192p-Xw@mail.gmail.com
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/nfs4proc.c |   24 +++++++++++++++++++++++-
+ 1 file changed, 23 insertions(+), 1 deletion(-)
+
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -1845,6 +1845,28 @@ static int nfs4_open_expired(struct nfs4
+       return ret;
+ }
++static void nfs_finish_clear_delegation_stateid(struct nfs4_state *state)
++{
++      nfs_remove_bad_delegation(state->inode);
++      write_seqlock(&state->seqlock);
++      nfs4_stateid_copy(&state->stateid, &state->open_stateid);
++      write_sequnlock(&state->seqlock);
++      clear_bit(NFS_DELEGATED_STATE, &state->flags);
++}
++
++static void nfs40_clear_delegation_stateid(struct nfs4_state *state)
++{
++      if (rcu_access_pointer(NFS_I(state->inode)->delegation) != NULL)
++              nfs_finish_clear_delegation_stateid(state);
++}
++
++static int nfs40_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state)
++{
++      /* NFSv4.0 doesn't allow for delegation recovery on open expire */
++      nfs40_clear_delegation_stateid(state);
++      return nfs4_open_expired(sp, state);
++}
++
+ #if defined(CONFIG_NFS_V4_1)
+ static void nfs41_clear_delegation_stateid(struct nfs4_state *state)
+ {
+@@ -6974,7 +6996,7 @@ static const struct nfs4_state_recovery_
+ static const struct nfs4_state_recovery_ops nfs40_nograce_recovery_ops = {
+       .owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE,
+       .state_flag_bit = NFS_STATE_RECLAIM_NOGRACE,
+-      .recover_open   = nfs4_open_expired,
++      .recover_open   = nfs40_open_expired,
+       .recover_lock   = nfs4_lock_expired,
+       .establish_clid = nfs4_init_clientid,
+       .get_clid_cred  = nfs4_get_setclientid_cred,
diff --git a/queue-3.10/nfsv4-fix-races-between-nfs_remove_bad_delegation-and-delegation-return.patch b/queue-3.10/nfsv4-fix-races-between-nfs_remove_bad_delegation-and-delegation-return.patch
new file mode 100644 (file)
index 0000000..75896c4
--- /dev/null
@@ -0,0 +1,105 @@
+From 869f9dfa4d6d57b79e0afc3af14772c2a023eeb1 Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+Date: Mon, 10 Nov 2014 18:43:56 -0500
+Subject: NFSv4: Fix races between nfs_remove_bad_delegation() and delegation return
+
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+
+commit 869f9dfa4d6d57b79e0afc3af14772c2a023eeb1 upstream.
+
+Any attempt to call nfs_remove_bad_delegation() while a delegation is being
+returned is currently a no-op. This means that we can end up looping
+forever in nfs_end_delegation_return() if something causes the delegation
+to be revoked.
+This patch adds a mechanism whereby the state recovery code can communicate
+to the delegation return code that the delegation is no longer valid and
+that it should not be used when reclaiming state.
+It also changes the return value for nfs4_handle_delegation_recall_error()
+to ensure that nfs_end_delegation_return() does not reattempt the lock
+reclaim before state recovery is done.
+
+http://lkml.kernel.org/r/CAN-5tyHwG=Cn2Q9KsHWadewjpTTy_K26ee+UnSvHvG4192p-Xw@mail.gmail.com
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/delegation.c |   23 +++++++++++++++++++++--
+ fs/nfs/delegation.h |    1 +
+ fs/nfs/nfs4proc.c   |    2 +-
+ 3 files changed, 23 insertions(+), 3 deletions(-)
+
+--- a/fs/nfs/delegation.c
++++ b/fs/nfs/delegation.c
+@@ -177,7 +177,11 @@ static int nfs_do_return_delegation(stru
+ {
+       int res = 0;
+-      res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid, issync);
++      if (!test_bit(NFS_DELEGATION_REVOKED, &delegation->flags))
++              res = nfs4_proc_delegreturn(inode,
++                              delegation->cred,
++                              &delegation->stateid,
++                              issync);
+       nfs_free_delegation(delegation);
+       return res;
+ }
+@@ -363,11 +367,13 @@ static int nfs_end_delegation_return(str
+ {
+       struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
+       struct nfs_inode *nfsi = NFS_I(inode);
+-      int err;
++      int err = 0;
+       if (delegation == NULL)
+               return 0;
+       do {
++              if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags))
++                      break;
+               err = nfs_delegation_claim_opens(inode, &delegation->stateid);
+               if (!issync || err != -EAGAIN)
+                       break;
+@@ -588,10 +594,23 @@ static void nfs_client_mark_return_unuse
+       rcu_read_unlock();
+ }
++static void nfs_revoke_delegation(struct inode *inode)
++{
++      struct nfs_delegation *delegation;
++      rcu_read_lock();
++      delegation = rcu_dereference(NFS_I(inode)->delegation);
++      if (delegation != NULL) {
++              set_bit(NFS_DELEGATION_REVOKED, &delegation->flags);
++              nfs_mark_return_delegation(NFS_SERVER(inode), delegation);
++      }
++      rcu_read_unlock();
++}
++
+ void nfs_remove_bad_delegation(struct inode *inode)
+ {
+       struct nfs_delegation *delegation;
++      nfs_revoke_delegation(inode);
+       delegation = nfs_inode_detach_delegation(inode);
+       if (delegation) {
+               nfs_inode_find_state_and_recover(inode, &delegation->stateid);
+--- a/fs/nfs/delegation.h
++++ b/fs/nfs/delegation.h
+@@ -31,6 +31,7 @@ enum {
+       NFS_DELEGATION_RETURN_IF_CLOSED,
+       NFS_DELEGATION_REFERENCED,
+       NFS_DELEGATION_RETURNING,
++      NFS_DELEGATION_REVOKED,
+ };
+ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -1416,7 +1416,7 @@ static int nfs4_handle_delegation_recall
+                       nfs_inode_find_state_and_recover(state->inode,
+                                       stateid);
+                       nfs4_schedule_stateid_recovery(server, state);
+-                      return 0;
++                      return -EAGAIN;
+               case -NFS4ERR_DELAY:
+               case -NFS4ERR_GRACE:
+                       set_bit(NFS_DELEGATED_STATE, &state->flags);
index d75d862c64b37b49a73b3efae8dc106223cb3bdc..741834fe71f1483994d3a8b8432bfce91a8d5159 100644 (file)
@@ -32,3 +32,7 @@ dm-btree-fix-a-recursion-depth-bug-in-btree-walking-code.patch
 dm-raid-ensure-superblock-s-size-matches-device-s-logical-block-size.patch
 input-alps-ignore-potential-bare-packets-when-device-is-out-of-sync.patch
 input-alps-allow-up-to-2-invalid-packets-without-resetting-device.patch
+nfsv4-ensure-that-we-remove-nfsv4.0-delegations-when-state-has-expired.patch
+nfs-don-t-try-to-reclaim-delegation-open-state-if-recovery-failed.patch
+nfs-fix-use-of-uninitialized-variable-in-nfs_getattr.patch
+nfsv4-fix-races-between-nfs_remove_bad_delegation-and-delegation-return.patch