diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-04-23 15:52:14 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-04-23 15:52:14 -0400 |
commit | b0212b84fb19cf89305ab96c73abdf3a76d05ef8 (patch) | |
tree | 429daec3f580ad8f4c39e90f212d259b19ba9394 | |
parent | bd1d421abcaae1b84ba377ea4c33bba31d654199 (diff) | |
parent | eb04e0ac198cec3bab407ad220438dfa65c19c67 (diff) |
Merge branch 'bugfixes' into linux-next
Fix up a conflict between the linux-next branch and mainline.
Conflicts:
fs/nfs/nfs4proc.c
-rw-r--r-- | fs/nfs/nfs4client.c | 45 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 8 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 11 |
4 files changed, 40 insertions, 25 deletions
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index c2b069e25819..947b0c908aa9 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c | |||
@@ -304,7 +304,7 @@ int nfs40_walk_client_list(struct nfs_client *new, | |||
304 | struct rpc_cred *cred) | 304 | struct rpc_cred *cred) |
305 | { | 305 | { |
306 | struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id); | 306 | struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id); |
307 | struct nfs_client *pos, *n, *prev = NULL; | 307 | struct nfs_client *pos, *prev = NULL; |
308 | struct nfs4_setclientid_res clid = { | 308 | struct nfs4_setclientid_res clid = { |
309 | .clientid = new->cl_clientid, | 309 | .clientid = new->cl_clientid, |
310 | .confirm = new->cl_confirm, | 310 | .confirm = new->cl_confirm, |
@@ -312,10 +312,23 @@ int nfs40_walk_client_list(struct nfs_client *new, | |||
312 | int status = -NFS4ERR_STALE_CLIENTID; | 312 | int status = -NFS4ERR_STALE_CLIENTID; |
313 | 313 | ||
314 | spin_lock(&nn->nfs_client_lock); | 314 | spin_lock(&nn->nfs_client_lock); |
315 | list_for_each_entry_safe(pos, n, &nn->nfs_client_list, cl_share_link) { | 315 | list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) { |
316 | /* If "pos" isn't marked ready, we can't trust the | 316 | /* If "pos" isn't marked ready, we can't trust the |
317 | * remaining fields in "pos" */ | 317 | * remaining fields in "pos" */ |
318 | if (pos->cl_cons_state < NFS_CS_READY) | 318 | if (pos->cl_cons_state > NFS_CS_READY) { |
319 | atomic_inc(&pos->cl_count); | ||
320 | spin_unlock(&nn->nfs_client_lock); | ||
321 | |||
322 | if (prev) | ||
323 | nfs_put_client(prev); | ||
324 | prev = pos; | ||
325 | |||
326 | status = nfs_wait_client_init_complete(pos); | ||
327 | spin_lock(&nn->nfs_client_lock); | ||
328 | if (status < 0) | ||
329 | continue; | ||
330 | } | ||
331 | if (pos->cl_cons_state != NFS_CS_READY) | ||
319 | continue; | 332 | continue; |
320 | 333 | ||
321 | if (pos->rpc_ops != new->rpc_ops) | 334 | if (pos->rpc_ops != new->rpc_ops) |
@@ -427,16 +440,16 @@ int nfs41_walk_client_list(struct nfs_client *new, | |||
427 | struct rpc_cred *cred) | 440 | struct rpc_cred *cred) |
428 | { | 441 | { |
429 | struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id); | 442 | struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id); |
430 | struct nfs_client *pos, *n, *prev = NULL; | 443 | struct nfs_client *pos, *prev = NULL; |
431 | int status = -NFS4ERR_STALE_CLIENTID; | 444 | int status = -NFS4ERR_STALE_CLIENTID; |
432 | 445 | ||
433 | spin_lock(&nn->nfs_client_lock); | 446 | spin_lock(&nn->nfs_client_lock); |
434 | list_for_each_entry_safe(pos, n, &nn->nfs_client_list, cl_share_link) { | 447 | list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) { |
435 | /* If "pos" isn't marked ready, we can't trust the | 448 | /* If "pos" isn't marked ready, we can't trust the |
436 | * remaining fields in "pos", especially the client | 449 | * remaining fields in "pos", especially the client |
437 | * ID and serverowner fields. Wait for CREATE_SESSION | 450 | * ID and serverowner fields. Wait for CREATE_SESSION |
438 | * to finish. */ | 451 | * to finish. */ |
439 | if (pos->cl_cons_state < NFS_CS_READY) { | 452 | if (pos->cl_cons_state > NFS_CS_READY) { |
440 | atomic_inc(&pos->cl_count); | 453 | atomic_inc(&pos->cl_count); |
441 | spin_unlock(&nn->nfs_client_lock); | 454 | spin_unlock(&nn->nfs_client_lock); |
442 | 455 | ||
@@ -444,18 +457,17 @@ int nfs41_walk_client_list(struct nfs_client *new, | |||
444 | nfs_put_client(prev); | 457 | nfs_put_client(prev); |
445 | prev = pos; | 458 | prev = pos; |
446 | 459 | ||
447 | nfs4_schedule_lease_recovery(pos); | ||
448 | status = nfs_wait_client_init_complete(pos); | 460 | status = nfs_wait_client_init_complete(pos); |
449 | if (status < 0) { | 461 | if (status == 0) { |
450 | nfs_put_client(pos); | 462 | nfs4_schedule_lease_recovery(pos); |
451 | spin_lock(&nn->nfs_client_lock); | 463 | status = nfs4_wait_clnt_recover(pos); |
452 | continue; | ||
453 | } | 464 | } |
454 | status = pos->cl_cons_state; | ||
455 | spin_lock(&nn->nfs_client_lock); | 465 | spin_lock(&nn->nfs_client_lock); |
456 | if (status < 0) | 466 | if (status < 0) |
457 | continue; | 467 | continue; |
458 | } | 468 | } |
469 | if (pos->cl_cons_state != NFS_CS_READY) | ||
470 | continue; | ||
459 | 471 | ||
460 | if (pos->rpc_ops != new->rpc_ops) | 472 | if (pos->rpc_ops != new->rpc_ops) |
461 | continue; | 473 | continue; |
@@ -473,17 +485,18 @@ int nfs41_walk_client_list(struct nfs_client *new, | |||
473 | continue; | 485 | continue; |
474 | 486 | ||
475 | atomic_inc(&pos->cl_count); | 487 | atomic_inc(&pos->cl_count); |
476 | spin_unlock(&nn->nfs_client_lock); | 488 | *result = pos; |
489 | status = 0; | ||
477 | dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n", | 490 | dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n", |
478 | __func__, pos, atomic_read(&pos->cl_count)); | 491 | __func__, pos, atomic_read(&pos->cl_count)); |
479 | 492 | break; | |
480 | *result = pos; | ||
481 | return 0; | ||
482 | } | 493 | } |
483 | 494 | ||
484 | /* No matching nfs_client found. */ | 495 | /* No matching nfs_client found. */ |
485 | spin_unlock(&nn->nfs_client_lock); | 496 | spin_unlock(&nn->nfs_client_lock); |
486 | dprintk("NFS: <-- %s status = %d\n", __func__, status); | 497 | dprintk("NFS: <-- %s status = %d\n", __func__, status); |
498 | if (prev) | ||
499 | nfs_put_client(prev); | ||
487 | return status; | 500 | return status; |
488 | } | 501 | } |
489 | #endif /* CONFIG_NFS_V4_1 */ | 502 | #endif /* CONFIG_NFS_V4_1 */ |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index e13b7ccee98d..3bc847ce4838 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -1102,6 +1102,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata) | |||
1102 | /* Save the delegation */ | 1102 | /* Save the delegation */ |
1103 | nfs4_stateid_copy(&stateid, &delegation->stateid); | 1103 | nfs4_stateid_copy(&stateid, &delegation->stateid); |
1104 | rcu_read_unlock(); | 1104 | rcu_read_unlock(); |
1105 | nfs_release_seqid(opendata->o_arg.seqid); | ||
1105 | if (!opendata->is_recover) { | 1106 | if (!opendata->is_recover) { |
1106 | ret = nfs_may_open(state->inode, state->owner->so_cred, open_mode); | 1107 | ret = nfs_may_open(state->inode, state->owner->so_cred, open_mode); |
1107 | if (ret != 0) | 1108 | if (ret != 0) |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 7a74ea64bf54..0b32f9483b7a 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -1897,7 +1897,13 @@ again: | |||
1897 | status = PTR_ERR(clnt); | 1897 | status = PTR_ERR(clnt); |
1898 | break; | 1898 | break; |
1899 | } | 1899 | } |
1900 | clp->cl_rpcclient = clnt; | 1900 | /* Note: this is safe because we haven't yet marked the |
1901 | * client as ready, so we are the only user of | ||
1902 | * clp->cl_rpcclient | ||
1903 | */ | ||
1904 | clnt = xchg(&clp->cl_rpcclient, clnt); | ||
1905 | rpc_shutdown_client(clnt); | ||
1906 | clnt = clp->cl_rpcclient; | ||
1901 | goto again; | 1907 | goto again; |
1902 | 1908 | ||
1903 | case -NFS4ERR_MINOR_VERS_MISMATCH: | 1909 | case -NFS4ERR_MINOR_VERS_MISMATCH: |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 651245aa829a..d259fa966927 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -304,10 +304,8 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru | |||
304 | err = rpciod_up(); | 304 | err = rpciod_up(); |
305 | if (err) | 305 | if (err) |
306 | goto out_no_rpciod; | 306 | goto out_no_rpciod; |
307 | err = -EINVAL; | ||
308 | if (!xprt) | ||
309 | goto out_no_xprt; | ||
310 | 307 | ||
308 | err = -EINVAL; | ||
311 | if (args->version >= program->nrvers) | 309 | if (args->version >= program->nrvers) |
312 | goto out_err; | 310 | goto out_err; |
313 | version = program->version[args->version]; | 311 | version = program->version[args->version]; |
@@ -382,10 +380,9 @@ out_no_principal: | |||
382 | out_no_stats: | 380 | out_no_stats: |
383 | kfree(clnt); | 381 | kfree(clnt); |
384 | out_err: | 382 | out_err: |
385 | xprt_put(xprt); | ||
386 | out_no_xprt: | ||
387 | rpciod_down(); | 383 | rpciod_down(); |
388 | out_no_rpciod: | 384 | out_no_rpciod: |
385 | xprt_put(xprt); | ||
389 | return ERR_PTR(err); | 386 | return ERR_PTR(err); |
390 | } | 387 | } |
391 | 388 | ||
@@ -514,7 +511,7 @@ static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args, | |||
514 | new = rpc_new_client(args, xprt); | 511 | new = rpc_new_client(args, xprt); |
515 | if (IS_ERR(new)) { | 512 | if (IS_ERR(new)) { |
516 | err = PTR_ERR(new); | 513 | err = PTR_ERR(new); |
517 | goto out_put; | 514 | goto out_err; |
518 | } | 515 | } |
519 | 516 | ||
520 | atomic_inc(&clnt->cl_count); | 517 | atomic_inc(&clnt->cl_count); |
@@ -527,8 +524,6 @@ static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args, | |||
527 | new->cl_chatty = clnt->cl_chatty; | 524 | new->cl_chatty = clnt->cl_chatty; |
528 | return new; | 525 | return new; |
529 | 526 | ||
530 | out_put: | ||
531 | xprt_put(xprt); | ||
532 | out_err: | 527 | out_err: |
533 | dprintk("RPC: %s: returned error %d\n", __func__, err); | 528 | dprintk("RPC: %s: returned error %d\n", __func__, err); |
534 | return ERR_PTR(err); | 529 | return ERR_PTR(err); |