From: Greg Kroah-Hartman Date: Sat, 8 Feb 2014 23:58:59 +0000 (-0800) Subject: 3.13-stable patches X-Git-Tag: v3.4.80~62 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c54442ede978dd5da612754d04f5a876c92db639;p=thirdparty%2Fkernel%2Fstable-queue.git 3.13-stable patches 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 --- 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 index 00000000000..4b03521ba8d --- /dev/null +++ b/queue-3.13/nfs-always-make-sure-page-is-up-to-date-before-extending-a-write-to-cover-the-entire-page.patch @@ -0,0 +1,67 @@ +From 263b4509ec4d47e0da3e753f85a39ea12d1eff24 Mon Sep 17 00:00:00 2001 +From: Scott Mayhew +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 + +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 +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..2f75964604b --- /dev/null +++ b/queue-3.13/nfs4-fix-discover_server_trunking-use-after-free.patch @@ -0,0 +1,41 @@ +From abad2fa5ba67725a3f9c376c8cfe76fbe94a3041 Mon Sep 17 00:00:00 2001 +From: Weston Andros Adamson +Date: Sun, 19 Jan 2014 22:45:36 -0500 +Subject: nfs4: fix discover_server_trunking use after free + +From: Weston Andros Adamson + +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 +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..10bcb605284 --- /dev/null +++ b/queue-3.13/nfs4.1-properly-handle-enotsup-in-secinfo_no_name.patch @@ -0,0 +1,44 @@ +From 78b19bae0813bd6f921ca58490196abd101297bd Mon Sep 17 00:00:00 2001 +From: Weston Andros Adamson +Date: Mon, 13 Jan 2014 16:54:45 -0500 +Subject: nfs4.1: properly handle ENOTSUP in SECINFO_NO_NAME + +From: Weston Andros Adamson + +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 +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..092b1d65ad0 --- /dev/null +++ b/queue-3.13/nfsv4-fix-a-slot-leak-in-nfs40_sequence_done.patch @@ -0,0 +1,35 @@ +From cab92c19821a814ecf5a5279e2699bf28e66caee Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Wed, 29 Jan 2014 12:12:15 -0500 +Subject: NFSv4: Fix a slot leak in nfs40_sequence_done + +From: Trond Myklebust + +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 +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..7b02bc8ea2c --- /dev/null +++ b/queue-3.13/nfsv4-open-must-handle-the-nfs4err_io-return-code-correctly.patch @@ -0,0 +1,97 @@ +From c7848f69ec4a8c03732cde5c949bd2aa711a9f4b Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Wed, 4 Dec 2013 17:39:23 -0500 +Subject: NFSv4: OPEN must handle the NFS4ERR_IO return code correctly + +From: Trond Myklebust + +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 +Link: http://lkml.kernel.org/r/20131204210356.GA19452@fieldses.org +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..13fd5ec271f --- /dev/null +++ b/queue-3.13/nfsv4.1-handle-errors-correctly-in-nfs41_walk_client_list.patch @@ -0,0 +1,48 @@ +From 64590daa9e0dfb3aad89e3ab9230683b76211d5b Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Fri, 17 Jan 2014 17:03:41 -0500 +Subject: NFSv4.1: Handle errors correctly in nfs41_walk_client_list + +From: Trond Myklebust + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..038dc3fe038 --- /dev/null +++ b/queue-3.13/pnfs-proper-delay-for-nfs4err_recallconflict-in-layout_get_done.patch @@ -0,0 +1,89 @@ +From ed7e5423014ad89720fcf315c0b73f2c5d0c7bd2 Mon Sep 17 00:00:00 2001 +From: Boaz Harrosh +Date: Wed, 22 Jan 2014 20:34:54 +0200 +Subject: pnfs: Proper delay for NFS4ERR_RECALLCONFLICT in layout_get_done + +From: Boaz Harrosh + +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 +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + 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: diff --git a/queue-3.13/series b/queue-3.13/series index 79f4b45aa3f..557b075e35a 100644 --- a/queue-3.13/series +++ b/queue-3.13/series @@ -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 index 00000000000..9d4ce5f6100 --- /dev/null +++ b/queue-3.13/sunrpc-don-t-wait-for-write-before-allowing-reads-from-use-gss-proxy-file.patch @@ -0,0 +1,112 @@ +From 1654a04cd702fd19c297c36300a6ab834cf8c072 Mon Sep 17 00:00:00 2001 +From: Jeff Layton +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 + +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 +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..0a3f1a6eb88 --- /dev/null +++ b/queue-3.13/sunrpc-fix-infinite-loop-in-rpc-state-machine.patch @@ -0,0 +1,119 @@ +From 6ff33b7dd0228b7d7ed44791bbbc98b03fd15d9d Mon Sep 17 00:00:00 2001 +From: Weston Andros Adamson +Date: Tue, 17 Dec 2013 12:16:11 -0500 +Subject: sunrpc: Fix infinite loop in RPC state machine + +From: Weston Andros Adamson + +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): [] restore_args+0x0/0x30 +hardirqs last disabled at (195724): [] apic_timer_interrupt+0x6a/0x80 +softirqs last enabled at (195722): [] __do_softirq+0x1df/0x276 +softirqs last disabled at (195717): [] 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:[] [] __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: + [] ? trace_hardirqs_on_caller+0x145/0x1a1 + [] rpc_async_schedule+0x27/0x32 [sunrpc] + [] process_one_work+0x211/0x3a5 + [] ? process_one_work+0x172/0x3a5 + [] worker_thread+0x134/0x202 + [] ? rescuer_thread+0x280/0x280 + [] ? rescuer_thread+0x280/0x280 + [] kthread+0xc9/0xd1 + [] ? __kthread_parkme+0x61/0x61 + [] ret_from_fork+0x7c/0xb0 + [] ? __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 +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + 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: