Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
nfsctl.c
Go to the documentation of this file.
1 /*
2  * Syscall interface to knfsd.
3  *
4  * Copyright (C) 1995, 1996 Olaf Kirch <[email protected]>
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>
17 #include <linux/module.h>
18 
19 #include "idmap.h"
20 #include "nfsd.h"
21 #include "cache.h"
22 #include "fault_inject.h"
23 #include "netns.h"
24 
25 /*
26  * We have a single directory with several nodes in it.
27  */
28 enum {
29  NFSD_Root = 1,
42  /*
43  * The below MUST come last. Otherwise we leave a hole in nfsd_files[]
44  * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops
45  */
46 #ifdef CONFIG_NFSD_V4
47  NFSD_Leasetime,
48  NFSD_Gracetime,
49  NFSD_RecoveryDir,
50 #endif
51 };
52 
53 /*
54  * write() for these nodes.
55  */
56 static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
57 static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size);
58 static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size);
59 static ssize_t write_threads(struct file *file, char *buf, size_t size);
60 static ssize_t write_pool_threads(struct file *file, char *buf, size_t size);
61 static ssize_t write_versions(struct file *file, char *buf, size_t size);
62 static ssize_t write_ports(struct file *file, char *buf, size_t size);
63 static ssize_t write_maxblksize(struct file *file, char *buf, size_t size);
64 #ifdef CONFIG_NFSD_V4
65 static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
66 static ssize_t write_gracetime(struct file *file, char *buf, size_t size);
67 static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
68 #endif
69 
70 static 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 
86 static 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 
107 static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
108 {
109  if (! file->private_data) {
110  /* An attempt to read a transaction file without writing
111  * causes a 0-byte write so that the file can return
112  * state information
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 
121 static 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 
128 static int exports_open(struct inode *inode, struct file *file)
129 {
130  int err;
131  struct seq_file *seq;
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 
143 static 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 
151 static 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 
157 static int export_features_open(struct inode *inode, struct file *file)
158 {
159  return single_open(file, export_features_show, NULL);
160 }
161 
162 static 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)
170 static int supported_enctypes_show(struct seq_file *m, void *v)
171 {
173  return 0;
174 }
175 
176 static int supported_enctypes_open(struct inode *inode, struct file *file)
177 {
178  return single_open(file, supported_enctypes_show, NULL);
179 }
180 
181 static 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 /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */
188 
189 extern int nfsd_pool_stats_open(struct inode *inode, struct file *file);
190 extern int nfsd_pool_stats_release(struct inode *inode, struct file *file);
191 
192 static const struct file_operations pool_stats_operations = {
193  .open = nfsd_pool_stats_open,
194  .read = seq_read,
195  .llseek = seq_lseek,
196  .release = nfsd_pool_stats_release,
197  .owner = THIS_MODULE,
198 };
199 
200 /*----------------------------------------------------------------------------*/
201 /*
202  * payload - write methods
203  */
204 
205 
220 static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size)
221 {
222  struct sockaddr_storage address;
223  struct sockaddr *sap = (struct sockaddr *)&address;
224  size_t salen = sizeof(address);
225  char *fo_path;
226 
227  /* sanity check */
228  if (size == 0)
229  return -EINVAL;
230 
231  if (buf[size-1] != '\n')
232  return -EINVAL;
233 
234  fo_path = buf;
235  if (qword_get(&buf, fo_path, size) < 0)
236  return -EINVAL;
237 
238  if (rpc_pton(&init_net, fo_path, size, sap, salen) == 0)
239  return -EINVAL;
240 
241  return nlmsvc_unlock_all_by_ip(sap);
242 }
243 
258 static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size)
259 {
260  struct path path;
261  char *fo_path;
262  int error;
263 
264  /* sanity check */
265  if (size == 0)
266  return -EINVAL;
267 
268  if (buf[size-1] != '\n')
269  return -EINVAL;
270 
271  fo_path = buf;
272  if (qword_get(&buf, fo_path, size) < 0)
273  return -EINVAL;
274 
275  error = kern_path(fo_path, 0, &path);
276  if (error)
277  return error;
278 
279  /*
280  * XXX: Needs better sanity checking. Otherwise we could end up
281  * releasing locks on the wrong file system.
282  *
283  * For example:
284  * 1. Does the path refer to a directory?
285  * 2. Is that directory a mount point, or
286  * 3. Is that directory the root of an exported file system?
287  */
288  error = nlmsvc_unlock_all_by_sb(path.dentry->d_sb);
289 
290  path_put(&path);
291  return error;
292 }
293 
315 static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
316 {
317  char *dname, *path;
318  int uninitialized_var(maxsize);
319  char *mesg = buf;
320  int len;
321  struct auth_domain *dom;
322  struct knfsd_fh fh;
323 
324  if (size == 0)
325  return -EINVAL;
326 
327  if (buf[size-1] != '\n')
328  return -EINVAL;
329  buf[size-1] = 0;
330 
331  dname = mesg;
332  len = qword_get(&mesg, dname, size);
333  if (len <= 0)
334  return -EINVAL;
335 
336  path = dname+len+1;
337  len = qword_get(&mesg, path, size);
338  if (len <= 0)
339  return -EINVAL;
340 
341  len = get_int(&mesg, &maxsize);
342  if (len)
343  return len;
344 
345  if (maxsize < NFS_FHSIZE)
346  return -EINVAL;
347  if (maxsize > NFS3_FHSIZE)
348  maxsize = NFS3_FHSIZE;
349 
350  if (qword_get(&mesg, mesg, size)>0)
351  return -EINVAL;
352 
353  /* we have all the words, they are in buf.. */
354  dom = unix_domain_find(dname);
355  if (!dom)
356  return -ENOMEM;
357 
358  len = exp_rootfh(&init_net, dom, path, &fh, maxsize);
359  auth_domain_put(dom);
360  if (len)
361  return len;
362 
363  mesg = buf;
365  qword_addhex(&mesg, &len, (char*)&fh.fh_base, fh.fh_size);
366  mesg[-1] = '\n';
367  return mesg - buf;
368 }
369 
398 static ssize_t write_threads(struct file *file, char *buf, size_t size)
399 {
400  char *mesg = buf;
401  int rv;
402  if (size > 0) {
403  int newthreads;
404  rv = get_int(&mesg, &newthreads);
405  if (rv)
406  return rv;
407  if (newthreads < 0)
408  return -EINVAL;
409  rv = nfsd_svc(newthreads);
410  if (rv < 0)
411  return rv;
412  } else
413  rv = nfsd_nrthreads();
414 
415  return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n", rv);
416 }
417 
440 static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
441 {
442  /* if size > 0, look for an array of number of threads per node
443  * and apply them then write out number of threads per node as reply
444  */
445  char *mesg = buf;
446  int i;
447  int rv;
448  int len;
449  int npools;
450  int *nthreads;
451 
452  mutex_lock(&nfsd_mutex);
453  npools = nfsd_nrpools();
454  if (npools == 0) {
455  /*
456  * NFS is shut down. The admin can start it by
457  * writing to the threads file but NOT the pool_threads
458  * file, sorry. Report zero threads.
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; /* fewer numbers than pools */
475  if (rv)
476  goto out_free; /* syntax error */
477  rv = -EINVAL;
478  if (nthreads[i] < 0)
479  goto out_free;
480  }
481  rv = nfsd_set_nrthreads(i, nthreads);
482  if (rv)
483  goto out_free;
484  }
485 
486  rv = nfsd_get_nrthreads(npools, nthreads);
487  if (rv)
488  goto out_free;
489 
490  mesg = buf;
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;
499 out_free:
500  kfree(nthreads);
501  mutex_unlock(&nfsd_mutex);
502  return rv;
503 }
504 
505 static 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 
514  if (size>0) {
515  if (nfsd_serv)
516  /* Cannot change versions without updating
517  * nfsd_serv->sv_xdrsize, and reallocing
518  * rq_argp and rq_resp
519  */
520  return -EBUSY;
521  if (buf[size-1] != '\n')
522  return -EINVAL;
523  buf[size-1] = 0;
524 
525  vers = mesg;
526  len = qword_get(&mesg, vers, size);
527  if (len <= 0) return -EINVAL;
528  do {
529  sign = *vers;
530  if (sign == '+' || sign == '-')
531  num = simple_strtol((vers+1), &minorp, 0);
532  else
533  num = simple_strtol(vers, &minorp, 0);
534  if (*minorp == '.') {
535  if (num < 4)
536  return -EINVAL;
537  minor = simple_strtoul(minorp+1, NULL, 0);
538  if (minor == 0)
539  return -EINVAL;
540  if (nfsd_minorversion(minor, sign == '-' ?
541  NFSD_CLEAR : NFSD_SET) < 0)
542  return -EINVAL;
543  goto next;
544  }
545  switch(num) {
546  case 2:
547  case 3:
548  case 4:
549  nfsd_vers(num, sign == '-' ? NFSD_CLEAR : NFSD_SET);
550  break;
551  default:
552  return -EINVAL;
553  }
554  next:
555  vers += len + 1;
556  } while ((len = qword_get(&mesg, vers, size)) > 0);
557  /* If all get turned off, turn them back on, as
558  * having no versions is BAD
559  */
561  }
562 
563  /* Now write current state into reply buffer */
564  len = 0;
565  sep = "";
566  remaining = SIMPLE_TRANSACTION_LIMIT;
567  for (num=2 ; num <= 4 ; num++)
568  if (nfsd_vers(num, NFSD_AVAIL)) {
569  len = snprintf(buf, remaining, "%s%c%d", sep,
570  nfsd_vers(num, NFSD_TEST)?'+':'-',
571  num);
572  sep = " ";
573 
574  if (len > remaining)
575  break;
576  remaining -= len;
577  buf += len;
578  tlen += len;
579  }
580  if (nfsd_vers(4, NFSD_AVAIL))
581  for (minor = 1; minor <= NFSD_SUPPORTED_MINOR_VERSION;
582  minor++) {
583  len = snprintf(buf, remaining, " %c4.%u",
584  (nfsd_vers(4, NFSD_TEST) &&
585  nfsd_minorversion(minor, NFSD_TEST)) ?
586  '+' : '-',
587  minor);
588 
589  if (len > remaining)
590  break;
591  remaining -= len;
592  buf += len;
593  tlen += len;
594  }
595 
596  len = snprintf(buf, remaining, "\n");
597  if (len > remaining)
598  return -EINVAL;
599  return tlen + len;
600 }
601 
634 static ssize_t write_versions(struct file *file, char *buf, size_t size)
635 {
636  ssize_t rv;
637 
638  mutex_lock(&nfsd_mutex);
639  rv = __write_versions(file, buf, size);
640  mutex_unlock(&nfsd_mutex);
641  return rv;
642 }
643 
644 /*
645  * Zero-length write. Return a list of NFSD's current listener
646  * transports.
647  */
648 static ssize_t __write_ports_names(char *buf)
649 {
650  if (nfsd_serv == NULL)
651  return 0;
653 }
654 
655 /*
656  * A single 'fd' number was written, in which case it must be for
657  * a socket of a supported family/protocol, and we use it as an
658  * nfsd listener.
659  */
660 static ssize_t __write_ports_addfd(char *buf)
661 {
662  char *mesg = buf;
663  int fd, err;
664  struct net *net = &init_net;
665 
666  err = get_int(&mesg, &fd);
667  if (err != 0 || fd < 0)
668  return -EINVAL;
669 
670  err = nfsd_create_serv();
671  if (err != 0)
672  return err;
673 
675  if (err < 0) {
676  nfsd_destroy(net);
677  return err;
678  }
679 
680  /* Decrease the count, but don't shut down the service */
681  nfsd_serv->sv_nrthreads--;
682  return err;
683 }
684 
685 /*
686  * A transport listener is added by writing it's transport name and
687  * a port number.
688  */
689 static ssize_t __write_ports_addxprt(char *buf)
690 {
691  char transport[16];
692  struct svc_xprt *xprt;
693  int port, err;
694  struct net *net = &init_net;
695 
696  if (sscanf(buf, "%15s %5u", transport, &port) != 2)
697  return -EINVAL;
698 
700  return -EINVAL;
701 
702  err = nfsd_create_serv();
703  if (err != 0)
704  return err;
705 
706  err = svc_create_xprt(nfsd_serv, transport, net,
707  PF_INET, port, SVC_SOCK_ANONYMOUS);
708  if (err < 0)
709  goto out_err;
710 
711  err = svc_create_xprt(nfsd_serv, transport, net,
713  if (err < 0 && err != -EAFNOSUPPORT)
714  goto out_close;
715 
716  /* Decrease the count, but don't shut down the service */
717  nfsd_serv->sv_nrthreads--;
718  return 0;
719 out_close:
720  xprt = svc_find_xprt(nfsd_serv, transport, net, PF_INET, port);
721  if (xprt != NULL) {
722  svc_close_xprt(xprt);
723  svc_xprt_put(xprt);
724  }
725 out_err:
726  nfsd_destroy(net);
727  return err;
728 }
729 
730 static ssize_t __write_ports(struct file *file, char *buf, size_t size)
731 {
732  if (size == 0)
733  return __write_ports_names(buf);
734 
735  if (isdigit(buf[0]))
736  return __write_ports_addfd(buf);
737 
738  if (isalpha(buf[0]))
739  return __write_ports_addxprt(buf);
740 
741  return -EINVAL;
742 }
743 
787 static ssize_t write_ports(struct file *file, char *buf, size_t size)
788 {
789  ssize_t rv;
790 
791  mutex_lock(&nfsd_mutex);
792  rv = __write_ports(file, buf, size);
793  mutex_unlock(&nfsd_mutex);
794  return rv;
795 }
796 
797 
799 
821 static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
822 {
823  char *mesg = buf;
824  if (size > 0) {
825  int bsize;
826  int rv = get_int(&mesg, &bsize);
827  if (rv)
828  return rv;
829  /* force bsize into allowed range and
830  * required alignment.
831  */
832  if (bsize < 1024)
833  bsize = 1024;
834  if (bsize > NFSSVC_MAXBLKSIZE)
835  bsize = NFSSVC_MAXBLKSIZE;
836  bsize &= ~(1024-1);
838  if (nfsd_serv) {
840  return -EBUSY;
841  }
842  nfsd_max_blksize = bsize;
844  }
845 
846  return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n",
847  nfsd_max_blksize);
848 }
849 
850 #ifdef CONFIG_NFSD_V4
851 static ssize_t __nfsd4_write_time(struct file *file, char *buf, size_t size, time_t *time)
852 {
853  char *mesg = buf;
854  int rv, i;
855 
856  if (size > 0) {
857  if (nfsd_serv)
858  return -EBUSY;
859  rv = get_int(&mesg, &i);
860  if (rv)
861  return rv;
862  /*
863  * Some sanity checking. We don't have a reason for
864  * these particular numbers, but problems with the
865  * extremes are:
866  * - Too short: the briefest network outage may
867  * cause clients to lose all their locks. Also,
868  * the frequent polling may be wasteful.
869  * - Too long: do you really want reboot recovery
870  * to take more than an hour? Or to make other
871  * clients wait an hour before being able to
872  * revoke a dead client's locks?
873  */
874  if (i < 10 || i > 3600)
875  return -EINVAL;
876  *time = i;
877  }
878 
879  return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%ld\n", *time);
880 }
881 
882 static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size, time_t *time)
883 {
884  ssize_t rv;
885 
886  mutex_lock(&nfsd_mutex);
887  rv = __nfsd4_write_time(file, buf, size, time);
888  mutex_unlock(&nfsd_mutex);
889  return rv;
890 }
891 
913 static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
914 {
915  return nfsd4_write_time(file, buf, size, &nfsd4_lease);
916 }
917 
928 static ssize_t write_gracetime(struct file *file, char *buf, size_t size)
929 {
930  return nfsd4_write_time(file, buf, size, &nfsd4_grace);
931 }
932 
933 static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size)
934 {
935  char *mesg = buf;
936  char *recdir;
937  int len, status;
938 
939  if (size > 0) {
940  if (nfsd_serv)
941  return -EBUSY;
942  if (size > PATH_MAX || buf[size-1] != '\n')
943  return -EINVAL;
944  buf[size-1] = 0;
945 
946  recdir = mesg;
947  len = qword_get(&mesg, recdir, size);
948  if (len <= 0)
949  return -EINVAL;
950 
951  status = nfs4_reset_recoverydir(recdir);
952  if (status)
953  return status;
954  }
955 
956  return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%s\n",
957  nfs4_recoverydir());
958 }
959 
981 static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
982 {
983  ssize_t rv;
984 
985  mutex_lock(&nfsd_mutex);
986  rv = __write_recoverydir(file, buf, size);
987  mutex_unlock(&nfsd_mutex);
988  return rv;
989 }
990 
991 #endif
992 
993 /*----------------------------------------------------------------------------*/
994 /*
995  * populating the filesystem.
996  */
997 
998 static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
999 {
1000  static struct tree_descr nfsd_files[] = {
1001  [NFSD_List] = {"exports", &exports_operations, S_IRUGO},
1002  [NFSD_Export_features] = {"export_features",
1003  &export_features_operations, S_IRUGO},
1004  [NFSD_FO_UnlockIP] = {"unlock_ip",
1005  &transaction_ops, S_IWUSR|S_IRUSR},
1006  [NFSD_FO_UnlockFS] = {"unlock_filesystem",
1007  &transaction_ops, S_IWUSR|S_IRUSR},
1008  [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR},
1009  [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
1010  [NFSD_Pool_Threads] = {"pool_threads", &transaction_ops, S_IWUSR|S_IRUSR},
1011  [NFSD_Pool_Stats] = {"pool_stats", &pool_stats_operations, S_IRUGO},
1012  [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR},
1013  [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO},
1014  [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO},
1015 #if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE)
1016  [NFSD_SupportedEnctypes] = {"supported_krb5_enctypes", &supported_enctypes_ops, S_IRUGO},
1017 #endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */
1018 #ifdef CONFIG_NFSD_V4
1019  [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR},
1020  [NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR},
1021  [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR},
1022 #endif
1023  /* last one */ {""}
1024  };
1025  return simple_fill_super(sb, 0x6e667364, nfsd_files);
1026 }
1027 
1028 static struct dentry *nfsd_mount(struct file_system_type *fs_type,
1029  int flags, const char *dev_name, void *data)
1030 {
1031  return mount_single(fs_type, flags, data, nfsd_fill_super);
1032 }
1033 
1034 static struct file_system_type nfsd_fs_type = {
1035  .owner = THIS_MODULE,
1036  .name = "nfsd",
1037  .mount = nfsd_mount,
1038  .kill_sb = kill_litter_super,
1039 };
1040 
1041 #ifdef CONFIG_PROC_FS
1042 static int create_proc_exports_entry(void)
1043 {
1044  struct proc_dir_entry *entry;
1045 
1046  entry = proc_mkdir("fs/nfs", NULL);
1047  if (!entry)
1048  return -ENOMEM;
1049  entry = proc_create("exports", 0, entry, &exports_operations);
1050  if (!entry)
1051  return -ENOMEM;
1052  return 0;
1053 }
1054 #else /* CONFIG_PROC_FS */
1055 static int create_proc_exports_entry(void)
1056 {
1057  return 0;
1058 }
1059 #endif
1060 
1062 
1063 static __net_init int nfsd_init_net(struct net *net)
1064 {
1065  int retval;
1066 
1067  retval = nfsd_export_init(net);
1068  if (retval)
1069  goto out_export_error;
1070  retval = nfsd_idmap_init(net);
1071  if (retval)
1072  goto out_idmap_error;
1073  return 0;
1074 
1075 out_idmap_error:
1076  nfsd_export_shutdown(net);
1077 out_export_error:
1078  return retval;
1079 }
1080 
1081 static __net_exit void nfsd_exit_net(struct net *net)
1082 {
1083  nfsd_idmap_shutdown(net);
1084  nfsd_export_shutdown(net);
1085 }
1086 
1087 static struct pernet_operations nfsd_net_ops = {
1088  .init = nfsd_init_net,
1089  .exit = nfsd_exit_net,
1090  .id = &nfsd_net_id,
1091  .size = sizeof(struct nfsd_net),
1092 };
1093 
1094 static int __init init_nfsd(void)
1095 {
1096  int retval;
1097  printk(KERN_INFO "Installing knfsd (copyright (C) 1996 [email protected]).\n");
1098 
1099  retval = register_cld_notifier();
1100  if (retval)
1101  return retval;
1102  retval = register_pernet_subsys(&nfsd_net_ops);
1103  if (retval < 0)
1104  goto out_unregister_notifier;
1105  retval = nfsd4_init_slabs();
1106  if (retval)
1107  goto out_unregister_pernet;
1108  nfs4_state_init();
1109  retval = nfsd_fault_inject_init(); /* nfsd fault injection controls */
1110  if (retval)
1111  goto out_free_slabs;
1112  nfsd_stat_init(); /* Statistics */
1113  retval = nfsd_reply_cache_init();
1114  if (retval)
1115  goto out_free_stat;
1116  nfsd_lockd_init(); /* lockd->nfsd callbacks */
1117  retval = create_proc_exports_entry();
1118  if (retval)
1119  goto out_free_lockd;
1120  retval = register_filesystem(&nfsd_fs_type);
1121  if (retval)
1122  goto out_free_all;
1123  return 0;
1124 out_free_all:
1125  remove_proc_entry("fs/nfs/exports", NULL);
1126  remove_proc_entry("fs/nfs", NULL);
1127 out_free_lockd:
1130 out_free_stat:
1133 out_free_slabs:
1134  nfsd4_free_slabs();
1135 out_unregister_pernet:
1136  unregister_pernet_subsys(&nfsd_net_ops);
1137 out_unregister_notifier:
1139  return retval;
1140 }
1141 
1142 static void __exit exit_nfsd(void)
1143 {
1145  remove_proc_entry("fs/nfs/exports", NULL);
1146  remove_proc_entry("fs/nfs", NULL);
1149  nfsd4_free_slabs();
1151  unregister_filesystem(&nfsd_fs_type);
1152  unregister_pernet_subsys(&nfsd_net_ops);
1154 }
1155 
1156 MODULE_AUTHOR("Olaf Kirch <[email protected]>");
1157 MODULE_LICENSE("GPL");
1158 module_init(init_nfsd)
1159 module_exit(exit_nfsd)