[PATCH] knfsd: Use SEQ_START_TOKEN instead of hardcoded magic (void*)1
[linux-2.6.git] / fs / nfsd / export.c
1 #define MSNFS   /* HACK HACK */
2 /*
3  * linux/fs/nfsd/export.c
4  *
5  * NFS exporting and validation.
6  *
7  * We maintain a list of clients, each of which has a list of
8  * exports. To export an fs to a given client, you first have
9  * to create the client entry with NFSCTL_ADDCLIENT, which
10  * creates a client control block and adds it to the hash
11  * table. Then, you call NFSCTL_EXPORT for each fs.
12  *
13  *
14  * Copyright (C) 1995, 1996 Olaf Kirch, <okir@monad.swb.de>
15  */
16
17 #include <linux/unistd.h>
18 #include <linux/slab.h>
19 #include <linux/sched.h>
20 #include <linux/stat.h>
21 #include <linux/in.h>
22 #include <linux/seq_file.h>
23 #include <linux/syscalls.h>
24 #include <linux/rwsem.h>
25 #include <linux/dcache.h>
26 #include <linux/namei.h>
27 #include <linux/mount.h>
28 #include <linux/hash.h>
29 #include <linux/module.h>
30
31 #include <linux/sunrpc/svc.h>
32 #include <linux/nfsd/nfsd.h>
33 #include <linux/nfsd/nfsfh.h>
34 #include <linux/nfsd/syscall.h>
35 #include <linux/lockd/bind.h>
36
37 #define NFSDDBG_FACILITY        NFSDDBG_EXPORT
38 #define NFSD_PARANOIA 1
39
40 typedef struct auth_domain      svc_client;
41 typedef struct svc_export       svc_export;
42
43 static void             exp_do_unexport(svc_export *unexp);
44 static int              exp_verify_string(char *cp, int max);
45
46 /*
47  * We have two caches.
48  * One maps client+vfsmnt+dentry to export options - the export map
49  * The other maps client+filehandle-fragment to export options. - the expkey map
50  *
51  * The export options are actually stored in the first map, and the
52  * second map contains a reference to the entry in the first map.
53  */
54
55 #define EXPKEY_HASHBITS         8
56 #define EXPKEY_HASHMAX          (1 << EXPKEY_HASHBITS)
57 #define EXPKEY_HASHMASK         (EXPKEY_HASHMAX -1)
58 static struct cache_head *expkey_table[EXPKEY_HASHMAX];
59
60 static void expkey_put(struct kref *ref)
61 {
62         struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref);
63
64         if (test_bit(CACHE_VALID, &key->h.flags) &&
65             !test_bit(CACHE_NEGATIVE, &key->h.flags)) {
66                 dput(key->ek_dentry);
67                 mntput(key->ek_mnt);
68         }
69         auth_domain_put(key->ek_client);
70         kfree(key);
71 }
72
73 static void expkey_request(struct cache_detail *cd,
74                            struct cache_head *h,
75                            char **bpp, int *blen)
76 {
77         /* client fsidtype \xfsid */
78         struct svc_expkey *ek = container_of(h, struct svc_expkey, h);
79         char type[5];
80
81         qword_add(bpp, blen, ek->ek_client->name);
82         snprintf(type, 5, "%d", ek->ek_fsidtype);
83         qword_add(bpp, blen, type);
84         qword_addhex(bpp, blen, (char*)ek->ek_fsid, key_len(ek->ek_fsidtype));
85         (*bpp)[-1] = '\n';
86 }
87
88 static struct svc_expkey *svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old);
89 static struct svc_expkey *svc_expkey_lookup(struct svc_expkey *);
90 static struct cache_detail svc_expkey_cache;
91
92 static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
93 {
94         /* client fsidtype fsid [path] */
95         char *buf;
96         int len;
97         struct auth_domain *dom = NULL;
98         int err;
99         int fsidtype;
100         char *ep;
101         struct svc_expkey key;
102         struct svc_expkey *ek;
103
104         if (mesg[mlen-1] != '\n')
105                 return -EINVAL;
106         mesg[mlen-1] = 0;
107
108         buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
109         err = -ENOMEM;
110         if (!buf) goto out;
111
112         err = -EINVAL;
113         if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
114                 goto out;
115
116         err = -ENOENT;
117         dom = auth_domain_find(buf);
118         if (!dom)
119                 goto out;
120         dprintk("found domain %s\n", buf);
121
122         err = -EINVAL;
123         if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
124                 goto out;
125         fsidtype = simple_strtoul(buf, &ep, 10);
126         if (*ep)
127                 goto out;
128         dprintk("found fsidtype %d\n", fsidtype);
129         if (key_len(fsidtype)==0) /* invalid type */
130                 goto out;
131         if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
132                 goto out;
133         dprintk("found fsid length %d\n", len);
134         if (len != key_len(fsidtype))
135                 goto out;
136
137         /* OK, we seem to have a valid key */
138         key.h.flags = 0;
139         key.h.expiry_time = get_expiry(&mesg);
140         if (key.h.expiry_time == 0)
141                 goto out;
142
143         key.ek_client = dom;    
144         key.ek_fsidtype = fsidtype;
145         memcpy(key.ek_fsid, buf, len);
146
147         ek = svc_expkey_lookup(&key);
148         err = -ENOMEM;
149         if (!ek)
150                 goto out;
151
152         /* now we want a pathname, or empty meaning NEGATIVE  */
153         err = -EINVAL;
154         if ((len=qword_get(&mesg, buf, PAGE_SIZE)) < 0)
155                 goto out;
156         dprintk("Path seems to be <%s>\n", buf);
157         err = 0;
158         if (len == 0) {
159                 set_bit(CACHE_NEGATIVE, &key.h.flags);
160                 ek = svc_expkey_update(&key, ek);
161                 if (ek)
162                         cache_put(&ek->h, &svc_expkey_cache);
163                 else err = -ENOMEM;
164         } else {
165                 struct nameidata nd;
166                 err = path_lookup(buf, 0, &nd);
167                 if (err)
168                         goto out;
169
170                 dprintk("Found the path %s\n", buf);
171                 key.ek_mnt = nd.mnt;
172                 key.ek_dentry = nd.dentry;
173                 
174                 ek = svc_expkey_update(&key, ek);
175                 if (ek)
176                         cache_put(&ek->h, &svc_expkey_cache);
177                 else
178                         err = -ENOMEM;
179                 path_release(&nd);
180         }
181         cache_flush();
182  out:
183         if (dom)
184                 auth_domain_put(dom);
185         kfree(buf);
186         return err;
187 }
188
189 static int expkey_show(struct seq_file *m,
190                        struct cache_detail *cd,
191                        struct cache_head *h)
192 {
193         struct svc_expkey *ek ;
194
195         if (h ==NULL) {
196                 seq_puts(m, "#domain fsidtype fsid [path]\n");
197                 return 0;
198         }
199         ek = container_of(h, struct svc_expkey, h);
200         seq_printf(m, "%s %d 0x%08x", ek->ek_client->name,
201                    ek->ek_fsidtype, ek->ek_fsid[0]);
202         if (ek->ek_fsidtype != 1)
203                 seq_printf(m, "%08x", ek->ek_fsid[1]);
204         if (ek->ek_fsidtype == 2)
205                 seq_printf(m, "%08x", ek->ek_fsid[2]);
206         if (test_bit(CACHE_VALID, &h->flags) && 
207             !test_bit(CACHE_NEGATIVE, &h->flags)) {
208                 seq_printf(m, " ");
209                 seq_path(m, ek->ek_mnt, ek->ek_dentry, "\\ \t\n");
210         }
211         seq_printf(m, "\n");
212         return 0;
213 }
214
215 static inline int expkey_match (struct cache_head *a, struct cache_head *b)
216 {
217         struct svc_expkey *orig = container_of(a, struct svc_expkey, h);
218         struct svc_expkey *new = container_of(b, struct svc_expkey, h);
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)
223                 return 0;
224         return 1;
225 }
226
227 static inline void expkey_init(struct cache_head *cnew,
228                                    struct cache_head *citem)
229 {
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);
234         new->ek_client = item->ek_client;
235         new->ek_fsidtype = item->ek_fsidtype;
236         new->ek_fsid[0] = item->ek_fsid[0];
237         new->ek_fsid[1] = item->ek_fsid[1];
238         new->ek_fsid[2] = item->ek_fsid[2];
239 }
240
241 static 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
251 static struct cache_head *expkey_alloc(void)
252 {
253         struct svc_expkey *i = kmalloc(sizeof(*i), GFP_KERNEL);
254         if (i)
255                 return &i->h;
256         else
257                 return NULL;
258 }
259
260 static 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 };
274
275 static struct svc_expkey *
276 svc_expkey_lookup(struct svc_expkey *item)
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);
282
283         hash ^= hash_mem(cp, len, EXPKEY_HASHBITS);
284         hash ^= hash_ptr(item->ek_client, EXPKEY_HASHBITS);
285         hash &= EXPKEY_HASHMASK;
286
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
295 static struct svc_expkey *
296 svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old)
297 {
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);
302
303         hash ^= hash_mem(cp, len, EXPKEY_HASHBITS);
304         hash ^= hash_ptr(new->ek_client, EXPKEY_HASHBITS);
305         hash &= EXPKEY_HASHMASK;
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;
313 }
314
315
316 #define EXPORT_HASHBITS         8
317 #define EXPORT_HASHMAX          (1<< EXPORT_HASHBITS)
318 #define EXPORT_HASHMASK         (EXPORT_HASHMAX -1)
319
320 static struct cache_head *export_table[EXPORT_HASHMAX];
321
322 static void svc_export_put(struct kref *ref)
323 {
324         struct svc_export *exp = container_of(ref, struct svc_export, h.ref);
325         dput(exp->ex_dentry);
326         mntput(exp->ex_mnt);
327         auth_domain_put(exp->ex_client);
328         kfree(exp);
329 }
330
331 static void svc_export_request(struct cache_detail *cd,
332                                struct cache_head *h,
333                                char **bpp, int *blen)
334 {
335         /*  client path */
336         struct svc_export *exp = container_of(h, struct svc_export, h);
337         char *pth;
338
339         qword_add(bpp, blen, exp->ex_client->name);
340         pth = d_path(exp->ex_dentry, exp->ex_mnt, *bpp, *blen);
341         if (IS_ERR(pth)) {
342                 /* is this correct? */
343                 (*bpp)[0] = '\n';
344                 return;
345         }
346         qword_add(bpp, blen, pth);
347         (*bpp)[-1] = '\n';
348 }
349
350 static struct svc_export *svc_export_update(struct svc_export *new,
351                                             struct svc_export *old);
352 static struct svc_export *svc_export_lookup(struct svc_export *);
353
354 static int check_export(struct inode *inode, int flags)
355 {
356
357         /* We currently export only dirs and regular files.
358          * This is what umountd does.
359          */
360         if (!S_ISDIR(inode->i_mode) &&
361             !S_ISREG(inode->i_mode))
362                 return -ENOTDIR;
363
364         /* There are two requirements on a filesystem to be exportable.
365          * 1:  We must be able to identify the filesystem from a number.
366          *       either a device number (so FS_REQUIRES_DEV needed)
367          *       or an FSID number (so NFSEXP_FSID needed).
368          * 2:  We must be able to find an inode from a filehandle.
369          *       This means that s_export_op must be set.
370          */
371         if (!(inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) &&
372             !(flags & NFSEXP_FSID)) {
373                 dprintk("exp_export: export of non-dev fs without fsid\n");
374                 return -EINVAL;
375         }
376         if (!inode->i_sb->s_export_op) {
377                 dprintk("exp_export: export of invalid fs type.\n");
378                 return -EINVAL;
379         }
380
381         /* Ok, we can export it */;
382         if (!inode->i_sb->s_export_op->find_exported_dentry)
383                 inode->i_sb->s_export_op->find_exported_dentry =
384                         find_exported_dentry;
385         return 0;
386
387 }
388
389 static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
390 {
391         /* client path expiry [flags anonuid anongid fsid] */
392         char *buf;
393         int len;
394         int err;
395         struct auth_domain *dom = NULL;
396         struct nameidata nd;
397         struct svc_export exp, *expp;
398         int an_int;
399
400         nd.dentry = NULL;
401
402         if (mesg[mlen-1] != '\n')
403                 return -EINVAL;
404         mesg[mlen-1] = 0;
405
406         buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
407         err = -ENOMEM;
408         if (!buf) goto out;
409
410         /* client */
411         len = qword_get(&mesg, buf, PAGE_SIZE);
412         err = -EINVAL;
413         if (len <= 0) goto out;
414
415         err = -ENOENT;
416         dom = auth_domain_find(buf);
417         if (!dom)
418                 goto out;
419
420         /* path */
421         err = -EINVAL;
422         if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
423                 goto out;
424         err = path_lookup(buf, 0, &nd);
425         if (err) goto out_no_path;
426
427         exp.h.flags = 0;
428         exp.ex_client = dom;
429         exp.ex_mnt = nd.mnt;
430         exp.ex_dentry = nd.dentry;
431
432         /* expiry */
433         err = -EINVAL;
434         exp.h.expiry_time = get_expiry(&mesg);
435         if (exp.h.expiry_time == 0)
436                 goto out;
437
438         /* flags */
439         err = get_int(&mesg, &an_int);
440         if (err == -ENOENT)
441                 set_bit(CACHE_NEGATIVE, &exp.h.flags);
442         else {
443                 if (err || an_int < 0) goto out;        
444                 exp.ex_flags= an_int;
445         
446                 /* anon uid */
447                 err = get_int(&mesg, &an_int);
448                 if (err) goto out;
449                 exp.ex_anon_uid= an_int;
450
451                 /* anon gid */
452                 err = get_int(&mesg, &an_int);
453                 if (err) goto out;
454                 exp.ex_anon_gid= an_int;
455
456                 /* fsid */
457                 err = get_int(&mesg, &an_int);
458                 if (err) goto out;
459                 exp.ex_fsid = an_int;
460
461                 err = check_export(nd.dentry->d_inode, exp.ex_flags);
462                 if (err) goto out;
463         }
464
465         expp = svc_export_lookup(&exp);
466         if (expp)
467                 expp = svc_export_update(&exp, expp);
468         else
469                 err = -ENOMEM;
470         cache_flush();
471         if (expp == NULL)
472                 err = -ENOMEM;
473         else
474                 exp_put(expp);
475  out:
476         if (nd.dentry)
477                 path_release(&nd);
478  out_no_path:
479         if (dom)
480                 auth_domain_put(dom);
481         kfree(buf);
482         return err;
483 }
484
485 static void exp_flags(struct seq_file *m, int flag, int fsid, uid_t anonu, uid_t anong);
486
487 static int svc_export_show(struct seq_file *m,
488                            struct cache_detail *cd,
489                            struct cache_head *h)
490 {
491         struct svc_export *exp ;
492
493         if (h ==NULL) {
494                 seq_puts(m, "#path domain(flags)\n");
495                 return 0;
496         }
497         exp = container_of(h, struct svc_export, h);
498         seq_path(m, exp->ex_mnt, exp->ex_dentry, " \t\n\\");
499         seq_putc(m, '\t');
500         seq_escape(m, exp->ex_client->name, " \t\n\\");
501         seq_putc(m, '(');
502         if (test_bit(CACHE_VALID, &h->flags) && 
503             !test_bit(CACHE_NEGATIVE, &h->flags))
504                 exp_flags(m, exp->ex_flags, exp->ex_fsid, 
505                           exp->ex_anon_uid, exp->ex_anon_gid);
506         seq_puts(m, ")\n");
507         return 0;
508 }
509 static int svc_export_match(struct cache_head *a, struct cache_head *b)
510 {
511         struct svc_export *orig = container_of(a, struct svc_export, h);
512         struct svc_export *new = container_of(b, struct svc_export, h);
513         return orig->ex_client == new->ex_client &&
514                 orig->ex_dentry == new->ex_dentry &&
515                 orig->ex_mnt == new->ex_mnt;
516 }
517
518 static void svc_export_init(struct cache_head *cnew, struct cache_head *citem)
519 {
520         struct svc_export *new = container_of(cnew, struct svc_export, h);
521         struct svc_export *item = container_of(citem, struct svc_export, h);
522
523         kref_get(&item->ex_client->ref);
524         new->ex_client = item->ex_client;
525         new->ex_dentry = dget(item->ex_dentry);
526         new->ex_mnt = mntget(item->ex_mnt);
527 }
528
529 static void export_update(struct cache_head *cnew, struct cache_head *citem)
530 {
531         struct svc_export *new = container_of(cnew, struct svc_export, h);
532         struct svc_export *item = container_of(citem, struct svc_export, h);
533
534         new->ex_flags = item->ex_flags;
535         new->ex_anon_uid = item->ex_anon_uid;
536         new->ex_anon_gid = item->ex_anon_gid;
537         new->ex_fsid = item->ex_fsid;
538 }
539
540 static struct cache_head *svc_export_alloc(void)
541 {
542         struct svc_export *i = kmalloc(sizeof(*i), GFP_KERNEL);
543         if (i)
544                 return &i->h;
545         else
546                 return NULL;
547 }
548
549 struct cache_detail svc_export_cache = {
550         .owner          = THIS_MODULE,
551         .hash_size      = EXPORT_HASHMAX,
552         .hash_table     = export_table,
553         .name           = "nfsd.export",
554         .cache_put      = svc_export_put,
555         .cache_request  = svc_export_request,
556         .cache_parse    = svc_export_parse,
557         .cache_show     = svc_export_show,
558         .match          = svc_export_match,
559         .init           = svc_export_init,
560         .update         = export_update,
561         .alloc          = svc_export_alloc,
562 };
563
564 static struct svc_export *
565 svc_export_lookup(struct svc_export *exp)
566 {
567         struct cache_head *ch;
568         int hash;
569         hash = hash_ptr(exp->ex_client, EXPORT_HASHBITS);
570         hash ^= hash_ptr(exp->ex_dentry, EXPORT_HASHBITS);
571         hash ^= hash_ptr(exp->ex_mnt, EXPORT_HASHBITS);
572
573         ch = sunrpc_cache_lookup(&svc_export_cache, &exp->h,
574                                  hash);
575         if (ch)
576                 return container_of(ch, struct svc_export, h);
577         else
578                 return NULL;
579 }
580
581 static struct svc_export *
582 svc_export_update(struct svc_export *new, struct svc_export *old)
583 {
584         struct cache_head *ch;
585         int hash;
586         hash = hash_ptr(old->ex_client, EXPORT_HASHBITS);
587         hash ^= hash_ptr(old->ex_dentry, EXPORT_HASHBITS);
588         hash ^= hash_ptr(old->ex_mnt, EXPORT_HASHBITS);
589
590         ch = sunrpc_cache_update(&svc_export_cache, &new->h,
591                                  &old->h,
592                                  hash);
593         if (ch)
594                 return container_of(ch, struct svc_export, h);
595         else
596                 return NULL;
597 }
598
599
600 static struct svc_expkey *
601 exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp)
602 {
603         struct svc_expkey key, *ek;
604         int err;
605         
606         if (!clp)
607                 return NULL;
608
609         key.ek_client = clp;
610         key.ek_fsidtype = fsid_type;
611         memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
612
613         ek = svc_expkey_lookup(&key);
614         if (ek != NULL)
615                 if ((err = cache_check(&svc_expkey_cache, &ek->h, reqp)))
616                         ek = ERR_PTR(err);
617         return ek;
618 }
619
620 static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv,
621                        struct svc_export *exp)
622 {
623         struct svc_expkey key, *ek;
624
625         key.ek_client = clp;
626         key.ek_fsidtype = fsid_type;
627         memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
628         key.ek_mnt = exp->ex_mnt;
629         key.ek_dentry = exp->ex_dentry;
630         key.h.expiry_time = NEVER;
631         key.h.flags = 0;
632
633         ek = svc_expkey_lookup(&key);
634         if (ek)
635                 ek = svc_expkey_update(&key,ek);
636         if (ek) {
637                 cache_put(&ek->h, &svc_expkey_cache);
638                 return 0;
639         }
640         return -ENOMEM;
641 }
642
643 /*
644  * Find the client's export entry matching xdev/xino.
645  */
646 static inline struct svc_expkey *
647 exp_get_key(svc_client *clp, dev_t dev, ino_t ino)
648 {
649         u32 fsidv[3];
650         
651         if (old_valid_dev(dev)) {
652                 mk_fsid_v0(fsidv, dev, ino);
653                 return exp_find_key(clp, 0, fsidv, NULL);
654         }
655         mk_fsid_v3(fsidv, dev, ino);
656         return exp_find_key(clp, 3, fsidv, NULL);
657 }
658
659 /*
660  * Find the client's export entry matching fsid
661  */
662 static inline struct svc_expkey *
663 exp_get_fsid_key(svc_client *clp, int fsid)
664 {
665         u32 fsidv[2];
666
667         mk_fsid_v1(fsidv, fsid);
668
669         return exp_find_key(clp, 1, fsidv, NULL);
670 }
671
672 svc_export *
673 exp_get_by_name(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry,
674                 struct cache_req *reqp)
675 {
676         struct svc_export *exp, key;
677         
678         if (!clp)
679                 return NULL;
680
681         key.ex_client = clp;
682         key.ex_mnt = mnt;
683         key.ex_dentry = dentry;
684
685         exp = svc_export_lookup(&key);
686         if (exp != NULL) 
687                 switch (cache_check(&svc_export_cache, &exp->h, reqp)) {
688                 case 0: break;
689                 case -EAGAIN:
690                         exp = ERR_PTR(-EAGAIN);
691                         break;
692                 default:
693                         exp = NULL;
694                 }
695
696         return exp;
697 }
698
699 /*
700  * Find the export entry for a given dentry.
701  */
702 struct svc_export *
703 exp_parent(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry,
704            struct cache_req *reqp)
705 {
706         svc_export *exp;
707
708         dget(dentry);
709         exp = exp_get_by_name(clp, mnt, dentry, reqp);
710
711         while (exp == NULL && !IS_ROOT(dentry)) {
712                 struct dentry *parent;
713
714                 parent = dget_parent(dentry);
715                 dput(dentry);
716                 dentry = parent;
717                 exp = exp_get_by_name(clp, mnt, dentry, reqp);
718         }
719         dput(dentry);
720         return exp;
721 }
722
723 /*
724  * Hashtable locking. Write locks are placed only by user processes
725  * wanting to modify export information.
726  * Write locking only done in this file.  Read locking
727  * needed externally.
728  */
729
730 static DECLARE_RWSEM(hash_sem);
731
732 void
733 exp_readlock(void)
734 {
735         down_read(&hash_sem);
736 }
737
738 static inline void
739 exp_writelock(void)
740 {
741         down_write(&hash_sem);
742 }
743
744 void
745 exp_readunlock(void)
746 {
747         up_read(&hash_sem);
748 }
749
750 static inline void
751 exp_writeunlock(void)
752 {
753         up_write(&hash_sem);
754 }
755
756 static void exp_fsid_unhash(struct svc_export *exp)
757 {
758         struct svc_expkey *ek;
759
760         if ((exp->ex_flags & NFSEXP_FSID) == 0)
761                 return;
762
763         ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid);
764         if (ek && !IS_ERR(ek)) {
765                 ek->h.expiry_time = get_seconds()-1;
766                 cache_put(&ek->h, &svc_expkey_cache);
767         }
768         svc_expkey_cache.nextcheck = get_seconds();
769 }
770
771 static int exp_fsid_hash(svc_client *clp, struct svc_export *exp)
772 {
773         u32 fsid[2];
774  
775         if ((exp->ex_flags & NFSEXP_FSID) == 0)
776                 return 0;
777
778         mk_fsid_v1(fsid, exp->ex_fsid);
779         return exp_set_key(clp, 1, fsid, exp);
780 }
781
782 static int exp_hash(struct auth_domain *clp, struct svc_export *exp)
783 {
784         u32 fsid[2];
785         struct inode *inode = exp->ex_dentry->d_inode;
786         dev_t dev = inode->i_sb->s_dev;
787
788         if (old_valid_dev(dev)) {
789                 mk_fsid_v0(fsid, dev, inode->i_ino);
790                 return exp_set_key(clp, 0, fsid, exp);
791         }
792         mk_fsid_v3(fsid, dev, inode->i_ino);
793         return exp_set_key(clp, 3, fsid, exp);
794 }
795
796 static void exp_unhash(struct svc_export *exp)
797 {
798         struct svc_expkey *ek;
799         struct inode *inode = exp->ex_dentry->d_inode;
800
801         ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino);
802         if (ek && !IS_ERR(ek)) {
803                 ek->h.expiry_time = get_seconds()-1;
804                 cache_put(&ek->h, &svc_expkey_cache);
805         }
806         svc_expkey_cache.nextcheck = get_seconds();
807 }
808         
809 /*
810  * Export a file system.
811  */
812 int
813 exp_export(struct nfsctl_export *nxp)
814 {
815         svc_client      *clp;
816         struct svc_export       *exp = NULL;
817         struct svc_export       new;
818         struct svc_expkey       *fsid_key = NULL;
819         struct nameidata nd;
820         int             err;
821
822         /* Consistency check */
823         err = -EINVAL;
824         if (!exp_verify_string(nxp->ex_path, NFS_MAXPATHLEN) ||
825             !exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX))
826                 goto out;
827
828         dprintk("exp_export called for %s:%s (%x/%ld fl %x).\n",
829                         nxp->ex_client, nxp->ex_path,
830                         (unsigned)nxp->ex_dev, (long)nxp->ex_ino,
831                         nxp->ex_flags);
832
833         /* Try to lock the export table for update */
834         exp_writelock();
835
836         /* Look up client info */
837         if (!(clp = auth_domain_find(nxp->ex_client)))
838                 goto out_unlock;
839
840
841         /* Look up the dentry */
842         err = path_lookup(nxp->ex_path, 0, &nd);
843         if (err)
844                 goto out_unlock;
845         err = -EINVAL;
846
847         exp = exp_get_by_name(clp, nd.mnt, nd.dentry, NULL);
848
849         /* must make sure there won't be an ex_fsid clash */
850         if ((nxp->ex_flags & NFSEXP_FSID) &&
851             (fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) &&
852             !IS_ERR(fsid_key) &&
853             fsid_key->ek_mnt &&
854             (fsid_key->ek_mnt != nd.mnt || fsid_key->ek_dentry != nd.dentry) )
855                 goto finish;
856
857         if (exp) {
858                 /* just a flags/id/fsid update */
859
860                 exp_fsid_unhash(exp);
861                 exp->ex_flags    = nxp->ex_flags;
862                 exp->ex_anon_uid = nxp->ex_anon_uid;
863                 exp->ex_anon_gid = nxp->ex_anon_gid;
864                 exp->ex_fsid     = nxp->ex_dev;
865
866                 err = exp_fsid_hash(clp, exp);
867                 goto finish;
868         }
869
870         err = check_export(nd.dentry->d_inode, nxp->ex_flags);
871         if (err) goto finish;
872
873         err = -ENOMEM;
874
875         dprintk("nfsd: creating export entry %p for client %p\n", exp, clp);
876
877         new.h.expiry_time = NEVER;
878         new.h.flags = 0;
879         new.ex_client = clp;
880         new.ex_mnt = nd.mnt;
881         new.ex_dentry = nd.dentry;
882         new.ex_flags = nxp->ex_flags;
883         new.ex_anon_uid = nxp->ex_anon_uid;
884         new.ex_anon_gid = nxp->ex_anon_gid;
885         new.ex_fsid = nxp->ex_dev;
886
887         exp = svc_export_lookup(&new);
888         if (exp)
889                 exp = svc_export_update(&new, exp);
890
891         if (!exp)
892                 goto finish;
893
894         if (exp_hash(clp, exp) ||
895             exp_fsid_hash(clp, exp)) {
896                 /* failed to create at least one index */
897                 exp_do_unexport(exp);
898                 cache_flush();
899                 err = -ENOMEM;
900         }
901
902 finish:
903         if (exp)
904                 exp_put(exp);
905         if (fsid_key && !IS_ERR(fsid_key))
906                 cache_put(&fsid_key->h, &svc_expkey_cache);
907         if (clp)
908                 auth_domain_put(clp);
909         path_release(&nd);
910 out_unlock:
911         exp_writeunlock();
912 out:
913         return err;
914 }
915
916 /*
917  * Unexport a file system. The export entry has already
918  * been removed from the client's list of exported fs's.
919  */
920 static void
921 exp_do_unexport(svc_export *unexp)
922 {
923         unexp->h.expiry_time = get_seconds()-1;
924         svc_export_cache.nextcheck = get_seconds();
925         exp_unhash(unexp);
926         exp_fsid_unhash(unexp);
927 }
928
929
930 /*
931  * unexport syscall.
932  */
933 int
934 exp_unexport(struct nfsctl_export *nxp)
935 {
936         struct auth_domain *dom;
937         svc_export *exp;
938         struct nameidata nd;
939         int             err;
940
941         /* Consistency check */
942         if (!exp_verify_string(nxp->ex_path, NFS_MAXPATHLEN) ||
943             !exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX))
944                 return -EINVAL;
945
946         exp_writelock();
947
948         err = -EINVAL;
949         dom = auth_domain_find(nxp->ex_client);
950         if (!dom) {
951                 dprintk("nfsd: unexport couldn't find %s\n", nxp->ex_client);
952                 goto out_unlock;
953         }
954
955         err = path_lookup(nxp->ex_path, 0, &nd);
956         if (err)
957                 goto out_domain;
958
959         err = -EINVAL;
960         exp = exp_get_by_name(dom, nd.mnt, nd.dentry, NULL);
961         path_release(&nd);
962         if (!exp)
963                 goto out_domain;
964
965         exp_do_unexport(exp);
966         exp_put(exp);
967         err = 0;
968
969 out_domain:
970         auth_domain_put(dom);
971         cache_flush();
972 out_unlock:
973         exp_writeunlock();
974         return err;
975 }
976
977 /*
978  * Obtain the root fh on behalf of a client.
979  * This could be done in user space, but I feel that it adds some safety
980  * since its harder to fool a kernel module than a user space program.
981  */
982 int
983 exp_rootfh(svc_client *clp, char *path, struct knfsd_fh *f, int maxsize)
984 {
985         struct svc_export       *exp;
986         struct nameidata        nd;
987         struct inode            *inode;
988         struct svc_fh           fh;
989         int                     err;
990
991         err = -EPERM;
992         /* NB: we probably ought to check that it's NUL-terminated */
993         if (path_lookup(path, 0, &nd)) {
994                 printk("nfsd: exp_rootfh path not found %s", path);
995                 return err;
996         }
997         inode = nd.dentry->d_inode;
998
999         dprintk("nfsd: exp_rootfh(%s [%p] %s:%s/%ld)\n",
1000                  path, nd.dentry, clp->name,
1001                  inode->i_sb->s_id, inode->i_ino);
1002         exp = exp_parent(clp, nd.mnt, nd.dentry, NULL);
1003         if (!exp) {
1004                 dprintk("nfsd: exp_rootfh export not found.\n");
1005                 goto out;
1006         }
1007
1008         /*
1009          * fh must be initialized before calling fh_compose
1010          */
1011         fh_init(&fh, maxsize);
1012         if (fh_compose(&fh, exp, nd.dentry, NULL))
1013                 err = -EINVAL;
1014         else
1015                 err = 0;
1016         memcpy(f, &fh.fh_handle, sizeof(struct knfsd_fh));
1017         fh_put(&fh);
1018         exp_put(exp);
1019 out:
1020         path_release(&nd);
1021         return err;
1022 }
1023
1024 struct svc_export *
1025 exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv,
1026          struct cache_req *reqp)
1027 {
1028         struct svc_export *exp;
1029         struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp);
1030         if (!ek || IS_ERR(ek))
1031                 return ERR_PTR(PTR_ERR(ek));
1032
1033         exp = exp_get_by_name(clp, ek->ek_mnt, ek->ek_dentry, reqp);
1034         cache_put(&ek->h, &svc_expkey_cache);
1035
1036         if (!exp || IS_ERR(exp))
1037                 return ERR_PTR(PTR_ERR(exp));
1038         return exp;
1039 }
1040
1041
1042 /*
1043  * Called when we need the filehandle for the root of the pseudofs,
1044  * for a given NFSv4 client.   The root is defined to be the
1045  * export point with fsid==0
1046  */
1047 int
1048 exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
1049                struct cache_req *creq)
1050 {
1051         struct svc_expkey *fsid_key;
1052         struct svc_export *exp;
1053         int rv;
1054         u32 fsidv[2];
1055
1056         mk_fsid_v1(fsidv, 0);
1057
1058         fsid_key = exp_find_key(clp, 1, fsidv, creq);
1059         if (IS_ERR(fsid_key) && PTR_ERR(fsid_key) == -EAGAIN)
1060                 return nfserr_dropit;
1061         if (!fsid_key || IS_ERR(fsid_key))
1062                 return nfserr_perm;
1063
1064         exp = exp_get_by_name(clp, fsid_key->ek_mnt, fsid_key->ek_dentry, creq);
1065         if (exp == NULL)
1066                 rv = nfserr_perm;
1067         else if (IS_ERR(exp))
1068                 rv = nfserrno(PTR_ERR(exp));
1069         else {
1070                 rv = fh_compose(fhp, exp,
1071                                 fsid_key->ek_dentry, NULL);
1072                 exp_put(exp);
1073         }
1074         cache_put(&fsid_key->h, &svc_expkey_cache);
1075         return rv;
1076 }
1077
1078 /* Iterator */
1079
1080 static void *e_start(struct seq_file *m, loff_t *pos)
1081 {
1082         loff_t n = *pos;
1083         unsigned hash, export;
1084         struct cache_head *ch;
1085         
1086         exp_readlock();
1087         read_lock(&svc_export_cache.hash_lock);
1088         if (!n--)
1089                 return SEQ_START_TOKEN;
1090         hash = n >> 32;
1091         export = n & ((1LL<<32) - 1);
1092
1093         
1094         for (ch=export_table[hash]; ch; ch=ch->next)
1095                 if (!export--)
1096                         return ch;
1097         n &= ~((1LL<<32) - 1);
1098         do {
1099                 hash++;
1100                 n += 1LL<<32;
1101         } while(hash < EXPORT_HASHMAX && export_table[hash]==NULL);
1102         if (hash >= EXPORT_HASHMAX)
1103                 return NULL;
1104         *pos = n+1;
1105         return export_table[hash];
1106 }
1107
1108 static void *e_next(struct seq_file *m, void *p, loff_t *pos)
1109 {
1110         struct cache_head *ch = p;
1111         int hash = (*pos >> 32);
1112
1113         if (p == SEQ_START_TOKEN)
1114                 hash = 0;
1115         else if (ch->next == NULL) {
1116                 hash++;
1117                 *pos += 1LL<<32;
1118         } else {
1119                 ++*pos;
1120                 return ch->next;
1121         }
1122         *pos &= ~((1LL<<32) - 1);
1123         while (hash < EXPORT_HASHMAX && export_table[hash] == NULL) {
1124                 hash++;
1125                 *pos += 1LL<<32;
1126         }
1127         if (hash >= EXPORT_HASHMAX)
1128                 return NULL;
1129         ++*pos;
1130         return export_table[hash];
1131 }
1132
1133 static void e_stop(struct seq_file *m, void *p)
1134 {
1135         read_unlock(&svc_export_cache.hash_lock);
1136         exp_readunlock();
1137 }
1138
1139 static struct flags {
1140         int flag;
1141         char *name[2];
1142 } expflags[] = {
1143         { NFSEXP_READONLY, {"ro", "rw"}},
1144         { NFSEXP_INSECURE_PORT, {"insecure", ""}},
1145         { NFSEXP_ROOTSQUASH, {"root_squash", "no_root_squash"}},
1146         { NFSEXP_ALLSQUASH, {"all_squash", ""}},
1147         { NFSEXP_ASYNC, {"async", "sync"}},
1148         { NFSEXP_GATHERED_WRITES, {"wdelay", "no_wdelay"}},
1149         { NFSEXP_NOHIDE, {"nohide", ""}},
1150         { NFSEXP_CROSSMOUNT, {"crossmnt", ""}},
1151         { NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
1152         { NFSEXP_NOAUTHNLM, {"insecure_locks", ""}},
1153 #ifdef MSNFS
1154         { NFSEXP_MSNFS, {"msnfs", ""}},
1155 #endif
1156         { 0, {"", ""}}
1157 };
1158
1159 static void exp_flags(struct seq_file *m, int flag, int fsid, uid_t anonu, uid_t anong)
1160 {
1161         int first = 0;
1162         struct flags *flg;
1163
1164         for (flg = expflags; flg->flag; flg++) {
1165                 int state = (flg->flag & flag)?0:1;
1166                 if (*flg->name[state])
1167                         seq_printf(m, "%s%s", first++?",":"", flg->name[state]);
1168         }
1169         if (flag & NFSEXP_FSID)
1170                 seq_printf(m, "%sfsid=%d", first++?",":"", fsid);
1171         if (anonu != (uid_t)-2 && anonu != (0x10000-2))
1172                 seq_printf(m, "%sanonuid=%d", first++?",":"", anonu);
1173         if (anong != (gid_t)-2 && anong != (0x10000-2))
1174                 seq_printf(m, "%sanongid=%d", first++?",":"", anong);
1175 }
1176
1177 static int e_show(struct seq_file *m, void *p)
1178 {
1179         struct cache_head *cp = p;
1180         struct svc_export *exp = container_of(cp, struct svc_export, h);
1181
1182         if (p == SEQ_START_TOKEN) {
1183                 seq_puts(m, "# Version 1.1\n");
1184                 seq_puts(m, "# Path Client(Flags) # IPs\n");
1185                 return 0;
1186         }
1187
1188         cache_get(&exp->h);
1189         if (cache_check(&svc_export_cache, &exp->h, NULL))
1190                 return 0;
1191         cache_put(&exp->h, &svc_export_cache);
1192         return svc_export_show(m, &svc_export_cache, cp);
1193 }
1194
1195 struct seq_operations nfs_exports_op = {
1196         .start  = e_start,
1197         .next   = e_next,
1198         .stop   = e_stop,
1199         .show   = e_show,
1200 };
1201
1202 /*
1203  * Add or modify a client.
1204  * Change requests may involve the list of host addresses. The list of
1205  * exports and possibly existing uid maps are left untouched.
1206  */
1207 int
1208 exp_addclient(struct nfsctl_client *ncp)
1209 {
1210         struct auth_domain      *dom;
1211         int                     i, err;
1212
1213         /* First, consistency check. */
1214         err = -EINVAL;
1215         if (! exp_verify_string(ncp->cl_ident, NFSCLNT_IDMAX))
1216                 goto out;
1217         if (ncp->cl_naddr > NFSCLNT_ADDRMAX)
1218                 goto out;
1219
1220         /* Lock the hashtable */
1221         exp_writelock();
1222
1223         dom = unix_domain_find(ncp->cl_ident);
1224
1225         err = -ENOMEM;
1226         if (!dom)
1227                 goto out_unlock;
1228
1229         /* Insert client into hashtable. */
1230         for (i = 0; i < ncp->cl_naddr; i++)
1231                 auth_unix_add_addr(ncp->cl_addrlist[i], dom);
1232
1233         auth_unix_forget_old(dom);
1234         auth_domain_put(dom);
1235
1236         err = 0;
1237
1238 out_unlock:
1239         exp_writeunlock();
1240 out:
1241         return err;
1242 }
1243
1244 /*
1245  * Delete a client given an identifier.
1246  */
1247 int
1248 exp_delclient(struct nfsctl_client *ncp)
1249 {
1250         int             err;
1251         struct auth_domain *dom;
1252
1253         err = -EINVAL;
1254         if (!exp_verify_string(ncp->cl_ident, NFSCLNT_IDMAX))
1255                 goto out;
1256
1257         /* Lock the hashtable */
1258         exp_writelock();
1259
1260         dom = auth_domain_find(ncp->cl_ident);
1261         /* just make sure that no addresses work 
1262          * and that it will expire soon 
1263          */
1264         if (dom) {
1265                 err = auth_unix_forget_old(dom);
1266                 auth_domain_put(dom);
1267         }
1268
1269         exp_writeunlock();
1270 out:
1271         return err;
1272 }
1273
1274 /*
1275  * Verify that string is non-empty and does not exceed max length.
1276  */
1277 static int
1278 exp_verify_string(char *cp, int max)
1279 {
1280         int     i;
1281
1282         for (i = 0; i < max; i++)
1283                 if (!cp[i])
1284                         return i;
1285         cp[i] = 0;
1286         printk(KERN_NOTICE "nfsd: couldn't validate string %s\n", cp);
1287         return 0;
1288 }
1289
1290 /*
1291  * Initialize the exports module.
1292  */
1293 void
1294 nfsd_export_init(void)
1295 {
1296         dprintk("nfsd: initializing export module.\n");
1297
1298         cache_register(&svc_export_cache);
1299         cache_register(&svc_expkey_cache);
1300
1301 }
1302
1303 /*
1304  * Flush exports table - called when last nfsd thread is killed
1305  */
1306 void
1307 nfsd_export_flush(void)
1308 {
1309         exp_writelock();
1310         cache_purge(&svc_expkey_cache);
1311         cache_purge(&svc_export_cache);
1312         exp_writeunlock();
1313 }
1314
1315 /*
1316  * Shutdown the exports module.
1317  */
1318 void
1319 nfsd_export_shutdown(void)
1320 {
1321
1322         dprintk("nfsd: shutting down export module.\n");
1323
1324         exp_writelock();
1325
1326         if (cache_unregister(&svc_expkey_cache))
1327                 printk(KERN_ERR "nfsd: failed to unregister expkey cache\n");
1328         if (cache_unregister(&svc_export_cache))
1329                 printk(KERN_ERR "nfsd: failed to unregister export cache\n");
1330         svcauth_unix_purge();
1331
1332         exp_writeunlock();
1333         dprintk("nfsd: export shutdown complete.\n");
1334 }