--- /dev/null
+From 7b1f1fd1842e6ede25183c267ae733a7f67f00bc Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+Date: Fri, 5 Apr 2013 16:11:11 -0400
+Subject: NFSv4/4.1: Fix bugs in nfs4[01]_walk_client_list
+
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+
+commit 7b1f1fd1842e6ede25183c267ae733a7f67f00bc upstream.
+
+It is unsafe to use list_for_each_entry_safe() here, because
+when we drop the nn->nfs_client_lock, we pin the _current_ list
+entry and ensure that it stays in the list, but we don't do the
+same for the _next_ list entry. Use of list_for_each_entry() is
+therefore the correct thing to do.
+
+Also fix the refcounting in nfs41_walk_client_list().
+
+Finally, ensure that the nfs_client has finished being initialised
+and, in the case of NFSv4.1, that the session is set up.
+
+Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
+Cc: Chuck Lever <chuck.lever@oracle.com>
+Cc: Bryan Schumaker <bjschuma@netapp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/nfs4client.c | 44 ++++++++++++++++++++++++++++----------------
+ 1 file changed, 28 insertions(+), 16 deletions(-)
+
+--- a/fs/nfs/nfs4client.c
++++ b/fs/nfs/nfs4client.c
+@@ -300,7 +300,7 @@ int nfs40_walk_client_list(struct nfs_cl
+ struct rpc_cred *cred)
+ {
+ struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id);
+- struct nfs_client *pos, *n, *prev = NULL;
++ struct nfs_client *pos, *prev = NULL;
+ struct nfs4_setclientid_res clid = {
+ .clientid = new->cl_clientid,
+ .confirm = new->cl_confirm,
+@@ -308,10 +308,23 @@ int nfs40_walk_client_list(struct nfs_cl
+ int status = -NFS4ERR_STALE_CLIENTID;
+
+ spin_lock(&nn->nfs_client_lock);
+- list_for_each_entry_safe(pos, n, &nn->nfs_client_list, cl_share_link) {
++ list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) {
+ /* If "pos" isn't marked ready, we can't trust the
+ * remaining fields in "pos" */
+- if (pos->cl_cons_state < NFS_CS_READY)
++ if (pos->cl_cons_state > NFS_CS_READY) {
++ atomic_inc(&pos->cl_count);
++ spin_unlock(&nn->nfs_client_lock);
++
++ if (prev)
++ nfs_put_client(prev);
++ prev = pos;
++
++ status = nfs_wait_client_init_complete(pos);
++ spin_lock(&nn->nfs_client_lock);
++ if (status < 0)
++ continue;
++ }
++ if (pos->cl_cons_state != NFS_CS_READY)
+ continue;
+
+ if (pos->rpc_ops != new->rpc_ops)
+@@ -423,16 +436,16 @@ int nfs41_walk_client_list(struct nfs_cl
+ struct rpc_cred *cred)
+ {
+ struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id);
+- struct nfs_client *pos, *n, *prev = NULL;
++ struct nfs_client *pos, *prev = NULL;
+ int status = -NFS4ERR_STALE_CLIENTID;
+
+ spin_lock(&nn->nfs_client_lock);
+- list_for_each_entry_safe(pos, n, &nn->nfs_client_list, cl_share_link) {
++ list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) {
+ /* If "pos" isn't marked ready, we can't trust the
+ * remaining fields in "pos", especially the client
+ * ID and serverowner fields. Wait for CREATE_SESSION
+ * to finish. */
+- if (pos->cl_cons_state < NFS_CS_READY) {
++ if (pos->cl_cons_state > NFS_CS_READY) {
+ atomic_inc(&pos->cl_count);
+ spin_unlock(&nn->nfs_client_lock);
+
+@@ -440,18 +453,17 @@ int nfs41_walk_client_list(struct nfs_cl
+ nfs_put_client(prev);
+ prev = pos;
+
+- nfs4_schedule_lease_recovery(pos);
+ status = nfs_wait_client_init_complete(pos);
+- if (status < 0) {
+- nfs_put_client(pos);
+- spin_lock(&nn->nfs_client_lock);
+- continue;
++ if (status == 0) {
++ nfs4_schedule_lease_recovery(pos);
++ status = nfs4_wait_clnt_recover(pos);
+ }
+- status = pos->cl_cons_state;
+ spin_lock(&nn->nfs_client_lock);
+ if (status < 0)
+ continue;
+ }
++ if (pos->cl_cons_state != NFS_CS_READY)
++ continue;
+
+ if (pos->rpc_ops != new->rpc_ops)
+ continue;
+@@ -469,17 +481,17 @@ int nfs41_walk_client_list(struct nfs_cl
+ continue;
+
+ atomic_inc(&pos->cl_count);
+- spin_unlock(&nn->nfs_client_lock);
++ *result = pos;
+ dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n",
+ __func__, pos, atomic_read(&pos->cl_count));
+-
+- *result = pos;
+- return 0;
++ break;
+ }
+
+ /* No matching nfs_client found. */
+ spin_unlock(&nn->nfs_client_lock);
+ dprintk("NFS: <-- %s status = %d\n", __func__, status);
++ if (prev)
++ nfs_put_client(prev);
+ return status;
+ }
+ #endif /* CONFIG_NFS_V4_1 */
--- /dev/null
+From b193d59a4863ea670872d76dc99231ddeb598625 Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+Date: Thu, 4 Apr 2013 15:55:00 -0400
+Subject: NFSv4: Fix a memory leak in nfs4_discover_server_trunking
+
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+
+commit b193d59a4863ea670872d76dc99231ddeb598625 upstream.
+
+When we assign a new rpc_client to clp->cl_rpcclient, we need to destroy
+the old one.
+
+Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
+Cc: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/nfs4state.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/fs/nfs/nfs4state.c
++++ b/fs/nfs/nfs4state.c
+@@ -1877,7 +1877,13 @@ again:
+ status = PTR_ERR(clnt);
+ break;
+ }
+- clp->cl_rpcclient = clnt;
++ /* Note: this is safe because we haven't yet marked the
++ * client as ready, so we are the only user of
++ * clp->cl_rpcclient
++ */
++ clnt = xchg(&clp->cl_rpcclient, clnt);
++ rpc_shutdown_client(clnt);
++ clnt = clp->cl_rpcclient;
+ goto again;
+
+ case -NFS4ERR_MINOR_VERS_MISMATCH:
--- /dev/null
+From a58e0be6f6b3eb2079b0b8fedc9df6fa86869f1e Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Fri, 22 Mar 2013 12:52:59 -0400
+Subject: SUNRPC: Remove extra xprt_put()
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+commit a58e0be6f6b3eb2079b0b8fedc9df6fa86869f1e upstream.
+
+While testing error cases where rpc_new_client() fails, I saw
+some oopses.
+
+If rpc_new_client() fails, it already invokes xprt_put(). Thus
+__rpc_clone_client() does not need to invoke it again.
+
+Introduced by commit 1b63a751 "SUNRPC: Refactor rpc_clone_client()"
+Fri Sep 14, 2012.
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/sunrpc/clnt.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/net/sunrpc/clnt.c
++++ b/net/sunrpc/clnt.c
+@@ -511,7 +511,7 @@ static struct rpc_clnt *__rpc_clone_clie
+ new = rpc_new_client(args, xprt);
+ if (IS_ERR(new)) {
+ err = PTR_ERR(new);
+- goto out_put;
++ goto out_err;
+ }
+
+ atomic_inc(&clnt->cl_count);
+@@ -524,8 +524,6 @@ static struct rpc_clnt *__rpc_clone_clie
+ new->cl_chatty = clnt->cl_chatty;
+ return new;
+
+-out_put:
+- xprt_put(xprt);
+ out_err:
+ dprintk("RPC: %s: returned error %d\n", __func__, err);
+ return ERR_PTR(err);