| From 202c312dba7d95b96493b412c606163a0cd83984 Mon Sep 17 00:00:00 2001 |
| From: Trond Myklebust <Trond.Myklebust@netapp.com> |
| Date: Fri, 18 Jan 2013 22:56:23 -0500 |
| Subject: NFSv4: Fix NFSv4 trunking discovery |
| |
| From: Trond Myklebust <Trond.Myklebust@netapp.com> |
| |
| commit 202c312dba7d95b96493b412c606163a0cd83984 upstream. |
| |
| If walking the list in nfs4[01]_walk_client_list fails, then the most |
| likely explanation is that the server dropped the clientid before we |
| actually managed to confirm it. As long as our nfs_client is the very |
| last one in the list to be tested, the caller can be assured that this |
| is the case when the final return value is NFS4ERR_STALE_CLIENTID. |
| |
| Reported-by: Ben Greear <greearb@candelatech.com> |
| Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> |
| Cc: Chuck Lever <chuck.lever@oracle.com> |
| Tested-by: Ben Greear <greearb@candelatech.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/nfs/nfs4client.c | 26 +++++++------------------- |
| fs/nfs/nfs4state.c | 8 ++------ |
| 2 files changed, 9 insertions(+), 25 deletions(-) |
| |
| --- a/fs/nfs/nfs4client.c |
| +++ b/fs/nfs/nfs4client.c |
| @@ -351,14 +351,8 @@ int nfs40_walk_client_list(struct nfs_cl |
| } |
| spin_unlock(&nn->nfs_client_lock); |
| |
| + /* No match found. The server lost our clientid */ |
| out: |
| - /* |
| - * No matching nfs_client found. This should be impossible, |
| - * because the new nfs_client has already been added to |
| - * nfs_client_list by nfs_get_client(). |
| - * |
| - * Don't BUG(), since the caller is holding a mutex. |
| - */ |
| if (prev) |
| nfs_put_client(prev); |
| dprintk("NFS: <-- %s status = %d\n", __func__, status); |
| @@ -429,7 +423,7 @@ int nfs41_walk_client_list(struct nfs_cl |
| { |
| struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id); |
| struct nfs_client *pos, *n, *prev = NULL; |
| - int error; |
| + 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) { |
| @@ -445,8 +439,8 @@ int nfs41_walk_client_list(struct nfs_cl |
| nfs_put_client(prev); |
| prev = pos; |
| |
| - error = nfs_wait_client_init_complete(pos); |
| - if (error < 0) { |
| + status = nfs_wait_client_init_complete(pos); |
| + if (status < 0) { |
| nfs_put_client(pos); |
| spin_lock(&nn->nfs_client_lock); |
| continue; |
| @@ -479,16 +473,10 @@ int nfs41_walk_client_list(struct nfs_cl |
| return 0; |
| } |
| |
| - /* |
| - * No matching nfs_client found. This should be impossible, |
| - * because the new nfs_client has already been added to |
| - * nfs_client_list by nfs_get_client(). |
| - * |
| - * Don't BUG(), since the caller is holding a mutex. |
| - */ |
| + /* No matching nfs_client found. */ |
| spin_unlock(&nn->nfs_client_lock); |
| - pr_err("NFS: %s Error: no matching nfs_client found\n", __func__); |
| - return -NFS4ERR_STALE_CLIENTID; |
| + dprintk("NFS: <-- %s status = %d\n", __func__, status); |
| + return status; |
| } |
| #endif /* CONFIG_NFS_V4_1 */ |
| |
| --- a/fs/nfs/nfs4state.c |
| +++ b/fs/nfs/nfs4state.c |
| @@ -136,16 +136,11 @@ int nfs40_discover_server_trunking(struc |
| clp->cl_confirm = clid.confirm; |
| |
| status = nfs40_walk_client_list(clp, result, cred); |
| - switch (status) { |
| - case -NFS4ERR_STALE_CLIENTID: |
| - set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); |
| - case 0: |
| + if (status == 0) { |
| /* Sustain the lease, even if it's empty. If the clientid4 |
| * goes stale it's of no use for trunking discovery. */ |
| nfs4_schedule_state_renewal(*result); |
| - break; |
| } |
| - |
| out: |
| return status; |
| } |
| @@ -1850,6 +1845,7 @@ again: |
| case -ETIMEDOUT: |
| case -EAGAIN: |
| ssleep(1); |
| + case -NFS4ERR_STALE_CLIENTID: |
| dprintk("NFS: %s after status %d, retrying\n", |
| __func__, status); |
| goto again; |