diff options
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r-- | fs/nfsd/nfs4state.c | 49 |
1 files changed, 31 insertions, 18 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 0be0b37c84e9..72f2b6fdae66 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -509,6 +509,30 @@ find_unconfirmed_client(clientid_t *clid) | |||
509 | return NULL; | 509 | return NULL; |
510 | } | 510 | } |
511 | 511 | ||
512 | static struct nfs4_client * | ||
513 | find_confirmed_client_by_str(const char *dname, unsigned int hashval) | ||
514 | { | ||
515 | struct nfs4_client *clp; | ||
516 | |||
517 | list_for_each_entry(clp, &conf_str_hashtbl[hashval], cl_strhash) { | ||
518 | if (same_name(clp->cl_recdir, dname)) | ||
519 | return clp; | ||
520 | } | ||
521 | return NULL; | ||
522 | } | ||
523 | |||
524 | static struct nfs4_client * | ||
525 | find_unconfirmed_client_by_str(const char *dname, unsigned int hashval) | ||
526 | { | ||
527 | struct nfs4_client *clp; | ||
528 | |||
529 | list_for_each_entry(clp, &unconf_str_hashtbl[hashval], cl_strhash) { | ||
530 | if (same_name(clp->cl_recdir, dname)) | ||
531 | return clp; | ||
532 | } | ||
533 | return NULL; | ||
534 | } | ||
535 | |||
512 | /* a helper function for parse_callback */ | 536 | /* a helper function for parse_callback */ |
513 | static int | 537 | static int |
514 | parse_octet(unsigned int *lenp, char **addrp) | 538 | parse_octet(unsigned int *lenp, char **addrp) |
@@ -647,7 +671,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid) | |||
647 | }; | 671 | }; |
648 | nfs4_verifier clverifier = setclid->se_verf; | 672 | nfs4_verifier clverifier = setclid->se_verf; |
649 | unsigned int strhashval; | 673 | unsigned int strhashval; |
650 | struct nfs4_client * conf, * unconf, * new, * clp; | 674 | struct nfs4_client *conf, *unconf, *new; |
651 | int status; | 675 | int status; |
652 | char dname[HEXDIR_LEN]; | 676 | char dname[HEXDIR_LEN]; |
653 | 677 | ||
@@ -666,35 +690,24 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid) | |||
666 | 690 | ||
667 | strhashval = clientstr_hashval(dname); | 691 | strhashval = clientstr_hashval(dname); |
668 | 692 | ||
669 | conf = NULL; | ||
670 | nfs4_lock_state(); | 693 | nfs4_lock_state(); |
671 | list_for_each_entry(clp, &conf_str_hashtbl[strhashval], cl_strhash) { | 694 | conf = find_confirmed_client_by_str(dname, strhashval); |
672 | if (!same_name(clp->cl_recdir, dname)) | 695 | if (conf) { |
673 | continue; | ||
674 | /* | 696 | /* |
675 | * CASE 0: | 697 | * CASE 0: |
676 | * clname match, confirmed, different principal | 698 | * clname match, confirmed, different principal |
677 | * or different ip_address | 699 | * or different ip_address |
678 | */ | 700 | */ |
679 | status = nfserr_clid_inuse; | 701 | status = nfserr_clid_inuse; |
680 | if (!cmp_creds(&clp->cl_cred,&rqstp->rq_cred) | 702 | if (!cmp_creds(&conf->cl_cred, &rqstp->rq_cred) |
681 | || clp->cl_addr != ip_addr) { | 703 | || conf->cl_addr != ip_addr) { |
682 | printk("NFSD: setclientid: string in use by client" | 704 | printk("NFSD: setclientid: string in use by client" |
683 | "(clientid %08x/%08x)\n", | 705 | "(clientid %08x/%08x)\n", |
684 | clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id); | 706 | conf->cl_clientid.cl_boot, conf->cl_clientid.cl_id); |
685 | goto out; | 707 | goto out; |
686 | } | 708 | } |
687 | conf = clp; | ||
688 | break; | ||
689 | } | ||
690 | unconf = NULL; | ||
691 | list_for_each_entry(clp, &unconf_str_hashtbl[strhashval], cl_strhash) { | ||
692 | if (!same_name(clp->cl_recdir, dname)) | ||
693 | continue; | ||
694 | /* cl_name match from a previous SETCLIENTID operation */ | ||
695 | unconf = clp; | ||
696 | break; | ||
697 | } | 709 | } |
710 | unconf = find_unconfirmed_client_by_str(dname, strhashval); | ||
698 | status = nfserr_resource; | 711 | status = nfserr_resource; |
699 | if (!conf) { | 712 | if (!conf) { |
700 | /* | 713 | /* |