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.c368
1 files changed, 250 insertions, 118 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 417ec02df44f..c340be0a3f59 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -57,27 +57,17 @@ static int exp_verify_string(char *cp, int max);
57#define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1) 57#define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1)
58static struct cache_head *expkey_table[EXPKEY_HASHMAX]; 58static struct cache_head *expkey_table[EXPKEY_HASHMAX];
59 59
60static inline int svc_expkey_hash(struct svc_expkey *item) 60static void expkey_put(struct kref *ref)
61{ 61{
62 int hash = item->ek_fsidtype; 62 struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref);
63 char * cp = (char*)item->ek_fsid;
64 int len = key_len(item->ek_fsidtype);
65 63
66 hash ^= hash_mem(cp, len, EXPKEY_HASHBITS); 64 if (test_bit(CACHE_VALID, &key->h.flags) &&
67 hash ^= hash_ptr(item->ek_client, EXPKEY_HASHBITS); 65 !test_bit(CACHE_NEGATIVE, &key->h.flags)) {
68 return hash & EXPKEY_HASHMASK; 66 dput(key->ek_dentry);
69} 67 mntput(key->ek_mnt);
70
71void expkey_put(struct cache_head *item, struct cache_detail *cd)
72{
73 if (cache_put(item, cd)) {
74 struct svc_expkey *key = container_of(item, struct svc_expkey, h);
75 if (test_bit(CACHE_VALID, &item->flags) &&
76 !test_bit(CACHE_NEGATIVE, &item->flags))
77 exp_put(key->ek_export);
78 auth_domain_put(key->ek_client);
79 kfree(key);
80 } 68 }
69 auth_domain_put(key->ek_client);
70 kfree(key);
81} 71}
82 72
83static void expkey_request(struct cache_detail *cd, 73static void expkey_request(struct cache_detail *cd,
@@ -95,7 +85,10 @@ static void expkey_request(struct cache_detail *cd,
95 (*bpp)[-1] = '\n'; 85 (*bpp)[-1] = '\n';
96} 86}
97 87
98static struct svc_expkey *svc_expkey_lookup(struct svc_expkey *, int); 88static struct svc_expkey *svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old);
89static struct svc_expkey *svc_expkey_lookup(struct svc_expkey *);
90static struct cache_detail svc_expkey_cache;
91
99static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) 92static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
100{ 93{
101 /* client fsidtype fsid [path] */ 94 /* client fsidtype fsid [path] */
@@ -106,6 +99,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
106 int fsidtype; 99 int fsidtype;
107 char *ep; 100 char *ep;
108 struct svc_expkey key; 101 struct svc_expkey key;
102 struct svc_expkey *ek;
109 103
110 if (mesg[mlen-1] != '\n') 104 if (mesg[mlen-1] != '\n')
111 return -EINVAL; 105 return -EINVAL;
@@ -150,40 +144,38 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
150 key.ek_fsidtype = fsidtype; 144 key.ek_fsidtype = fsidtype;
151 memcpy(key.ek_fsid, buf, len); 145 memcpy(key.ek_fsid, buf, len);
152 146
147 ek = svc_expkey_lookup(&key);
148 err = -ENOMEM;
149 if (!ek)
150 goto out;
151
153 /* now we want a pathname, or empty meaning NEGATIVE */ 152 /* now we want a pathname, or empty meaning NEGATIVE */
153 err = -EINVAL;
154 if ((len=qword_get(&mesg, buf, PAGE_SIZE)) < 0) 154 if ((len=qword_get(&mesg, buf, PAGE_SIZE)) < 0)
155 goto out; 155 goto out;
156 dprintk("Path seems to be <%s>\n", buf); 156 dprintk("Path seems to be <%s>\n", buf);
157 err = 0; 157 err = 0;
158 if (len == 0) { 158 if (len == 0) {
159 struct svc_expkey *ek;
160 set_bit(CACHE_NEGATIVE, &key.h.flags); 159 set_bit(CACHE_NEGATIVE, &key.h.flags);
161 ek = svc_expkey_lookup(&key, 1); 160 ek = svc_expkey_update(&key, ek);
162 if (ek) 161 if (ek)
163 expkey_put(&ek->h, &svc_expkey_cache); 162 cache_put(&ek->h, &svc_expkey_cache);
163 else err = -ENOMEM;
164 } else { 164 } else {
165 struct nameidata nd; 165 struct nameidata nd;
166 struct svc_expkey *ek;
167 struct svc_export *exp;
168 err = path_lookup(buf, 0, &nd); 166 err = path_lookup(buf, 0, &nd);
169 if (err) 167 if (err)
170 goto out; 168 goto out;
171 169
172 dprintk("Found the path %s\n", buf); 170 dprintk("Found the path %s\n", buf);
173 exp = exp_get_by_name(dom, nd.mnt, nd.dentry, NULL); 171 key.ek_mnt = nd.mnt;
174 172 key.ek_dentry = nd.dentry;
175 err = -ENOENT;
176 if (!exp)
177 goto out_nd;
178 key.ek_export = exp;
179 dprintk("And found export\n");
180 173
181 ek = svc_expkey_lookup(&key, 1); 174 ek = svc_expkey_update(&key, ek);
182 if (ek) 175 if (ek)
183 expkey_put(&ek->h, &svc_expkey_cache); 176 cache_put(&ek->h, &svc_expkey_cache);
184 exp_put(exp); 177 else
185 err = 0; 178 err = -ENOMEM;
186 out_nd:
187 path_release(&nd); 179 path_release(&nd);
188 } 180 }
189 cache_flush(); 181 cache_flush();
@@ -214,35 +206,31 @@ static int expkey_show(struct seq_file *m,
214 if (test_bit(CACHE_VALID, &h->flags) && 206 if (test_bit(CACHE_VALID, &h->flags) &&
215 !test_bit(CACHE_NEGATIVE, &h->flags)) { 207 !test_bit(CACHE_NEGATIVE, &h->flags)) {
216 seq_printf(m, " "); 208 seq_printf(m, " ");
217 seq_path(m, ek->ek_export->ex_mnt, ek->ek_export->ex_dentry, "\\ \t\n"); 209 seq_path(m, ek->ek_mnt, ek->ek_dentry, "\\ \t\n");
218 } 210 }
219 seq_printf(m, "\n"); 211 seq_printf(m, "\n");
220 return 0; 212 return 0;
221} 213}
222
223struct cache_detail svc_expkey_cache = {
224 .owner = THIS_MODULE,
225 .hash_size = EXPKEY_HASHMAX,
226 .hash_table = expkey_table,
227 .name = "nfsd.fh",
228 .cache_put = expkey_put,
229 .cache_request = expkey_request,
230 .cache_parse = expkey_parse,
231 .cache_show = expkey_show,
232};
233 214
234static inline int svc_expkey_match (struct svc_expkey *a, struct svc_expkey *b) 215static inline int expkey_match (struct cache_head *a, struct cache_head *b)
235{ 216{
236 if (a->ek_fsidtype != b->ek_fsidtype || 217 struct svc_expkey *orig = container_of(a, struct svc_expkey, h);
237 a->ek_client != b->ek_client || 218 struct svc_expkey *new = container_of(b, struct svc_expkey, h);
238 memcmp(a->ek_fsid, b->ek_fsid, key_len(a->ek_fsidtype)) != 0) 219
220 if (orig->ek_fsidtype != new->ek_fsidtype ||
221 orig->ek_client != new->ek_client ||
222 memcmp(orig->ek_fsid, new->ek_fsid, key_len(orig->ek_fsidtype)) != 0)
239 return 0; 223 return 0;
240 return 1; 224 return 1;
241} 225}
242 226
243static inline void svc_expkey_init(struct svc_expkey *new, struct svc_expkey *item) 227static inline void expkey_init(struct cache_head *cnew,
228 struct cache_head *citem)
244{ 229{
245 cache_get(&item->ek_client->h); 230 struct svc_expkey *new = container_of(cnew, struct svc_expkey, h);
231 struct svc_expkey *item = container_of(citem, struct svc_expkey, h);
232
233 kref_get(&item->ek_client->ref);
246 new->ek_client = item->ek_client; 234 new->ek_client = item->ek_client;
247 new->ek_fsidtype = item->ek_fsidtype; 235 new->ek_fsidtype = item->ek_fsidtype;
248 new->ek_fsid[0] = item->ek_fsid[0]; 236 new->ek_fsid[0] = item->ek_fsid[0];
@@ -250,39 +238,94 @@ static inline void svc_expkey_init(struct svc_expkey *new, struct svc_expkey *it
250 new->ek_fsid[2] = item->ek_fsid[2]; 238 new->ek_fsid[2] = item->ek_fsid[2];
251} 239}
252 240
253static inline void svc_expkey_update(struct svc_expkey *new, struct svc_expkey *item) 241static inline void expkey_update(struct cache_head *cnew,
242 struct cache_head *citem)
243{
244 struct svc_expkey *new = container_of(cnew, struct svc_expkey, h);
245 struct svc_expkey *item = container_of(citem, struct svc_expkey, h);
246
247 new->ek_mnt = mntget(item->ek_mnt);
248 new->ek_dentry = dget(item->ek_dentry);
249}
250
251static struct cache_head *expkey_alloc(void)
254{ 252{
255 cache_get(&item->ek_export->h); 253 struct svc_expkey *i = kmalloc(sizeof(*i), GFP_KERNEL);
256 new->ek_export = item->ek_export; 254 if (i)
255 return &i->h;
256 else
257 return NULL;
257} 258}
258 259
259static DefineSimpleCacheLookup(svc_expkey,0) /* no inplace updates */ 260static struct cache_detail svc_expkey_cache = {
261 .owner = THIS_MODULE,
262 .hash_size = EXPKEY_HASHMAX,
263 .hash_table = expkey_table,
264 .name = "nfsd.fh",
265 .cache_put = expkey_put,
266 .cache_request = expkey_request,
267 .cache_parse = expkey_parse,
268 .cache_show = expkey_show,
269 .match = expkey_match,
270 .init = expkey_init,
271 .update = expkey_update,
272 .alloc = expkey_alloc,
273};
260 274
261#define EXPORT_HASHBITS 8 275static struct svc_expkey *
262#define EXPORT_HASHMAX (1<< EXPORT_HASHBITS) 276svc_expkey_lookup(struct svc_expkey *item)
263#define EXPORT_HASHMASK (EXPORT_HASHMAX -1) 277{
278 struct cache_head *ch;
279 int hash = item->ek_fsidtype;
280 char * cp = (char*)item->ek_fsid;
281 int len = key_len(item->ek_fsidtype);
264 282
265static struct cache_head *export_table[EXPORT_HASHMAX]; 283 hash ^= hash_mem(cp, len, EXPKEY_HASHBITS);
284 hash ^= hash_ptr(item->ek_client, EXPKEY_HASHBITS);
285 hash &= EXPKEY_HASHMASK;
266 286
267static inline int svc_export_hash(struct svc_export *item) 287 ch = sunrpc_cache_lookup(&svc_expkey_cache, &item->h,
288 hash);
289 if (ch)
290 return container_of(ch, struct svc_expkey, h);
291 else
292 return NULL;
293}
294
295static struct svc_expkey *
296svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old)
268{ 297{
269 int rv; 298 struct cache_head *ch;
299 int hash = new->ek_fsidtype;
300 char * cp = (char*)new->ek_fsid;
301 int len = key_len(new->ek_fsidtype);
270 302
271 rv = hash_ptr(item->ex_client, EXPORT_HASHBITS); 303 hash ^= hash_mem(cp, len, EXPKEY_HASHBITS);
272 rv ^= hash_ptr(item->ex_dentry, EXPORT_HASHBITS); 304 hash ^= hash_ptr(new->ek_client, EXPKEY_HASHBITS);
273 rv ^= hash_ptr(item->ex_mnt, EXPORT_HASHBITS); 305 hash &= EXPKEY_HASHMASK;
274 return rv; 306
307 ch = sunrpc_cache_update(&svc_expkey_cache, &new->h,
308 &old->h, hash);
309 if (ch)
310 return container_of(ch, struct svc_expkey, h);
311 else
312 return NULL;
275} 313}
276 314
277void svc_export_put(struct cache_head *item, struct cache_detail *cd) 315
316#define EXPORT_HASHBITS 8
317#define EXPORT_HASHMAX (1<< EXPORT_HASHBITS)
318#define EXPORT_HASHMASK (EXPORT_HASHMAX -1)
319
320static struct cache_head *export_table[EXPORT_HASHMAX];
321
322static void svc_export_put(struct kref *ref)
278{ 323{
279 if (cache_put(item, cd)) { 324 struct svc_export *exp = container_of(ref, struct svc_export, h.ref);
280 struct svc_export *exp = container_of(item, struct svc_export, h); 325 dput(exp->ex_dentry);
281 dput(exp->ex_dentry); 326 mntput(exp->ex_mnt);
282 mntput(exp->ex_mnt); 327 auth_domain_put(exp->ex_client);
283 auth_domain_put(exp->ex_client); 328 kfree(exp);
284 kfree(exp);
285 }
286} 329}
287 330
288static void svc_export_request(struct cache_detail *cd, 331static void svc_export_request(struct cache_detail *cd,
@@ -304,7 +347,9 @@ static void svc_export_request(struct cache_detail *cd,
304 (*bpp)[-1] = '\n'; 347 (*bpp)[-1] = '\n';
305} 348}
306 349
307static struct svc_export *svc_export_lookup(struct svc_export *, int); 350static struct svc_export *svc_export_update(struct svc_export *new,
351 struct svc_export *old);
352static struct svc_export *svc_export_lookup(struct svc_export *);
308 353
309static int check_export(struct inode *inode, int flags) 354static int check_export(struct inode *inode, int flags)
310{ 355{
@@ -417,11 +462,16 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
417 if (err) goto out; 462 if (err) goto out;
418 } 463 }
419 464
420 expp = svc_export_lookup(&exp, 1); 465 expp = svc_export_lookup(&exp);
421 if (expp) 466 if (expp)
422 exp_put(expp); 467 expp = svc_export_update(&exp, expp);
423 err = 0; 468 else
469 err = -ENOMEM;
424 cache_flush(); 470 cache_flush();
471 if (expp == NULL)
472 err = -ENOMEM;
473 else
474 exp_put(expp);
425 out: 475 out:
426 if (nd.dentry) 476 if (nd.dentry)
427 path_release(&nd); 477 path_release(&nd);
@@ -455,6 +505,46 @@ static int svc_export_show(struct seq_file *m,
455 seq_puts(m, ")\n"); 505 seq_puts(m, ")\n");
456 return 0; 506 return 0;
457} 507}
508static int svc_export_match(struct cache_head *a, struct cache_head *b)
509{
510 struct svc_export *orig = container_of(a, struct svc_export, h);
511 struct svc_export *new = container_of(b, struct svc_export, h);
512 return orig->ex_client == new->ex_client &&
513 orig->ex_dentry == new->ex_dentry &&
514 orig->ex_mnt == new->ex_mnt;
515}
516
517static void svc_export_init(struct cache_head *cnew, struct cache_head *citem)
518{
519 struct svc_export *new = container_of(cnew, struct svc_export, h);
520 struct svc_export *item = container_of(citem, struct svc_export, h);
521
522 kref_get(&item->ex_client->ref);
523 new->ex_client = item->ex_client;
524 new->ex_dentry = dget(item->ex_dentry);
525 new->ex_mnt = mntget(item->ex_mnt);
526}
527
528static void export_update(struct cache_head *cnew, struct cache_head *citem)
529{
530 struct svc_export *new = container_of(cnew, struct svc_export, h);
531 struct svc_export *item = container_of(citem, struct svc_export, h);
532
533 new->ex_flags = item->ex_flags;
534 new->ex_anon_uid = item->ex_anon_uid;
535 new->ex_anon_gid = item->ex_anon_gid;
536 new->ex_fsid = item->ex_fsid;
537}
538
539static struct cache_head *svc_export_alloc(void)
540{
541 struct svc_export *i = kmalloc(sizeof(*i), GFP_KERNEL);
542 if (i)
543 return &i->h;
544 else
545 return NULL;
546}
547
458struct cache_detail svc_export_cache = { 548struct cache_detail svc_export_cache = {
459 .owner = THIS_MODULE, 549 .owner = THIS_MODULE,
460 .hash_size = EXPORT_HASHMAX, 550 .hash_size = EXPORT_HASHMAX,
@@ -464,34 +554,49 @@ struct cache_detail svc_export_cache = {
464 .cache_request = svc_export_request, 554 .cache_request = svc_export_request,
465 .cache_parse = svc_export_parse, 555 .cache_parse = svc_export_parse,
466 .cache_show = svc_export_show, 556 .cache_show = svc_export_show,
557 .match = svc_export_match,
558 .init = svc_export_init,
559 .update = export_update,
560 .alloc = svc_export_alloc,
467}; 561};
468 562
469static inline int svc_export_match(struct svc_export *a, struct svc_export *b) 563static struct svc_export *
564svc_export_lookup(struct svc_export *exp)
470{ 565{
471 return a->ex_client == b->ex_client && 566 struct cache_head *ch;
472 a->ex_dentry == b->ex_dentry && 567 int hash;
473 a->ex_mnt == b->ex_mnt; 568 hash = hash_ptr(exp->ex_client, EXPORT_HASHBITS);
474} 569 hash ^= hash_ptr(exp->ex_dentry, EXPORT_HASHBITS);
475static inline void svc_export_init(struct svc_export *new, struct svc_export *item) 570 hash ^= hash_ptr(exp->ex_mnt, EXPORT_HASHBITS);
476{ 571
477 cache_get(&item->ex_client->h); 572 ch = sunrpc_cache_lookup(&svc_export_cache, &exp->h,
478 new->ex_client = item->ex_client; 573 hash);
479 new->ex_dentry = dget(item->ex_dentry); 574 if (ch)
480 new->ex_mnt = mntget(item->ex_mnt); 575 return container_of(ch, struct svc_export, h);
576 else
577 return NULL;
481} 578}
482 579
483static inline void svc_export_update(struct svc_export *new, struct svc_export *item) 580static struct svc_export *
581svc_export_update(struct svc_export *new, struct svc_export *old)
484{ 582{
485 new->ex_flags = item->ex_flags; 583 struct cache_head *ch;
486 new->ex_anon_uid = item->ex_anon_uid; 584 int hash;
487 new->ex_anon_gid = item->ex_anon_gid; 585 hash = hash_ptr(old->ex_client, EXPORT_HASHBITS);
488 new->ex_fsid = item->ex_fsid; 586 hash ^= hash_ptr(old->ex_dentry, EXPORT_HASHBITS);
587 hash ^= hash_ptr(old->ex_mnt, EXPORT_HASHBITS);
588
589 ch = sunrpc_cache_update(&svc_export_cache, &new->h,
590 &old->h,
591 hash);
592 if (ch)
593 return container_of(ch, struct svc_export, h);
594 else
595 return NULL;
489} 596}
490 597
491static DefineSimpleCacheLookup(svc_export,1) /* allow inplace updates */
492 598
493 599static struct svc_expkey *
494struct svc_expkey *
495exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp) 600exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp)
496{ 601{
497 struct svc_expkey key, *ek; 602 struct svc_expkey key, *ek;
@@ -504,7 +609,7 @@ exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp)
504 key.ek_fsidtype = fsid_type; 609 key.ek_fsidtype = fsid_type;
505 memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); 610 memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
506 611
507 ek = svc_expkey_lookup(&key, 0); 612 ek = svc_expkey_lookup(&key);
508 if (ek != NULL) 613 if (ek != NULL)
509 if ((err = cache_check(&svc_expkey_cache, &ek->h, reqp))) 614 if ((err = cache_check(&svc_expkey_cache, &ek->h, reqp)))
510 ek = ERR_PTR(err); 615 ek = ERR_PTR(err);
@@ -519,13 +624,16 @@ static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv,
519 key.ek_client = clp; 624 key.ek_client = clp;
520 key.ek_fsidtype = fsid_type; 625 key.ek_fsidtype = fsid_type;
521 memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); 626 memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
522 key.ek_export = exp; 627 key.ek_mnt = exp->ex_mnt;
628 key.ek_dentry = exp->ex_dentry;
523 key.h.expiry_time = NEVER; 629 key.h.expiry_time = NEVER;
524 key.h.flags = 0; 630 key.h.flags = 0;
525 631
526 ek = svc_expkey_lookup(&key, 1); 632 ek = svc_expkey_lookup(&key);
633 if (ek)
634 ek = svc_expkey_update(&key,ek);
527 if (ek) { 635 if (ek) {
528 expkey_put(&ek->h, &svc_expkey_cache); 636 cache_put(&ek->h, &svc_expkey_cache);
529 return 0; 637 return 0;
530 } 638 }
531 return -ENOMEM; 639 return -ENOMEM;
@@ -573,7 +681,7 @@ exp_get_by_name(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry,
573 key.ex_mnt = mnt; 681 key.ex_mnt = mnt;
574 key.ex_dentry = dentry; 682 key.ex_dentry = dentry;
575 683
576 exp = svc_export_lookup(&key, 0); 684 exp = svc_export_lookup(&key);
577 if (exp != NULL) 685 if (exp != NULL)
578 switch (cache_check(&svc_export_cache, &exp->h, reqp)) { 686 switch (cache_check(&svc_export_cache, &exp->h, reqp)) {
579 case 0: break; 687 case 0: break;
@@ -654,7 +762,7 @@ static void exp_fsid_unhash(struct svc_export *exp)
654 ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid); 762 ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid);
655 if (ek && !IS_ERR(ek)) { 763 if (ek && !IS_ERR(ek)) {
656 ek->h.expiry_time = get_seconds()-1; 764 ek->h.expiry_time = get_seconds()-1;
657 expkey_put(&ek->h, &svc_expkey_cache); 765 cache_put(&ek->h, &svc_expkey_cache);
658 } 766 }
659 svc_expkey_cache.nextcheck = get_seconds(); 767 svc_expkey_cache.nextcheck = get_seconds();
660} 768}
@@ -692,7 +800,7 @@ static void exp_unhash(struct svc_export *exp)
692 ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino); 800 ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino);
693 if (ek && !IS_ERR(ek)) { 801 if (ek && !IS_ERR(ek)) {
694 ek->h.expiry_time = get_seconds()-1; 802 ek->h.expiry_time = get_seconds()-1;
695 expkey_put(&ek->h, &svc_expkey_cache); 803 cache_put(&ek->h, &svc_expkey_cache);
696 } 804 }
697 svc_expkey_cache.nextcheck = get_seconds(); 805 svc_expkey_cache.nextcheck = get_seconds();
698} 806}
@@ -741,8 +849,8 @@ exp_export(struct nfsctl_export *nxp)
741 if ((nxp->ex_flags & NFSEXP_FSID) && 849 if ((nxp->ex_flags & NFSEXP_FSID) &&
742 (fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) && 850 (fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) &&
743 !IS_ERR(fsid_key) && 851 !IS_ERR(fsid_key) &&
744 fsid_key->ek_export && 852 fsid_key->ek_mnt &&
745 fsid_key->ek_export != exp) 853 (fsid_key->ek_mnt != nd.mnt || fsid_key->ek_dentry != nd.dentry) )
746 goto finish; 854 goto finish;
747 855
748 if (exp) { 856 if (exp) {
@@ -775,13 +883,13 @@ exp_export(struct nfsctl_export *nxp)
775 new.ex_anon_gid = nxp->ex_anon_gid; 883 new.ex_anon_gid = nxp->ex_anon_gid;
776 new.ex_fsid = nxp->ex_dev; 884 new.ex_fsid = nxp->ex_dev;
777 885
778 exp = svc_export_lookup(&new, 1); 886 exp = svc_export_lookup(&new);
887 if (exp)
888 exp = svc_export_update(&new, exp);
779 889
780 if (exp == NULL) 890 if (!exp)
781 goto finish; 891 goto finish;
782 892
783 err = 0;
784
785 if (exp_hash(clp, exp) || 893 if (exp_hash(clp, exp) ||
786 exp_fsid_hash(clp, exp)) { 894 exp_fsid_hash(clp, exp)) {
787 /* failed to create at least one index */ 895 /* failed to create at least one index */
@@ -794,7 +902,7 @@ finish:
794 if (exp) 902 if (exp)
795 exp_put(exp); 903 exp_put(exp);
796 if (fsid_key && !IS_ERR(fsid_key)) 904 if (fsid_key && !IS_ERR(fsid_key))
797 expkey_put(&fsid_key->h, &svc_expkey_cache); 905 cache_put(&fsid_key->h, &svc_expkey_cache);
798 if (clp) 906 if (clp)
799 auth_domain_put(clp); 907 auth_domain_put(clp);
800 path_release(&nd); 908 path_release(&nd);
@@ -912,6 +1020,24 @@ out:
912 return err; 1020 return err;
913} 1021}
914 1022
1023struct svc_export *
1024exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv,
1025 struct cache_req *reqp)
1026{
1027 struct svc_export *exp;
1028 struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp);
1029 if (!ek || IS_ERR(ek))
1030 return ERR_PTR(PTR_ERR(ek));
1031
1032 exp = exp_get_by_name(clp, ek->ek_mnt, ek->ek_dentry, reqp);
1033 cache_put(&ek->h, &svc_expkey_cache);
1034
1035 if (!exp || IS_ERR(exp))
1036 return ERR_PTR(PTR_ERR(exp));
1037 return exp;
1038}
1039
1040
915/* 1041/*
916 * Called when we need the filehandle for the root of the pseudofs, 1042 * Called when we need the filehandle for the root of the pseudofs,
917 * for a given NFSv4 client. The root is defined to be the 1043 * for a given NFSv4 client. The root is defined to be the
@@ -922,6 +1048,7 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
922 struct cache_req *creq) 1048 struct cache_req *creq)
923{ 1049{
924 struct svc_expkey *fsid_key; 1050 struct svc_expkey *fsid_key;
1051 struct svc_export *exp;
925 int rv; 1052 int rv;
926 u32 fsidv[2]; 1053 u32 fsidv[2];
927 1054
@@ -933,9 +1060,15 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
933 if (!fsid_key || IS_ERR(fsid_key)) 1060 if (!fsid_key || IS_ERR(fsid_key))
934 return nfserr_perm; 1061 return nfserr_perm;
935 1062
936 rv = fh_compose(fhp, fsid_key->ek_export, 1063 exp = exp_get_by_name(clp, fsid_key->ek_mnt, fsid_key->ek_dentry, creq);
937 fsid_key->ek_export->ex_dentry, NULL); 1064 if (exp == NULL)
938 expkey_put(&fsid_key->h, &svc_expkey_cache); 1065 rv = nfserr_perm;
1066 else if (IS_ERR(exp))
1067 rv = nfserrno(PTR_ERR(exp));
1068 else
1069 rv = fh_compose(fhp, exp,
1070 fsid_key->ek_dentry, NULL);
1071 cache_put(&fsid_key->h, &svc_expkey_cache);
939 return rv; 1072 return rv;
940} 1073}
941 1074
@@ -1054,7 +1187,7 @@ static int e_show(struct seq_file *m, void *p)
1054 cache_get(&exp->h); 1187 cache_get(&exp->h);
1055 if (cache_check(&svc_export_cache, &exp->h, NULL)) 1188 if (cache_check(&svc_export_cache, &exp->h, NULL))
1056 return 0; 1189 return 0;
1057 if (cache_put(&exp->h, &svc_export_cache)) BUG(); 1190 cache_put(&exp->h, &svc_export_cache);
1058 return svc_export_show(m, &svc_export_cache, cp); 1191 return svc_export_show(m, &svc_export_cache, cp);
1059} 1192}
1060 1193
@@ -1129,7 +1262,6 @@ exp_delclient(struct nfsctl_client *ncp)
1129 */ 1262 */
1130 if (dom) { 1263 if (dom) {
1131 err = auth_unix_forget_old(dom); 1264 err = auth_unix_forget_old(dom);
1132 dom->h.expiry_time = get_seconds();
1133 auth_domain_put(dom); 1265 auth_domain_put(dom);
1134 } 1266 }
1135 1267