aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4state.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r--fs/nfsd/nfs4state.c49
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
512static struct nfs4_client *
513find_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
524static struct nfs4_client *
525find_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 */
513static int 537static int
514parse_octet(unsigned int *lenp, char **addrp) 538parse_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 /*