diff options
Diffstat (limited to 'fs/nfs/nfs4client.c')
| -rw-r--r-- | fs/nfs/nfs4client.c | 42 |
1 files changed, 27 insertions, 15 deletions
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index 03311259b0c4..953daa44a282 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 | ||
| @@ -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); |
