1
2
3
4
5
6
7#include <linux/slab.h>
8#include <linux/namei.h>
9#include <linux/ctype.h>
10
11#include <linux/sunrpc/svcsock.h>
12#include <linux/lockd/lockd.h>
13#include <linux/sunrpc/addr.h>
14#include <linux/sunrpc/gss_api.h>
15#include <linux/sunrpc/gss_krb5_enctypes.h>
16#include <linux/sunrpc/rpc_pipe_fs.h>
17#include <linux/module.h>
18
19#include "idmap.h"
20#include "nfsd.h"
21#include "cache.h"
22#include "state.h"
23#include "netns.h"
24
25
26
27
28enum {
29 NFSD_Root = 1,
30 NFSD_List,
31 NFSD_Export_features,
32 NFSD_Fh,
33 NFSD_FO_UnlockIP,
34 NFSD_FO_UnlockFS,
35 NFSD_Threads,
36 NFSD_Pool_Threads,
37 NFSD_Pool_Stats,
38 NFSD_Versions,
39 NFSD_Ports,
40 NFSD_MaxBlkSize,
41 NFSD_SupportedEnctypes,
42
43
44
45
46#ifdef CONFIG_NFSD_V4
47 NFSD_Leasetime,
48 NFSD_Gracetime,
49 NFSD_RecoveryDir,
50#endif
51};
52
53
54
55
56static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
57static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size);
58static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size);
59static ssize_t write_threads(struct file *file, char *buf, size_t size);
60static ssize_t write_pool_threads(struct file *file, char *buf, size_t size);
61static ssize_t write_versions(struct file *file, char *buf, size_t size);
62static ssize_t write_ports(struct file *file, char *buf, size_t size);
63static ssize_t write_maxblksize(struct file *file, char *buf, size_t size);
64#ifdef CONFIG_NFSD_V4
65static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
66static ssize_t write_gracetime(struct file *file, char *buf, size_t size);
67static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
68#endif
69
70static ssize_t (*write_op[])(struct file *, char *, size_t) = {
71 [NFSD_Fh] = write_filehandle,
72 [NFSD_FO_UnlockIP] = write_unlock_ip,
73 [NFSD_FO_UnlockFS] = write_unlock_fs,
74 [NFSD_Threads] = write_threads,
75 [NFSD_Pool_Threads] = write_pool_threads,
76 [NFSD_Versions] = write_versions,
77 [NFSD_Ports] = write_ports,
78 [NFSD_MaxBlkSize] = write_maxblksize,
79#ifdef CONFIG_NFSD_V4
80 [NFSD_Leasetime] = write_leasetime,
81 [NFSD_Gracetime] = write_gracetime,
82 [NFSD_RecoveryDir] = write_recoverydir,
83#endif
84};
85
86static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
87{
88 ino_t ino = file_inode(file)->i_ino;
89 char *data;
90 ssize_t rv;
91
92 if (ino >= ARRAY_SIZE(write_op) || !write_op[ino])
93 return -EINVAL;
94
95 data = simple_transaction_get(file, buf, size);
96 if (IS_ERR(data))
97 return PTR_ERR(data);
98
99 rv = write_op[ino](file, data, size);
100 if (rv >= 0) {
101 simple_transaction_set(file, rv);
102 rv = size;
103 }
104 return rv;
105}
106
107static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
108{
109 if (! file->private_data) {
110
111
112
113
114 ssize_t rv = nfsctl_transaction_write(file, buf, 0, pos);
115 if (rv < 0)
116 return rv;
117 }
118 return simple_transaction_read(file, buf, size, pos);
119}
120
121static const struct file_operations transaction_ops = {
122 .write = nfsctl_transaction_write,
123 .read = nfsctl_transaction_read,
124 .release = simple_transaction_release,
125 .llseek = default_llseek,
126};
127
128static int exports_net_open(struct net *net, struct file *file)
129{
130 int err;
131 struct seq_file *seq;
132 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
133
134 err = seq_open(file, &nfs_exports_op);
135 if (err)
136 return err;
137
138 seq = file->private_data;
139 seq->private = nn->svc_export_cache;
140 return 0;
141}
142
143static int exports_proc_open(struct inode *inode, struct file *file)
144{
145 return exports_net_open(current->nsproxy->net_ns, file);
146}
147
148static const struct file_operations exports_proc_operations = {
149 .open = exports_proc_open,
150 .read = seq_read,
151 .llseek = seq_lseek,
152 .release = seq_release,
153 .owner = THIS_MODULE,
154};
155
156static int exports_nfsd_open(struct inode *inode, struct file *file)
157{
158 return exports_net_open(inode->i_sb->s_fs_info, file);
159}
160
161static const struct file_operations exports_nfsd_operations = {
162 .open = exports_nfsd_open,
163 .read = seq_read,
164 .llseek = seq_lseek,
165 .release = seq_release,
166 .owner = THIS_MODULE,
167};
168
169static int export_features_show(struct seq_file *m, void *v)
170{
171 seq_printf(m, "0x%x 0x%x\n", NFSEXP_ALLFLAGS, NFSEXP_SECINFO_FLAGS);
172 return 0;
173}
174
175static int export_features_open(struct inode *inode, struct file *file)
176{
177 return single_open(file, export_features_show, NULL);
178}
179
180static struct file_operations export_features_operations = {
181 .open = export_features_open,
182 .read = seq_read,
183 .llseek = seq_lseek,
184 .release = single_release,
185};
186
187#if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE)
188static int supported_enctypes_show(struct seq_file *m, void *v)
189{
190 seq_printf(m, KRB5_SUPPORTED_ENCTYPES);
191 return 0;
192}
193
194static int supported_enctypes_open(struct inode *inode, struct file *file)
195{
196 return single_open(file, supported_enctypes_show, NULL);
197}
198
199static struct file_operations supported_enctypes_ops = {
200 .open = supported_enctypes_open,
201 .read = seq_read,
202 .llseek = seq_lseek,
203 .release = single_release,
204};
205#endif
206
207static const struct file_operations pool_stats_operations = {
208 .open = nfsd_pool_stats_open,
209 .read = seq_read,
210 .llseek = seq_lseek,
211 .release = nfsd_pool_stats_release,
212 .owner = THIS_MODULE,
213};
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size)
236{
237 struct sockaddr_storage address;
238 struct sockaddr *sap = (struct sockaddr *)&address;
239 size_t salen = sizeof(address);
240 char *fo_path;
241 struct net *net = file->f_dentry->d_sb->s_fs_info;
242
243
244 if (size == 0)
245 return -EINVAL;
246
247 if (buf[size-1] != '\n')
248 return -EINVAL;
249
250 fo_path = buf;
251 if (qword_get(&buf, fo_path, size) < 0)
252 return -EINVAL;
253
254 if (rpc_pton(net, fo_path, size, sap, salen) == 0)
255 return -EINVAL;
256
257 return nlmsvc_unlock_all_by_ip(sap);
258}
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size)
275{
276 struct path path;
277 char *fo_path;
278 int error;
279
280
281 if (size == 0)
282 return -EINVAL;
283
284 if (buf[size-1] != '\n')
285 return -EINVAL;
286
287 fo_path = buf;
288 if (qword_get(&buf, fo_path, size) < 0)
289 return -EINVAL;
290
291 error = kern_path(fo_path, 0, &path);
292 if (error)
293 return error;
294
295
296
297
298
299
300
301
302
303
304 error = nlmsvc_unlock_all_by_sb(path.dentry->d_sb);
305
306 path_put(&path);
307 return error;
308}
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
332{
333 char *dname, *path;
334 int uninitialized_var(maxsize);
335 char *mesg = buf;
336 int len;
337 struct auth_domain *dom;
338 struct knfsd_fh fh;
339 struct net *net = file->f_dentry->d_sb->s_fs_info;
340
341 if (size == 0)
342 return -EINVAL;
343
344 if (buf[size-1] != '\n')
345 return -EINVAL;
346 buf[size-1] = 0;
347
348 dname = mesg;
349 len = qword_get(&mesg, dname, size);
350 if (len <= 0)
351 return -EINVAL;
352
353 path = dname+len+1;
354 len = qword_get(&mesg, path, size);
355 if (len <= 0)
356 return -EINVAL;
357
358 len = get_int(&mesg, &maxsize);
359 if (len)
360 return len;
361
362 if (maxsize < NFS_FHSIZE)
363 return -EINVAL;
364 if (maxsize > NFS3_FHSIZE)
365 maxsize = NFS3_FHSIZE;
366
367 if (qword_get(&mesg, mesg, size)>0)
368 return -EINVAL;
369
370
371 dom = unix_domain_find(dname);
372 if (!dom)
373 return -ENOMEM;
374
375 len = exp_rootfh(net, dom, path, &fh, maxsize);
376 auth_domain_put(dom);
377 if (len)
378 return len;
379
380 mesg = buf;
381 len = SIMPLE_TRANSACTION_LIMIT;
382 qword_addhex(&mesg, &len, (char*)&fh.fh_base, fh.fh_size);
383 mesg[-1] = '\n';
384 return mesg - buf;
385}
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415static ssize_t write_threads(struct file *file, char *buf, size_t size)
416{
417 char *mesg = buf;
418 int rv;
419 struct net *net = file->f_dentry->d_sb->s_fs_info;
420
421 if (size > 0) {
422 int newthreads;
423 rv = get_int(&mesg, &newthreads);
424 if (rv)
425 return rv;
426 if (newthreads < 0)
427 return -EINVAL;
428 rv = nfsd_svc(newthreads, net);
429 if (rv < 0)
430 return rv;
431 } else
432 rv = nfsd_nrthreads(net);
433
434 return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n", rv);
435}
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
460{
461
462
463
464 char *mesg = buf;
465 int i;
466 int rv;
467 int len;
468 int npools;
469 int *nthreads;
470 struct net *net = file->f_dentry->d_sb->s_fs_info;
471
472 mutex_lock(&nfsd_mutex);
473 npools = nfsd_nrpools(net);
474 if (npools == 0) {
475
476
477
478
479
480 mutex_unlock(&nfsd_mutex);
481 strcpy(buf, "0\n");
482 return strlen(buf);
483 }
484
485 nthreads = kcalloc(npools, sizeof(int), GFP_KERNEL);
486 rv = -ENOMEM;
487 if (nthreads == NULL)
488 goto out_free;
489
490 if (size > 0) {
491 for (i = 0; i < npools; i++) {
492 rv = get_int(&mesg, &nthreads[i]);
493 if (rv == -ENOENT)
494 break;
495 if (rv)
496 goto out_free;
497 rv = -EINVAL;
498 if (nthreads[i] < 0)
499 goto out_free;
500 }
501 rv = nfsd_set_nrthreads(i, nthreads, net);
502 if (rv)
503 goto out_free;
504 }
505
506 rv = nfsd_get_nrthreads(npools, nthreads, net);
507 if (rv)
508 goto out_free;
509
510 mesg = buf;
511 size = SIMPLE_TRANSACTION_LIMIT;
512 for (i = 0; i < npools && size > 0; i++) {
513 snprintf(mesg, size, "%d%c", nthreads[i], (i == npools-1 ? '\n' : ' '));
514 len = strlen(mesg);
515 size -= len;
516 mesg += len;
517 }
518 rv = mesg - buf;
519out_free:
520 kfree(nthreads);
521 mutex_unlock(&nfsd_mutex);
522 return rv;
523}
524
525static ssize_t __write_versions(struct file *file, char *buf, size_t size)
526{
527 char *mesg = buf;
528 char *vers, *minorp, sign;
529 int len, num, remaining;
530 unsigned minor;
531 ssize_t tlen = 0;
532 char *sep;
533 struct net *net = file->f_dentry->d_sb->s_fs_info;
534 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
535
536 if (size>0) {
537 if (nn->nfsd_serv)
538
539
540
541
542 return -EBUSY;
543 if (buf[size-1] != '\n')
544 return -EINVAL;
545 buf[size-1] = 0;
546
547 vers = mesg;
548 len = qword_get(&mesg, vers, size);
549 if (len <= 0) return -EINVAL;
550 do {
551 sign = *vers;
552 if (sign == '+' || sign == '-')
553 num = simple_strtol((vers+1), &minorp, 0);
554 else
555 num = simple_strtol(vers, &minorp, 0);
556 if (*minorp == '.') {
557 if (num != 4)
558 return -EINVAL;
559 minor = simple_strtoul(minorp+1, NULL, 0);
560 if (minor == 0)
561 return -EINVAL;
562 if (nfsd_minorversion(minor, sign == '-' ?
563 NFSD_CLEAR : NFSD_SET) < 0)
564 return -EINVAL;
565 goto next;
566 }
567 switch(num) {
568 case 2:
569 case 3:
570 case 4:
571 nfsd_vers(num, sign == '-' ? NFSD_CLEAR : NFSD_SET);
572 break;
573 default:
574 return -EINVAL;
575 }
576 next:
577 vers += len + 1;
578 } while ((len = qword_get(&mesg, vers, size)) > 0);
579
580
581
582 nfsd_reset_versions();
583 }
584
585
586 len = 0;
587 sep = "";
588 remaining = SIMPLE_TRANSACTION_LIMIT;
589 for (num=2 ; num <= 4 ; num++)
590 if (nfsd_vers(num, NFSD_AVAIL)) {
591 len = snprintf(buf, remaining, "%s%c%d", sep,
592 nfsd_vers(num, NFSD_TEST)?'+':'-',
593 num);
594 sep = " ";
595
596 if (len > remaining)
597 break;
598 remaining -= len;
599 buf += len;
600 tlen += len;
601 }
602 if (nfsd_vers(4, NFSD_AVAIL))
603 for (minor = 1; minor <= NFSD_SUPPORTED_MINOR_VERSION;
604 minor++) {
605 len = snprintf(buf, remaining, " %c4.%u",
606 (nfsd_vers(4, NFSD_TEST) &&
607 nfsd_minorversion(minor, NFSD_TEST)) ?
608 '+' : '-',
609 minor);
610
611 if (len > remaining)
612 break;
613 remaining -= len;
614 buf += len;
615 tlen += len;
616 }
617
618 len = snprintf(buf, remaining, "\n");
619 if (len > remaining)
620 return -EINVAL;
621 return tlen + len;
622}
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656static ssize_t write_versions(struct file *file, char *buf, size_t size)
657{
658 ssize_t rv;
659
660 mutex_lock(&nfsd_mutex);
661 rv = __write_versions(file, buf, size);
662 mutex_unlock(&nfsd_mutex);
663 return rv;
664}
665
666
667
668
669
670static ssize_t __write_ports_names(char *buf, struct net *net)
671{
672 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
673
674 if (nn->nfsd_serv == NULL)
675 return 0;
676 return svc_xprt_names(nn->nfsd_serv, buf, SIMPLE_TRANSACTION_LIMIT);
677}
678
679
680
681
682
683
684static ssize_t __write_ports_addfd(char *buf, struct net *net)
685{
686 char *mesg = buf;
687 int fd, err;
688 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
689
690 err = get_int(&mesg, &fd);
691 if (err != 0 || fd < 0)
692 return -EINVAL;
693
694 err = nfsd_create_serv(net);
695 if (err != 0)
696 return err;
697
698 err = svc_addsock(nn->nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT);
699 if (err < 0) {
700 nfsd_destroy(net);
701 return err;
702 }
703
704
705 nn->nfsd_serv->sv_nrthreads--;
706 return err;
707}
708
709
710
711
712
713static ssize_t __write_ports_addxprt(char *buf, struct net *net)
714{
715 char transport[16];
716 struct svc_xprt *xprt;
717 int port, err;
718 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
719
720 if (sscanf(buf, "%15s %5u", transport, &port) != 2)
721 return -EINVAL;
722
723 if (port < 1 || port > USHRT_MAX)
724 return -EINVAL;
725
726 err = nfsd_create_serv(net);
727 if (err != 0)
728 return err;
729
730 err = svc_create_xprt(nn->nfsd_serv, transport, net,
731 PF_INET, port, SVC_SOCK_ANONYMOUS);
732 if (err < 0)
733 goto out_err;
734
735 err = svc_create_xprt(nn->nfsd_serv, transport, net,
736 PF_INET6, port, SVC_SOCK_ANONYMOUS);
737 if (err < 0 && err != -EAFNOSUPPORT)
738 goto out_close;
739
740
741 nn->nfsd_serv->sv_nrthreads--;
742 return 0;
743out_close:
744 xprt = svc_find_xprt(nn->nfsd_serv, transport, net, PF_INET, port);
745 if (xprt != NULL) {
746 svc_close_xprt(xprt);
747 svc_xprt_put(xprt);
748 }
749out_err:
750 nfsd_destroy(net);
751 return err;
752}
753
754static ssize_t __write_ports(struct file *file, char *buf, size_t size,
755 struct net *net)
756{
757 if (size == 0)
758 return __write_ports_names(buf, net);
759
760 if (isdigit(buf[0]))
761 return __write_ports_addfd(buf, net);
762
763 if (isalpha(buf[0]))
764 return __write_ports_addxprt(buf, net);
765
766 return -EINVAL;
767}
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812static ssize_t write_ports(struct file *file, char *buf, size_t size)
813{
814 ssize_t rv;
815 struct net *net = file->f_dentry->d_sb->s_fs_info;
816
817 mutex_lock(&nfsd_mutex);
818 rv = __write_ports(file, buf, size, net);
819 mutex_unlock(&nfsd_mutex);
820 return rv;
821}
822
823
824int nfsd_max_blksize;
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
848{
849 char *mesg = buf;
850 struct net *net = file->f_dentry->d_sb->s_fs_info;
851 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
852
853 if (size > 0) {
854 int bsize;
855 int rv = get_int(&mesg, &bsize);
856 if (rv)
857 return rv;
858
859
860
861 if (bsize < 1024)
862 bsize = 1024;
863 if (bsize > NFSSVC_MAXBLKSIZE)
864 bsize = NFSSVC_MAXBLKSIZE;
865 bsize &= ~(1024-1);
866 mutex_lock(&nfsd_mutex);
867 if (nn->nfsd_serv) {
868 mutex_unlock(&nfsd_mutex);
869 return -EBUSY;
870 }
871 nfsd_max_blksize = bsize;
872 mutex_unlock(&nfsd_mutex);
873 }
874
875 return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n",
876 nfsd_max_blksize);
877}
878
879#ifdef CONFIG_NFSD_V4
880static ssize_t __nfsd4_write_time(struct file *file, char *buf, size_t size,
881 time_t *time, struct nfsd_net *nn)
882{
883 char *mesg = buf;
884 int rv, i;
885
886 if (size > 0) {
887 if (nn->nfsd_serv)
888 return -EBUSY;
889 rv = get_int(&mesg, &i);
890 if (rv)
891 return rv;
892
893
894
895
896
897
898
899
900
901
902
903
904 if (i < 10 || i > 3600)
905 return -EINVAL;
906 *time = i;
907 }
908
909 return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%ld\n", *time);
910}
911
912static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size,
913 time_t *time, struct nfsd_net *nn)
914{
915 ssize_t rv;
916
917 mutex_lock(&nfsd_mutex);
918 rv = __nfsd4_write_time(file, buf, size, time, nn);
919 mutex_unlock(&nfsd_mutex);
920 return rv;
921}
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
945{
946 struct net *net = file->f_dentry->d_sb->s_fs_info;
947 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
948 return nfsd4_write_time(file, buf, size, &nn->nfsd4_lease, nn);
949}
950
951
952
953
954
955
956
957
958
959
960
961static ssize_t write_gracetime(struct file *file, char *buf, size_t size)
962{
963 struct net *net = file->f_dentry->d_sb->s_fs_info;
964 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
965 return nfsd4_write_time(file, buf, size, &nn->nfsd4_grace, nn);
966}
967
968static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size,
969 struct nfsd_net *nn)
970{
971 char *mesg = buf;
972 char *recdir;
973 int len, status;
974
975 if (size > 0) {
976 if (nn->nfsd_serv)
977 return -EBUSY;
978 if (size > PATH_MAX || buf[size-1] != '\n')
979 return -EINVAL;
980 buf[size-1] = 0;
981
982 recdir = mesg;
983 len = qword_get(&mesg, recdir, size);
984 if (len <= 0)
985 return -EINVAL;
986
987 status = nfs4_reset_recoverydir(recdir);
988 if (status)
989 return status;
990 }
991
992 return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%s\n",
993 nfs4_recoverydir());
994}
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
1018{
1019 ssize_t rv;
1020 struct net *net = file->f_dentry->d_sb->s_fs_info;
1021 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
1022
1023 mutex_lock(&nfsd_mutex);
1024 rv = __write_recoverydir(file, buf, size, nn);
1025 mutex_unlock(&nfsd_mutex);
1026 return rv;
1027}
1028
1029#endif
1030
1031
1032
1033
1034
1035
1036static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
1037{
1038 static struct tree_descr nfsd_files[] = {
1039 [NFSD_List] = {"exports", &exports_nfsd_operations, S_IRUGO},
1040 [NFSD_Export_features] = {"export_features",
1041 &export_features_operations, S_IRUGO},
1042 [NFSD_FO_UnlockIP] = {"unlock_ip",
1043 &transaction_ops, S_IWUSR|S_IRUSR},
1044 [NFSD_FO_UnlockFS] = {"unlock_filesystem",
1045 &transaction_ops, S_IWUSR|S_IRUSR},
1046 [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR},
1047 [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
1048 [NFSD_Pool_Threads] = {"pool_threads", &transaction_ops, S_IWUSR|S_IRUSR},
1049 [NFSD_Pool_Stats] = {"pool_stats", &pool_stats_operations, S_IRUGO},
1050 [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR},
1051 [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO},
1052 [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO},
1053#if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE)
1054 [NFSD_SupportedEnctypes] = {"supported_krb5_enctypes", &supported_enctypes_ops, S_IRUGO},
1055#endif
1056#ifdef CONFIG_NFSD_V4
1057 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR},
1058 [NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR},
1059 [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR},
1060#endif
1061 {""}
1062 };
1063 struct net *net = data;
1064 int ret;
1065
1066 ret = simple_fill_super(sb, 0x6e667364, nfsd_files);
1067 if (ret)
1068 return ret;
1069 sb->s_fs_info = get_net(net);
1070 return 0;
1071}
1072
1073static struct dentry *nfsd_mount(struct file_system_type *fs_type,
1074 int flags, const char *dev_name, void *data)
1075{
1076 return mount_ns(fs_type, flags, current->nsproxy->net_ns, nfsd_fill_super);
1077}
1078
1079static void nfsd_umount(struct super_block *sb)
1080{
1081 struct net *net = sb->s_fs_info;
1082
1083 kill_litter_super(sb);
1084 put_net(net);
1085}
1086
1087static struct file_system_type nfsd_fs_type = {
1088 .owner = THIS_MODULE,
1089 .name = "nfsd",
1090 .mount = nfsd_mount,
1091 .kill_sb = nfsd_umount,
1092};
1093MODULE_ALIAS_FS("nfsd");
1094
1095#ifdef CONFIG_PROC_FS
1096static int create_proc_exports_entry(void)
1097{
1098 struct proc_dir_entry *entry;
1099
1100 entry = proc_mkdir("fs/nfs", NULL);
1101 if (!entry)
1102 return -ENOMEM;
1103 entry = proc_create("exports", 0, entry,
1104 &exports_proc_operations);
1105 if (!entry)
1106 return -ENOMEM;
1107 return 0;
1108}
1109#else
1110static int create_proc_exports_entry(void)
1111{
1112 return 0;
1113}
1114#endif
1115
1116int nfsd_net_id;
1117
1118static __net_init int nfsd_init_net(struct net *net)
1119{
1120 int retval;
1121 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
1122
1123 retval = nfsd_export_init(net);
1124 if (retval)
1125 goto out_export_error;
1126 retval = nfsd_idmap_init(net);
1127 if (retval)
1128 goto out_idmap_error;
1129 nn->nfsd4_lease = 90;
1130 nn->nfsd4_grace = 90;
1131 return 0;
1132
1133out_idmap_error:
1134 nfsd_export_shutdown(net);
1135out_export_error:
1136 return retval;
1137}
1138
1139static __net_exit void nfsd_exit_net(struct net *net)
1140{
1141 nfsd_idmap_shutdown(net);
1142 nfsd_export_shutdown(net);
1143}
1144
1145static struct pernet_operations nfsd_net_ops = {
1146 .init = nfsd_init_net,
1147 .exit = nfsd_exit_net,
1148 .id = &nfsd_net_id,
1149 .size = sizeof(struct nfsd_net),
1150};
1151
1152static int __init init_nfsd(void)
1153{
1154 int retval;
1155 printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n");
1156
1157 retval = register_cld_notifier();
1158 if (retval)
1159 return retval;
1160 retval = register_pernet_subsys(&nfsd_net_ops);
1161 if (retval < 0)
1162 goto out_unregister_notifier;
1163 retval = nfsd4_init_slabs();
1164 if (retval)
1165 goto out_unregister_pernet;
1166 nfs4_state_init();
1167 retval = nfsd_fault_inject_init();
1168 if (retval)
1169 goto out_free_slabs;
1170 nfsd_stat_init();
1171 retval = nfsd_reply_cache_init();
1172 if (retval)
1173 goto out_free_stat;
1174 nfsd_lockd_init();
1175 retval = create_proc_exports_entry();
1176 if (retval)
1177 goto out_free_lockd;
1178 retval = register_filesystem(&nfsd_fs_type);
1179 if (retval)
1180 goto out_free_all;
1181 return 0;
1182out_free_all:
1183 remove_proc_entry("fs/nfs/exports", NULL);
1184 remove_proc_entry("fs/nfs", NULL);
1185out_free_lockd:
1186 nfsd_lockd_shutdown();
1187 nfsd_reply_cache_shutdown();
1188out_free_stat:
1189 nfsd_stat_shutdown();
1190 nfsd_fault_inject_cleanup();
1191out_free_slabs:
1192 nfsd4_free_slabs();
1193out_unregister_pernet:
1194 unregister_pernet_subsys(&nfsd_net_ops);
1195out_unregister_notifier:
1196 unregister_cld_notifier();
1197 return retval;
1198}
1199
1200static void __exit exit_nfsd(void)
1201{
1202 nfsd_reply_cache_shutdown();
1203 remove_proc_entry("fs/nfs/exports", NULL);
1204 remove_proc_entry("fs/nfs", NULL);
1205 nfsd_stat_shutdown();
1206 nfsd_lockd_shutdown();
1207 nfsd4_free_slabs();
1208 nfsd_fault_inject_cleanup();
1209 unregister_filesystem(&nfsd_fs_type);
1210 unregister_pernet_subsys(&nfsd_net_ops);
1211 unregister_cld_notifier();
1212}
1213
1214MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
1215MODULE_LICENSE("GPL");
1216module_init(init_nfsd)
1217module_exit(exit_nfsd)
1218