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 const 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
540nfsd_print_version_support(char *buf, int remaining, const char *sep,
541 unsigned vers, int minor)
542{
543 const char *format = minor < 0 ? "%s%c%u" : "%s%c%u.%u";
544 bool supported = !!nfsd_vers(vers, NFSD_TEST);
545
546 if (vers == 4 && minor >= 0 &&
547 !nfsd_minorversion(minor, NFSD_TEST))
548 supported = false;
549 if (minor == 0 && supported)
550
551
552
553
554
555 return 0;
556 return snprintf(buf, remaining, format, sep,
557 supported ? '+' : '-', vers, minor);
558}
559
560static ssize_t __write_versions(struct file *file, char *buf, size_t size)
561{
562 char *mesg = buf;
563 char *vers, *minorp, sign;
564 int len, num, remaining;
565 ssize_t tlen = 0;
566 char *sep;
567 struct nfsd_net *nn = net_generic(netns(file), nfsd_net_id);
568
569 if (size>0) {
570 if (nn->nfsd_serv)
571
572
573
574
575 return -EBUSY;
576 if (buf[size-1] != '\n')
577 return -EINVAL;
578 buf[size-1] = 0;
579
580 vers = mesg;
581 len = qword_get(&mesg, vers, size);
582 if (len <= 0) return -EINVAL;
583 do {
584 enum vers_op cmd;
585 unsigned minor;
586 sign = *vers;
587 if (sign == '+' || sign == '-')
588 num = simple_strtol((vers+1), &minorp, 0);
589 else
590 num = simple_strtol(vers, &minorp, 0);
591 if (*minorp == '.') {
592 if (num != 4)
593 return -EINVAL;
594 if (kstrtouint(minorp+1, 0, &minor) < 0)
595 return -EINVAL;
596 }
597
598 cmd = sign == '-' ? NFSD_CLEAR : NFSD_SET;
599 switch(num) {
600 case 2:
601 case 3:
602 nfsd_vers(num, cmd);
603 break;
604 case 4:
605 if (*minorp == '.') {
606 if (nfsd_minorversion(minor, cmd) < 0)
607 return -EINVAL;
608 } else if ((cmd == NFSD_SET) != nfsd_vers(num, NFSD_TEST)) {
609
610
611
612
613
614 minor = 0;
615 while (nfsd_minorversion(minor, cmd) >= 0)
616 minor++;
617 }
618 break;
619 default:
620 return -EINVAL;
621 }
622 vers += len + 1;
623 } while ((len = qword_get(&mesg, vers, size)) > 0);
624
625
626
627 nfsd_reset_versions();
628 }
629
630
631 len = 0;
632 sep = "";
633 remaining = SIMPLE_TRANSACTION_LIMIT;
634 for (num=2 ; num <= 4 ; num++) {
635 int minor;
636 if (!nfsd_vers(num, NFSD_AVAIL))
637 continue;
638
639 minor = -1;
640 do {
641 len = nfsd_print_version_support(buf, remaining,
642 sep, num, minor);
643 if (len >= remaining)
644 goto out;
645 remaining -= len;
646 buf += len;
647 tlen += len;
648 minor++;
649 if (len)
650 sep = " ";
651 } while (num == 4 && minor <= NFSD_SUPPORTED_MINOR_VERSION);
652 }
653out:
654 len = snprintf(buf, remaining, "\n");
655 if (len >= remaining)
656 return -EINVAL;
657 return tlen + len;
658}
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692static ssize_t write_versions(struct file *file, char *buf, size_t size)
693{
694 ssize_t rv;
695
696 mutex_lock(&nfsd_mutex);
697 rv = __write_versions(file, buf, size);
698 mutex_unlock(&nfsd_mutex);
699 return rv;
700}
701
702
703
704
705
706static ssize_t __write_ports_names(char *buf, struct net *net)
707{
708 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
709
710 if (nn->nfsd_serv == NULL)
711 return 0;
712 return svc_xprt_names(nn->nfsd_serv, buf, SIMPLE_TRANSACTION_LIMIT);
713}
714
715
716
717
718
719
720static ssize_t __write_ports_addfd(char *buf, struct net *net)
721{
722 char *mesg = buf;
723 int fd, err;
724 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
725
726 err = get_int(&mesg, &fd);
727 if (err != 0 || fd < 0)
728 return -EINVAL;
729
730 if (svc_alien_sock(net, fd)) {
731 printk(KERN_ERR "%s: socket net is different to NFSd's one\n", __func__);
732 return -EINVAL;
733 }
734
735 err = nfsd_create_serv(net);
736 if (err != 0)
737 return err;
738
739 err = svc_addsock(nn->nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT);
740 if (err < 0) {
741 nfsd_destroy(net);
742 return err;
743 }
744
745
746 nn->nfsd_serv->sv_nrthreads--;
747 return err;
748}
749
750
751
752
753
754static ssize_t __write_ports_addxprt(char *buf, struct net *net)
755{
756 char transport[16];
757 struct svc_xprt *xprt;
758 int port, err;
759 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
760
761 if (sscanf(buf, "%15s %5u", transport, &port) != 2)
762 return -EINVAL;
763
764 if (port < 1 || port > USHRT_MAX)
765 return -EINVAL;
766
767 err = nfsd_create_serv(net);
768 if (err != 0)
769 return err;
770
771 err = svc_create_xprt(nn->nfsd_serv, transport, net,
772 PF_INET, port, SVC_SOCK_ANONYMOUS);
773 if (err < 0)
774 goto out_err;
775
776 err = svc_create_xprt(nn->nfsd_serv, transport, net,
777 PF_INET6, port, SVC_SOCK_ANONYMOUS);
778 if (err < 0 && err != -EAFNOSUPPORT)
779 goto out_close;
780
781
782 nn->nfsd_serv->sv_nrthreads--;
783 return 0;
784out_close:
785 xprt = svc_find_xprt(nn->nfsd_serv, transport, net, PF_INET, port);
786 if (xprt != NULL) {
787 svc_close_xprt(xprt);
788 svc_xprt_put(xprt);
789 }
790out_err:
791 nfsd_destroy(net);
792 return err;
793}
794
795static ssize_t __write_ports(struct file *file, char *buf, size_t size,
796 struct net *net)
797{
798 if (size == 0)
799 return __write_ports_names(buf, net);
800
801 if (isdigit(buf[0]))
802 return __write_ports_addfd(buf, net);
803
804 if (isalpha(buf[0]))
805 return __write_ports_addxprt(buf, net);
806
807 return -EINVAL;
808}
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853static ssize_t write_ports(struct file *file, char *buf, size_t size)
854{
855 ssize_t rv;
856
857 mutex_lock(&nfsd_mutex);
858 rv = __write_ports(file, buf, size, netns(file));
859 mutex_unlock(&nfsd_mutex);
860 return rv;
861}
862
863
864int nfsd_max_blksize;
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
888{
889 char *mesg = buf;
890 struct nfsd_net *nn = net_generic(netns(file), nfsd_net_id);
891
892 if (size > 0) {
893 int bsize;
894 int rv = get_int(&mesg, &bsize);
895 if (rv)
896 return rv;
897
898
899
900 bsize = max_t(int, bsize, 1024);
901 bsize = min_t(int, bsize, NFSSVC_MAXBLKSIZE);
902 bsize &= ~(1024-1);
903 mutex_lock(&nfsd_mutex);
904 if (nn->nfsd_serv) {
905 mutex_unlock(&nfsd_mutex);
906 return -EBUSY;
907 }
908 nfsd_max_blksize = bsize;
909 mutex_unlock(&nfsd_mutex);
910 }
911
912 return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n",
913 nfsd_max_blksize);
914}
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936static ssize_t write_maxconn(struct file *file, char *buf, size_t size)
937{
938 char *mesg = buf;
939 struct nfsd_net *nn = net_generic(netns(file), nfsd_net_id);
940 unsigned int maxconn = nn->max_connections;
941
942 if (size > 0) {
943 int rv = get_uint(&mesg, &maxconn);
944
945 if (rv)
946 return rv;
947 nn->max_connections = maxconn;
948 }
949
950 return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%u\n", maxconn);
951}
952
953#ifdef CONFIG_NFSD_V4
954static ssize_t __nfsd4_write_time(struct file *file, char *buf, size_t size,
955 time_t *time, struct nfsd_net *nn)
956{
957 char *mesg = buf;
958 int rv, i;
959
960 if (size > 0) {
961 if (nn->nfsd_serv)
962 return -EBUSY;
963 rv = get_int(&mesg, &i);
964 if (rv)
965 return rv;
966
967
968
969
970
971
972
973
974
975
976
977
978 if (i < 10 || i > 3600)
979 return -EINVAL;
980 *time = i;
981 }
982
983 return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%ld\n", *time);
984}
985
986static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size,
987 time_t *time, struct nfsd_net *nn)
988{
989 ssize_t rv;
990
991 mutex_lock(&nfsd_mutex);
992 rv = __nfsd4_write_time(file, buf, size, time, nn);
993 mutex_unlock(&nfsd_mutex);
994 return rv;
995}
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
1019{
1020 struct nfsd_net *nn = net_generic(netns(file), nfsd_net_id);
1021 return nfsd4_write_time(file, buf, size, &nn->nfsd4_lease, nn);
1022}
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034static ssize_t write_gracetime(struct file *file, char *buf, size_t size)
1035{
1036 struct nfsd_net *nn = net_generic(netns(file), nfsd_net_id);
1037 return nfsd4_write_time(file, buf, size, &nn->nfsd4_grace, nn);
1038}
1039
1040static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size,
1041 struct nfsd_net *nn)
1042{
1043 char *mesg = buf;
1044 char *recdir;
1045 int len, status;
1046
1047 if (size > 0) {
1048 if (nn->nfsd_serv)
1049 return -EBUSY;
1050 if (size > PATH_MAX || buf[size-1] != '\n')
1051 return -EINVAL;
1052 buf[size-1] = 0;
1053
1054 recdir = mesg;
1055 len = qword_get(&mesg, recdir, size);
1056 if (len <= 0)
1057 return -EINVAL;
1058
1059 status = nfs4_reset_recoverydir(recdir);
1060 if (status)
1061 return status;
1062 }
1063
1064 return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%s\n",
1065 nfs4_recoverydir());
1066}
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
1090{
1091 ssize_t rv;
1092 struct nfsd_net *nn = net_generic(netns(file), nfsd_net_id);
1093
1094 mutex_lock(&nfsd_mutex);
1095 rv = __write_recoverydir(file, buf, size, nn);
1096 mutex_unlock(&nfsd_mutex);
1097 return rv;
1098}
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120static ssize_t write_v4_end_grace(struct file *file, char *buf, size_t size)
1121{
1122 struct nfsd_net *nn = net_generic(netns(file), nfsd_net_id);
1123
1124 if (size > 0) {
1125 switch(buf[0]) {
1126 case 'Y':
1127 case 'y':
1128 case '1':
1129 nfsd4_end_grace(nn);
1130 break;
1131 default:
1132 return -EINVAL;
1133 }
1134 }
1135
1136 return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%c\n",
1137 nn->grace_ended ? 'Y' : 'N');
1138}
1139
1140#endif
1141
1142
1143
1144
1145
1146
1147static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
1148{
1149 static const struct tree_descr nfsd_files[] = {
1150 [NFSD_List] = {"exports", &exports_nfsd_operations, S_IRUGO},
1151 [NFSD_Export_features] = {"export_features",
1152 &export_features_operations, S_IRUGO},
1153 [NFSD_FO_UnlockIP] = {"unlock_ip",
1154 &transaction_ops, S_IWUSR|S_IRUSR},
1155 [NFSD_FO_UnlockFS] = {"unlock_filesystem",
1156 &transaction_ops, S_IWUSR|S_IRUSR},
1157 [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR},
1158 [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
1159 [NFSD_Pool_Threads] = {"pool_threads", &transaction_ops, S_IWUSR|S_IRUSR},
1160 [NFSD_Pool_Stats] = {"pool_stats", &pool_stats_operations, S_IRUGO},
1161 [NFSD_Reply_Cache_Stats] = {"reply_cache_stats", &reply_cache_stats_operations, S_IRUGO},
1162 [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR},
1163 [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO},
1164 [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO},
1165 [NFSD_MaxConnections] = {"max_connections", &transaction_ops, S_IWUSR|S_IRUGO},
1166#if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE)
1167 [NFSD_SupportedEnctypes] = {"supported_krb5_enctypes", &supported_enctypes_ops, S_IRUGO},
1168#endif
1169#ifdef CONFIG_NFSD_V4
1170 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR},
1171 [NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR},
1172 [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR},
1173 [NFSD_V4EndGrace] = {"v4_end_grace", &transaction_ops, S_IWUSR|S_IRUGO},
1174#endif
1175 {""}
1176 };
1177 get_net(sb->s_fs_info);
1178 return simple_fill_super(sb, 0x6e667364, nfsd_files);
1179}
1180
1181static struct dentry *nfsd_mount(struct file_system_type *fs_type,
1182 int flags, const char *dev_name, void *data)
1183{
1184 struct net *net = current->nsproxy->net_ns;
1185 return mount_ns(fs_type, flags, data, net, net->user_ns, nfsd_fill_super);
1186}
1187
1188static void nfsd_umount(struct super_block *sb)
1189{
1190 struct net *net = sb->s_fs_info;
1191
1192 kill_litter_super(sb);
1193 put_net(net);
1194}
1195
1196static struct file_system_type nfsd_fs_type = {
1197 .owner = THIS_MODULE,
1198 .name = "nfsd",
1199 .mount = nfsd_mount,
1200 .kill_sb = nfsd_umount,
1201};
1202MODULE_ALIAS_FS("nfsd");
1203
1204#ifdef CONFIG_PROC_FS
1205static int create_proc_exports_entry(void)
1206{
1207 struct proc_dir_entry *entry;
1208
1209 entry = proc_mkdir("fs/nfs", NULL);
1210 if (!entry)
1211 return -ENOMEM;
1212 entry = proc_create("exports", 0, entry,
1213 &exports_proc_operations);
1214 if (!entry) {
1215 remove_proc_entry("fs/nfs", NULL);
1216 return -ENOMEM;
1217 }
1218 return 0;
1219}
1220#else
1221static int create_proc_exports_entry(void)
1222{
1223 return 0;
1224}
1225#endif
1226
1227unsigned int nfsd_net_id;
1228
1229static __net_init int nfsd_init_net(struct net *net)
1230{
1231 int retval;
1232 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
1233
1234 retval = nfsd_export_init(net);
1235 if (retval)
1236 goto out_export_error;
1237 retval = nfsd_idmap_init(net);
1238 if (retval)
1239 goto out_idmap_error;
1240 nn->nfsd4_lease = 90;
1241 nn->nfsd4_grace = 90;
1242 nn->clverifier_counter = prandom_u32();
1243 nn->clientid_counter = prandom_u32();
1244 return 0;
1245
1246out_idmap_error:
1247 nfsd_export_shutdown(net);
1248out_export_error:
1249 return retval;
1250}
1251
1252static __net_exit void nfsd_exit_net(struct net *net)
1253{
1254 nfsd_idmap_shutdown(net);
1255 nfsd_export_shutdown(net);
1256}
1257
1258static struct pernet_operations nfsd_net_ops = {
1259 .init = nfsd_init_net,
1260 .exit = nfsd_exit_net,
1261 .id = &nfsd_net_id,
1262 .size = sizeof(struct nfsd_net),
1263};
1264
1265static int __init init_nfsd(void)
1266{
1267 int retval;
1268 printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n");
1269
1270 retval = register_pernet_subsys(&nfsd_net_ops);
1271 if (retval < 0)
1272 return retval;
1273 retval = register_cld_notifier();
1274 if (retval)
1275 goto out_unregister_pernet;
1276 retval = nfsd4_init_slabs();
1277 if (retval)
1278 goto out_unregister_notifier;
1279 retval = nfsd4_init_pnfs();
1280 if (retval)
1281 goto out_free_slabs;
1282 retval = nfsd_fault_inject_init();
1283 if (retval)
1284 goto out_exit_pnfs;
1285 nfsd_stat_init();
1286 retval = nfsd_reply_cache_init();
1287 if (retval)
1288 goto out_free_stat;
1289 nfsd_lockd_init();
1290 retval = create_proc_exports_entry();
1291 if (retval)
1292 goto out_free_lockd;
1293 retval = register_filesystem(&nfsd_fs_type);
1294 if (retval)
1295 goto out_free_all;
1296 return 0;
1297out_free_all:
1298 remove_proc_entry("fs/nfs/exports", NULL);
1299 remove_proc_entry("fs/nfs", NULL);
1300out_free_lockd:
1301 nfsd_lockd_shutdown();
1302 nfsd_reply_cache_shutdown();
1303out_free_stat:
1304 nfsd_stat_shutdown();
1305 nfsd_fault_inject_cleanup();
1306out_exit_pnfs:
1307 nfsd4_exit_pnfs();
1308out_free_slabs:
1309 nfsd4_free_slabs();
1310out_unregister_notifier:
1311 unregister_cld_notifier();
1312out_unregister_pernet:
1313 unregister_pernet_subsys(&nfsd_net_ops);
1314 return retval;
1315}
1316
1317static void __exit exit_nfsd(void)
1318{
1319 nfsd_reply_cache_shutdown();
1320 remove_proc_entry("fs/nfs/exports", NULL);
1321 remove_proc_entry("fs/nfs", NULL);
1322 nfsd_stat_shutdown();
1323 nfsd_lockd_shutdown();
1324 nfsd4_free_slabs();
1325 nfsd4_exit_pnfs();
1326 nfsd_fault_inject_cleanup();
1327 unregister_filesystem(&nfsd_fs_type);
1328 unregister_cld_notifier();
1329 unregister_pernet_subsys(&nfsd_net_ops);
1330}
1331
1332MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
1333MODULE_LICENSE("GPL");
1334module_init(init_nfsd)
1335module_exit(exit_nfsd)
1336