aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/export.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/export.c')
-rw-r--r--fs/nfsd/export.c181
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)
41static struct cache_head *expkey_table[EXPKEY_HASHMAX];
42 43
43static void expkey_put(struct kref *ref) 44static 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
74static struct svc_expkey *svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old); 75static struct svc_expkey *svc_expkey_update(struct cache_detail *cd, struct svc_expkey *new,
75static struct svc_expkey *svc_expkey_lookup(struct svc_expkey *); 76 struct svc_expkey *old);
76static struct cache_detail svc_expkey_cache; 77static struct svc_expkey *svc_expkey_lookup(struct cache_detail *cd, struct svc_expkey *);
77 78
78static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) 79static 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
242static struct cache_detail svc_expkey_cache = { 243static 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
270static struct svc_expkey * 270static struct svc_expkey *
271svc_expkey_lookup(struct svc_expkey *item) 271svc_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
284static struct svc_expkey * 283static struct svc_expkey *
285svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old) 284svc_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
302static struct cache_head *export_table[EXPORT_HASHMAX];
303
304static void nfsd4_fslocs_free(struct nfsd4_fs_locations *fsloc) 301static 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
677static void export_update(struct cache_head *cnew, struct cache_head *citem) 676static 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
710struct cache_detail svc_export_cache = { 709static 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
766static struct svc_expkey * 761static struct svc_expkey *
767exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp) 762exp_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
789static svc_export *exp_get_by_name(svc_client *clp, const struct path *path, 785static 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 */
813static struct svc_export *exp_parent(svc_client *clp, struct path *path) 810static 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 */
836int 834int
837exp_rootfh(svc_client *clp, char *name, struct knfsd_fh *f, int maxsize) 835exp_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
878static struct svc_export *exp_find(struct auth_domain *clp, int fsid_type, 879static 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 *
926rqst_exp_get_by_name(struct svc_rqst *rqstp, struct path *path) 929rqst_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 *
955rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv) 960rqst_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
1031static void *e_start(struct seq_file *m, loff_t *pos) 1039static 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
1084static void e_stop(struct seq_file *m, void *p) 1096static 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
1090static struct flags { 1104static 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
1212const struct seq_operations nfs_exports_op = { 1227const 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 */
1223int 1237int
1224nfsd_export_init(void) 1238nfsd_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
1262destroy_expkey_cache:
1263 cache_destroy_net(nn->svc_expkey_cache, net);
1264unregister_export_cache:
1265 cache_unregister_net(nn->svc_export_cache, net);
1266destroy_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 */
1242void 1274void
1243nfsd_export_flush(void) 1275nfsd_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 */
1252void 1286void
1253nfsd_export_shutdown(void) 1287nfsd_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}