diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-01-18 22:56:23 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-01-27 15:51:28 -0500 |
commit | 202c312dba7d95b96493b412c606163a0cd83984 (patch) | |
tree | 09bdba985da1addd3ae48e16b8953027645f2c62 /fs/nfs | |
parent | 4ae19c2dd713edb7b8ad3d4ab9d234ed5dcb6b98 (diff) |
NFSv4: Fix NFSv4 trunking discovery
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>
Cc: stable@vger.kernel.org [>=3.7]
Tested-by: Ben Greear <greearb@candelatech.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/nfs4client.c | 26 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 8 |
2 files changed, 9 insertions, 25 deletions
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index 65a290a73065..2f21f17fb16c 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c | |||
@@ -352,14 +352,8 @@ int nfs40_walk_client_list(struct nfs_client *new, | |||
352 | } | 352 | } |
353 | spin_unlock(&nn->nfs_client_lock); | 353 | spin_unlock(&nn->nfs_client_lock); |
354 | 354 | ||
355 | /* No match found. The server lost our clientid */ | ||
355 | out: | 356 | out: |
356 | /* | ||
357 | * No matching nfs_client found. This should be impossible, | ||
358 | * because the new nfs_client has already been added to | ||
359 | * nfs_client_list by nfs_get_client(). | ||
360 | * | ||
361 | * Don't BUG(), since the caller is holding a mutex. | ||
362 | */ | ||
363 | if (prev) | 357 | if (prev) |
364 | nfs_put_client(prev); | 358 | nfs_put_client(prev); |
365 | dprintk("NFS: <-- %s status = %d\n", __func__, status); | 359 | dprintk("NFS: <-- %s status = %d\n", __func__, status); |
@@ -430,7 +424,7 @@ int nfs41_walk_client_list(struct nfs_client *new, | |||
430 | { | 424 | { |
431 | struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id); | 425 | struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id); |
432 | struct nfs_client *pos, *n, *prev = NULL; | 426 | struct nfs_client *pos, *n, *prev = NULL; |
433 | int error; | 427 | int status = -NFS4ERR_STALE_CLIENTID; |
434 | 428 | ||
435 | spin_lock(&nn->nfs_client_lock); | 429 | spin_lock(&nn->nfs_client_lock); |
436 | list_for_each_entry_safe(pos, n, &nn->nfs_client_list, cl_share_link) { | 430 | list_for_each_entry_safe(pos, n, &nn->nfs_client_list, cl_share_link) { |
@@ -446,8 +440,8 @@ int nfs41_walk_client_list(struct nfs_client *new, | |||
446 | nfs_put_client(prev); | 440 | nfs_put_client(prev); |
447 | prev = pos; | 441 | prev = pos; |
448 | 442 | ||
449 | error = nfs_wait_client_init_complete(pos); | 443 | status = nfs_wait_client_init_complete(pos); |
450 | if (error < 0) { | 444 | if (status < 0) { |
451 | nfs_put_client(pos); | 445 | nfs_put_client(pos); |
452 | spin_lock(&nn->nfs_client_lock); | 446 | spin_lock(&nn->nfs_client_lock); |
453 | continue; | 447 | continue; |
@@ -480,16 +474,10 @@ int nfs41_walk_client_list(struct nfs_client *new, | |||
480 | return 0; | 474 | return 0; |
481 | } | 475 | } |
482 | 476 | ||
483 | /* | 477 | /* No matching nfs_client found. */ |
484 | * No matching nfs_client found. This should be impossible, | ||
485 | * because the new nfs_client has already been added to | ||
486 | * nfs_client_list by nfs_get_client(). | ||
487 | * | ||
488 | * Don't BUG(), since the caller is holding a mutex. | ||
489 | */ | ||
490 | spin_unlock(&nn->nfs_client_lock); | 478 | spin_unlock(&nn->nfs_client_lock); |
491 | pr_err("NFS: %s Error: no matching nfs_client found\n", __func__); | 479 | dprintk("NFS: <-- %s status = %d\n", __func__, status); |
492 | return -NFS4ERR_STALE_CLIENTID; | 480 | return status; |
493 | } | 481 | } |
494 | #endif /* CONFIG_NFS_V4_1 */ | 482 | #endif /* CONFIG_NFS_V4_1 */ |
495 | 483 | ||
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 9448c579d41a..f72561ca6895 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -136,16 +136,11 @@ int nfs40_discover_server_trunking(struct nfs_client *clp, | |||
136 | clp->cl_confirm = clid.confirm; | 136 | clp->cl_confirm = clid.confirm; |
137 | 137 | ||
138 | status = nfs40_walk_client_list(clp, result, cred); | 138 | status = nfs40_walk_client_list(clp, result, cred); |
139 | switch (status) { | 139 | if (status == 0) { |
140 | case -NFS4ERR_STALE_CLIENTID: | ||
141 | set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); | ||
142 | case 0: | ||
143 | /* Sustain the lease, even if it's empty. If the clientid4 | 140 | /* Sustain the lease, even if it's empty. If the clientid4 |
144 | * goes stale it's of no use for trunking discovery. */ | 141 | * goes stale it's of no use for trunking discovery. */ |
145 | nfs4_schedule_state_renewal(*result); | 142 | nfs4_schedule_state_renewal(*result); |
146 | break; | ||
147 | } | 143 | } |
148 | |||
149 | out: | 144 | out: |
150 | return status; | 145 | return status; |
151 | } | 146 | } |
@@ -1863,6 +1858,7 @@ again: | |||
1863 | case -ETIMEDOUT: | 1858 | case -ETIMEDOUT: |
1864 | case -EAGAIN: | 1859 | case -EAGAIN: |
1865 | ssleep(1); | 1860 | ssleep(1); |
1861 | case -NFS4ERR_STALE_CLIENTID: | ||
1866 | dprintk("NFS: %s after status %d, retrying\n", | 1862 | dprintk("NFS: %s after status %d, retrying\n", |
1867 | __func__, status); | 1863 | __func__, status); |
1868 | goto again; | 1864 | goto again; |