diff options
Diffstat (limited to 'fs/nfs/nfs4client.c')
| -rw-r--r-- | fs/nfs/nfs4client.c | 51 |
1 files changed, 32 insertions, 19 deletions
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index 03311259b0c4..8646af9b11d2 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c | |||
| @@ -228,6 +228,7 @@ static void nfs4_shutdown_client(struct nfs_client *clp) | |||
| 228 | kfree(clp->cl_serverowner); | 228 | kfree(clp->cl_serverowner); |
| 229 | kfree(clp->cl_serverscope); | 229 | kfree(clp->cl_serverscope); |
| 230 | kfree(clp->cl_implid); | 230 | kfree(clp->cl_implid); |
| 231 | kfree(clp->cl_owner_id); | ||
| 231 | } | 232 | } |
| 232 | 233 | ||
| 233 | void nfs4_free_client(struct nfs_client *clp) | 234 | void nfs4_free_client(struct nfs_client *clp) |
| @@ -452,6 +453,14 @@ static void nfs4_swap_callback_idents(struct nfs_client *keep, | |||
| 452 | spin_unlock(&nn->nfs_client_lock); | 453 | spin_unlock(&nn->nfs_client_lock); |
| 453 | } | 454 | } |
| 454 | 455 | ||
| 456 | static bool nfs4_match_client_owner_id(const struct nfs_client *clp1, | ||
| 457 | const struct nfs_client *clp2) | ||
| 458 | { | ||
| 459 | if (clp1->cl_owner_id == NULL || clp2->cl_owner_id == NULL) | ||
| 460 | return true; | ||
| 461 | return strcmp(clp1->cl_owner_id, clp2->cl_owner_id) == 0; | ||
| 462 | } | ||
| 463 | |||
| 455 | /** | 464 | /** |
| 456 | * nfs40_walk_client_list - Find server that recognizes a client ID | 465 | * nfs40_walk_client_list - Find server that recognizes a client ID |
| 457 | * | 466 | * |
| @@ -483,9 +492,6 @@ int nfs40_walk_client_list(struct nfs_client *new, | |||
| 483 | if (pos->rpc_ops != new->rpc_ops) | 492 | if (pos->rpc_ops != new->rpc_ops) |
| 484 | continue; | 493 | continue; |
| 485 | 494 | ||
| 486 | if (pos->cl_proto != new->cl_proto) | ||
| 487 | continue; | ||
| 488 | |||
| 489 | if (pos->cl_minorversion != new->cl_minorversion) | 495 | if (pos->cl_minorversion != new->cl_minorversion) |
| 490 | continue; | 496 | continue; |
| 491 | 497 | ||
| @@ -510,6 +516,9 @@ int nfs40_walk_client_list(struct nfs_client *new, | |||
| 510 | if (pos->cl_clientid != new->cl_clientid) | 516 | if (pos->cl_clientid != new->cl_clientid) |
| 511 | continue; | 517 | continue; |
| 512 | 518 | ||
| 519 | if (!nfs4_match_client_owner_id(pos, new)) | ||
| 520 | continue; | ||
| 521 | |||
| 513 | atomic_inc(&pos->cl_count); | 522 | atomic_inc(&pos->cl_count); |
| 514 | spin_unlock(&nn->nfs_client_lock); | 523 | spin_unlock(&nn->nfs_client_lock); |
| 515 | 524 | ||
| @@ -566,20 +575,14 @@ static bool nfs4_match_clientids(struct nfs_client *a, struct nfs_client *b) | |||
| 566 | } | 575 | } |
| 567 | 576 | ||
| 568 | /* | 577 | /* |
| 569 | * Returns true if the server owners match | 578 | * Returns true if the server major ids match |
| 570 | */ | 579 | */ |
| 571 | static bool | 580 | static bool |
| 572 | nfs4_match_serverowners(struct nfs_client *a, struct nfs_client *b) | 581 | nfs4_check_clientid_trunking(struct nfs_client *a, struct nfs_client *b) |
| 573 | { | 582 | { |
| 574 | struct nfs41_server_owner *o1 = a->cl_serverowner; | 583 | struct nfs41_server_owner *o1 = a->cl_serverowner; |
| 575 | struct nfs41_server_owner *o2 = b->cl_serverowner; | 584 | struct nfs41_server_owner *o2 = b->cl_serverowner; |
| 576 | 585 | ||
| 577 | if (o1->minor_id != o2->minor_id) { | ||
| 578 | dprintk("NFS: --> %s server owner minor IDs do not match\n", | ||
| 579 | __func__); | ||
| 580 | return false; | ||
| 581 | } | ||
| 582 | |||
| 583 | if (o1->major_id_sz != o2->major_id_sz) | 586 | if (o1->major_id_sz != o2->major_id_sz) |
| 584 | goto out_major_mismatch; | 587 | goto out_major_mismatch; |
| 585 | if (memcmp(o1->major_id, o2->major_id, o1->major_id_sz) != 0) | 588 | if (memcmp(o1->major_id, o2->major_id, o1->major_id_sz) != 0) |
| @@ -621,9 +624,6 @@ int nfs41_walk_client_list(struct nfs_client *new, | |||
| 621 | if (pos->rpc_ops != new->rpc_ops) | 624 | if (pos->rpc_ops != new->rpc_ops) |
| 622 | continue; | 625 | continue; |
| 623 | 626 | ||
| 624 | if (pos->cl_proto != new->cl_proto) | ||
| 625 | continue; | ||
| 626 | |||
| 627 | if (pos->cl_minorversion != new->cl_minorversion) | 627 | if (pos->cl_minorversion != new->cl_minorversion) |
| 628 | continue; | 628 | continue; |
| 629 | 629 | ||
| @@ -639,7 +639,7 @@ int nfs41_walk_client_list(struct nfs_client *new, | |||
| 639 | prev = pos; | 639 | prev = pos; |
| 640 | 640 | ||
| 641 | status = nfs_wait_client_init_complete(pos); | 641 | status = nfs_wait_client_init_complete(pos); |
| 642 | if (status == 0) { | 642 | if (pos->cl_cons_state == NFS_CS_SESSION_INITING) { |
| 643 | nfs4_schedule_lease_recovery(pos); | 643 | nfs4_schedule_lease_recovery(pos); |
| 644 | status = nfs4_wait_clnt_recover(pos); | 644 | status = nfs4_wait_clnt_recover(pos); |
| 645 | } | 645 | } |
| @@ -654,7 +654,19 @@ int nfs41_walk_client_list(struct nfs_client *new, | |||
| 654 | if (!nfs4_match_clientids(pos, new)) | 654 | if (!nfs4_match_clientids(pos, new)) |
| 655 | continue; | 655 | continue; |
| 656 | 656 | ||
| 657 | if (!nfs4_match_serverowners(pos, new)) | 657 | /* |
| 658 | * Note that session trunking is just a special subcase of | ||
| 659 | * client id trunking. In either case, we want to fall back | ||
| 660 | * to using the existing nfs_client. | ||
| 661 | */ | ||
| 662 | if (!nfs4_check_clientid_trunking(pos, new)) | ||
| 663 | continue; | ||
| 664 | |||
| 665 | /* Unlike NFSv4.0, we know that NFSv4.1 always uses the | ||
| 666 | * uniform string, however someone might switch the | ||
| 667 | * uniquifier string on us. | ||
| 668 | */ | ||
| 669 | if (!nfs4_match_client_owner_id(pos, new)) | ||
| 658 | continue; | 670 | continue; |
| 659 | 671 | ||
| 660 | atomic_inc(&pos->cl_count); | 672 | atomic_inc(&pos->cl_count); |
| @@ -837,14 +849,15 @@ error: | |||
| 837 | */ | 849 | */ |
| 838 | struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp, | 850 | struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp, |
| 839 | const struct sockaddr *ds_addr, int ds_addrlen, | 851 | const struct sockaddr *ds_addr, int ds_addrlen, |
| 840 | int ds_proto, unsigned int ds_timeo, unsigned int ds_retrans) | 852 | int ds_proto, unsigned int ds_timeo, unsigned int ds_retrans, |
| 853 | u32 minor_version, rpc_authflavor_t au_flavor) | ||
| 841 | { | 854 | { |
| 842 | struct nfs_client_initdata cl_init = { | 855 | struct nfs_client_initdata cl_init = { |
| 843 | .addr = ds_addr, | 856 | .addr = ds_addr, |
| 844 | .addrlen = ds_addrlen, | 857 | .addrlen = ds_addrlen, |
| 845 | .nfs_mod = &nfs_v4, | 858 | .nfs_mod = &nfs_v4, |
| 846 | .proto = ds_proto, | 859 | .proto = ds_proto, |
| 847 | .minorversion = mds_clp->cl_minorversion, | 860 | .minorversion = minor_version, |
| 848 | .net = mds_clp->cl_net, | 861 | .net = mds_clp->cl_net, |
| 849 | }; | 862 | }; |
| 850 | struct rpc_timeout ds_timeout; | 863 | struct rpc_timeout ds_timeout; |
| @@ -862,7 +875,7 @@ struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp, | |||
| 862 | */ | 875 | */ |
| 863 | nfs_init_timeout_values(&ds_timeout, ds_proto, ds_timeo, ds_retrans); | 876 | nfs_init_timeout_values(&ds_timeout, ds_proto, ds_timeo, ds_retrans); |
| 864 | clp = nfs_get_client(&cl_init, &ds_timeout, mds_clp->cl_ipaddr, | 877 | clp = nfs_get_client(&cl_init, &ds_timeout, mds_clp->cl_ipaddr, |
| 865 | mds_clp->cl_rpcclient->cl_auth->au_flavor); | 878 | au_flavor); |
| 866 | 879 | ||
| 867 | dprintk("<-- %s %p\n", __func__, clp); | 880 | dprintk("<-- %s %p\n", __func__, clp); |
| 868 | return clp; | 881 | return clp; |
