diff options
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r-- | fs/nfsd/nfs4state.c | 80 |
1 files changed, 38 insertions, 42 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 2a59d176e69a..0be0b37c84e9 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -231,8 +231,8 @@ unhash_delegation(struct nfs4_delegation *dp) | |||
231 | 231 | ||
232 | #define clientid_hashval(id) \ | 232 | #define clientid_hashval(id) \ |
233 | ((id) & CLIENT_HASH_MASK) | 233 | ((id) & CLIENT_HASH_MASK) |
234 | #define clientstr_hashval(name, namelen) \ | 234 | #define clientstr_hashval(name) \ |
235 | (opaque_hashval((name), (namelen)) & CLIENT_HASH_MASK) | 235 | (opaque_hashval((name), 8) & CLIENT_HASH_MASK) |
236 | /* | 236 | /* |
237 | * reclaim_str_hashtbl[] holds known client info from previous reset/reboot | 237 | * reclaim_str_hashtbl[] holds known client info from previous reset/reboot |
238 | * used in reboot/reset lease grace period processing | 238 | * used in reboot/reset lease grace period processing |
@@ -366,11 +366,12 @@ expire_client(struct nfs4_client *clp) | |||
366 | } | 366 | } |
367 | 367 | ||
368 | static struct nfs4_client * | 368 | static struct nfs4_client * |
369 | create_client(struct xdr_netobj name) { | 369 | create_client(struct xdr_netobj name, char *recdir) { |
370 | struct nfs4_client *clp; | 370 | struct nfs4_client *clp; |
371 | 371 | ||
372 | if (!(clp = alloc_client(name))) | 372 | if (!(clp = alloc_client(name))) |
373 | goto out; | 373 | goto out; |
374 | memcpy(clp->cl_recdir, recdir, HEXDIR_LEN); | ||
374 | atomic_set(&clp->cl_count, 1); | 375 | atomic_set(&clp->cl_count, 1); |
375 | atomic_set(&clp->cl_callback.cb_set, 0); | 376 | atomic_set(&clp->cl_callback.cb_set, 0); |
376 | clp->cl_callback.cb_parsed = 0; | 377 | clp->cl_callback.cb_parsed = 0; |
@@ -403,11 +404,9 @@ copy_cred(struct svc_cred *target, struct svc_cred *source) { | |||
403 | get_group_info(target->cr_group_info); | 404 | get_group_info(target->cr_group_info); |
404 | } | 405 | } |
405 | 406 | ||
406 | static int | 407 | static inline int |
407 | cmp_name(struct xdr_netobj *n1, struct xdr_netobj *n2) { | 408 | same_name(const char *n1, const char *n2) { |
408 | if (!n1 || !n2) | 409 | return 0 == memcmp(n1, n2, HEXDIR_LEN); |
409 | return 0; | ||
410 | return((n1->len == n2->len) && !memcmp(n1->data, n2->data, n2->len)); | ||
411 | } | 410 | } |
412 | 411 | ||
413 | static int | 412 | static int |
@@ -479,8 +478,7 @@ move_to_confirmed(struct nfs4_client *clp) | |||
479 | list_del_init(&clp->cl_strhash); | 478 | list_del_init(&clp->cl_strhash); |
480 | list_del_init(&clp->cl_idhash); | 479 | list_del_init(&clp->cl_idhash); |
481 | list_add(&clp->cl_idhash, &conf_id_hashtbl[idhashval]); | 480 | list_add(&clp->cl_idhash, &conf_id_hashtbl[idhashval]); |
482 | strhashval = clientstr_hashval(clp->cl_name.data, | 481 | strhashval = clientstr_hashval(clp->cl_recdir); |
483 | clp->cl_name.len); | ||
484 | list_add(&clp->cl_strhash, &conf_str_hashtbl[strhashval]); | 482 | list_add(&clp->cl_strhash, &conf_str_hashtbl[strhashval]); |
485 | renew_client(clp); | 483 | renew_client(clp); |
486 | } | 484 | } |
@@ -651,22 +649,27 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid) | |||
651 | unsigned int strhashval; | 649 | unsigned int strhashval; |
652 | struct nfs4_client * conf, * unconf, * new, * clp; | 650 | struct nfs4_client * conf, * unconf, * new, * clp; |
653 | int status; | 651 | int status; |
652 | char dname[HEXDIR_LEN]; | ||
654 | 653 | ||
655 | status = nfserr_inval; | 654 | status = nfserr_inval; |
656 | if (!check_name(clname)) | 655 | if (!check_name(clname)) |
657 | goto out; | 656 | goto out; |
658 | 657 | ||
658 | status = nfs4_make_rec_clidname(dname, &clname); | ||
659 | if (status) | ||
660 | goto out; | ||
661 | |||
659 | /* | 662 | /* |
660 | * XXX The Duplicate Request Cache (DRC) has been checked (??) | 663 | * XXX The Duplicate Request Cache (DRC) has been checked (??) |
661 | * We get here on a DRC miss. | 664 | * We get here on a DRC miss. |
662 | */ | 665 | */ |
663 | 666 | ||
664 | strhashval = clientstr_hashval(clname.data, clname.len); | 667 | strhashval = clientstr_hashval(dname); |
665 | 668 | ||
666 | conf = NULL; | 669 | conf = NULL; |
667 | nfs4_lock_state(); | 670 | nfs4_lock_state(); |
668 | list_for_each_entry(clp, &conf_str_hashtbl[strhashval], cl_strhash) { | 671 | list_for_each_entry(clp, &conf_str_hashtbl[strhashval], cl_strhash) { |
669 | if (!cmp_name(&clp->cl_name, &clname)) | 672 | if (!same_name(clp->cl_recdir, dname)) |
670 | continue; | 673 | continue; |
671 | /* | 674 | /* |
672 | * CASE 0: | 675 | * CASE 0: |
@@ -686,7 +689,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid) | |||
686 | } | 689 | } |
687 | unconf = NULL; | 690 | unconf = NULL; |
688 | list_for_each_entry(clp, &unconf_str_hashtbl[strhashval], cl_strhash) { | 691 | list_for_each_entry(clp, &unconf_str_hashtbl[strhashval], cl_strhash) { |
689 | if (!cmp_name(&clp->cl_name, &clname)) | 692 | if (!same_name(clp->cl_recdir, dname)) |
690 | continue; | 693 | continue; |
691 | /* cl_name match from a previous SETCLIENTID operation */ | 694 | /* cl_name match from a previous SETCLIENTID operation */ |
692 | unconf = clp; | 695 | unconf = clp; |
@@ -700,7 +703,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid) | |||
700 | */ | 703 | */ |
701 | if (unconf) | 704 | if (unconf) |
702 | expire_client(unconf); | 705 | expire_client(unconf); |
703 | if (!(new = create_client(clname))) | 706 | new = create_client(clname, dname); |
707 | if (new == NULL) | ||
704 | goto out; | 708 | goto out; |
705 | copy_verf(new, &clverifier); | 709 | copy_verf(new, &clverifier); |
706 | new->cl_addr = ip_addr; | 710 | new->cl_addr = ip_addr; |
@@ -728,7 +732,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid) | |||
728 | cmp_clid(&unconf->cl_clientid, &conf->cl_clientid)) { | 732 | cmp_clid(&unconf->cl_clientid, &conf->cl_clientid)) { |
729 | expire_client(unconf); | 733 | expire_client(unconf); |
730 | } | 734 | } |
731 | if (!(new = create_client(clname))) | 735 | new = create_client(clname, dname); |
736 | if (new == NULL) | ||
732 | goto out; | 737 | goto out; |
733 | copy_verf(new,&conf->cl_verifier); | 738 | copy_verf(new,&conf->cl_verifier); |
734 | new->cl_addr = ip_addr; | 739 | new->cl_addr = ip_addr; |
@@ -746,7 +751,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid) | |||
746 | * using input clverifier, clname, and callback info | 751 | * using input clverifier, clname, and callback info |
747 | * and generate a new cl_clientid and cl_confirm. | 752 | * and generate a new cl_clientid and cl_confirm. |
748 | */ | 753 | */ |
749 | if (!(new = create_client(clname))) | 754 | new = create_client(clname, dname); |
755 | if (new == NULL) | ||
750 | goto out; | 756 | goto out; |
751 | copy_verf(new,&clverifier); | 757 | copy_verf(new,&clverifier); |
752 | new->cl_addr = ip_addr; | 758 | new->cl_addr = ip_addr; |
@@ -772,7 +778,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid) | |||
772 | * new cl_verifier and a new cl_confirm | 778 | * new cl_verifier and a new cl_confirm |
773 | */ | 779 | */ |
774 | expire_client(unconf); | 780 | expire_client(unconf); |
775 | if (!(new = create_client(clname))) | 781 | new = create_client(clname, dname); |
782 | if (new == NULL) | ||
776 | goto out; | 783 | goto out; |
777 | copy_verf(new,&clverifier); | 784 | copy_verf(new,&clverifier); |
778 | new->cl_addr = ip_addr; | 785 | new->cl_addr = ip_addr; |
@@ -856,7 +863,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi | |||
856 | if ((conf && unconf) && | 863 | if ((conf && unconf) && |
857 | (cmp_verf(&unconf->cl_confirm, &confirm)) && | 864 | (cmp_verf(&unconf->cl_confirm, &confirm)) && |
858 | (cmp_verf(&conf->cl_verifier, &unconf->cl_verifier)) && | 865 | (cmp_verf(&conf->cl_verifier, &unconf->cl_verifier)) && |
859 | (cmp_name(&conf->cl_name,&unconf->cl_name)) && | 866 | (same_name(conf->cl_recdir,unconf->cl_recdir)) && |
860 | (!cmp_verf(&conf->cl_confirm, &unconf->cl_confirm))) { | 867 | (!cmp_verf(&conf->cl_confirm, &unconf->cl_confirm))) { |
861 | if (!cmp_creds(&conf->cl_cred, &unconf->cl_cred)) | 868 | if (!cmp_creds(&conf->cl_cred, &unconf->cl_cred)) |
862 | status = nfserr_clid_inuse; | 869 | status = nfserr_clid_inuse; |
@@ -876,7 +883,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi | |||
876 | if ((conf && !unconf) || | 883 | if ((conf && !unconf) || |
877 | ((conf && unconf) && | 884 | ((conf && unconf) && |
878 | (!cmp_verf(&conf->cl_verifier, &unconf->cl_verifier) || | 885 | (!cmp_verf(&conf->cl_verifier, &unconf->cl_verifier) || |
879 | !cmp_name(&conf->cl_name, &unconf->cl_name)))) { | 886 | !same_name(conf->cl_recdir, unconf->cl_recdir)))) { |
880 | if (!cmp_creds(&conf->cl_cred,&rqstp->rq_cred)) { | 887 | if (!cmp_creds(&conf->cl_cred,&rqstp->rq_cred)) { |
881 | status = nfserr_clid_inuse; | 888 | status = nfserr_clid_inuse; |
882 | } else { | 889 | } else { |
@@ -3074,39 +3081,28 @@ out: | |||
3074 | } | 3081 | } |
3075 | 3082 | ||
3076 | static inline struct nfs4_client_reclaim * | 3083 | static inline struct nfs4_client_reclaim * |
3077 | alloc_reclaim(int namelen) | 3084 | alloc_reclaim(void) |
3078 | { | 3085 | { |
3079 | struct nfs4_client_reclaim *crp = NULL; | 3086 | return kmalloc(sizeof(struct nfs4_client_reclaim), GFP_KERNEL); |
3080 | |||
3081 | crp = kmalloc(sizeof(struct nfs4_client_reclaim), GFP_KERNEL); | ||
3082 | if (!crp) | ||
3083 | return NULL; | ||
3084 | crp->cr_name.data = kmalloc(namelen, GFP_KERNEL); | ||
3085 | if (!crp->cr_name.data) { | ||
3086 | kfree(crp); | ||
3087 | return NULL; | ||
3088 | } | ||
3089 | return crp; | ||
3090 | } | 3087 | } |
3091 | 3088 | ||
3092 | /* | 3089 | /* |
3093 | * failure => all reset bets are off, nfserr_no_grace... | 3090 | * failure => all reset bets are off, nfserr_no_grace... |
3094 | */ | 3091 | */ |
3095 | static int | 3092 | static int |
3096 | nfs4_client_to_reclaim(char *name, int namlen) | 3093 | nfs4_client_to_reclaim(char *name) |
3097 | { | 3094 | { |
3098 | unsigned int strhashval; | 3095 | unsigned int strhashval; |
3099 | struct nfs4_client_reclaim *crp = NULL; | 3096 | struct nfs4_client_reclaim *crp = NULL; |
3100 | 3097 | ||
3101 | dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s\n", namlen, name); | 3098 | dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s\n", HEXDIR_LEN, name); |
3102 | crp = alloc_reclaim(namlen); | 3099 | crp = alloc_reclaim(); |
3103 | if (!crp) | 3100 | if (!crp) |
3104 | return 0; | 3101 | return 0; |
3105 | strhashval = clientstr_hashval(name, namlen); | 3102 | strhashval = clientstr_hashval(name); |
3106 | INIT_LIST_HEAD(&crp->cr_strhash); | 3103 | INIT_LIST_HEAD(&crp->cr_strhash); |
3107 | list_add(&crp->cr_strhash, &reclaim_str_hashtbl[strhashval]); | 3104 | list_add(&crp->cr_strhash, &reclaim_str_hashtbl[strhashval]); |
3108 | memcpy(crp->cr_name.data, name, namlen); | 3105 | memcpy(crp->cr_recdir, name, HEXDIR_LEN); |
3109 | crp->cr_name.len = namlen; | ||
3110 | reclaim_str_hashtbl_size++; | 3106 | reclaim_str_hashtbl_size++; |
3111 | return 1; | 3107 | return 1; |
3112 | } | 3108 | } |
@@ -3122,7 +3118,6 @@ nfs4_release_reclaim(void) | |||
3122 | crp = list_entry(reclaim_str_hashtbl[i].next, | 3118 | crp = list_entry(reclaim_str_hashtbl[i].next, |
3123 | struct nfs4_client_reclaim, cr_strhash); | 3119 | struct nfs4_client_reclaim, cr_strhash); |
3124 | list_del(&crp->cr_strhash); | 3120 | list_del(&crp->cr_strhash); |
3125 | kfree(crp->cr_name.data); | ||
3126 | kfree(crp); | 3121 | kfree(crp); |
3127 | reclaim_str_hashtbl_size--; | 3122 | reclaim_str_hashtbl_size--; |
3128 | } | 3123 | } |
@@ -3145,13 +3140,14 @@ nfs4_find_reclaim_client(clientid_t *clid) | |||
3145 | if (clp == NULL) | 3140 | if (clp == NULL) |
3146 | return NULL; | 3141 | return NULL; |
3147 | 3142 | ||
3148 | dprintk("NFSD: nfs4_find_reclaim_client for %.*s\n", | 3143 | dprintk("NFSD: nfs4_find_reclaim_client for %.*s with recdir %s\n", |
3149 | clp->cl_name.len, clp->cl_name.data); | 3144 | clp->cl_name.len, clp->cl_name.data, |
3145 | clp->cl_recdir); | ||
3150 | 3146 | ||
3151 | /* find clp->cl_name in reclaim_str_hashtbl */ | 3147 | /* find clp->cl_name in reclaim_str_hashtbl */ |
3152 | strhashval = clientstr_hashval(clp->cl_name.data, clp->cl_name.len); | 3148 | strhashval = clientstr_hashval(clp->cl_recdir); |
3153 | list_for_each_entry(crp, &reclaim_str_hashtbl[strhashval], cr_strhash) { | 3149 | list_for_each_entry(crp, &reclaim_str_hashtbl[strhashval], cr_strhash) { |
3154 | if (cmp_name(&crp->cr_name, &clp->cl_name)) { | 3150 | if (same_name(crp->cr_recdir, clp->cl_recdir)) { |
3155 | return crp; | 3151 | return crp; |
3156 | } | 3152 | } |
3157 | } | 3153 | } |