Merge branch 'devel-stable' of master.kernel.org:/home/rmk/linux-2.6-arm
[pandora-kernel.git] / fs / nfsd / export.c
1 /*
2  * NFS exporting and validation.
3  *
4  * We maintain a list of clients, each of which has a list of
5  * exports. To export an fs to a given client, you first have
6  * to create the client entry with NFSCTL_ADDCLIENT, which
7  * creates a client control block and adds it to the hash
8  * table. Then, you call NFSCTL_EXPORT for each fs.
9  *
10  *
11  * Copyright (C) 1995, 1996 Olaf Kirch, <okir@monad.swb.de>
12  */
13
14 #include <linux/slab.h>
15 #include <linux/namei.h>
16 #include <linux/module.h>
17 #include <linux/exportfs.h>
18
19 #include <linux/nfsd/syscall.h>
20 #include <net/ipv6.h>
21
22 #include "nfsd.h"
23 #include "nfsfh.h"
24
25 #define NFSDDBG_FACILITY        NFSDDBG_EXPORT
26
27 typedef struct auth_domain      svc_client;
28 typedef struct svc_export       svc_export;
29
30 /*
31  * We have two caches.
32  * One maps client+vfsmnt+dentry to export options - the export map
33  * The other maps client+filehandle-fragment to export options. - the expkey map
34  *
35  * The export options are actually stored in the first map, and the
36  * second map contains a reference to the entry in the first map.
37  */
38
39 #define EXPKEY_HASHBITS         8
40 #define EXPKEY_HASHMAX          (1 << EXPKEY_HASHBITS)
41 #define EXPKEY_HASHMASK         (EXPKEY_HASHMAX -1)
42 static struct cache_head *expkey_table[EXPKEY_HASHMAX];
43
44 static void expkey_put(struct kref *ref)
45 {
46         struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref);
47
48         if (test_bit(CACHE_VALID, &key->h.flags) &&
49             !test_bit(CACHE_NEGATIVE, &key->h.flags))
50                 path_put(&key->ek_path);
51         auth_domain_put(key->ek_client);
52         kfree(key);
53 }
54
55 static void expkey_request(struct cache_detail *cd,
56                            struct cache_head *h,
57                            char **bpp, int *blen)
58 {
59         /* client fsidtype \xfsid */
60         struct svc_expkey *ek = container_of(h, struct svc_expkey, h);
61         char type[5];
62
63         qword_add(bpp, blen, ek->ek_client->name);
64         snprintf(type, 5, "%d", ek->ek_fsidtype);
65         qword_add(bpp, blen, type);
66         qword_addhex(bpp, blen, (char*)ek->ek_fsid, key_len(ek->ek_fsidtype));
67         (*bpp)[-1] = '\n';
68 }
69
70 static int expkey_upcall(struct cache_detail *cd, struct cache_head *h)
71 {
72         return sunrpc_cache_pipe_upcall(cd, h, expkey_request);
73 }
74
75 static struct svc_expkey *svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old);
76 static struct svc_expkey *svc_expkey_lookup(struct svc_expkey *);
77 static struct cache_detail svc_expkey_cache;
78
79 static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
80 {
81         /* client fsidtype fsid [path] */
82         char *buf;
83         int len;
84         struct auth_domain *dom = NULL;
85         int err;
86         int fsidtype;
87         char *ep;
88         struct svc_expkey key;
89         struct svc_expkey *ek = NULL;
90
91         if (mesg[mlen-1] != '\n')
92                 return -EINVAL;
93         mesg[mlen-1] = 0;
94
95         buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
96         err = -ENOMEM;
97         if (!buf)
98                 goto out;
99
100         err = -EINVAL;
101         if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
102                 goto out;
103
104         err = -ENOENT;
105         dom = auth_domain_find(buf);
106         if (!dom)
107                 goto out;
108         dprintk("found domain %s\n", buf);
109
110         err = -EINVAL;
111         if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
112                 goto out;
113         fsidtype = simple_strtoul(buf, &ep, 10);
114         if (*ep)
115                 goto out;
116         dprintk("found fsidtype %d\n", fsidtype);
117         if (key_len(fsidtype)==0) /* invalid type */
118                 goto out;
119         if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
120                 goto out;
121         dprintk("found fsid length %d\n", len);
122         if (len != key_len(fsidtype))
123                 goto out;
124
125         /* OK, we seem to have a valid key */
126         key.h.flags = 0;
127         key.h.expiry_time = get_expiry(&mesg);
128         if (key.h.expiry_time == 0)
129                 goto out;
130
131         key.ek_client = dom;    
132         key.ek_fsidtype = fsidtype;
133         memcpy(key.ek_fsid, buf, len);
134
135         ek = svc_expkey_lookup(&key);
136         err = -ENOMEM;
137         if (!ek)
138                 goto out;
139
140         /* now we want a pathname, or empty meaning NEGATIVE  */
141         err = -EINVAL;
142         len = qword_get(&mesg, buf, PAGE_SIZE);
143         if (len < 0)
144                 goto out;
145         dprintk("Path seems to be <%s>\n", buf);
146         err = 0;
147         if (len == 0) {
148                 set_bit(CACHE_NEGATIVE, &key.h.flags);
149                 ek = svc_expkey_update(&key, ek);
150                 if (!ek)
151                         err = -ENOMEM;
152         } else {
153                 err = kern_path(buf, 0, &key.ek_path);
154                 if (err)
155                         goto out;
156
157                 dprintk("Found the path %s\n", buf);
158
159                 ek = svc_expkey_update(&key, ek);
160                 if (!ek)
161                         err = -ENOMEM;
162                 path_put(&key.ek_path);
163         }
164         cache_flush();
165  out:
166         if (ek)
167                 cache_put(&ek->h, &svc_expkey_cache);
168         if (dom)
169                 auth_domain_put(dom);
170         kfree(buf);
171         return err;
172 }
173
174 static int expkey_show(struct seq_file *m,
175                        struct cache_detail *cd,
176                        struct cache_head *h)
177 {
178         struct svc_expkey *ek ;
179         int i;
180
181         if (h ==NULL) {
182                 seq_puts(m, "#domain fsidtype fsid [path]\n");
183                 return 0;
184         }
185         ek = container_of(h, struct svc_expkey, h);
186         seq_printf(m, "%s %d 0x", ek->ek_client->name,
187                    ek->ek_fsidtype);
188         for (i=0; i < key_len(ek->ek_fsidtype)/4; i++)
189                 seq_printf(m, "%08x", ek->ek_fsid[i]);
190         if (test_bit(CACHE_VALID, &h->flags) && 
191             !test_bit(CACHE_NEGATIVE, &h->flags)) {
192                 seq_printf(m, " ");
193                 seq_path(m, &ek->ek_path, "\\ \t\n");
194         }
195         seq_printf(m, "\n");
196         return 0;
197 }
198
199 static inline int expkey_match (struct cache_head *a, struct cache_head *b)
200 {
201         struct svc_expkey *orig = container_of(a, struct svc_expkey, h);
202         struct svc_expkey *new = container_of(b, struct svc_expkey, h);
203
204         if (orig->ek_fsidtype != new->ek_fsidtype ||
205             orig->ek_client != new->ek_client ||
206             memcmp(orig->ek_fsid, new->ek_fsid, key_len(orig->ek_fsidtype)) != 0)
207                 return 0;
208         return 1;
209 }
210
211 static inline void expkey_init(struct cache_head *cnew,
212                                    struct cache_head *citem)
213 {
214         struct svc_expkey *new = container_of(cnew, struct svc_expkey, h);
215         struct svc_expkey *item = container_of(citem, struct svc_expkey, h);
216
217         kref_get(&item->ek_client->ref);
218         new->ek_client = item->ek_client;
219         new->ek_fsidtype = item->ek_fsidtype;
220
221         memcpy(new->ek_fsid, item->ek_fsid, sizeof(new->ek_fsid));
222 }
223
224 static inline void expkey_update(struct cache_head *cnew,
225                                    struct cache_head *citem)
226 {
227         struct svc_expkey *new = container_of(cnew, struct svc_expkey, h);
228         struct svc_expkey *item = container_of(citem, struct svc_expkey, h);
229
230         new->ek_path = item->ek_path;
231         path_get(&item->ek_path);
232 }
233
234 static struct cache_head *expkey_alloc(void)
235 {
236         struct svc_expkey *i = kmalloc(sizeof(*i), GFP_KERNEL);
237         if (i)
238                 return &i->h;
239         else
240                 return NULL;
241 }
242
243 static struct cache_detail svc_expkey_cache = {
244         .owner          = THIS_MODULE,
245         .hash_size      = EXPKEY_HASHMAX,
246         .hash_table     = expkey_table,
247         .name           = "nfsd.fh",
248         .cache_put      = expkey_put,
249         .cache_upcall   = expkey_upcall,
250         .cache_parse    = expkey_parse,
251         .cache_show     = expkey_show,
252         .match          = expkey_match,
253         .init           = expkey_init,
254         .update         = expkey_update,
255         .alloc          = expkey_alloc,
256 };
257
258 static int
259 svc_expkey_hash(struct svc_expkey *item)
260 {
261         int hash = item->ek_fsidtype;
262         char * cp = (char*)item->ek_fsid;
263         int len = key_len(item->ek_fsidtype);
264
265         hash ^= hash_mem(cp, len, EXPKEY_HASHBITS);
266         hash ^= hash_ptr(item->ek_client, EXPKEY_HASHBITS);
267         hash &= EXPKEY_HASHMASK;
268         return hash;
269 }
270
271 static struct svc_expkey *
272 svc_expkey_lookup(struct svc_expkey *item)
273 {
274         struct cache_head *ch;
275         int hash = svc_expkey_hash(item);
276
277         ch = sunrpc_cache_lookup(&svc_expkey_cache, &item->h,
278                                  hash);
279         if (ch)
280                 return container_of(ch, struct svc_expkey, h);
281         else
282                 return NULL;
283 }
284
285 static struct svc_expkey *
286 svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old)
287 {
288         struct cache_head *ch;
289         int hash = svc_expkey_hash(new);
290
291         ch = sunrpc_cache_update(&svc_expkey_cache, &new->h,
292                                  &old->h, hash);
293         if (ch)
294                 return container_of(ch, struct svc_expkey, h);
295         else
296                 return NULL;
297 }
298
299
300 #define EXPORT_HASHBITS         8
301 #define EXPORT_HASHMAX          (1<< EXPORT_HASHBITS)
302 #define EXPORT_HASHMASK         (EXPORT_HASHMAX -1)
303
304 static struct cache_head *export_table[EXPORT_HASHMAX];
305
306 static void nfsd4_fslocs_free(struct nfsd4_fs_locations *fsloc)
307 {
308         int i;
309
310         for (i = 0; i < fsloc->locations_count; i++) {
311                 kfree(fsloc->locations[i].path);
312                 kfree(fsloc->locations[i].hosts);
313         }
314         kfree(fsloc->locations);
315 }
316
317 static void svc_export_put(struct kref *ref)
318 {
319         struct svc_export *exp = container_of(ref, struct svc_export, h.ref);
320         path_put(&exp->ex_path);
321         auth_domain_put(exp->ex_client);
322         kfree(exp->ex_pathname);
323         nfsd4_fslocs_free(&exp->ex_fslocs);
324         kfree(exp);
325 }
326
327 static void svc_export_request(struct cache_detail *cd,
328                                struct cache_head *h,
329                                char **bpp, int *blen)
330 {
331         /*  client path */
332         struct svc_export *exp = container_of(h, struct svc_export, h);
333         char *pth;
334
335         qword_add(bpp, blen, exp->ex_client->name);
336         pth = d_path(&exp->ex_path, *bpp, *blen);
337         if (IS_ERR(pth)) {
338                 /* is this correct? */
339                 (*bpp)[0] = '\n';
340                 return;
341         }
342         qword_add(bpp, blen, pth);
343         (*bpp)[-1] = '\n';
344 }
345
346 static int svc_export_upcall(struct cache_detail *cd, struct cache_head *h)
347 {
348         return sunrpc_cache_pipe_upcall(cd, h, svc_export_request);
349 }
350
351 static struct svc_export *svc_export_update(struct svc_export *new,
352                                             struct svc_export *old);
353 static struct svc_export *svc_export_lookup(struct svc_export *);
354
355 static int check_export(struct inode *inode, int *flags, unsigned char *uuid)
356 {
357
358         /*
359          * We currently export only dirs, regular files, and (for v4
360          * pseudoroot) symlinks.
361          */
362         if (!S_ISDIR(inode->i_mode) &&
363             !S_ISLNK(inode->i_mode) &&
364             !S_ISREG(inode->i_mode))
365                 return -ENOTDIR;
366
367         /*
368          * Mountd should never pass down a writeable V4ROOT export, but,
369          * just to make sure:
370          */
371         if (*flags & NFSEXP_V4ROOT)
372                 *flags |= NFSEXP_READONLY;
373
374         /* There are two requirements on a filesystem to be exportable.
375          * 1:  We must be able to identify the filesystem from a number.
376          *       either a device number (so FS_REQUIRES_DEV needed)
377          *       or an FSID number (so NFSEXP_FSID or ->uuid is needed).
378          * 2:  We must be able to find an inode from a filehandle.
379          *       This means that s_export_op must be set.
380          */
381         if (!(inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) &&
382             !(*flags & NFSEXP_FSID) &&
383             uuid == NULL) {
384                 dprintk("exp_export: export of non-dev fs without fsid\n");
385                 return -EINVAL;
386         }
387
388         if (!inode->i_sb->s_export_op ||
389             !inode->i_sb->s_export_op->fh_to_dentry) {
390                 dprintk("exp_export: export of invalid fs type.\n");
391                 return -EINVAL;
392         }
393
394         return 0;
395
396 }
397
398 #ifdef CONFIG_NFSD_V4
399
400 static int
401 fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc)
402 {
403         int len;
404         int migrated, i, err;
405
406         /* listsize */
407         err = get_int(mesg, &fsloc->locations_count);
408         if (err)
409                 return err;
410         if (fsloc->locations_count > MAX_FS_LOCATIONS)
411                 return -EINVAL;
412         if (fsloc->locations_count == 0)
413                 return 0;
414
415         fsloc->locations = kzalloc(fsloc->locations_count
416                         * sizeof(struct nfsd4_fs_location), GFP_KERNEL);
417         if (!fsloc->locations)
418                 return -ENOMEM;
419         for (i=0; i < fsloc->locations_count; i++) {
420                 /* colon separated host list */
421                 err = -EINVAL;
422                 len = qword_get(mesg, buf, PAGE_SIZE);
423                 if (len <= 0)
424                         goto out_free_all;
425                 err = -ENOMEM;
426                 fsloc->locations[i].hosts = kstrdup(buf, GFP_KERNEL);
427                 if (!fsloc->locations[i].hosts)
428                         goto out_free_all;
429                 err = -EINVAL;
430                 /* slash separated path component list */
431                 len = qword_get(mesg, buf, PAGE_SIZE);
432                 if (len <= 0)
433                         goto out_free_all;
434                 err = -ENOMEM;
435                 fsloc->locations[i].path = kstrdup(buf, GFP_KERNEL);
436                 if (!fsloc->locations[i].path)
437                         goto out_free_all;
438         }
439         /* migrated */
440         err = get_int(mesg, &migrated);
441         if (err)
442                 goto out_free_all;
443         err = -EINVAL;
444         if (migrated < 0 || migrated > 1)
445                 goto out_free_all;
446         fsloc->migrated = migrated;
447         return 0;
448 out_free_all:
449         nfsd4_fslocs_free(fsloc);
450         return err;
451 }
452
453 static int secinfo_parse(char **mesg, char *buf, struct svc_export *exp)
454 {
455         int listsize, err;
456         struct exp_flavor_info *f;
457
458         err = get_int(mesg, &listsize);
459         if (err)
460                 return err;
461         if (listsize < 0 || listsize > MAX_SECINFO_LIST)
462                 return -EINVAL;
463
464         for (f = exp->ex_flavors; f < exp->ex_flavors + listsize; f++) {
465                 err = get_int(mesg, &f->pseudoflavor);
466                 if (err)
467                         return err;
468                 /*
469                  * XXX: It would be nice to also check whether this
470                  * pseudoflavor is supported, so we can discover the
471                  * problem at export time instead of when a client fails
472                  * to authenticate.
473                  */
474                 err = get_int(mesg, &f->flags);
475                 if (err)
476                         return err;
477                 /* Only some flags are allowed to differ between flavors: */
478                 if (~NFSEXP_SECINFO_FLAGS & (f->flags ^ exp->ex_flags))
479                         return -EINVAL;
480         }
481         exp->ex_nflavors = listsize;
482         return 0;
483 }
484
485 #else /* CONFIG_NFSD_V4 */
486 static inline int
487 fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc){return 0;}
488 static inline int
489 secinfo_parse(char **mesg, char *buf, struct svc_export *exp) { return 0; }
490 #endif
491
492 static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
493 {
494         /* client path expiry [flags anonuid anongid fsid] */
495         char *buf;
496         int len;
497         int err;
498         struct auth_domain *dom = NULL;
499         struct svc_export exp = {}, *expp;
500         int an_int;
501
502         if (mesg[mlen-1] != '\n')
503                 return -EINVAL;
504         mesg[mlen-1] = 0;
505
506         buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
507         if (!buf)
508                 return -ENOMEM;
509
510         /* client */
511         err = -EINVAL;
512         len = qword_get(&mesg, buf, PAGE_SIZE);
513         if (len <= 0)
514                 goto out;
515
516         err = -ENOENT;
517         dom = auth_domain_find(buf);
518         if (!dom)
519                 goto out;
520
521         /* path */
522         err = -EINVAL;
523         if ((len = qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
524                 goto out1;
525
526         err = kern_path(buf, 0, &exp.ex_path);
527         if (err)
528                 goto out1;
529
530         exp.ex_client = dom;
531
532         err = -ENOMEM;
533         exp.ex_pathname = kstrdup(buf, GFP_KERNEL);
534         if (!exp.ex_pathname)
535                 goto out2;
536
537         /* expiry */
538         err = -EINVAL;
539         exp.h.expiry_time = get_expiry(&mesg);
540         if (exp.h.expiry_time == 0)
541                 goto out3;
542
543         /* flags */
544         err = get_int(&mesg, &an_int);
545         if (err == -ENOENT) {
546                 err = 0;
547                 set_bit(CACHE_NEGATIVE, &exp.h.flags);
548         } else {
549                 if (err || an_int < 0)
550                         goto out3;
551                 exp.ex_flags= an_int;
552         
553                 /* anon uid */
554                 err = get_int(&mesg, &an_int);
555                 if (err)
556                         goto out3;
557                 exp.ex_anon_uid= an_int;
558
559                 /* anon gid */
560                 err = get_int(&mesg, &an_int);
561                 if (err)
562                         goto out3;
563                 exp.ex_anon_gid= an_int;
564
565                 /* fsid */
566                 err = get_int(&mesg, &an_int);
567                 if (err)
568                         goto out3;
569                 exp.ex_fsid = an_int;
570
571                 while ((len = qword_get(&mesg, buf, PAGE_SIZE)) > 0) {
572                         if (strcmp(buf, "fsloc") == 0)
573                                 err = fsloc_parse(&mesg, buf, &exp.ex_fslocs);
574                         else if (strcmp(buf, "uuid") == 0) {
575                                 /* expect a 16 byte uuid encoded as \xXXXX... */
576                                 len = qword_get(&mesg, buf, PAGE_SIZE);
577                                 if (len != 16)
578                                         err  = -EINVAL;
579                                 else {
580                                         exp.ex_uuid =
581                                                 kmemdup(buf, 16, GFP_KERNEL);
582                                         if (exp.ex_uuid == NULL)
583                                                 err = -ENOMEM;
584                                 }
585                         } else if (strcmp(buf, "secinfo") == 0)
586                                 err = secinfo_parse(&mesg, buf, &exp);
587                         else
588                                 /* quietly ignore unknown words and anything
589                                  * following. Newer user-space can try to set
590                                  * new values, then see what the result was.
591                                  */
592                                 break;
593                         if (err)
594                                 goto out4;
595                 }
596
597                 err = check_export(exp.ex_path.dentry->d_inode, &exp.ex_flags,
598                                    exp.ex_uuid);
599                 if (err)
600                         goto out4;
601         }
602
603         expp = svc_export_lookup(&exp);
604         if (expp)
605                 expp = svc_export_update(&exp, expp);
606         else
607                 err = -ENOMEM;
608         cache_flush();
609         if (expp == NULL)
610                 err = -ENOMEM;
611         else
612                 exp_put(expp);
613 out4:
614         nfsd4_fslocs_free(&exp.ex_fslocs);
615         kfree(exp.ex_uuid);
616 out3:
617         kfree(exp.ex_pathname);
618 out2:
619         path_put(&exp.ex_path);
620 out1:
621         auth_domain_put(dom);
622 out:
623         kfree(buf);
624         return err;
625 }
626
627 static void exp_flags(struct seq_file *m, int flag, int fsid,
628                 uid_t anonu, uid_t anong, struct nfsd4_fs_locations *fslocs);
629 static void show_secinfo(struct seq_file *m, struct svc_export *exp);
630
631 static int svc_export_show(struct seq_file *m,
632                            struct cache_detail *cd,
633                            struct cache_head *h)
634 {
635         struct svc_export *exp ;
636
637         if (h ==NULL) {
638                 seq_puts(m, "#path domain(flags)\n");
639                 return 0;
640         }
641         exp = container_of(h, struct svc_export, h);
642         seq_path(m, &exp->ex_path, " \t\n\\");
643         seq_putc(m, '\t');
644         seq_escape(m, exp->ex_client->name, " \t\n\\");
645         seq_putc(m, '(');
646         if (test_bit(CACHE_VALID, &h->flags) && 
647             !test_bit(CACHE_NEGATIVE, &h->flags)) {
648                 exp_flags(m, exp->ex_flags, exp->ex_fsid,
649                           exp->ex_anon_uid, exp->ex_anon_gid, &exp->ex_fslocs);
650                 if (exp->ex_uuid) {
651                         int i;
652                         seq_puts(m, ",uuid=");
653                         for (i=0; i<16; i++) {
654                                 if ((i&3) == 0 && i)
655                                         seq_putc(m, ':');
656                                 seq_printf(m, "%02x", exp->ex_uuid[i]);
657                         }
658                 }
659                 show_secinfo(m, exp);
660         }
661         seq_puts(m, ")\n");
662         return 0;
663 }
664 static int svc_export_match(struct cache_head *a, struct cache_head *b)
665 {
666         struct svc_export *orig = container_of(a, struct svc_export, h);
667         struct svc_export *new = container_of(b, struct svc_export, h);
668         return orig->ex_client == new->ex_client &&
669                 orig->ex_path.dentry == new->ex_path.dentry &&
670                 orig->ex_path.mnt == new->ex_path.mnt;
671 }
672
673 static void svc_export_init(struct cache_head *cnew, struct cache_head *citem)
674 {
675         struct svc_export *new = container_of(cnew, struct svc_export, h);
676         struct svc_export *item = container_of(citem, struct svc_export, h);
677
678         kref_get(&item->ex_client->ref);
679         new->ex_client = item->ex_client;
680         new->ex_path.dentry = dget(item->ex_path.dentry);
681         new->ex_path.mnt = mntget(item->ex_path.mnt);
682         new->ex_pathname = NULL;
683         new->ex_fslocs.locations = NULL;
684         new->ex_fslocs.locations_count = 0;
685         new->ex_fslocs.migrated = 0;
686 }
687
688 static void export_update(struct cache_head *cnew, struct cache_head *citem)
689 {
690         struct svc_export *new = container_of(cnew, struct svc_export, h);
691         struct svc_export *item = container_of(citem, struct svc_export, h);
692         int i;
693
694         new->ex_flags = item->ex_flags;
695         new->ex_anon_uid = item->ex_anon_uid;
696         new->ex_anon_gid = item->ex_anon_gid;
697         new->ex_fsid = item->ex_fsid;
698         new->ex_uuid = item->ex_uuid;
699         item->ex_uuid = NULL;
700         new->ex_pathname = item->ex_pathname;
701         item->ex_pathname = NULL;
702         new->ex_fslocs.locations = item->ex_fslocs.locations;
703         item->ex_fslocs.locations = NULL;
704         new->ex_fslocs.locations_count = item->ex_fslocs.locations_count;
705         item->ex_fslocs.locations_count = 0;
706         new->ex_fslocs.migrated = item->ex_fslocs.migrated;
707         item->ex_fslocs.migrated = 0;
708         new->ex_nflavors = item->ex_nflavors;
709         for (i = 0; i < MAX_SECINFO_LIST; i++) {
710                 new->ex_flavors[i] = item->ex_flavors[i];
711         }
712 }
713
714 static struct cache_head *svc_export_alloc(void)
715 {
716         struct svc_export *i = kmalloc(sizeof(*i), GFP_KERNEL);
717         if (i)
718                 return &i->h;
719         else
720                 return NULL;
721 }
722
723 struct cache_detail svc_export_cache = {
724         .owner          = THIS_MODULE,
725         .hash_size      = EXPORT_HASHMAX,
726         .hash_table     = export_table,
727         .name           = "nfsd.export",
728         .cache_put      = svc_export_put,
729         .cache_upcall   = svc_export_upcall,
730         .cache_parse    = svc_export_parse,
731         .cache_show     = svc_export_show,
732         .match          = svc_export_match,
733         .init           = svc_export_init,
734         .update         = export_update,
735         .alloc          = svc_export_alloc,
736 };
737
738 static int
739 svc_export_hash(struct svc_export *exp)
740 {
741         int hash;
742
743         hash = hash_ptr(exp->ex_client, EXPORT_HASHBITS);
744         hash ^= hash_ptr(exp->ex_path.dentry, EXPORT_HASHBITS);
745         hash ^= hash_ptr(exp->ex_path.mnt, EXPORT_HASHBITS);
746         return hash;
747 }
748
749 static struct svc_export *
750 svc_export_lookup(struct svc_export *exp)
751 {
752         struct cache_head *ch;
753         int hash = svc_export_hash(exp);
754
755         ch = sunrpc_cache_lookup(&svc_export_cache, &exp->h,
756                                  hash);
757         if (ch)
758                 return container_of(ch, struct svc_export, h);
759         else
760                 return NULL;
761 }
762
763 static struct svc_export *
764 svc_export_update(struct svc_export *new, struct svc_export *old)
765 {
766         struct cache_head *ch;
767         int hash = svc_export_hash(old);
768
769         ch = sunrpc_cache_update(&svc_export_cache, &new->h,
770                                  &old->h,
771                                  hash);
772         if (ch)
773                 return container_of(ch, struct svc_export, h);
774         else
775                 return NULL;
776 }
777
778
779 static struct svc_expkey *
780 exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp)
781 {
782         struct svc_expkey key, *ek;
783         int err;
784         
785         if (!clp)
786                 return ERR_PTR(-ENOENT);
787
788         key.ek_client = clp;
789         key.ek_fsidtype = fsid_type;
790         memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
791
792         ek = svc_expkey_lookup(&key);
793         if (ek == NULL)
794                 return ERR_PTR(-ENOMEM);
795         err = cache_check(&svc_expkey_cache, &ek->h, reqp);
796         if (err)
797                 return ERR_PTR(err);
798         return ek;
799 }
800
801 #ifdef CONFIG_NFSD_DEPRECATED
802 static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv,
803                        struct svc_export *exp)
804 {
805         struct svc_expkey key, *ek;
806
807         key.ek_client = clp;
808         key.ek_fsidtype = fsid_type;
809         memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
810         key.ek_path = exp->ex_path;
811         key.h.expiry_time = NEVER;
812         key.h.flags = 0;
813
814         ek = svc_expkey_lookup(&key);
815         if (ek)
816                 ek = svc_expkey_update(&key,ek);
817         if (ek) {
818                 cache_put(&ek->h, &svc_expkey_cache);
819                 return 0;
820         }
821         return -ENOMEM;
822 }
823
824 /*
825  * Find the client's export entry matching xdev/xino.
826  */
827 static inline struct svc_expkey *
828 exp_get_key(svc_client *clp, dev_t dev, ino_t ino)
829 {
830         u32 fsidv[3];
831         
832         if (old_valid_dev(dev)) {
833                 mk_fsid(FSID_DEV, fsidv, dev, ino, 0, NULL);
834                 return exp_find_key(clp, FSID_DEV, fsidv, NULL);
835         }
836         mk_fsid(FSID_ENCODE_DEV, fsidv, dev, ino, 0, NULL);
837         return exp_find_key(clp, FSID_ENCODE_DEV, fsidv, NULL);
838 }
839
840 /*
841  * Find the client's export entry matching fsid
842  */
843 static inline struct svc_expkey *
844 exp_get_fsid_key(svc_client *clp, int fsid)
845 {
846         u32 fsidv[2];
847
848         mk_fsid(FSID_NUM, fsidv, 0, 0, fsid, NULL);
849
850         return exp_find_key(clp, FSID_NUM, fsidv, NULL);
851 }
852 #endif
853
854 static svc_export *exp_get_by_name(svc_client *clp, const struct path *path,
855                                      struct cache_req *reqp)
856 {
857         struct svc_export *exp, key;
858         int err;
859
860         if (!clp)
861                 return ERR_PTR(-ENOENT);
862
863         key.ex_client = clp;
864         key.ex_path = *path;
865
866         exp = svc_export_lookup(&key);
867         if (exp == NULL)
868                 return ERR_PTR(-ENOMEM);
869         err = cache_check(&svc_export_cache, &exp->h, reqp);
870         if (err)
871                 return ERR_PTR(err);
872         return exp;
873 }
874
875 /*
876  * Find the export entry for a given dentry.
877  */
878 static struct svc_export *exp_parent(svc_client *clp, struct path *path)
879 {
880         struct dentry *saved = dget(path->dentry);
881         svc_export *exp = exp_get_by_name(clp, path, NULL);
882
883         while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(path->dentry)) {
884                 struct dentry *parent = dget_parent(path->dentry);
885                 dput(path->dentry);
886                 path->dentry = parent;
887                 exp = exp_get_by_name(clp, path, NULL);
888         }
889         dput(path->dentry);
890         path->dentry = saved;
891         return exp;
892 }
893
894 #ifdef CONFIG_NFSD_DEPRECATED
895 /*
896  * Hashtable locking. Write locks are placed only by user processes
897  * wanting to modify export information.
898  * Write locking only done in this file.  Read locking
899  * needed externally.
900  */
901
902 static DECLARE_RWSEM(hash_sem);
903
904 void
905 exp_readlock(void)
906 {
907         down_read(&hash_sem);
908 }
909
910 static inline void
911 exp_writelock(void)
912 {
913         down_write(&hash_sem);
914 }
915
916 void
917 exp_readunlock(void)
918 {
919         up_read(&hash_sem);
920 }
921
922 static inline void
923 exp_writeunlock(void)
924 {
925         up_write(&hash_sem);
926 }
927 #else
928
929 /* hash_sem not needed once deprecated interface is removed */
930 void exp_readlock(void) {}
931 static inline void exp_writelock(void){}
932 void exp_readunlock(void) {}
933 static inline void exp_writeunlock(void){}
934
935 #endif
936
937 #ifdef CONFIG_NFSD_DEPRECATED
938 static void             exp_do_unexport(svc_export *unexp);
939 static int              exp_verify_string(char *cp, int max);
940
941 static void exp_fsid_unhash(struct svc_export *exp)
942 {
943         struct svc_expkey *ek;
944
945         if ((exp->ex_flags & NFSEXP_FSID) == 0)
946                 return;
947
948         ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid);
949         if (!IS_ERR(ek)) {
950                 sunrpc_invalidate(&ek->h, &svc_expkey_cache);
951                 cache_put(&ek->h, &svc_expkey_cache);
952         }
953 }
954
955 static int exp_fsid_hash(svc_client *clp, struct svc_export *exp)
956 {
957         u32 fsid[2];
958  
959         if ((exp->ex_flags & NFSEXP_FSID) == 0)
960                 return 0;
961
962         mk_fsid(FSID_NUM, fsid, 0, 0, exp->ex_fsid, NULL);
963         return exp_set_key(clp, FSID_NUM, fsid, exp);
964 }
965
966 static int exp_hash(struct auth_domain *clp, struct svc_export *exp)
967 {
968         u32 fsid[2];
969         struct inode *inode = exp->ex_path.dentry->d_inode;
970         dev_t dev = inode->i_sb->s_dev;
971
972         if (old_valid_dev(dev)) {
973                 mk_fsid(FSID_DEV, fsid, dev, inode->i_ino, 0, NULL);
974                 return exp_set_key(clp, FSID_DEV, fsid, exp);
975         }
976         mk_fsid(FSID_ENCODE_DEV, fsid, dev, inode->i_ino, 0, NULL);
977         return exp_set_key(clp, FSID_ENCODE_DEV, fsid, exp);
978 }
979
980 static void exp_unhash(struct svc_export *exp)
981 {
982         struct svc_expkey *ek;
983         struct inode *inode = exp->ex_path.dentry->d_inode;
984
985         ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino);
986         if (!IS_ERR(ek)) {
987                 sunrpc_invalidate(&ek->h, &svc_expkey_cache);
988                 cache_put(&ek->h, &svc_expkey_cache);
989         }
990 }
991         
992 /*
993  * Export a file system.
994  */
995 int
996 exp_export(struct nfsctl_export *nxp)
997 {
998         svc_client      *clp;
999         struct svc_export       *exp = NULL;
1000         struct svc_export       new;
1001         struct svc_expkey       *fsid_key = NULL;
1002         struct path path;
1003         int             err;
1004
1005         /* Consistency check */
1006         err = -EINVAL;
1007         if (!exp_verify_string(nxp->ex_path, NFS_MAXPATHLEN) ||
1008             !exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX))
1009                 goto out;
1010
1011         dprintk("exp_export called for %s:%s (%x/%ld fl %x).\n",
1012                         nxp->ex_client, nxp->ex_path,
1013                         (unsigned)nxp->ex_dev, (long)nxp->ex_ino,
1014                         nxp->ex_flags);
1015
1016         /* Try to lock the export table for update */
1017         exp_writelock();
1018
1019         /* Look up client info */
1020         if (!(clp = auth_domain_find(nxp->ex_client)))
1021                 goto out_unlock;
1022
1023
1024         /* Look up the dentry */
1025         err = kern_path(nxp->ex_path, 0, &path);
1026         if (err)
1027                 goto out_put_clp;
1028         err = -EINVAL;
1029
1030         exp = exp_get_by_name(clp, &path, NULL);
1031
1032         memset(&new, 0, sizeof(new));
1033
1034         /* must make sure there won't be an ex_fsid clash */
1035         if ((nxp->ex_flags & NFSEXP_FSID) &&
1036             (!IS_ERR(fsid_key = exp_get_fsid_key(clp, nxp->ex_dev))) &&
1037             fsid_key->ek_path.mnt &&
1038             (fsid_key->ek_path.mnt != path.mnt ||
1039              fsid_key->ek_path.dentry != path.dentry))
1040                 goto finish;
1041
1042         if (!IS_ERR(exp)) {
1043                 /* just a flags/id/fsid update */
1044
1045                 exp_fsid_unhash(exp);
1046                 exp->ex_flags    = nxp->ex_flags;
1047                 exp->ex_anon_uid = nxp->ex_anon_uid;
1048                 exp->ex_anon_gid = nxp->ex_anon_gid;
1049                 exp->ex_fsid     = nxp->ex_dev;
1050
1051                 err = exp_fsid_hash(clp, exp);
1052                 goto finish;
1053         }
1054
1055         err = check_export(path.dentry->d_inode, &nxp->ex_flags, NULL);
1056         if (err) goto finish;
1057
1058         err = -ENOMEM;
1059
1060         dprintk("nfsd: creating export entry %p for client %p\n", exp, clp);
1061
1062         new.h.expiry_time = NEVER;
1063         new.h.flags = 0;
1064         new.ex_pathname = kstrdup(nxp->ex_path, GFP_KERNEL);
1065         if (!new.ex_pathname)
1066                 goto finish;
1067         new.ex_client = clp;
1068         new.ex_path = path;
1069         new.ex_flags = nxp->ex_flags;
1070         new.ex_anon_uid = nxp->ex_anon_uid;
1071         new.ex_anon_gid = nxp->ex_anon_gid;
1072         new.ex_fsid = nxp->ex_dev;
1073
1074         exp = svc_export_lookup(&new);
1075         if (exp)
1076                 exp = svc_export_update(&new, exp);
1077
1078         if (!exp)
1079                 goto finish;
1080
1081         if (exp_hash(clp, exp) ||
1082             exp_fsid_hash(clp, exp)) {
1083                 /* failed to create at least one index */
1084                 exp_do_unexport(exp);
1085                 cache_flush();
1086         } else
1087                 err = 0;
1088 finish:
1089         kfree(new.ex_pathname);
1090         if (!IS_ERR_OR_NULL(exp))
1091                 exp_put(exp);
1092         if (!IS_ERR_OR_NULL(fsid_key))
1093                 cache_put(&fsid_key->h, &svc_expkey_cache);
1094         path_put(&path);
1095 out_put_clp:
1096         auth_domain_put(clp);
1097 out_unlock:
1098         exp_writeunlock();
1099 out:
1100         return err;
1101 }
1102
1103 /*
1104  * Unexport a file system. The export entry has already
1105  * been removed from the client's list of exported fs's.
1106  */
1107 static void
1108 exp_do_unexport(svc_export *unexp)
1109 {
1110         sunrpc_invalidate(&unexp->h, &svc_export_cache);
1111         exp_unhash(unexp);
1112         exp_fsid_unhash(unexp);
1113 }
1114
1115
1116 /*
1117  * unexport syscall.
1118  */
1119 int
1120 exp_unexport(struct nfsctl_export *nxp)
1121 {
1122         struct auth_domain *dom;
1123         svc_export *exp;
1124         struct path path;
1125         int             err;
1126
1127         /* Consistency check */
1128         if (!exp_verify_string(nxp->ex_path, NFS_MAXPATHLEN) ||
1129             !exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX))
1130                 return -EINVAL;
1131
1132         exp_writelock();
1133
1134         err = -EINVAL;
1135         dom = auth_domain_find(nxp->ex_client);
1136         if (!dom) {
1137                 dprintk("nfsd: unexport couldn't find %s\n", nxp->ex_client);
1138                 goto out_unlock;
1139         }
1140
1141         err = kern_path(nxp->ex_path, 0, &path);
1142         if (err)
1143                 goto out_domain;
1144
1145         err = -EINVAL;
1146         exp = exp_get_by_name(dom, &path, NULL);
1147         path_put(&path);
1148         if (IS_ERR(exp))
1149                 goto out_domain;
1150
1151         exp_do_unexport(exp);
1152         exp_put(exp);
1153         err = 0;
1154
1155 out_domain:
1156         auth_domain_put(dom);
1157         cache_flush();
1158 out_unlock:
1159         exp_writeunlock();
1160         return err;
1161 }
1162 #endif /* CONFIG_NFSD_DEPRECATED */
1163
1164 /*
1165  * Obtain the root fh on behalf of a client.
1166  * This could be done in user space, but I feel that it adds some safety
1167  * since its harder to fool a kernel module than a user space program.
1168  */
1169 int
1170 exp_rootfh(svc_client *clp, char *name, struct knfsd_fh *f, int maxsize)
1171 {
1172         struct svc_export       *exp;
1173         struct path             path;
1174         struct inode            *inode;
1175         struct svc_fh           fh;
1176         int                     err;
1177
1178         err = -EPERM;
1179         /* NB: we probably ought to check that it's NUL-terminated */
1180         if (kern_path(name, 0, &path)) {
1181                 printk("nfsd: exp_rootfh path not found %s", name);
1182                 return err;
1183         }
1184         inode = path.dentry->d_inode;
1185
1186         dprintk("nfsd: exp_rootfh(%s [%p] %s:%s/%ld)\n",
1187                  name, path.dentry, clp->name,
1188                  inode->i_sb->s_id, inode->i_ino);
1189         exp = exp_parent(clp, &path);
1190         if (IS_ERR(exp)) {
1191                 err = PTR_ERR(exp);
1192                 goto out;
1193         }
1194
1195         /*
1196          * fh must be initialized before calling fh_compose
1197          */
1198         fh_init(&fh, maxsize);
1199         if (fh_compose(&fh, exp, path.dentry, NULL))
1200                 err = -EINVAL;
1201         else
1202                 err = 0;
1203         memcpy(f, &fh.fh_handle, sizeof(struct knfsd_fh));
1204         fh_put(&fh);
1205         exp_put(exp);
1206 out:
1207         path_put(&path);
1208         return err;
1209 }
1210
1211 static struct svc_export *exp_find(struct auth_domain *clp, int fsid_type,
1212                                    u32 *fsidv, struct cache_req *reqp)
1213 {
1214         struct svc_export *exp;
1215         struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp);
1216         if (IS_ERR(ek))
1217                 return ERR_CAST(ek);
1218
1219         exp = exp_get_by_name(clp, &ek->ek_path, reqp);
1220         cache_put(&ek->h, &svc_expkey_cache);
1221
1222         if (IS_ERR(exp))
1223                 return ERR_CAST(exp);
1224         return exp;
1225 }
1226
1227 __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)
1228 {
1229         struct exp_flavor_info *f;
1230         struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
1231
1232         /* legacy gss-only clients are always OK: */
1233         if (exp->ex_client == rqstp->rq_gssclient)
1234                 return 0;
1235         /* ip-address based client; check sec= export option: */
1236         for (f = exp->ex_flavors; f < end; f++) {
1237                 if (f->pseudoflavor == rqstp->rq_flavor)
1238                         return 0;
1239         }
1240         /* defaults in absence of sec= options: */
1241         if (exp->ex_nflavors == 0) {
1242                 if (rqstp->rq_flavor == RPC_AUTH_NULL ||
1243                     rqstp->rq_flavor == RPC_AUTH_UNIX)
1244                         return 0;
1245         }
1246         return nfserr_wrongsec;
1247 }
1248
1249 /*
1250  * Uses rq_client and rq_gssclient to find an export; uses rq_client (an
1251  * auth_unix client) if it's available and has secinfo information;
1252  * otherwise, will try to use rq_gssclient.
1253  *
1254  * Called from functions that handle requests; functions that do work on
1255  * behalf of mountd are passed a single client name to use, and should
1256  * use exp_get_by_name() or exp_find().
1257  */
1258 struct svc_export *
1259 rqst_exp_get_by_name(struct svc_rqst *rqstp, struct path *path)
1260 {
1261         struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT);
1262
1263         if (rqstp->rq_client == NULL)
1264                 goto gss;
1265
1266         /* First try the auth_unix client: */
1267         exp = exp_get_by_name(rqstp->rq_client, path, &rqstp->rq_chandle);
1268         if (PTR_ERR(exp) == -ENOENT)
1269                 goto gss;
1270         if (IS_ERR(exp))
1271                 return exp;
1272         /* If it has secinfo, assume there are no gss/... clients */
1273         if (exp->ex_nflavors > 0)
1274                 return exp;
1275 gss:
1276         /* Otherwise, try falling back on gss client */
1277         if (rqstp->rq_gssclient == NULL)
1278                 return exp;
1279         gssexp = exp_get_by_name(rqstp->rq_gssclient, path, &rqstp->rq_chandle);
1280         if (PTR_ERR(gssexp) == -ENOENT)
1281                 return exp;
1282         if (!IS_ERR(exp))
1283                 exp_put(exp);
1284         return gssexp;
1285 }
1286
1287 struct svc_export *
1288 rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv)
1289 {
1290         struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT);
1291
1292         if (rqstp->rq_client == NULL)
1293                 goto gss;
1294
1295         /* First try the auth_unix client: */
1296         exp = exp_find(rqstp->rq_client, fsid_type, fsidv, &rqstp->rq_chandle);
1297         if (PTR_ERR(exp) == -ENOENT)
1298                 goto gss;
1299         if (IS_ERR(exp))
1300                 return exp;
1301         /* If it has secinfo, assume there are no gss/... clients */
1302         if (exp->ex_nflavors > 0)
1303                 return exp;
1304 gss:
1305         /* Otherwise, try falling back on gss client */
1306         if (rqstp->rq_gssclient == NULL)
1307                 return exp;
1308         gssexp = exp_find(rqstp->rq_gssclient, fsid_type, fsidv,
1309                                                 &rqstp->rq_chandle);
1310         if (PTR_ERR(gssexp) == -ENOENT)
1311                 return exp;
1312         if (!IS_ERR(exp))
1313                 exp_put(exp);
1314         return gssexp;
1315 }
1316
1317 struct svc_export *
1318 rqst_exp_parent(struct svc_rqst *rqstp, struct path *path)
1319 {
1320         struct dentry *saved = dget(path->dentry);
1321         struct svc_export *exp = rqst_exp_get_by_name(rqstp, path);
1322
1323         while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(path->dentry)) {
1324                 struct dentry *parent = dget_parent(path->dentry);
1325                 dput(path->dentry);
1326                 path->dentry = parent;
1327                 exp = rqst_exp_get_by_name(rqstp, path);
1328         }
1329         dput(path->dentry);
1330         path->dentry = saved;
1331         return exp;
1332 }
1333
1334 static struct svc_export *find_fsidzero_export(struct svc_rqst *rqstp)
1335 {
1336         u32 fsidv[2];
1337
1338         mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL);
1339
1340         return rqst_exp_find(rqstp, FSID_NUM, fsidv);
1341 }
1342
1343 /*
1344  * Called when we need the filehandle for the root of the pseudofs,
1345  * for a given NFSv4 client.   The root is defined to be the
1346  * export point with fsid==0
1347  */
1348 __be32
1349 exp_pseudoroot(struct svc_rqst *rqstp, struct svc_fh *fhp)
1350 {
1351         struct svc_export *exp;
1352         __be32 rv;
1353
1354         exp = find_fsidzero_export(rqstp);
1355         if (IS_ERR(exp))
1356                 return nfserrno(PTR_ERR(exp));
1357         rv = fh_compose(fhp, exp, exp->ex_path.dentry, NULL);
1358         if (rv)
1359                 goto out;
1360         rv = check_nfsd_access(exp, rqstp);
1361         if (rv)
1362                 fh_put(fhp);
1363 out:
1364         exp_put(exp);
1365         return rv;
1366 }
1367
1368 /* Iterator */
1369
1370 static void *e_start(struct seq_file *m, loff_t *pos)
1371         __acquires(svc_export_cache.hash_lock)
1372 {
1373         loff_t n = *pos;
1374         unsigned hash, export;
1375         struct cache_head *ch;
1376         
1377         exp_readlock();
1378         read_lock(&svc_export_cache.hash_lock);
1379         if (!n--)
1380                 return SEQ_START_TOKEN;
1381         hash = n >> 32;
1382         export = n & ((1LL<<32) - 1);
1383
1384         
1385         for (ch=export_table[hash]; ch; ch=ch->next)
1386                 if (!export--)
1387                         return ch;
1388         n &= ~((1LL<<32) - 1);
1389         do {
1390                 hash++;
1391                 n += 1LL<<32;
1392         } while(hash < EXPORT_HASHMAX && export_table[hash]==NULL);
1393         if (hash >= EXPORT_HASHMAX)
1394                 return NULL;
1395         *pos = n+1;
1396         return export_table[hash];
1397 }
1398
1399 static void *e_next(struct seq_file *m, void *p, loff_t *pos)
1400 {
1401         struct cache_head *ch = p;
1402         int hash = (*pos >> 32);
1403
1404         if (p == SEQ_START_TOKEN)
1405                 hash = 0;
1406         else if (ch->next == NULL) {
1407                 hash++;
1408                 *pos += 1LL<<32;
1409         } else {
1410                 ++*pos;
1411                 return ch->next;
1412         }
1413         *pos &= ~((1LL<<32) - 1);
1414         while (hash < EXPORT_HASHMAX && export_table[hash] == NULL) {
1415                 hash++;
1416                 *pos += 1LL<<32;
1417         }
1418         if (hash >= EXPORT_HASHMAX)
1419                 return NULL;
1420         ++*pos;
1421         return export_table[hash];
1422 }
1423
1424 static void e_stop(struct seq_file *m, void *p)
1425         __releases(svc_export_cache.hash_lock)
1426 {
1427         read_unlock(&svc_export_cache.hash_lock);
1428         exp_readunlock();
1429 }
1430
1431 static struct flags {
1432         int flag;
1433         char *name[2];
1434 } expflags[] = {
1435         { NFSEXP_READONLY, {"ro", "rw"}},
1436         { NFSEXP_INSECURE_PORT, {"insecure", ""}},
1437         { NFSEXP_ROOTSQUASH, {"root_squash", "no_root_squash"}},
1438         { NFSEXP_ALLSQUASH, {"all_squash", ""}},
1439         { NFSEXP_ASYNC, {"async", "sync"}},
1440         { NFSEXP_GATHERED_WRITES, {"wdelay", "no_wdelay"}},
1441         { NFSEXP_NOHIDE, {"nohide", ""}},
1442         { NFSEXP_CROSSMOUNT, {"crossmnt", ""}},
1443         { NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
1444         { NFSEXP_NOAUTHNLM, {"insecure_locks", ""}},
1445         { NFSEXP_V4ROOT, {"v4root", ""}},
1446         { 0, {"", ""}}
1447 };
1448
1449 static void show_expflags(struct seq_file *m, int flags, int mask)
1450 {
1451         struct flags *flg;
1452         int state, first = 0;
1453
1454         for (flg = expflags; flg->flag; flg++) {
1455                 if (flg->flag & ~mask)
1456                         continue;
1457                 state = (flg->flag & flags) ? 0 : 1;
1458                 if (*flg->name[state])
1459                         seq_printf(m, "%s%s", first++?",":"", flg->name[state]);
1460         }
1461 }
1462
1463 static void show_secinfo_flags(struct seq_file *m, int flags)
1464 {
1465         seq_printf(m, ",");
1466         show_expflags(m, flags, NFSEXP_SECINFO_FLAGS);
1467 }
1468
1469 static bool secinfo_flags_equal(int f, int g)
1470 {
1471         f &= NFSEXP_SECINFO_FLAGS;
1472         g &= NFSEXP_SECINFO_FLAGS;
1473         return f == g;
1474 }
1475
1476 static int show_secinfo_run(struct seq_file *m, struct exp_flavor_info **fp, struct exp_flavor_info *end)
1477 {
1478         int flags;
1479
1480         flags = (*fp)->flags;
1481         seq_printf(m, ",sec=%d", (*fp)->pseudoflavor);
1482         (*fp)++;
1483         while (*fp != end && secinfo_flags_equal(flags, (*fp)->flags)) {
1484                 seq_printf(m, ":%d", (*fp)->pseudoflavor);
1485                 (*fp)++;
1486         }
1487         return flags;
1488 }
1489
1490 static void show_secinfo(struct seq_file *m, struct svc_export *exp)
1491 {
1492         struct exp_flavor_info *f;
1493         struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
1494         int flags;
1495
1496         if (exp->ex_nflavors == 0)
1497                 return;
1498         f = exp->ex_flavors;
1499         flags = show_secinfo_run(m, &f, end);
1500         if (!secinfo_flags_equal(flags, exp->ex_flags))
1501                 show_secinfo_flags(m, flags);
1502         while (f != end) {
1503                 flags = show_secinfo_run(m, &f, end);
1504                 show_secinfo_flags(m, flags);
1505         }
1506 }
1507
1508 static void exp_flags(struct seq_file *m, int flag, int fsid,
1509                 uid_t anonu, uid_t anong, struct nfsd4_fs_locations *fsloc)
1510 {
1511         show_expflags(m, flag, NFSEXP_ALLFLAGS);
1512         if (flag & NFSEXP_FSID)
1513                 seq_printf(m, ",fsid=%d", fsid);
1514         if (anonu != (uid_t)-2 && anonu != (0x10000-2))
1515                 seq_printf(m, ",anonuid=%u", anonu);
1516         if (anong != (gid_t)-2 && anong != (0x10000-2))
1517                 seq_printf(m, ",anongid=%u", anong);
1518         if (fsloc && fsloc->locations_count > 0) {
1519                 char *loctype = (fsloc->migrated) ? "refer" : "replicas";
1520                 int i;
1521
1522                 seq_printf(m, ",%s=", loctype);
1523                 seq_escape(m, fsloc->locations[0].path, ",;@ \t\n\\");
1524                 seq_putc(m, '@');
1525                 seq_escape(m, fsloc->locations[0].hosts, ",;@ \t\n\\");
1526                 for (i = 1; i < fsloc->locations_count; i++) {
1527                         seq_putc(m, ';');
1528                         seq_escape(m, fsloc->locations[i].path, ",;@ \t\n\\");
1529                         seq_putc(m, '@');
1530                         seq_escape(m, fsloc->locations[i].hosts, ",;@ \t\n\\");
1531                 }
1532         }
1533 }
1534
1535 static int e_show(struct seq_file *m, void *p)
1536 {
1537         struct cache_head *cp = p;
1538         struct svc_export *exp = container_of(cp, struct svc_export, h);
1539
1540         if (p == SEQ_START_TOKEN) {
1541                 seq_puts(m, "# Version 1.1\n");
1542                 seq_puts(m, "# Path Client(Flags) # IPs\n");
1543                 return 0;
1544         }
1545
1546         cache_get(&exp->h);
1547         if (cache_check(&svc_export_cache, &exp->h, NULL))
1548                 return 0;
1549         cache_put(&exp->h, &svc_export_cache);
1550         return svc_export_show(m, &svc_export_cache, cp);
1551 }
1552
1553 const struct seq_operations nfs_exports_op = {
1554         .start  = e_start,
1555         .next   = e_next,
1556         .stop   = e_stop,
1557         .show   = e_show,
1558 };
1559
1560 #ifdef CONFIG_NFSD_DEPRECATED
1561 /*
1562  * Add or modify a client.
1563  * Change requests may involve the list of host addresses. The list of
1564  * exports and possibly existing uid maps are left untouched.
1565  */
1566 int
1567 exp_addclient(struct nfsctl_client *ncp)
1568 {
1569         struct auth_domain      *dom;
1570         int                     i, err;
1571         struct in6_addr addr6;
1572
1573         /* First, consistency check. */
1574         err = -EINVAL;
1575         if (! exp_verify_string(ncp->cl_ident, NFSCLNT_IDMAX))
1576                 goto out;
1577         if (ncp->cl_naddr > NFSCLNT_ADDRMAX)
1578                 goto out;
1579
1580         /* Lock the hashtable */
1581         exp_writelock();
1582
1583         dom = unix_domain_find(ncp->cl_ident);
1584
1585         err = -ENOMEM;
1586         if (!dom)
1587                 goto out_unlock;
1588
1589         /* Insert client into hashtable. */
1590         for (i = 0; i < ncp->cl_naddr; i++) {
1591                 ipv6_addr_set_v4mapped(ncp->cl_addrlist[i].s_addr, &addr6);
1592                 auth_unix_add_addr(&init_net, &addr6, dom);
1593         }
1594         auth_unix_forget_old(dom);
1595         auth_domain_put(dom);
1596
1597         err = 0;
1598
1599 out_unlock:
1600         exp_writeunlock();
1601 out:
1602         return err;
1603 }
1604
1605 /*
1606  * Delete a client given an identifier.
1607  */
1608 int
1609 exp_delclient(struct nfsctl_client *ncp)
1610 {
1611         int             err;
1612         struct auth_domain *dom;
1613
1614         err = -EINVAL;
1615         if (!exp_verify_string(ncp->cl_ident, NFSCLNT_IDMAX))
1616                 goto out;
1617
1618         /* Lock the hashtable */
1619         exp_writelock();
1620
1621         dom = auth_domain_find(ncp->cl_ident);
1622         /* just make sure that no addresses work 
1623          * and that it will expire soon 
1624          */
1625         if (dom) {
1626                 err = auth_unix_forget_old(dom);
1627                 auth_domain_put(dom);
1628         }
1629
1630         exp_writeunlock();
1631 out:
1632         return err;
1633 }
1634
1635 /*
1636  * Verify that string is non-empty and does not exceed max length.
1637  */
1638 static int
1639 exp_verify_string(char *cp, int max)
1640 {
1641         int     i;
1642
1643         for (i = 0; i < max; i++)
1644                 if (!cp[i])
1645                         return i;
1646         cp[i] = 0;
1647         printk(KERN_NOTICE "nfsd: couldn't validate string %s\n", cp);
1648         return 0;
1649 }
1650 #endif /* CONFIG_NFSD_DEPRECATED */
1651
1652 /*
1653  * Initialize the exports module.
1654  */
1655 int
1656 nfsd_export_init(void)
1657 {
1658         int rv;
1659         dprintk("nfsd: initializing export module.\n");
1660
1661         rv = cache_register(&svc_export_cache);
1662         if (rv)
1663                 return rv;
1664         rv = cache_register(&svc_expkey_cache);
1665         if (rv)
1666                 cache_unregister(&svc_export_cache);
1667         return rv;
1668
1669 }
1670
1671 /*
1672  * Flush exports table - called when last nfsd thread is killed
1673  */
1674 void
1675 nfsd_export_flush(void)
1676 {
1677         exp_writelock();
1678         cache_purge(&svc_expkey_cache);
1679         cache_purge(&svc_export_cache);
1680         exp_writeunlock();
1681 }
1682
1683 /*
1684  * Shutdown the exports module.
1685  */
1686 void
1687 nfsd_export_shutdown(void)
1688 {
1689
1690         dprintk("nfsd: shutting down export module.\n");
1691
1692         exp_writelock();
1693
1694         cache_unregister(&svc_expkey_cache);
1695         cache_unregister(&svc_export_cache);
1696         svcauth_unix_purge();
1697
1698         exp_writeunlock();
1699         dprintk("nfsd: export shutdown complete.\n");
1700 }