]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.13-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 8 Feb 2014 23:58:59 +0000 (15:58 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 8 Feb 2014 23:58:59 +0000 (15:58 -0800)
added patches:
nfs4.1-properly-handle-enotsup-in-secinfo_no_name.patch
nfs4-fix-discover_server_trunking-use-after-free.patch
nfs-always-make-sure-page-is-up-to-date-before-extending-a-write-to-cover-the-entire-page.patch
nfsv4.1-handle-errors-correctly-in-nfs41_walk_client_list.patch
nfsv4-fix-a-slot-leak-in-nfs40_sequence_done.patch
nfsv4-open-must-handle-the-nfs4err_io-return-code-correctly.patch
pnfs-proper-delay-for-nfs4err_recallconflict-in-layout_get_done.patch
sunrpc-don-t-wait-for-write-before-allowing-reads-from-use-gss-proxy-file.patch
sunrpc-fix-infinite-loop-in-rpc-state-machine.patch

queue-3.13/nfs-always-make-sure-page-is-up-to-date-before-extending-a-write-to-cover-the-entire-page.patch [new file with mode: 0644]
queue-3.13/nfs4-fix-discover_server_trunking-use-after-free.patch [new file with mode: 0644]
queue-3.13/nfs4.1-properly-handle-enotsup-in-secinfo_no_name.patch [new file with mode: 0644]
queue-3.13/nfsv4-fix-a-slot-leak-in-nfs40_sequence_done.patch [new file with mode: 0644]
queue-3.13/nfsv4-open-must-handle-the-nfs4err_io-return-code-correctly.patch [new file with mode: 0644]
queue-3.13/nfsv4.1-handle-errors-correctly-in-nfs41_walk_client_list.patch [new file with mode: 0644]
queue-3.13/pnfs-proper-delay-for-nfs4err_recallconflict-in-layout_get_done.patch [new file with mode: 0644]
queue-3.13/series
queue-3.13/sunrpc-don-t-wait-for-write-before-allowing-reads-from-use-gss-proxy-file.patch [new file with mode: 0644]
queue-3.13/sunrpc-fix-infinite-loop-in-rpc-state-machine.patch [new file with mode: 0644]

diff --git a/queue-3.13/nfs-always-make-sure-page-is-up-to-date-before-extending-a-write-to-cover-the-entire-page.patch b/queue-3.13/nfs-always-make-sure-page-is-up-to-date-before-extending-a-write-to-cover-the-entire-page.patch
new file mode 100644 (file)
index 0000000..4b03521
--- /dev/null
@@ -0,0 +1,67 @@
+From 263b4509ec4d47e0da3e753f85a39ea12d1eff24 Mon Sep 17 00:00:00 2001
+From: Scott Mayhew <smayhew@redhat.com>
+Date: Fri, 17 Jan 2014 15:12:05 -0500
+Subject: nfs: always make sure page is up-to-date before extending a write to cover the entire page
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Scott Mayhew <smayhew@redhat.com>
+
+commit 263b4509ec4d47e0da3e753f85a39ea12d1eff24 upstream.
+
+We should always make sure the cached page is up-to-date when we're
+determining whether we can extend a write to cover the full page -- even
+if we've received a write delegation from the server.
+
+Commit c7559663 added logic to skip this check if we have a write
+delegation, which can lead to data corruption such as the following
+scenario if client B receives a write delegation from the NFS server:
+
+Client A:
+    # echo 123456789 > /mnt/file
+
+Client B:
+    # echo abcdefghi >> /mnt/file
+    # cat /mnt/file
+    0�D0�abcdefghi
+
+Just because we hold a write delegation doesn't mean that we've read in
+the entire page contents.
+
+Signed-off-by: Scott Mayhew <smayhew@redhat.com>
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/write.c |   11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+--- a/fs/nfs/write.c
++++ b/fs/nfs/write.c
+@@ -922,19 +922,20 @@ out:
+  * extend the write to cover the entire page in order to avoid fragmentation
+  * inefficiencies.
+  *
+- * If the file is opened for synchronous writes or if we have a write delegation
+- * from the server then we can just skip the rest of the checks.
++ * If the file is opened for synchronous writes then we can just skip the rest
++ * of the checks.
+  */
+ static int nfs_can_extend_write(struct file *file, struct page *page, struct inode *inode)
+ {
+       if (file->f_flags & O_DSYNC)
+               return 0;
++      if (!nfs_write_pageuptodate(page, inode))
++              return 0;
+       if (NFS_PROTO(inode)->have_delegation(inode, FMODE_WRITE))
+               return 1;
+-      if (nfs_write_pageuptodate(page, inode) && (inode->i_flock == NULL ||
+-                      (inode->i_flock->fl_start == 0 &&
++      if (inode->i_flock == NULL || (inode->i_flock->fl_start == 0 &&
+                       inode->i_flock->fl_end == OFFSET_MAX &&
+-                      inode->i_flock->fl_type != F_RDLCK)))
++                      inode->i_flock->fl_type != F_RDLCK))
+               return 1;
+       return 0;
+ }
diff --git a/queue-3.13/nfs4-fix-discover_server_trunking-use-after-free.patch b/queue-3.13/nfs4-fix-discover_server_trunking-use-after-free.patch
new file mode 100644 (file)
index 0000000..2f75964
--- /dev/null
@@ -0,0 +1,41 @@
+From abad2fa5ba67725a3f9c376c8cfe76fbe94a3041 Mon Sep 17 00:00:00 2001
+From: Weston Andros Adamson <dros@primarydata.com>
+Date: Sun, 19 Jan 2014 22:45:36 -0500
+Subject: nfs4: fix discover_server_trunking use after free
+
+From: Weston Andros Adamson <dros@primarydata.com>
+
+commit abad2fa5ba67725a3f9c376c8cfe76fbe94a3041 upstream.
+
+If clp is new (cl_count = 1) and it matches another client in
+nfs4_discover_server_trunking, the nfs_put_client will free clp before
+->cl_preserve_clid is set.
+
+Signed-off-by: Weston Andros Adamson <dros@primarydata.com>
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/nfs4client.c |   10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+--- a/fs/nfs/nfs4client.c
++++ b/fs/nfs/nfs4client.c
+@@ -409,13 +409,11 @@ struct nfs_client *nfs4_init_client(stru
+       error = nfs4_discover_server_trunking(clp, &old);
+       if (error < 0)
+               goto error;
+-      nfs_put_client(clp);
+-      if (clp != old) {
+-              clp->cl_preserve_clid = true;
+-              clp = old;
+-      }
+-      return clp;
++      if (clp != old)
++              clp->cl_preserve_clid = true;
++      nfs_put_client(clp);
++      return old;
+ error:
+       nfs_mark_client_ready(clp, error);
diff --git a/queue-3.13/nfs4.1-properly-handle-enotsup-in-secinfo_no_name.patch b/queue-3.13/nfs4.1-properly-handle-enotsup-in-secinfo_no_name.patch
new file mode 100644 (file)
index 0000000..10bcb60
--- /dev/null
@@ -0,0 +1,44 @@
+From 78b19bae0813bd6f921ca58490196abd101297bd Mon Sep 17 00:00:00 2001
+From: Weston Andros Adamson <dros@primarydata.com>
+Date: Mon, 13 Jan 2014 16:54:45 -0500
+Subject: nfs4.1: properly handle ENOTSUP in SECINFO_NO_NAME
+
+From: Weston Andros Adamson <dros@primarydata.com>
+
+commit 78b19bae0813bd6f921ca58490196abd101297bd upstream.
+
+Don't check for -NFS4ERR_NOTSUPP, it's already been mapped to -ENOTSUPP
+by nfs4_stat_to_errno.
+
+This allows the client to mount v4.1 servers that don't support
+SECINFO_NO_NAME by falling back to the "guess and check" method of
+nfs4_find_root_sec.
+
+Signed-off-by: Weston Andros Adamson <dros@primarydata.com>
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/nfs4proc.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -7920,7 +7920,7 @@ nfs41_proc_secinfo_no_name(struct nfs_se
+               switch (err) {
+               case 0:
+               case -NFS4ERR_WRONGSEC:
+-              case -NFS4ERR_NOTSUPP:
++              case -ENOTSUPP:
+                       goto out;
+               default:
+                       err = nfs4_handle_exception(server, err, &exception);
+@@ -7954,7 +7954,7 @@ nfs41_find_root_sec(struct nfs_server *s
+        * Fall back on "guess and check" method if
+        * the server doesn't support SECINFO_NO_NAME
+        */
+-      if (err == -NFS4ERR_WRONGSEC || err == -NFS4ERR_NOTSUPP) {
++      if (err == -NFS4ERR_WRONGSEC || err == -ENOTSUPP) {
+               err = nfs4_find_root_sec(server, fhandle, info);
+               goto out_freepage;
+       }
diff --git a/queue-3.13/nfsv4-fix-a-slot-leak-in-nfs40_sequence_done.patch b/queue-3.13/nfsv4-fix-a-slot-leak-in-nfs40_sequence_done.patch
new file mode 100644 (file)
index 0000000..092b1d6
--- /dev/null
@@ -0,0 +1,35 @@
+From cab92c19821a814ecf5a5279e2699bf28e66caee Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+Date: Wed, 29 Jan 2014 12:12:15 -0500
+Subject: NFSv4: Fix a slot leak in nfs40_sequence_done
+
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+
+commit cab92c19821a814ecf5a5279e2699bf28e66caee upstream.
+
+The check for whether or not we sent an RPC call in nfs40_sequence_done
+is insufficient to decide whether or not we are holding a session slot,
+and thus should not be used to decide when to free that slot.
+
+This patch replaces the RPC_WAS_SENT() test with the correct test for
+whether or not slot == NULL.
+
+Cc: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/nfs4proc.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -539,7 +539,7 @@ static int nfs40_sequence_done(struct rp
+       struct nfs4_slot *slot = res->sr_slot;
+       struct nfs4_slot_table *tbl;
+-      if (!RPC_WAS_SENT(task))
++      if (slot == NULL)
+               goto out;
+       tbl = slot->table;
diff --git a/queue-3.13/nfsv4-open-must-handle-the-nfs4err_io-return-code-correctly.patch b/queue-3.13/nfsv4-open-must-handle-the-nfs4err_io-return-code-correctly.patch
new file mode 100644 (file)
index 0000000..7b02bc8
--- /dev/null
@@ -0,0 +1,97 @@
+From c7848f69ec4a8c03732cde5c949bd2aa711a9f4b Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+Date: Wed, 4 Dec 2013 17:39:23 -0500
+Subject: NFSv4: OPEN must handle the NFS4ERR_IO return code correctly
+
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+
+commit c7848f69ec4a8c03732cde5c949bd2aa711a9f4b upstream.
+
+decode_op_hdr() cannot distinguish between an XDR decoding error and
+the perfectly valid errorcode NFS4ERR_IO. This is normally not a
+problem, but for the particular case of OPEN, we need to be able
+to increment the NFSv4 open sequence id when the server returns
+a valid response.
+
+Reported-by: J Bruce Fields <bfields@fieldses.org>
+Link: http://lkml.kernel.org/r/20131204210356.GA19452@fieldses.org
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/nfs4xdr.c |   47 +++++++++++++++++++++++++++++++----------------
+ 1 file changed, 31 insertions(+), 16 deletions(-)
+
+--- a/fs/nfs/nfs4xdr.c
++++ b/fs/nfs/nfs4xdr.c
+@@ -3097,7 +3097,8 @@ out_overflow:
+       return -EIO;
+ }
+-static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
++static bool __decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected,
++              int *nfs_retval)
+ {
+       __be32 *p;
+       uint32_t opnum;
+@@ -3107,19 +3108,32 @@ static int decode_op_hdr(struct xdr_stre
+       if (unlikely(!p))
+               goto out_overflow;
+       opnum = be32_to_cpup(p++);
+-      if (opnum != expected) {
+-              dprintk("nfs: Server returned operation"
+-                      " %d but we issued a request for %d\n",
+-                              opnum, expected);
+-              return -EIO;
+-      }
++      if (unlikely(opnum != expected))
++              goto out_bad_operation;
+       nfserr = be32_to_cpup(p);
+-      if (nfserr != NFS_OK)
+-              return nfs4_stat_to_errno(nfserr);
+-      return 0;
++      if (nfserr == NFS_OK)
++              *nfs_retval = 0;
++      else
++              *nfs_retval = nfs4_stat_to_errno(nfserr);
++      return true;
++out_bad_operation:
++      dprintk("nfs: Server returned operation"
++              " %d but we issued a request for %d\n",
++                      opnum, expected);
++      *nfs_retval = -EREMOTEIO;
++      return false;
+ out_overflow:
+       print_overflow_msg(__func__, xdr);
+-      return -EIO;
++      *nfs_retval = -EIO;
++      return false;
++}
++
++static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
++{
++      int retval;
++
++      __decode_op_hdr(xdr, expected, &retval);
++      return retval;
+ }
+ /* Dummy routine */
+@@ -5001,11 +5015,12 @@ static int decode_open(struct xdr_stream
+       uint32_t savewords, bmlen, i;
+       int status;
+-      status = decode_op_hdr(xdr, OP_OPEN);
+-      if (status != -EIO)
+-              nfs_increment_open_seqid(status, res->seqid);
+-      if (!status)
+-              status = decode_stateid(xdr, &res->stateid);
++      if (!__decode_op_hdr(xdr, OP_OPEN, &status))
++              return status;
++      nfs_increment_open_seqid(status, res->seqid);
++      if (status)
++              return status;
++      status = decode_stateid(xdr, &res->stateid);
+       if (unlikely(status))
+               return status;
diff --git a/queue-3.13/nfsv4.1-handle-errors-correctly-in-nfs41_walk_client_list.patch b/queue-3.13/nfsv4.1-handle-errors-correctly-in-nfs41_walk_client_list.patch
new file mode 100644 (file)
index 0000000..13fd5ec
--- /dev/null
@@ -0,0 +1,48 @@
+From 64590daa9e0dfb3aad89e3ab9230683b76211d5b Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+Date: Fri, 17 Jan 2014 17:03:41 -0500
+Subject: NFSv4.1: Handle errors correctly in nfs41_walk_client_list
+
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+
+commit 64590daa9e0dfb3aad89e3ab9230683b76211d5b upstream.
+
+Both nfs41_walk_client_list and nfs40_walk_client_list expect the
+'status' variable to be set to the value -NFS4ERR_STALE_CLIENTID
+if the loop fails to find a match.
+The problem is that the 'pos->cl_cons_state > NFS_CS_READY' changes
+the value of 'status', and sets it either to the value '0' (which
+indicates success), or to the value EINTR.
+
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/nfs4client.c |    8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/fs/nfs/nfs4client.c
++++ b/fs/nfs/nfs4client.c
+@@ -493,9 +493,10 @@ int nfs40_walk_client_list(struct nfs_cl
+                       prev = pos;
+                       status = nfs_wait_client_init_complete(pos);
+-                      spin_lock(&nn->nfs_client_lock);
+                       if (status < 0)
+-                              continue;
++                              goto out;
++                      status = -NFS4ERR_STALE_CLIENTID;
++                      spin_lock(&nn->nfs_client_lock);
+               }
+               if (pos->cl_cons_state != NFS_CS_READY)
+                       continue;
+@@ -633,7 +634,8 @@ int nfs41_walk_client_list(struct nfs_cl
+                       }
+                       spin_lock(&nn->nfs_client_lock);
+                       if (status < 0)
+-                              continue;
++                              break;
++                      status = -NFS4ERR_STALE_CLIENTID;
+               }
+               if (pos->cl_cons_state != NFS_CS_READY)
+                       continue;
diff --git a/queue-3.13/pnfs-proper-delay-for-nfs4err_recallconflict-in-layout_get_done.patch b/queue-3.13/pnfs-proper-delay-for-nfs4err_recallconflict-in-layout_get_done.patch
new file mode 100644 (file)
index 0000000..038dc3f
--- /dev/null
@@ -0,0 +1,89 @@
+From ed7e5423014ad89720fcf315c0b73f2c5d0c7bd2 Mon Sep 17 00:00:00 2001
+From: Boaz Harrosh <bharrosh@panasas.com>
+Date: Wed, 22 Jan 2014 20:34:54 +0200
+Subject: pnfs: Proper delay for NFS4ERR_RECALLCONFLICT in layout_get_done
+
+From: Boaz Harrosh <bharrosh@panasas.com>
+
+commit ed7e5423014ad89720fcf315c0b73f2c5d0c7bd2 upstream.
+
+An NFS4ERR_RECALLCONFLICT is returned by server from a GET_LAYOUT
+only when a Server Sent a RECALL do to that GET_LAYOUT, or
+the RECALL and GET_LAYOUT crossed on the wire.
+In any way this means we want to wait at most until in-flight IO
+is finished and the RECALL can be satisfied.
+
+So a proper wait here is more like 1/10 of a second, not 15 seconds
+like we have now. In case of a server bug we delay exponentially
+longer on each retry.
+
+Current code totally craps out performance of very large files on
+most pnfs-objects layouts, because of how the map changes when the
+file has grown into the next raid group.
+
+[Stable: This will patch back to 3.9. If there are earlier still
+ maintained trees, please tell me I'll send a patch]
+
+Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/nfs4proc.c |   34 ++++++++++++++++++++++++++++++----
+ 1 file changed, 30 insertions(+), 4 deletions(-)
+
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -7409,9 +7409,9 @@ static void nfs4_layoutget_done(struct r
+       struct nfs_server *server = NFS_SERVER(inode);
+       struct pnfs_layout_hdr *lo;
+       struct nfs4_state *state = NULL;
+-      unsigned long timeo, giveup;
++      unsigned long timeo, now, giveup;
+-      dprintk("--> %s\n", __func__);
++      dprintk("--> %s tk_status => %d\n", __func__, -task->tk_status);
+       if (!nfs41_sequence_done(task, &lgp->res.seq_res))
+               goto out;
+@@ -7419,12 +7419,38 @@ static void nfs4_layoutget_done(struct r
+       switch (task->tk_status) {
+       case 0:
+               goto out;
++      /*
++       * NFS4ERR_LAYOUTTRYLATER is a conflict with another client
++       * (or clients) writing to the same RAID stripe
++       */
+       case -NFS4ERR_LAYOUTTRYLATER:
++      /*
++       * NFS4ERR_RECALLCONFLICT is when conflict with self (must recall
++       * existing layout before getting a new one).
++       */
+       case -NFS4ERR_RECALLCONFLICT:
+               timeo = rpc_get_timeout(task->tk_client);
+               giveup = lgp->args.timestamp + timeo;
+-              if (time_after(giveup, jiffies))
+-                      task->tk_status = -NFS4ERR_DELAY;
++              now = jiffies;
++              if (time_after(giveup, now)) {
++                      unsigned long delay;
++
++                      /* Delay for:
++                       * - Not less then NFS4_POLL_RETRY_MIN.
++                       * - One last time a jiffie before we give up
++                       * - exponential backoff (time_now minus start_attempt)
++                       */
++                      delay = max_t(unsigned long, NFS4_POLL_RETRY_MIN,
++                                  min((giveup - now - 1),
++                                      now - lgp->args.timestamp));
++
++                      dprintk("%s: NFS4ERR_RECALLCONFLICT waiting %lu\n",
++                              __func__, delay);
++                      rpc_delay(task, delay);
++                      task->tk_status = 0;
++                      rpc_restart_call_prepare(task);
++                      goto out; /* Do not call nfs4_async_handle_error() */
++              }
+               break;
+       case -NFS4ERR_EXPIRED:
+       case -NFS4ERR_BAD_STATEID:
index 79f4b45aa3f2a5aa6b0f6af498160386e5b5599a..557b075e35a183c43cb33eeb73d76a951c72a8ac 100644 (file)
@@ -40,3 +40,12 @@ ib-qib-fix-qp-check-when-looping-back-to-from-qp1.patch
 spi-bcm63xx-don-t-substract-prepend-length-from-total-length.patch
 spidev-fix-hang-when-transfer_one_message-fails.patch
 spi-pxa2xx-initialize-dma-channels-to-1-to-prevent-inadvertent-match.patch
+nfsv4-open-must-handle-the-nfs4err_io-return-code-correctly.patch
+nfs4.1-properly-handle-enotsup-in-secinfo_no_name.patch
+nfs-always-make-sure-page-is-up-to-date-before-extending-a-write-to-cover-the-entire-page.patch
+nfsv4.1-handle-errors-correctly-in-nfs41_walk_client_list.patch
+nfs4-fix-discover_server_trunking-use-after-free.patch
+pnfs-proper-delay-for-nfs4err_recallconflict-in-layout_get_done.patch
+nfsv4-fix-a-slot-leak-in-nfs40_sequence_done.patch
+sunrpc-fix-infinite-loop-in-rpc-state-machine.patch
+sunrpc-don-t-wait-for-write-before-allowing-reads-from-use-gss-proxy-file.patch
diff --git a/queue-3.13/sunrpc-don-t-wait-for-write-before-allowing-reads-from-use-gss-proxy-file.patch b/queue-3.13/sunrpc-don-t-wait-for-write-before-allowing-reads-from-use-gss-proxy-file.patch
new file mode 100644 (file)
index 0000000..9d4ce5f
--- /dev/null
@@ -0,0 +1,112 @@
+From 1654a04cd702fd19c297c36300a6ab834cf8c072 Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@redhat.com>
+Date: Sat, 4 Jan 2014 07:18:03 -0500
+Subject: sunrpc: don't wait for write before allowing reads from use-gss-proxy file
+
+From: Jeff Layton <jlayton@redhat.com>
+
+commit 1654a04cd702fd19c297c36300a6ab834cf8c072 upstream.
+
+It doesn't make much sense to make reads from this procfile hang. As
+far as I can tell, only gssproxy itself will open this file and it
+never reads from it. Change it to just give the present setting of
+sn->use_gss_proxy without waiting for anything.
+
+Note that we do not want to call use_gss_proxy() in this codepath
+since an inopportune read of this file could cause it to be disabled
+prematurely.
+
+Signed-off-by: Jeff Layton <jlayton@redhat.com>
+Signed-off-by: J. Bruce Fields <bfields@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/sunrpc/auth_gss/gss_rpc_upcall.c |    2 --
+ net/sunrpc/auth_gss/svcauth_gss.c    |   33 ++-------------------------------
+ net/sunrpc/netns.h                   |    1 -
+ 3 files changed, 2 insertions(+), 34 deletions(-)
+
+--- a/net/sunrpc/auth_gss/gss_rpc_upcall.c
++++ b/net/sunrpc/auth_gss/gss_rpc_upcall.c
+@@ -137,7 +137,6 @@ void init_gssp_clnt(struct sunrpc_net *s
+ {
+       mutex_init(&sn->gssp_lock);
+       sn->gssp_clnt = NULL;
+-      init_waitqueue_head(&sn->gssp_wq);
+ }
+ int set_gssp_clnt(struct net *net)
+@@ -154,7 +153,6 @@ int set_gssp_clnt(struct net *net)
+               sn->gssp_clnt = clnt;
+       }
+       mutex_unlock(&sn->gssp_lock);
+-      wake_up(&sn->gssp_wq);
+       return ret;
+ }
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -1295,34 +1295,9 @@ static int set_gss_proxy(struct net *net
+       else
+               ret = -EBUSY;
+       spin_unlock(&use_gssp_lock);
+-      wake_up(&sn->gssp_wq);
+       return ret;
+ }
+-static inline bool gssp_ready(struct sunrpc_net *sn)
+-{
+-      switch (sn->use_gss_proxy) {
+-              case -1:
+-                      return false;
+-              case 0:
+-                      return true;
+-              case 1:
+-                      return sn->gssp_clnt;
+-      }
+-      WARN_ON_ONCE(1);
+-      return false;
+-}
+-
+-static int wait_for_gss_proxy(struct net *net, struct file *file)
+-{
+-      struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
+-
+-      if (file->f_flags & O_NONBLOCK && !gssp_ready(sn))
+-              return -EAGAIN;
+-      return wait_event_interruptible(sn->gssp_wq, gssp_ready(sn));
+-}
+-
+-
+ static ssize_t write_gssp(struct file *file, const char __user *buf,
+                        size_t count, loff_t *ppos)
+ {
+@@ -1355,16 +1330,12 @@ static ssize_t read_gssp(struct file *fi
+                        size_t count, loff_t *ppos)
+ {
+       struct net *net = PDE_DATA(file_inode(file));
++      struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
+       unsigned long p = *ppos;
+       char tbuf[10];
+       size_t len;
+-      int ret;
+-
+-      ret = wait_for_gss_proxy(net, file);
+-      if (ret)
+-              return ret;
+-      snprintf(tbuf, sizeof(tbuf), "%d\n", use_gss_proxy(net));
++      snprintf(tbuf, sizeof(tbuf), "%d\n", sn->use_gss_proxy);
+       len = strlen(tbuf);
+       if (p >= len)
+               return 0;
+--- a/net/sunrpc/netns.h
++++ b/net/sunrpc/netns.h
+@@ -26,7 +26,6 @@ struct sunrpc_net {
+       unsigned int rpcb_is_af_local : 1;
+       struct mutex gssp_lock;
+-      wait_queue_head_t gssp_wq;
+       struct rpc_clnt *gssp_clnt;
+       int use_gss_proxy;
+       int pipe_version;
diff --git a/queue-3.13/sunrpc-fix-infinite-loop-in-rpc-state-machine.patch b/queue-3.13/sunrpc-fix-infinite-loop-in-rpc-state-machine.patch
new file mode 100644 (file)
index 0000000..0a3f1a6
--- /dev/null
@@ -0,0 +1,119 @@
+From 6ff33b7dd0228b7d7ed44791bbbc98b03fd15d9d Mon Sep 17 00:00:00 2001
+From: Weston Andros Adamson <dros@netapp.com>
+Date: Tue, 17 Dec 2013 12:16:11 -0500
+Subject: sunrpc: Fix infinite loop in RPC state machine
+
+From: Weston Andros Adamson <dros@netapp.com>
+
+commit 6ff33b7dd0228b7d7ed44791bbbc98b03fd15d9d upstream.
+
+When a task enters call_refreshresult with status 0 from call_refresh and
+!rpcauth_uptodatecred(task) it enters call_refresh again with no rate-limiting
+or max number of retries.
+
+Instead of trying forever, make use of the retry path that other errors use.
+
+This only seems to be possible when the crrefresh callback is gss_refresh_null,
+which only happens when destroying the context.
+
+To reproduce:
+
+1) mount with sec=krb5 (or sec=sys with krb5 negotiated for non FSID specific
+   operations).
+
+2) reboot - the client will be stuck and will need to be hard rebooted
+
+BUG: soft lockup - CPU#0 stuck for 22s! [kworker/0:2:46]
+Modules linked in: rpcsec_gss_krb5 nfsv4 nfs fscache ppdev crc32c_intel aesni_intel aes_x86_64 glue_helper lrw gf128mul ablk_helper cryptd serio_raw i2c_piix4 i2c_core e1000 parport_pc parport shpchp nfsd auth_rpcgss oid_registry exportfs nfs_acl lockd sunrpc autofs4 mptspi scsi_transport_spi mptscsih mptbase ata_generic floppy
+irq event stamp: 195724
+hardirqs last  enabled at (195723): [<ffffffff814a925c>] restore_args+0x0/0x30
+hardirqs last disabled at (195724): [<ffffffff814b0a6a>] apic_timer_interrupt+0x6a/0x80
+softirqs last  enabled at (195722): [<ffffffff8103f583>] __do_softirq+0x1df/0x276
+softirqs last disabled at (195717): [<ffffffff8103f852>] irq_exit+0x53/0x9a
+CPU: 0 PID: 46 Comm: kworker/0:2 Not tainted 3.13.0-rc3-branch-dros_testing+ #4
+Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 07/31/2013
+Workqueue: rpciod rpc_async_schedule [sunrpc]
+task: ffff8800799c4260 ti: ffff880079002000 task.ti: ffff880079002000
+RIP: 0010:[<ffffffffa0064fd4>]  [<ffffffffa0064fd4>] __rpc_execute+0x8a/0x362 [sunrpc]
+RSP: 0018:ffff880079003d18  EFLAGS: 00000246
+RAX: 0000000000000005 RBX: 0000000000000007 RCX: 0000000000000007
+RDX: 0000000000000007 RSI: ffff88007aecbae8 RDI: ffff8800783d8900
+RBP: ffff880079003d78 R08: ffff88006e30e9f8 R09: ffffffffa005a3d7
+R10: ffff88006e30e7b0 R11: ffff8800783d8900 R12: ffffffffa006675e
+R13: ffff880079003ce8 R14: ffff88006e30e7b0 R15: ffff8800783d8900
+FS:  0000000000000000(0000) GS:ffff88007f200000(0000) knlGS:0000000000000000
+CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 00007f3072333000 CR3: 0000000001a0b000 CR4: 00000000001407f0
+Stack:
+ ffff880079003d98 0000000000000246 0000000000000000 ffff88007a9a4830
+ ffff880000000000 ffffffff81073f47 ffff88007f212b00 ffff8800799c4260
+ ffff8800783d8988 ffff88007f212b00 ffffe8ffff604800 0000000000000000
+Call Trace:
+ [<ffffffff81073f47>] ? trace_hardirqs_on_caller+0x145/0x1a1
+ [<ffffffffa00652d3>] rpc_async_schedule+0x27/0x32 [sunrpc]
+ [<ffffffff81052974>] process_one_work+0x211/0x3a5
+ [<ffffffff810528d5>] ? process_one_work+0x172/0x3a5
+ [<ffffffff81052eeb>] worker_thread+0x134/0x202
+ [<ffffffff81052db7>] ? rescuer_thread+0x280/0x280
+ [<ffffffff81052db7>] ? rescuer_thread+0x280/0x280
+ [<ffffffff810584a0>] kthread+0xc9/0xd1
+ [<ffffffff810583d7>] ? __kthread_parkme+0x61/0x61
+ [<ffffffff814afd6c>] ret_from_fork+0x7c/0xb0
+ [<ffffffff810583d7>] ? __kthread_parkme+0x61/0x61
+Code: e8 87 63 fd e0 c6 05 10 dd 01 00 01 48 8b 43 70 4c 8d 6b 70 45 31 e4 a8 02 0f 85 d5 02 00 00 4c 8b 7b 48 48 c7 43 48 00 00 00 00 <4c> 8b 4b 50 4d 85 ff 75 0c 4d 85 c9 4d 89 cf 0f 84 32 01 00 00
+
+And the output of "rpcdebug -m rpc -s all":
+
+RPC:    61 call_refresh (status 0)
+RPC:    61 call_refresh (status 0)
+RPC:    61 refreshing RPCSEC_GSS cred ffff88007a413cf0
+RPC:    61 refreshing RPCSEC_GSS cred ffff88007a413cf0
+RPC:    61 call_refreshresult (status 0)
+RPC:    61 refreshing RPCSEC_GSS cred ffff88007a413cf0
+RPC:    61 call_refreshresult (status 0)
+RPC:    61 refreshing RPCSEC_GSS cred ffff88007a413cf0
+RPC:    61 call_refresh (status 0)
+RPC:    61 call_refreshresult (status 0)
+RPC:    61 call_refresh (status 0)
+RPC:    61 call_refresh (status 0)
+RPC:    61 refreshing RPCSEC_GSS cred ffff88007a413cf0
+RPC:    61 call_refreshresult (status 0)
+RPC:    61 call_refresh (status 0)
+RPC:    61 refreshing RPCSEC_GSS cred ffff88007a413cf0
+RPC:    61 call_refresh (status 0)
+RPC:    61 refreshing RPCSEC_GSS cred ffff88007a413cf0
+RPC:    61 refreshing RPCSEC_GSS cred ffff88007a413cf0
+RPC:    61 call_refreshresult (status 0)
+RPC:    61 call_refresh (status 0)
+RPC:    61 call_refresh (status 0)
+RPC:    61 call_refresh (status 0)
+RPC:    61 call_refresh (status 0)
+RPC:    61 call_refreshresult (status 0)
+RPC:    61 refreshing RPCSEC_GSS cred ffff88007a413cf0
+
+Signed-off-by: Weston Andros Adamson <dros@netapp.com>
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/sunrpc/clnt.c |    8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/net/sunrpc/clnt.c
++++ b/net/sunrpc/clnt.c
+@@ -1529,9 +1529,13 @@ call_refreshresult(struct rpc_task *task
+       task->tk_action = call_refresh;
+       switch (status) {
+       case 0:
+-              if (rpcauth_uptodatecred(task))
++              if (rpcauth_uptodatecred(task)) {
+                       task->tk_action = call_allocate;
+-              return;
++                      return;
++              }
++              /* Use rate-limiting and a max number of retries if refresh
++               * had status 0 but failed to update the cred.
++               */
+       case -ETIMEDOUT:
+               rpc_delay(task, 3*HZ);
+       case -EAGAIN: