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