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