diff options
Diffstat (limited to 'fs/nfsd/export.c')
-rw-r--r-- | fs/nfsd/export.c | 181 |
1 files changed, 109 insertions, 72 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 8e9689abbc0c..ba233499b9a5 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c | |||
@@ -15,11 +15,13 @@ | |||
15 | #include <linux/namei.h> | 15 | #include <linux/namei.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/exportfs.h> | 17 | #include <linux/exportfs.h> |
18 | #include <linux/sunrpc/svc_xprt.h> | ||
18 | 19 | ||
19 | #include <net/ipv6.h> | 20 | #include <net/ipv6.h> |
20 | 21 | ||
21 | #include "nfsd.h" | 22 | #include "nfsd.h" |
22 | #include "nfsfh.h" | 23 | #include "nfsfh.h" |
24 | #include "netns.h" | ||
23 | 25 | ||
24 | #define NFSDDBG_FACILITY NFSDDBG_EXPORT | 26 | #define NFSDDBG_FACILITY NFSDDBG_EXPORT |
25 | 27 | ||
@@ -38,7 +40,6 @@ typedef struct svc_export svc_export; | |||
38 | #define EXPKEY_HASHBITS 8 | 40 | #define EXPKEY_HASHBITS 8 |
39 | #define EXPKEY_HASHMAX (1 << EXPKEY_HASHBITS) | 41 | #define EXPKEY_HASHMAX (1 << EXPKEY_HASHBITS) |
40 | #define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1) | 42 | #define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1) |
41 | static struct cache_head *expkey_table[EXPKEY_HASHMAX]; | ||
42 | 43 | ||
43 | static void expkey_put(struct kref *ref) | 44 | static void expkey_put(struct kref *ref) |
44 | { | 45 | { |
@@ -71,9 +72,9 @@ static int expkey_upcall(struct cache_detail *cd, struct cache_head *h) | |||
71 | return sunrpc_cache_pipe_upcall(cd, h, expkey_request); | 72 | return sunrpc_cache_pipe_upcall(cd, h, expkey_request); |
72 | } | 73 | } |
73 | 74 | ||
74 | static struct svc_expkey *svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old); | 75 | static struct svc_expkey *svc_expkey_update(struct cache_detail *cd, struct svc_expkey *new, |
75 | static struct svc_expkey *svc_expkey_lookup(struct svc_expkey *); | 76 | struct svc_expkey *old); |
76 | static struct cache_detail svc_expkey_cache; | 77 | static struct svc_expkey *svc_expkey_lookup(struct cache_detail *cd, struct svc_expkey *); |
77 | 78 | ||
78 | static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) | 79 | static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) |
79 | { | 80 | { |
@@ -131,7 +132,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
131 | key.ek_fsidtype = fsidtype; | 132 | key.ek_fsidtype = fsidtype; |
132 | memcpy(key.ek_fsid, buf, len); | 133 | memcpy(key.ek_fsid, buf, len); |
133 | 134 | ||
134 | ek = svc_expkey_lookup(&key); | 135 | ek = svc_expkey_lookup(cd, &key); |
135 | err = -ENOMEM; | 136 | err = -ENOMEM; |
136 | if (!ek) | 137 | if (!ek) |
137 | goto out; | 138 | goto out; |
@@ -145,7 +146,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
145 | err = 0; | 146 | err = 0; |
146 | if (len == 0) { | 147 | if (len == 0) { |
147 | set_bit(CACHE_NEGATIVE, &key.h.flags); | 148 | set_bit(CACHE_NEGATIVE, &key.h.flags); |
148 | ek = svc_expkey_update(&key, ek); | 149 | ek = svc_expkey_update(cd, &key, ek); |
149 | if (!ek) | 150 | if (!ek) |
150 | err = -ENOMEM; | 151 | err = -ENOMEM; |
151 | } else { | 152 | } else { |
@@ -155,7 +156,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
155 | 156 | ||
156 | dprintk("Found the path %s\n", buf); | 157 | dprintk("Found the path %s\n", buf); |
157 | 158 | ||
158 | ek = svc_expkey_update(&key, ek); | 159 | ek = svc_expkey_update(cd, &key, ek); |
159 | if (!ek) | 160 | if (!ek) |
160 | err = -ENOMEM; | 161 | err = -ENOMEM; |
161 | path_put(&key.ek_path); | 162 | path_put(&key.ek_path); |
@@ -163,7 +164,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
163 | cache_flush(); | 164 | cache_flush(); |
164 | out: | 165 | out: |
165 | if (ek) | 166 | if (ek) |
166 | cache_put(&ek->h, &svc_expkey_cache); | 167 | cache_put(&ek->h, cd); |
167 | if (dom) | 168 | if (dom) |
168 | auth_domain_put(dom); | 169 | auth_domain_put(dom); |
169 | kfree(buf); | 170 | kfree(buf); |
@@ -239,10 +240,9 @@ static struct cache_head *expkey_alloc(void) | |||
239 | return NULL; | 240 | return NULL; |
240 | } | 241 | } |
241 | 242 | ||
242 | static struct cache_detail svc_expkey_cache = { | 243 | static struct cache_detail svc_expkey_cache_template = { |
243 | .owner = THIS_MODULE, | 244 | .owner = THIS_MODULE, |
244 | .hash_size = EXPKEY_HASHMAX, | 245 | .hash_size = EXPKEY_HASHMAX, |
245 | .hash_table = expkey_table, | ||
246 | .name = "nfsd.fh", | 246 | .name = "nfsd.fh", |
247 | .cache_put = expkey_put, | 247 | .cache_put = expkey_put, |
248 | .cache_upcall = expkey_upcall, | 248 | .cache_upcall = expkey_upcall, |
@@ -268,13 +268,12 @@ svc_expkey_hash(struct svc_expkey *item) | |||
268 | } | 268 | } |
269 | 269 | ||
270 | static struct svc_expkey * | 270 | static struct svc_expkey * |
271 | svc_expkey_lookup(struct svc_expkey *item) | 271 | svc_expkey_lookup(struct cache_detail *cd, struct svc_expkey *item) |
272 | { | 272 | { |
273 | struct cache_head *ch; | 273 | struct cache_head *ch; |
274 | int hash = svc_expkey_hash(item); | 274 | int hash = svc_expkey_hash(item); |
275 | 275 | ||
276 | ch = sunrpc_cache_lookup(&svc_expkey_cache, &item->h, | 276 | ch = sunrpc_cache_lookup(cd, &item->h, hash); |
277 | hash); | ||
278 | if (ch) | 277 | if (ch) |
279 | return container_of(ch, struct svc_expkey, h); | 278 | return container_of(ch, struct svc_expkey, h); |
280 | else | 279 | else |
@@ -282,13 +281,13 @@ svc_expkey_lookup(struct svc_expkey *item) | |||
282 | } | 281 | } |
283 | 282 | ||
284 | static struct svc_expkey * | 283 | static struct svc_expkey * |
285 | svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old) | 284 | svc_expkey_update(struct cache_detail *cd, struct svc_expkey *new, |
285 | struct svc_expkey *old) | ||
286 | { | 286 | { |
287 | struct cache_head *ch; | 287 | struct cache_head *ch; |
288 | int hash = svc_expkey_hash(new); | 288 | int hash = svc_expkey_hash(new); |
289 | 289 | ||
290 | ch = sunrpc_cache_update(&svc_expkey_cache, &new->h, | 290 | ch = sunrpc_cache_update(cd, &new->h, &old->h, hash); |
291 | &old->h, hash); | ||
292 | if (ch) | 291 | if (ch) |
293 | return container_of(ch, struct svc_expkey, h); | 292 | return container_of(ch, struct svc_expkey, h); |
294 | else | 293 | else |
@@ -299,8 +298,6 @@ svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old) | |||
299 | #define EXPORT_HASHBITS 8 | 298 | #define EXPORT_HASHBITS 8 |
300 | #define EXPORT_HASHMAX (1<< EXPORT_HASHBITS) | 299 | #define EXPORT_HASHMAX (1<< EXPORT_HASHBITS) |
301 | 300 | ||
302 | static struct cache_head *export_table[EXPORT_HASHMAX]; | ||
303 | |||
304 | static void nfsd4_fslocs_free(struct nfsd4_fs_locations *fsloc) | 301 | static void nfsd4_fslocs_free(struct nfsd4_fs_locations *fsloc) |
305 | { | 302 | { |
306 | int i; | 303 | int i; |
@@ -525,6 +522,7 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
525 | goto out1; | 522 | goto out1; |
526 | 523 | ||
527 | exp.ex_client = dom; | 524 | exp.ex_client = dom; |
525 | exp.cd = cd; | ||
528 | 526 | ||
529 | /* expiry */ | 527 | /* expiry */ |
530 | err = -EINVAL; | 528 | err = -EINVAL; |
@@ -672,6 +670,7 @@ static void svc_export_init(struct cache_head *cnew, struct cache_head *citem) | |||
672 | new->ex_fslocs.locations = NULL; | 670 | new->ex_fslocs.locations = NULL; |
673 | new->ex_fslocs.locations_count = 0; | 671 | new->ex_fslocs.locations_count = 0; |
674 | new->ex_fslocs.migrated = 0; | 672 | new->ex_fslocs.migrated = 0; |
673 | new->cd = item->cd; | ||
675 | } | 674 | } |
676 | 675 | ||
677 | static void export_update(struct cache_head *cnew, struct cache_head *citem) | 676 | static void export_update(struct cache_head *cnew, struct cache_head *citem) |
@@ -707,10 +706,9 @@ static struct cache_head *svc_export_alloc(void) | |||
707 | return NULL; | 706 | return NULL; |
708 | } | 707 | } |
709 | 708 | ||
710 | struct cache_detail svc_export_cache = { | 709 | static struct cache_detail svc_export_cache_template = { |
711 | .owner = THIS_MODULE, | 710 | .owner = THIS_MODULE, |
712 | .hash_size = EXPORT_HASHMAX, | 711 | .hash_size = EXPORT_HASHMAX, |
713 | .hash_table = export_table, | ||
714 | .name = "nfsd.export", | 712 | .name = "nfsd.export", |
715 | .cache_put = svc_export_put, | 713 | .cache_put = svc_export_put, |
716 | .cache_upcall = svc_export_upcall, | 714 | .cache_upcall = svc_export_upcall, |
@@ -739,8 +737,7 @@ svc_export_lookup(struct svc_export *exp) | |||
739 | struct cache_head *ch; | 737 | struct cache_head *ch; |
740 | int hash = svc_export_hash(exp); | 738 | int hash = svc_export_hash(exp); |
741 | 739 | ||
742 | ch = sunrpc_cache_lookup(&svc_export_cache, &exp->h, | 740 | ch = sunrpc_cache_lookup(exp->cd, &exp->h, hash); |
743 | hash); | ||
744 | if (ch) | 741 | if (ch) |
745 | return container_of(ch, struct svc_export, h); | 742 | return container_of(ch, struct svc_export, h); |
746 | else | 743 | else |
@@ -753,9 +750,7 @@ svc_export_update(struct svc_export *new, struct svc_export *old) | |||
753 | struct cache_head *ch; | 750 | struct cache_head *ch; |
754 | int hash = svc_export_hash(old); | 751 | int hash = svc_export_hash(old); |
755 | 752 | ||
756 | ch = sunrpc_cache_update(&svc_export_cache, &new->h, | 753 | ch = sunrpc_cache_update(old->cd, &new->h, &old->h, hash); |
757 | &old->h, | ||
758 | hash); | ||
759 | if (ch) | 754 | if (ch) |
760 | return container_of(ch, struct svc_export, h); | 755 | return container_of(ch, struct svc_export, h); |
761 | else | 756 | else |
@@ -764,7 +759,8 @@ svc_export_update(struct svc_export *new, struct svc_export *old) | |||
764 | 759 | ||
765 | 760 | ||
766 | static struct svc_expkey * | 761 | static struct svc_expkey * |
767 | exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp) | 762 | exp_find_key(struct cache_detail *cd, svc_client *clp, int fsid_type, |
763 | u32 *fsidv, struct cache_req *reqp) | ||
768 | { | 764 | { |
769 | struct svc_expkey key, *ek; | 765 | struct svc_expkey key, *ek; |
770 | int err; | 766 | int err; |
@@ -776,18 +772,18 @@ exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp) | |||
776 | key.ek_fsidtype = fsid_type; | 772 | key.ek_fsidtype = fsid_type; |
777 | memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); | 773 | memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); |
778 | 774 | ||
779 | ek = svc_expkey_lookup(&key); | 775 | ek = svc_expkey_lookup(cd, &key); |
780 | if (ek == NULL) | 776 | if (ek == NULL) |
781 | return ERR_PTR(-ENOMEM); | 777 | return ERR_PTR(-ENOMEM); |
782 | err = cache_check(&svc_expkey_cache, &ek->h, reqp); | 778 | err = cache_check(cd, &ek->h, reqp); |
783 | if (err) | 779 | if (err) |
784 | return ERR_PTR(err); | 780 | return ERR_PTR(err); |
785 | return ek; | 781 | return ek; |
786 | } | 782 | } |
787 | 783 | ||
788 | 784 | ||
789 | static svc_export *exp_get_by_name(svc_client *clp, const struct path *path, | 785 | static svc_export *exp_get_by_name(struct cache_detail *cd, svc_client *clp, |
790 | struct cache_req *reqp) | 786 | const struct path *path, struct cache_req *reqp) |
791 | { | 787 | { |
792 | struct svc_export *exp, key; | 788 | struct svc_export *exp, key; |
793 | int err; | 789 | int err; |
@@ -797,11 +793,12 @@ static svc_export *exp_get_by_name(svc_client *clp, const struct path *path, | |||
797 | 793 | ||
798 | key.ex_client = clp; | 794 | key.ex_client = clp; |
799 | key.ex_path = *path; | 795 | key.ex_path = *path; |
796 | key.cd = cd; | ||
800 | 797 | ||
801 | exp = svc_export_lookup(&key); | 798 | exp = svc_export_lookup(&key); |
802 | if (exp == NULL) | 799 | if (exp == NULL) |
803 | return ERR_PTR(-ENOMEM); | 800 | return ERR_PTR(-ENOMEM); |
804 | err = cache_check(&svc_export_cache, &exp->h, reqp); | 801 | err = cache_check(cd, &exp->h, reqp); |
805 | if (err) | 802 | if (err) |
806 | return ERR_PTR(err); | 803 | return ERR_PTR(err); |
807 | return exp; | 804 | return exp; |
@@ -810,16 +807,17 @@ static svc_export *exp_get_by_name(svc_client *clp, const struct path *path, | |||
810 | /* | 807 | /* |
811 | * Find the export entry for a given dentry. | 808 | * Find the export entry for a given dentry. |
812 | */ | 809 | */ |
813 | static struct svc_export *exp_parent(svc_client *clp, struct path *path) | 810 | static struct svc_export *exp_parent(struct cache_detail *cd, svc_client *clp, |
811 | struct path *path) | ||
814 | { | 812 | { |
815 | struct dentry *saved = dget(path->dentry); | 813 | struct dentry *saved = dget(path->dentry); |
816 | svc_export *exp = exp_get_by_name(clp, path, NULL); | 814 | svc_export *exp = exp_get_by_name(cd, clp, path, NULL); |
817 | 815 | ||
818 | while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(path->dentry)) { | 816 | while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(path->dentry)) { |
819 | struct dentry *parent = dget_parent(path->dentry); | 817 | struct dentry *parent = dget_parent(path->dentry); |
820 | dput(path->dentry); | 818 | dput(path->dentry); |
821 | path->dentry = parent; | 819 | path->dentry = parent; |
822 | exp = exp_get_by_name(clp, path, NULL); | 820 | exp = exp_get_by_name(cd, clp, path, NULL); |
823 | } | 821 | } |
824 | dput(path->dentry); | 822 | dput(path->dentry); |
825 | path->dentry = saved; | 823 | path->dentry = saved; |
@@ -834,13 +832,16 @@ static struct svc_export *exp_parent(svc_client *clp, struct path *path) | |||
834 | * since its harder to fool a kernel module than a user space program. | 832 | * since its harder to fool a kernel module than a user space program. |
835 | */ | 833 | */ |
836 | int | 834 | int |
837 | exp_rootfh(svc_client *clp, char *name, struct knfsd_fh *f, int maxsize) | 835 | exp_rootfh(struct net *net, svc_client *clp, char *name, |
836 | struct knfsd_fh *f, int maxsize) | ||
838 | { | 837 | { |
839 | struct svc_export *exp; | 838 | struct svc_export *exp; |
840 | struct path path; | 839 | struct path path; |
841 | struct inode *inode; | 840 | struct inode *inode; |
842 | struct svc_fh fh; | 841 | struct svc_fh fh; |
843 | int err; | 842 | int err; |
843 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); | ||
844 | struct cache_detail *cd = nn->svc_export_cache; | ||
844 | 845 | ||
845 | err = -EPERM; | 846 | err = -EPERM; |
846 | /* NB: we probably ought to check that it's NUL-terminated */ | 847 | /* NB: we probably ought to check that it's NUL-terminated */ |
@@ -853,7 +854,7 @@ exp_rootfh(svc_client *clp, char *name, struct knfsd_fh *f, int maxsize) | |||
853 | dprintk("nfsd: exp_rootfh(%s [%p] %s:%s/%ld)\n", | 854 | dprintk("nfsd: exp_rootfh(%s [%p] %s:%s/%ld)\n", |
854 | name, path.dentry, clp->name, | 855 | name, path.dentry, clp->name, |
855 | inode->i_sb->s_id, inode->i_ino); | 856 | inode->i_sb->s_id, inode->i_ino); |
856 | exp = exp_parent(clp, &path); | 857 | exp = exp_parent(cd, clp, &path); |
857 | if (IS_ERR(exp)) { | 858 | if (IS_ERR(exp)) { |
858 | err = PTR_ERR(exp); | 859 | err = PTR_ERR(exp); |
859 | goto out; | 860 | goto out; |
@@ -875,16 +876,18 @@ out: | |||
875 | return err; | 876 | return err; |
876 | } | 877 | } |
877 | 878 | ||
878 | static struct svc_export *exp_find(struct auth_domain *clp, int fsid_type, | 879 | static struct svc_export *exp_find(struct cache_detail *cd, |
880 | struct auth_domain *clp, int fsid_type, | ||
879 | u32 *fsidv, struct cache_req *reqp) | 881 | u32 *fsidv, struct cache_req *reqp) |
880 | { | 882 | { |
881 | struct svc_export *exp; | 883 | struct svc_export *exp; |
882 | struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp); | 884 | struct nfsd_net *nn = net_generic(cd->net, nfsd_net_id); |
885 | struct svc_expkey *ek = exp_find_key(nn->svc_expkey_cache, clp, fsid_type, fsidv, reqp); | ||
883 | if (IS_ERR(ek)) | 886 | if (IS_ERR(ek)) |
884 | return ERR_CAST(ek); | 887 | return ERR_CAST(ek); |
885 | 888 | ||
886 | exp = exp_get_by_name(clp, &ek->ek_path, reqp); | 889 | exp = exp_get_by_name(cd, clp, &ek->ek_path, reqp); |
887 | cache_put(&ek->h, &svc_expkey_cache); | 890 | cache_put(&ek->h, nn->svc_expkey_cache); |
888 | 891 | ||
889 | if (IS_ERR(exp)) | 892 | if (IS_ERR(exp)) |
890 | return ERR_CAST(exp); | 893 | return ERR_CAST(exp); |
@@ -901,13 +904,13 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp) | |||
901 | return 0; | 904 | return 0; |
902 | /* ip-address based client; check sec= export option: */ | 905 | /* ip-address based client; check sec= export option: */ |
903 | for (f = exp->ex_flavors; f < end; f++) { | 906 | for (f = exp->ex_flavors; f < end; f++) { |
904 | if (f->pseudoflavor == rqstp->rq_flavor) | 907 | if (f->pseudoflavor == rqstp->rq_cred.cr_flavor) |
905 | return 0; | 908 | return 0; |
906 | } | 909 | } |
907 | /* defaults in absence of sec= options: */ | 910 | /* defaults in absence of sec= options: */ |
908 | if (exp->ex_nflavors == 0) { | 911 | if (exp->ex_nflavors == 0) { |
909 | if (rqstp->rq_flavor == RPC_AUTH_NULL || | 912 | if (rqstp->rq_cred.cr_flavor == RPC_AUTH_NULL || |
910 | rqstp->rq_flavor == RPC_AUTH_UNIX) | 913 | rqstp->rq_cred.cr_flavor == RPC_AUTH_UNIX) |
911 | return 0; | 914 | return 0; |
912 | } | 915 | } |
913 | return nfserr_wrongsec; | 916 | return nfserr_wrongsec; |
@@ -926,12 +929,14 @@ struct svc_export * | |||
926 | rqst_exp_get_by_name(struct svc_rqst *rqstp, struct path *path) | 929 | rqst_exp_get_by_name(struct svc_rqst *rqstp, struct path *path) |
927 | { | 930 | { |
928 | struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT); | 931 | struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT); |
932 | struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id); | ||
933 | struct cache_detail *cd = nn->svc_export_cache; | ||
929 | 934 | ||
930 | if (rqstp->rq_client == NULL) | 935 | if (rqstp->rq_client == NULL) |
931 | goto gss; | 936 | goto gss; |
932 | 937 | ||
933 | /* First try the auth_unix client: */ | 938 | /* First try the auth_unix client: */ |
934 | exp = exp_get_by_name(rqstp->rq_client, path, &rqstp->rq_chandle); | 939 | exp = exp_get_by_name(cd, rqstp->rq_client, path, &rqstp->rq_chandle); |
935 | if (PTR_ERR(exp) == -ENOENT) | 940 | if (PTR_ERR(exp) == -ENOENT) |
936 | goto gss; | 941 | goto gss; |
937 | if (IS_ERR(exp)) | 942 | if (IS_ERR(exp)) |
@@ -943,7 +948,7 @@ gss: | |||
943 | /* Otherwise, try falling back on gss client */ | 948 | /* Otherwise, try falling back on gss client */ |
944 | if (rqstp->rq_gssclient == NULL) | 949 | if (rqstp->rq_gssclient == NULL) |
945 | return exp; | 950 | return exp; |
946 | gssexp = exp_get_by_name(rqstp->rq_gssclient, path, &rqstp->rq_chandle); | 951 | gssexp = exp_get_by_name(cd, rqstp->rq_gssclient, path, &rqstp->rq_chandle); |
947 | if (PTR_ERR(gssexp) == -ENOENT) | 952 | if (PTR_ERR(gssexp) == -ENOENT) |
948 | return exp; | 953 | return exp; |
949 | if (!IS_ERR(exp)) | 954 | if (!IS_ERR(exp)) |
@@ -955,12 +960,15 @@ struct svc_export * | |||
955 | rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv) | 960 | rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv) |
956 | { | 961 | { |
957 | struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT); | 962 | struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT); |
963 | struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id); | ||
964 | struct cache_detail *cd = nn->svc_export_cache; | ||
958 | 965 | ||
959 | if (rqstp->rq_client == NULL) | 966 | if (rqstp->rq_client == NULL) |
960 | goto gss; | 967 | goto gss; |
961 | 968 | ||
962 | /* First try the auth_unix client: */ | 969 | /* First try the auth_unix client: */ |
963 | exp = exp_find(rqstp->rq_client, fsid_type, fsidv, &rqstp->rq_chandle); | 970 | exp = exp_find(cd, rqstp->rq_client, fsid_type, |
971 | fsidv, &rqstp->rq_chandle); | ||
964 | if (PTR_ERR(exp) == -ENOENT) | 972 | if (PTR_ERR(exp) == -ENOENT) |
965 | goto gss; | 973 | goto gss; |
966 | if (IS_ERR(exp)) | 974 | if (IS_ERR(exp)) |
@@ -972,7 +980,7 @@ gss: | |||
972 | /* Otherwise, try falling back on gss client */ | 980 | /* Otherwise, try falling back on gss client */ |
973 | if (rqstp->rq_gssclient == NULL) | 981 | if (rqstp->rq_gssclient == NULL) |
974 | return exp; | 982 | return exp; |
975 | gssexp = exp_find(rqstp->rq_gssclient, fsid_type, fsidv, | 983 | gssexp = exp_find(cd, rqstp->rq_gssclient, fsid_type, fsidv, |
976 | &rqstp->rq_chandle); | 984 | &rqstp->rq_chandle); |
977 | if (PTR_ERR(gssexp) == -ENOENT) | 985 | if (PTR_ERR(gssexp) == -ENOENT) |
978 | return exp; | 986 | return exp; |
@@ -1029,13 +1037,15 @@ exp_pseudoroot(struct svc_rqst *rqstp, struct svc_fh *fhp) | |||
1029 | /* Iterator */ | 1037 | /* Iterator */ |
1030 | 1038 | ||
1031 | static void *e_start(struct seq_file *m, loff_t *pos) | 1039 | static void *e_start(struct seq_file *m, loff_t *pos) |
1032 | __acquires(svc_export_cache.hash_lock) | 1040 | __acquires(((struct cache_detail *)m->private)->hash_lock) |
1033 | { | 1041 | { |
1034 | loff_t n = *pos; | 1042 | loff_t n = *pos; |
1035 | unsigned hash, export; | 1043 | unsigned hash, export; |
1036 | struct cache_head *ch; | 1044 | struct cache_head *ch; |
1037 | 1045 | struct cache_detail *cd = m->private; | |
1038 | read_lock(&svc_export_cache.hash_lock); | 1046 | struct cache_head **export_table = cd->hash_table; |
1047 | |||
1048 | read_lock(&cd->hash_lock); | ||
1039 | if (!n--) | 1049 | if (!n--) |
1040 | return SEQ_START_TOKEN; | 1050 | return SEQ_START_TOKEN; |
1041 | hash = n >> 32; | 1051 | hash = n >> 32; |
@@ -1060,6 +1070,8 @@ static void *e_next(struct seq_file *m, void *p, loff_t *pos) | |||
1060 | { | 1070 | { |
1061 | struct cache_head *ch = p; | 1071 | struct cache_head *ch = p; |
1062 | int hash = (*pos >> 32); | 1072 | int hash = (*pos >> 32); |
1073 | struct cache_detail *cd = m->private; | ||
1074 | struct cache_head **export_table = cd->hash_table; | ||
1063 | 1075 | ||
1064 | if (p == SEQ_START_TOKEN) | 1076 | if (p == SEQ_START_TOKEN) |
1065 | hash = 0; | 1077 | hash = 0; |
@@ -1082,9 +1094,11 @@ static void *e_next(struct seq_file *m, void *p, loff_t *pos) | |||
1082 | } | 1094 | } |
1083 | 1095 | ||
1084 | static void e_stop(struct seq_file *m, void *p) | 1096 | static void e_stop(struct seq_file *m, void *p) |
1085 | __releases(svc_export_cache.hash_lock) | 1097 | __releases(((struct cache_detail *)m->private)->hash_lock) |
1086 | { | 1098 | { |
1087 | read_unlock(&svc_export_cache.hash_lock); | 1099 | struct cache_detail *cd = m->private; |
1100 | |||
1101 | read_unlock(&cd->hash_lock); | ||
1088 | } | 1102 | } |
1089 | 1103 | ||
1090 | static struct flags { | 1104 | static struct flags { |
@@ -1195,6 +1209,7 @@ static int e_show(struct seq_file *m, void *p) | |||
1195 | { | 1209 | { |
1196 | struct cache_head *cp = p; | 1210 | struct cache_head *cp = p; |
1197 | struct svc_export *exp = container_of(cp, struct svc_export, h); | 1211 | struct svc_export *exp = container_of(cp, struct svc_export, h); |
1212 | struct cache_detail *cd = m->private; | ||
1198 | 1213 | ||
1199 | if (p == SEQ_START_TOKEN) { | 1214 | if (p == SEQ_START_TOKEN) { |
1200 | seq_puts(m, "# Version 1.1\n"); | 1215 | seq_puts(m, "# Version 1.1\n"); |
@@ -1203,10 +1218,10 @@ static int e_show(struct seq_file *m, void *p) | |||
1203 | } | 1218 | } |
1204 | 1219 | ||
1205 | cache_get(&exp->h); | 1220 | cache_get(&exp->h); |
1206 | if (cache_check(&svc_export_cache, &exp->h, NULL)) | 1221 | if (cache_check(cd, &exp->h, NULL)) |
1207 | return 0; | 1222 | return 0; |
1208 | cache_put(&exp->h, &svc_export_cache); | 1223 | exp_put(exp); |
1209 | return svc_export_show(m, &svc_export_cache, cp); | 1224 | return svc_export_show(m, cd, cp); |
1210 | } | 1225 | } |
1211 | 1226 | ||
1212 | const struct seq_operations nfs_exports_op = { | 1227 | const struct seq_operations nfs_exports_op = { |
@@ -1216,48 +1231,70 @@ const struct seq_operations nfs_exports_op = { | |||
1216 | .show = e_show, | 1231 | .show = e_show, |
1217 | }; | 1232 | }; |
1218 | 1233 | ||
1219 | |||
1220 | /* | 1234 | /* |
1221 | * Initialize the exports module. | 1235 | * Initialize the exports module. |
1222 | */ | 1236 | */ |
1223 | int | 1237 | int |
1224 | nfsd_export_init(void) | 1238 | nfsd_export_init(struct net *net) |
1225 | { | 1239 | { |
1226 | int rv; | 1240 | int rv; |
1227 | dprintk("nfsd: initializing export module.\n"); | 1241 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); |
1242 | |||
1243 | dprintk("nfsd: initializing export module (net: %p).\n", net); | ||
1228 | 1244 | ||
1229 | rv = cache_register_net(&svc_export_cache, &init_net); | 1245 | nn->svc_export_cache = cache_create_net(&svc_export_cache_template, net); |
1246 | if (IS_ERR(nn->svc_export_cache)) | ||
1247 | return PTR_ERR(nn->svc_export_cache); | ||
1248 | rv = cache_register_net(nn->svc_export_cache, net); | ||
1230 | if (rv) | 1249 | if (rv) |
1231 | return rv; | 1250 | goto destroy_export_cache; |
1232 | rv = cache_register_net(&svc_expkey_cache, &init_net); | 1251 | |
1252 | nn->svc_expkey_cache = cache_create_net(&svc_expkey_cache_template, net); | ||
1253 | if (IS_ERR(nn->svc_expkey_cache)) { | ||
1254 | rv = PTR_ERR(nn->svc_expkey_cache); | ||
1255 | goto unregister_export_cache; | ||
1256 | } | ||
1257 | rv = cache_register_net(nn->svc_expkey_cache, net); | ||
1233 | if (rv) | 1258 | if (rv) |
1234 | cache_unregister_net(&svc_export_cache, &init_net); | 1259 | goto destroy_expkey_cache; |
1235 | return rv; | 1260 | return 0; |
1236 | 1261 | ||
1262 | destroy_expkey_cache: | ||
1263 | cache_destroy_net(nn->svc_expkey_cache, net); | ||
1264 | unregister_export_cache: | ||
1265 | cache_unregister_net(nn->svc_export_cache, net); | ||
1266 | destroy_export_cache: | ||
1267 | cache_destroy_net(nn->svc_export_cache, net); | ||
1268 | return rv; | ||
1237 | } | 1269 | } |
1238 | 1270 | ||
1239 | /* | 1271 | /* |
1240 | * Flush exports table - called when last nfsd thread is killed | 1272 | * Flush exports table - called when last nfsd thread is killed |
1241 | */ | 1273 | */ |
1242 | void | 1274 | void |
1243 | nfsd_export_flush(void) | 1275 | nfsd_export_flush(struct net *net) |
1244 | { | 1276 | { |
1245 | cache_purge(&svc_expkey_cache); | 1277 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); |
1246 | cache_purge(&svc_export_cache); | 1278 | |
1279 | cache_purge(nn->svc_expkey_cache); | ||
1280 | cache_purge(nn->svc_export_cache); | ||
1247 | } | 1281 | } |
1248 | 1282 | ||
1249 | /* | 1283 | /* |
1250 | * Shutdown the exports module. | 1284 | * Shutdown the exports module. |
1251 | */ | 1285 | */ |
1252 | void | 1286 | void |
1253 | nfsd_export_shutdown(void) | 1287 | nfsd_export_shutdown(struct net *net) |
1254 | { | 1288 | { |
1289 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); | ||
1255 | 1290 | ||
1256 | dprintk("nfsd: shutting down export module.\n"); | 1291 | dprintk("nfsd: shutting down export module (net: %p).\n", net); |
1257 | 1292 | ||
1258 | cache_unregister_net(&svc_expkey_cache, &init_net); | 1293 | cache_unregister_net(nn->svc_expkey_cache, net); |
1259 | cache_unregister_net(&svc_export_cache, &init_net); | 1294 | cache_unregister_net(nn->svc_export_cache, net); |
1260 | svcauth_unix_purge(); | 1295 | cache_destroy_net(nn->svc_expkey_cache, net); |
1296 | cache_destroy_net(nn->svc_export_cache, net); | ||
1297 | svcauth_unix_purge(net); | ||
1261 | 1298 | ||
1262 | dprintk("nfsd: export shutdown complete.\n"); | 1299 | dprintk("nfsd: export shutdown complete (net: %p).\n", net); |
1263 | } | 1300 | } |