xref: /linux/fs/nfsd/nfsctl.c (revision 040932cdcfca9b0ac55a4f74f194c2e2c8a2527b)
1 /*
2  * linux/fs/nfsd/nfsctl.c
3  *
4  * Syscall interface to knfsd.
5  *
6  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
7  */
8 
9 #include <linux/module.h>
10 
11 #include <linux/linkage.h>
12 #include <linux/time.h>
13 #include <linux/errno.h>
14 #include <linux/fs.h>
15 #include <linux/namei.h>
16 #include <linux/fcntl.h>
17 #include <linux/net.h>
18 #include <linux/in.h>
19 #include <linux/syscalls.h>
20 #include <linux/unistd.h>
21 #include <linux/slab.h>
22 #include <linux/proc_fs.h>
23 #include <linux/seq_file.h>
24 #include <linux/pagemap.h>
25 #include <linux/init.h>
26 #include <linux/inet.h>
27 #include <linux/string.h>
28 #include <linux/ctype.h>
29 
30 #include <linux/nfs.h>
31 #include <linux/nfsd_idmap.h>
32 #include <linux/lockd/bind.h>
33 #include <linux/sunrpc/svc.h>
34 #include <linux/sunrpc/svcsock.h>
35 #include <linux/nfsd/nfsd.h>
36 #include <linux/nfsd/cache.h>
37 #include <linux/nfsd/xdr.h>
38 #include <linux/nfsd/syscall.h>
39 #include <linux/lockd/lockd.h>
40 #include <linux/sunrpc/clnt.h>
41 
42 #include <asm/uaccess.h>
43 #include <net/ipv6.h>
44 
45 /*
46  *	We have a single directory with 9 nodes in it.
47  */
48 enum {
49 	NFSD_Root = 1,
50 	NFSD_Svc,
51 	NFSD_Add,
52 	NFSD_Del,
53 	NFSD_Export,
54 	NFSD_Unexport,
55 	NFSD_Getfd,
56 	NFSD_Getfs,
57 	NFSD_List,
58 	NFSD_Fh,
59 	NFSD_FO_UnlockIP,
60 	NFSD_FO_UnlockFS,
61 	NFSD_Threads,
62 	NFSD_Pool_Threads,
63 	NFSD_Pool_Stats,
64 	NFSD_Versions,
65 	NFSD_Ports,
66 	NFSD_MaxBlkSize,
67 	/*
68 	 * The below MUST come last.  Otherwise we leave a hole in nfsd_files[]
69 	 * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops
70 	 */
71 #ifdef CONFIG_NFSD_V4
72 	NFSD_Leasetime,
73 	NFSD_RecoveryDir,
74 #endif
75 };
76 
77 /*
78  * write() for these nodes.
79  */
80 static ssize_t write_svc(struct file *file, char *buf, size_t size);
81 static ssize_t write_add(struct file *file, char *buf, size_t size);
82 static ssize_t write_del(struct file *file, char *buf, size_t size);
83 static ssize_t write_export(struct file *file, char *buf, size_t size);
84 static ssize_t write_unexport(struct file *file, char *buf, size_t size);
85 static ssize_t write_getfd(struct file *file, char *buf, size_t size);
86 static ssize_t write_getfs(struct file *file, char *buf, size_t size);
87 static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
88 static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size);
89 static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size);
90 static ssize_t write_threads(struct file *file, char *buf, size_t size);
91 static ssize_t write_pool_threads(struct file *file, char *buf, size_t size);
92 static ssize_t write_versions(struct file *file, char *buf, size_t size);
93 static ssize_t write_ports(struct file *file, char *buf, size_t size);
94 static ssize_t write_maxblksize(struct file *file, char *buf, size_t size);
95 #ifdef CONFIG_NFSD_V4
96 static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
97 static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
98 #endif
99 
100 static ssize_t (*write_op[])(struct file *, char *, size_t) = {
101 	[NFSD_Svc] = write_svc,
102 	[NFSD_Add] = write_add,
103 	[NFSD_Del] = write_del,
104 	[NFSD_Export] = write_export,
105 	[NFSD_Unexport] = write_unexport,
106 	[NFSD_Getfd] = write_getfd,
107 	[NFSD_Getfs] = write_getfs,
108 	[NFSD_Fh] = write_filehandle,
109 	[NFSD_FO_UnlockIP] = write_unlock_ip,
110 	[NFSD_FO_UnlockFS] = write_unlock_fs,
111 	[NFSD_Threads] = write_threads,
112 	[NFSD_Pool_Threads] = write_pool_threads,
113 	[NFSD_Versions] = write_versions,
114 	[NFSD_Ports] = write_ports,
115 	[NFSD_MaxBlkSize] = write_maxblksize,
116 #ifdef CONFIG_NFSD_V4
117 	[NFSD_Leasetime] = write_leasetime,
118 	[NFSD_RecoveryDir] = write_recoverydir,
119 #endif
120 };
121 
122 static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
123 {
124 	ino_t ino =  file->f_path.dentry->d_inode->i_ino;
125 	char *data;
126 	ssize_t rv;
127 
128 	if (ino >= ARRAY_SIZE(write_op) || !write_op[ino])
129 		return -EINVAL;
130 
131 	data = simple_transaction_get(file, buf, size);
132 	if (IS_ERR(data))
133 		return PTR_ERR(data);
134 
135 	rv =  write_op[ino](file, data, size);
136 	if (rv >= 0) {
137 		simple_transaction_set(file, rv);
138 		rv = size;
139 	}
140 	return rv;
141 }
142 
143 static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
144 {
145 	if (! file->private_data) {
146 		/* An attempt to read a transaction file without writing
147 		 * causes a 0-byte write so that the file can return
148 		 * state information
149 		 */
150 		ssize_t rv = nfsctl_transaction_write(file, buf, 0, pos);
151 		if (rv < 0)
152 			return rv;
153 	}
154 	return simple_transaction_read(file, buf, size, pos);
155 }
156 
157 static const struct file_operations transaction_ops = {
158 	.write		= nfsctl_transaction_write,
159 	.read		= nfsctl_transaction_read,
160 	.release	= simple_transaction_release,
161 };
162 
163 static int exports_open(struct inode *inode, struct file *file)
164 {
165 	return seq_open(file, &nfs_exports_op);
166 }
167 
168 static const struct file_operations exports_operations = {
169 	.open		= exports_open,
170 	.read		= seq_read,
171 	.llseek		= seq_lseek,
172 	.release	= seq_release,
173 	.owner		= THIS_MODULE,
174 };
175 
176 extern int nfsd_pool_stats_open(struct inode *inode, struct file *file);
177 
178 static struct file_operations pool_stats_operations = {
179 	.open		= nfsd_pool_stats_open,
180 	.read		= seq_read,
181 	.llseek		= seq_lseek,
182 	.release	= seq_release,
183 	.owner		= THIS_MODULE,
184 };
185 
186 /*----------------------------------------------------------------------------*/
187 /*
188  * payload - write methods
189  */
190 
191 /**
192  * write_svc - Start kernel's NFSD server
193  *
194  * Deprecated.  /proc/fs/nfsd/threads is preferred.
195  * Function remains to support old versions of nfs-utils.
196  *
197  * Input:
198  *			buf:	struct nfsctl_svc
199  *				svc_port:	port number of this
200  *						server's listener
201  *				svc_nthreads:	number of threads to start
202  *			size:	size in bytes of passed in nfsctl_svc
203  * Output:
204  *	On success:	returns zero
205  *	On error:	return code is negative errno value
206  */
207 static ssize_t write_svc(struct file *file, char *buf, size_t size)
208 {
209 	struct nfsctl_svc *data;
210 	int err;
211 	if (size < sizeof(*data))
212 		return -EINVAL;
213 	data = (struct nfsctl_svc*) buf;
214 	err = nfsd_svc(data->svc_port, data->svc_nthreads);
215 	if (err < 0)
216 		return err;
217 	return 0;
218 }
219 
220 /**
221  * write_add - Add or modify client entry in auth unix cache
222  *
223  * Deprecated.  /proc/net/rpc/auth.unix.ip is preferred.
224  * Function remains to support old versions of nfs-utils.
225  *
226  * Input:
227  *			buf:	struct nfsctl_client
228  *				cl_ident:	'\0'-terminated C string
229  *						containing domain name
230  *						of client
231  *				cl_naddr:	no. of items in cl_addrlist
232  *				cl_addrlist:	array of client addresses
233  *				cl_fhkeytype:	ignored
234  *				cl_fhkeylen:	ignored
235  *				cl_fhkey:	ignored
236  *			size:	size in bytes of passed in nfsctl_client
237  * Output:
238  *	On success:	returns zero
239  *	On error:	return code is negative errno value
240  *
241  * Note: Only AF_INET client addresses are passed in, since
242  * nfsctl_client.cl_addrlist contains only in_addr fields for addresses.
243  */
244 static ssize_t write_add(struct file *file, char *buf, size_t size)
245 {
246 	struct nfsctl_client *data;
247 	if (size < sizeof(*data))
248 		return -EINVAL;
249 	data = (struct nfsctl_client *)buf;
250 	return exp_addclient(data);
251 }
252 
253 /**
254  * write_del - Remove client from auth unix cache
255  *
256  * Deprecated.  /proc/net/rpc/auth.unix.ip is preferred.
257  * Function remains to support old versions of nfs-utils.
258  *
259  * Input:
260  *			buf:	struct nfsctl_client
261  *				cl_ident:	'\0'-terminated C string
262  *						containing domain name
263  *						of client
264  *				cl_naddr:	ignored
265  *				cl_addrlist:	ignored
266  *				cl_fhkeytype:	ignored
267  *				cl_fhkeylen:	ignored
268  *				cl_fhkey:	ignored
269  *			size:	size in bytes of passed in nfsctl_client
270  * Output:
271  *	On success:	returns zero
272  *	On error:	return code is negative errno value
273  *
274  * Note: Only AF_INET client addresses are passed in, since
275  * nfsctl_client.cl_addrlist contains only in_addr fields for addresses.
276  */
277 static ssize_t write_del(struct file *file, char *buf, size_t size)
278 {
279 	struct nfsctl_client *data;
280 	if (size < sizeof(*data))
281 		return -EINVAL;
282 	data = (struct nfsctl_client *)buf;
283 	return exp_delclient(data);
284 }
285 
286 /**
287  * write_export - Export part or all of a local file system
288  *
289  * Deprecated.  /proc/net/rpc/{nfsd.export,nfsd.fh} are preferred.
290  * Function remains to support old versions of nfs-utils.
291  *
292  * Input:
293  *			buf:	struct nfsctl_export
294  *				ex_client:	'\0'-terminated C string
295  *						containing domain name
296  *						of client allowed to access
297  *						this export
298  *				ex_path:	'\0'-terminated C string
299  *						containing pathname of
300  *						directory in local file system
301  *				ex_dev:		fsid to use for this export
302  *				ex_ino:		ignored
303  *				ex_flags:	export flags for this export
304  *				ex_anon_uid:	UID to use for anonymous
305  *						requests
306  *				ex_anon_gid:	GID to use for anonymous
307  *						requests
308  *			size:	size in bytes of passed in nfsctl_export
309  * Output:
310  *	On success:	returns zero
311  *	On error:	return code is negative errno value
312  */
313 static ssize_t write_export(struct file *file, char *buf, size_t size)
314 {
315 	struct nfsctl_export *data;
316 	if (size < sizeof(*data))
317 		return -EINVAL;
318 	data = (struct nfsctl_export*)buf;
319 	return exp_export(data);
320 }
321 
322 /**
323  * write_unexport - Unexport a previously exported file system
324  *
325  * Deprecated.  /proc/net/rpc/{nfsd.export,nfsd.fh} are preferred.
326  * Function remains to support old versions of nfs-utils.
327  *
328  * Input:
329  *			buf:	struct nfsctl_export
330  *				ex_client:	'\0'-terminated C string
331  *						containing domain name
332  *						of client no longer allowed
333  *						to access this export
334  *				ex_path:	'\0'-terminated C string
335  *						containing pathname of
336  *						directory in local file system
337  *				ex_dev:		ignored
338  *				ex_ino:		ignored
339  *				ex_flags:	ignored
340  *				ex_anon_uid:	ignored
341  *				ex_anon_gid:	ignored
342  *			size:	size in bytes of passed in nfsctl_export
343  * Output:
344  *	On success:	returns zero
345  *	On error:	return code is negative errno value
346  */
347 static ssize_t write_unexport(struct file *file, char *buf, size_t size)
348 {
349 	struct nfsctl_export *data;
350 
351 	if (size < sizeof(*data))
352 		return -EINVAL;
353 	data = (struct nfsctl_export*)buf;
354 	return exp_unexport(data);
355 }
356 
357 /**
358  * write_getfs - Get a variable-length NFS file handle by path
359  *
360  * Deprecated.  /proc/fs/nfsd/filehandle is preferred.
361  * Function remains to support old versions of nfs-utils.
362  *
363  * Input:
364  *			buf:	struct nfsctl_fsparm
365  *				gd_addr:	socket address of client
366  *				gd_path:	'\0'-terminated C string
367  *						containing pathname of
368  *						directory in local file system
369  *				gd_maxlen:	maximum size of returned file
370  *						handle
371  *			size:	size in bytes of passed in nfsctl_fsparm
372  * Output:
373  *	On success:	passed-in buffer filled with a knfsd_fh structure
374  *			(a variable-length raw NFS file handle);
375  *			return code is the size in bytes of the file handle
376  *	On error:	return code is negative errno value
377  *
378  * Note: Only AF_INET client addresses are passed in, since gd_addr
379  * is the same size as a struct sockaddr_in.
380  */
381 static ssize_t write_getfs(struct file *file, char *buf, size_t size)
382 {
383 	struct nfsctl_fsparm *data;
384 	struct sockaddr_in *sin;
385 	struct auth_domain *clp;
386 	int err = 0;
387 	struct knfsd_fh *res;
388 	struct in6_addr in6;
389 
390 	if (size < sizeof(*data))
391 		return -EINVAL;
392 	data = (struct nfsctl_fsparm*)buf;
393 	err = -EPROTONOSUPPORT;
394 	if (data->gd_addr.sa_family != AF_INET)
395 		goto out;
396 	sin = (struct sockaddr_in *)&data->gd_addr;
397 	if (data->gd_maxlen > NFS3_FHSIZE)
398 		data->gd_maxlen = NFS3_FHSIZE;
399 
400 	res = (struct knfsd_fh*)buf;
401 
402 	exp_readlock();
403 
404 	ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
405 
406 	clp = auth_unix_lookup(&in6);
407 	if (!clp)
408 		err = -EPERM;
409 	else {
410 		err = exp_rootfh(clp, data->gd_path, res, data->gd_maxlen);
411 		auth_domain_put(clp);
412 	}
413 	exp_readunlock();
414 	if (err == 0)
415 		err = res->fh_size + offsetof(struct knfsd_fh, fh_base);
416  out:
417 	return err;
418 }
419 
420 /**
421  * write_getfd - Get a fixed-length NFS file handle by path (used by mountd)
422  *
423  * Deprecated.  /proc/fs/nfsd/filehandle is preferred.
424  * Function remains to support old versions of nfs-utils.
425  *
426  * Input:
427  *			buf:	struct nfsctl_fdparm
428  *				gd_addr:	socket address of client
429  *				gd_path:	'\0'-terminated C string
430  *						containing pathname of
431  *						directory in local file system
432  *				gd_version:	fdparm structure version
433  *			size:	size in bytes of passed in nfsctl_fdparm
434  * Output:
435  *	On success:	passed-in buffer filled with nfsctl_res
436  *			(a fixed-length raw NFS file handle);
437  *			return code is the size in bytes of the file handle
438  *	On error:	return code is negative errno value
439  *
440  * Note: Only AF_INET client addresses are passed in, since gd_addr
441  * is the same size as a struct sockaddr_in.
442  */
443 static ssize_t write_getfd(struct file *file, char *buf, size_t size)
444 {
445 	struct nfsctl_fdparm *data;
446 	struct sockaddr_in *sin;
447 	struct auth_domain *clp;
448 	int err = 0;
449 	struct knfsd_fh fh;
450 	char *res;
451 	struct in6_addr in6;
452 
453 	if (size < sizeof(*data))
454 		return -EINVAL;
455 	data = (struct nfsctl_fdparm*)buf;
456 	err = -EPROTONOSUPPORT;
457 	if (data->gd_addr.sa_family != AF_INET)
458 		goto out;
459 	err = -EINVAL;
460 	if (data->gd_version < 2 || data->gd_version > NFSSVC_MAXVERS)
461 		goto out;
462 
463 	res = buf;
464 	sin = (struct sockaddr_in *)&data->gd_addr;
465 	exp_readlock();
466 
467 	ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
468 
469 	clp = auth_unix_lookup(&in6);
470 	if (!clp)
471 		err = -EPERM;
472 	else {
473 		err = exp_rootfh(clp, data->gd_path, &fh, NFS_FHSIZE);
474 		auth_domain_put(clp);
475 	}
476 	exp_readunlock();
477 
478 	if (err == 0) {
479 		memset(res,0, NFS_FHSIZE);
480 		memcpy(res, &fh.fh_base, fh.fh_size);
481 		err = NFS_FHSIZE;
482 	}
483  out:
484 	return err;
485 }
486 
487 /**
488  * write_unlock_ip - Release all locks used by a client
489  *
490  * Experimental.
491  *
492  * Input:
493  *			buf:	'\n'-terminated C string containing a
494  *				presentation format IP address
495  *			size:	length of C string in @buf
496  * Output:
497  *	On success:	returns zero if all specified locks were released;
498  *			returns one if one or more locks were not released
499  *	On error:	return code is negative errno value
500  */
501 static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size)
502 {
503 	struct sockaddr_storage address;
504 	struct sockaddr *sap = (struct sockaddr *)&address;
505 	size_t salen = sizeof(address);
506 	char *fo_path;
507 
508 	/* sanity check */
509 	if (size == 0)
510 		return -EINVAL;
511 
512 	if (buf[size-1] != '\n')
513 		return -EINVAL;
514 
515 	fo_path = buf;
516 	if (qword_get(&buf, fo_path, size) < 0)
517 		return -EINVAL;
518 
519 	if (rpc_pton(fo_path, size, sap, salen) == 0)
520 		return -EINVAL;
521 
522 	return nlmsvc_unlock_all_by_ip(sap);
523 }
524 
525 /**
526  * write_unlock_fs - Release all locks on a local file system
527  *
528  * Experimental.
529  *
530  * Input:
531  *			buf:	'\n'-terminated C string containing the
532  *				absolute pathname of a local file system
533  *			size:	length of C string in @buf
534  * Output:
535  *	On success:	returns zero if all specified locks were released;
536  *			returns one if one or more locks were not released
537  *	On error:	return code is negative errno value
538  */
539 static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size)
540 {
541 	struct path path;
542 	char *fo_path;
543 	int error;
544 
545 	/* sanity check */
546 	if (size == 0)
547 		return -EINVAL;
548 
549 	if (buf[size-1] != '\n')
550 		return -EINVAL;
551 
552 	fo_path = buf;
553 	if (qword_get(&buf, fo_path, size) < 0)
554 		return -EINVAL;
555 
556 	error = kern_path(fo_path, 0, &path);
557 	if (error)
558 		return error;
559 
560 	/*
561 	 * XXX: Needs better sanity checking.  Otherwise we could end up
562 	 * releasing locks on the wrong file system.
563 	 *
564 	 * For example:
565 	 * 1.  Does the path refer to a directory?
566 	 * 2.  Is that directory a mount point, or
567 	 * 3.  Is that directory the root of an exported file system?
568 	 */
569 	error = nlmsvc_unlock_all_by_sb(path.mnt->mnt_sb);
570 
571 	path_put(&path);
572 	return error;
573 }
574 
575 /**
576  * write_filehandle - Get a variable-length NFS file handle by path
577  *
578  * On input, the buffer contains a '\n'-terminated C string comprised of
579  * three alphanumeric words separated by whitespace.  The string may
580  * contain escape sequences.
581  *
582  * Input:
583  *			buf:
584  *				domain:		client domain name
585  *				path:		export pathname
586  *				maxsize:	numeric maximum size of
587  *						@buf
588  *			size:	length of C string in @buf
589  * Output:
590  *	On success:	passed-in buffer filled with '\n'-terminated C
591  *			string containing a ASCII hex text version
592  *			of the NFS file handle;
593  *			return code is the size in bytes of the string
594  *	On error:	return code is negative errno value
595  */
596 static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
597 {
598 	char *dname, *path;
599 	int uninitialized_var(maxsize);
600 	char *mesg = buf;
601 	int len;
602 	struct auth_domain *dom;
603 	struct knfsd_fh fh;
604 
605 	if (size == 0)
606 		return -EINVAL;
607 
608 	if (buf[size-1] != '\n')
609 		return -EINVAL;
610 	buf[size-1] = 0;
611 
612 	dname = mesg;
613 	len = qword_get(&mesg, dname, size);
614 	if (len <= 0)
615 		return -EINVAL;
616 
617 	path = dname+len+1;
618 	len = qword_get(&mesg, path, size);
619 	if (len <= 0)
620 		return -EINVAL;
621 
622 	len = get_int(&mesg, &maxsize);
623 	if (len)
624 		return len;
625 
626 	if (maxsize < NFS_FHSIZE)
627 		return -EINVAL;
628 	if (maxsize > NFS3_FHSIZE)
629 		maxsize = NFS3_FHSIZE;
630 
631 	if (qword_get(&mesg, mesg, size)>0)
632 		return -EINVAL;
633 
634 	/* we have all the words, they are in buf.. */
635 	dom = unix_domain_find(dname);
636 	if (!dom)
637 		return -ENOMEM;
638 
639 	len = exp_rootfh(dom, path, &fh,  maxsize);
640 	auth_domain_put(dom);
641 	if (len)
642 		return len;
643 
644 	mesg = buf;
645 	len = SIMPLE_TRANSACTION_LIMIT;
646 	qword_addhex(&mesg, &len, (char*)&fh.fh_base, fh.fh_size);
647 	mesg[-1] = '\n';
648 	return mesg - buf;
649 }
650 
651 /**
652  * write_threads - Start NFSD, or report the current number of running threads
653  *
654  * Input:
655  *			buf:		ignored
656  *			size:		zero
657  * Output:
658  *	On success:	passed-in buffer filled with '\n'-terminated C
659  *			string numeric value representing the number of
660  *			running NFSD threads;
661  *			return code is the size in bytes of the string
662  *	On error:	return code is zero
663  *
664  * OR
665  *
666  * Input:
667  *			buf:		C string containing an unsigned
668  *					integer value representing the
669  *					number of NFSD threads to start
670  *			size:		non-zero length of C string in @buf
671  * Output:
672  *	On success:	NFS service is started;
673  *			passed-in buffer filled with '\n'-terminated C
674  *			string numeric value representing the number of
675  *			running NFSD threads;
676  *			return code is the size in bytes of the string
677  *	On error:	return code is zero or a negative errno value
678  */
679 static ssize_t write_threads(struct file *file, char *buf, size_t size)
680 {
681 	char *mesg = buf;
682 	int rv;
683 	if (size > 0) {
684 		int newthreads;
685 		rv = get_int(&mesg, &newthreads);
686 		if (rv)
687 			return rv;
688 		if (newthreads < 0)
689 			return -EINVAL;
690 		rv = nfsd_svc(NFS_PORT, newthreads);
691 		if (rv < 0)
692 			return rv;
693 	} else
694 		rv = nfsd_nrthreads();
695 
696 	return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n", rv);
697 }
698 
699 /**
700  * write_pool_threads - Set or report the current number of threads per pool
701  *
702  * Input:
703  *			buf:		ignored
704  *			size:		zero
705  *
706  * OR
707  *
708  * Input:
709  * 			buf:		C string containing whitespace-
710  * 					separated unsigned integer values
711  *					representing the number of NFSD
712  *					threads to start in each pool
713  *			size:		non-zero length of C string in @buf
714  * Output:
715  *	On success:	passed-in buffer filled with '\n'-terminated C
716  *			string containing integer values representing the
717  *			number of NFSD threads in each pool;
718  *			return code is the size in bytes of the string
719  *	On error:	return code is zero or a negative errno value
720  */
721 static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
722 {
723 	/* if size > 0, look for an array of number of threads per node
724 	 * and apply them  then write out number of threads per node as reply
725 	 */
726 	char *mesg = buf;
727 	int i;
728 	int rv;
729 	int len;
730 	int npools;
731 	int *nthreads;
732 
733 	mutex_lock(&nfsd_mutex);
734 	npools = nfsd_nrpools();
735 	if (npools == 0) {
736 		/*
737 		 * NFS is shut down.  The admin can start it by
738 		 * writing to the threads file but NOT the pool_threads
739 		 * file, sorry.  Report zero threads.
740 		 */
741 		mutex_unlock(&nfsd_mutex);
742 		strcpy(buf, "0\n");
743 		return strlen(buf);
744 	}
745 
746 	nthreads = kcalloc(npools, sizeof(int), GFP_KERNEL);
747 	rv = -ENOMEM;
748 	if (nthreads == NULL)
749 		goto out_free;
750 
751 	if (size > 0) {
752 		for (i = 0; i < npools; i++) {
753 			rv = get_int(&mesg, &nthreads[i]);
754 			if (rv == -ENOENT)
755 				break;		/* fewer numbers than pools */
756 			if (rv)
757 				goto out_free;	/* syntax error */
758 			rv = -EINVAL;
759 			if (nthreads[i] < 0)
760 				goto out_free;
761 		}
762 		rv = nfsd_set_nrthreads(i, nthreads);
763 		if (rv)
764 			goto out_free;
765 	}
766 
767 	rv = nfsd_get_nrthreads(npools, nthreads);
768 	if (rv)
769 		goto out_free;
770 
771 	mesg = buf;
772 	size = SIMPLE_TRANSACTION_LIMIT;
773 	for (i = 0; i < npools && size > 0; i++) {
774 		snprintf(mesg, size, "%d%c", nthreads[i], (i == npools-1 ? '\n' : ' '));
775 		len = strlen(mesg);
776 		size -= len;
777 		mesg += len;
778 	}
779 
780 	mutex_unlock(&nfsd_mutex);
781 	return (mesg-buf);
782 
783 out_free:
784 	kfree(nthreads);
785 	mutex_unlock(&nfsd_mutex);
786 	return rv;
787 }
788 
789 static ssize_t __write_versions(struct file *file, char *buf, size_t size)
790 {
791 	char *mesg = buf;
792 	char *vers, *minorp, sign;
793 	int len, num, remaining;
794 	unsigned minor;
795 	ssize_t tlen = 0;
796 	char *sep;
797 
798 	if (size>0) {
799 		if (nfsd_serv)
800 			/* Cannot change versions without updating
801 			 * nfsd_serv->sv_xdrsize, and reallocing
802 			 * rq_argp and rq_resp
803 			 */
804 			return -EBUSY;
805 		if (buf[size-1] != '\n')
806 			return -EINVAL;
807 		buf[size-1] = 0;
808 
809 		vers = mesg;
810 		len = qword_get(&mesg, vers, size);
811 		if (len <= 0) return -EINVAL;
812 		do {
813 			sign = *vers;
814 			if (sign == '+' || sign == '-')
815 				num = simple_strtol((vers+1), &minorp, 0);
816 			else
817 				num = simple_strtol(vers, &minorp, 0);
818 			if (*minorp == '.') {
819 				if (num < 4)
820 					return -EINVAL;
821 				minor = simple_strtoul(minorp+1, NULL, 0);
822 				if (minor == 0)
823 					return -EINVAL;
824 				if (nfsd_minorversion(minor, sign == '-' ?
825 						     NFSD_CLEAR : NFSD_SET) < 0)
826 					return -EINVAL;
827 				goto next;
828 			}
829 			switch(num) {
830 			case 2:
831 			case 3:
832 			case 4:
833 				nfsd_vers(num, sign == '-' ? NFSD_CLEAR : NFSD_SET);
834 				break;
835 			default:
836 				return -EINVAL;
837 			}
838 		next:
839 			vers += len + 1;
840 		} while ((len = qword_get(&mesg, vers, size)) > 0);
841 		/* If all get turned off, turn them back on, as
842 		 * having no versions is BAD
843 		 */
844 		nfsd_reset_versions();
845 	}
846 
847 	/* Now write current state into reply buffer */
848 	len = 0;
849 	sep = "";
850 	remaining = SIMPLE_TRANSACTION_LIMIT;
851 	for (num=2 ; num <= 4 ; num++)
852 		if (nfsd_vers(num, NFSD_AVAIL)) {
853 			len = snprintf(buf, remaining, "%s%c%d", sep,
854 				       nfsd_vers(num, NFSD_TEST)?'+':'-',
855 				       num);
856 			sep = " ";
857 
858 			if (len > remaining)
859 				break;
860 			remaining -= len;
861 			buf += len;
862 			tlen += len;
863 		}
864 	if (nfsd_vers(4, NFSD_AVAIL))
865 		for (minor = 1; minor <= NFSD_SUPPORTED_MINOR_VERSION;
866 		     minor++) {
867 			len = snprintf(buf, remaining, " %c4.%u",
868 					(nfsd_vers(4, NFSD_TEST) &&
869 					 nfsd_minorversion(minor, NFSD_TEST)) ?
870 						'+' : '-',
871 					minor);
872 
873 			if (len > remaining)
874 				break;
875 			remaining -= len;
876 			buf += len;
877 			tlen += len;
878 		}
879 
880 	len = snprintf(buf, remaining, "\n");
881 	if (len > remaining)
882 		return -EINVAL;
883 	return tlen + len;
884 }
885 
886 /**
887  * write_versions - Set or report the available NFS protocol versions
888  *
889  * Input:
890  *			buf:		ignored
891  *			size:		zero
892  * Output:
893  *	On success:	passed-in buffer filled with '\n'-terminated C
894  *			string containing positive or negative integer
895  *			values representing the current status of each
896  *			protocol version;
897  *			return code is the size in bytes of the string
898  *	On error:	return code is zero or a negative errno value
899  *
900  * OR
901  *
902  * Input:
903  * 			buf:		C string containing whitespace-
904  * 					separated positive or negative
905  * 					integer values representing NFS
906  * 					protocol versions to enable ("+n")
907  * 					or disable ("-n")
908  *			size:		non-zero length of C string in @buf
909  * Output:
910  *	On success:	status of zero or more protocol versions has
911  *			been updated; passed-in buffer filled with
912  *			'\n'-terminated C string containing positive
913  *			or negative integer values representing the
914  *			current status of each protocol version;
915  *			return code is the size in bytes of the string
916  *	On error:	return code is zero or a negative errno value
917  */
918 static ssize_t write_versions(struct file *file, char *buf, size_t size)
919 {
920 	ssize_t rv;
921 
922 	mutex_lock(&nfsd_mutex);
923 	rv = __write_versions(file, buf, size);
924 	mutex_unlock(&nfsd_mutex);
925 	return rv;
926 }
927 
928 /*
929  * Zero-length write.  Return a list of NFSD's current listener
930  * transports.
931  */
932 static ssize_t __write_ports_names(char *buf)
933 {
934 	if (nfsd_serv == NULL)
935 		return 0;
936 	return svc_xprt_names(nfsd_serv, buf, SIMPLE_TRANSACTION_LIMIT);
937 }
938 
939 /*
940  * A single 'fd' number was written, in which case it must be for
941  * a socket of a supported family/protocol, and we use it as an
942  * nfsd listener.
943  */
944 static ssize_t __write_ports_addfd(char *buf)
945 {
946 	char *mesg = buf;
947 	int fd, err;
948 
949 	err = get_int(&mesg, &fd);
950 	if (err != 0 || fd < 0)
951 		return -EINVAL;
952 
953 	err = nfsd_create_serv();
954 	if (err != 0)
955 		return err;
956 
957 	err = lockd_up();
958 	if (err != 0)
959 		goto out;
960 
961 	err = svc_addsock(nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT);
962 	if (err < 0)
963 		lockd_down();
964 
965 out:
966 	/* Decrease the count, but don't shut down the service */
967 	nfsd_serv->sv_nrthreads--;
968 	return err;
969 }
970 
971 /*
972  * A '-' followed by the 'name' of a socket means we close the socket.
973  */
974 static ssize_t __write_ports_delfd(char *buf)
975 {
976 	char *toclose;
977 	int len = 0;
978 
979 	toclose = kstrdup(buf + 1, GFP_KERNEL);
980 	if (toclose == NULL)
981 		return -ENOMEM;
982 
983 	if (nfsd_serv != NULL)
984 		len = svc_sock_names(nfsd_serv, buf,
985 					SIMPLE_TRANSACTION_LIMIT, toclose);
986 	if (len >= 0)
987 		lockd_down();
988 
989 	kfree(toclose);
990 	return len;
991 }
992 
993 /*
994  * A transport listener is added by writing it's transport name and
995  * a port number.
996  */
997 static ssize_t __write_ports_addxprt(char *buf)
998 {
999 	char transport[16];
1000 	int port, err;
1001 
1002 	if (sscanf(buf, "%15s %4u", transport, &port) != 2)
1003 		return -EINVAL;
1004 
1005 	if (port < 1 || port > USHORT_MAX)
1006 		return -EINVAL;
1007 
1008 	err = nfsd_create_serv();
1009 	if (err != 0)
1010 		return err;
1011 
1012 	err = svc_create_xprt(nfsd_serv, transport,
1013 				PF_INET, port, SVC_SOCK_ANONYMOUS);
1014 	if (err < 0) {
1015 		/* Give a reasonable perror msg for bad transport string */
1016 		if (err == -ENOENT)
1017 			err = -EPROTONOSUPPORT;
1018 		return err;
1019 	}
1020 	return 0;
1021 }
1022 
1023 /*
1024  * A transport listener is removed by writing a "-", it's transport
1025  * name, and it's port number.
1026  */
1027 static ssize_t __write_ports_delxprt(char *buf)
1028 {
1029 	struct svc_xprt *xprt;
1030 	char transport[16];
1031 	int port;
1032 
1033 	if (sscanf(&buf[1], "%15s %4u", transport, &port) != 2)
1034 		return -EINVAL;
1035 
1036 	if (port < 1 || port > USHORT_MAX || nfsd_serv == NULL)
1037 		return -EINVAL;
1038 
1039 	xprt = svc_find_xprt(nfsd_serv, transport, AF_UNSPEC, port);
1040 	if (xprt == NULL)
1041 		return -ENOTCONN;
1042 
1043 	svc_close_xprt(xprt);
1044 	svc_xprt_put(xprt);
1045 	return 0;
1046 }
1047 
1048 static ssize_t __write_ports(struct file *file, char *buf, size_t size)
1049 {
1050 	if (size == 0)
1051 		return __write_ports_names(buf);
1052 
1053 	if (isdigit(buf[0]))
1054 		return __write_ports_addfd(buf);
1055 
1056 	if (buf[0] == '-' && isdigit(buf[1]))
1057 		return __write_ports_delfd(buf);
1058 
1059 	if (isalpha(buf[0]))
1060 		return __write_ports_addxprt(buf);
1061 
1062 	if (buf[0] == '-' && isalpha(buf[1]))
1063 		return __write_ports_delxprt(buf);
1064 
1065 	return -EINVAL;
1066 }
1067 
1068 /**
1069  * write_ports - Pass a socket file descriptor or transport name to listen on
1070  *
1071  * Input:
1072  *			buf:		ignored
1073  *			size:		zero
1074  * Output:
1075  *	On success:	passed-in buffer filled with a '\n'-terminated C
1076  *			string containing a whitespace-separated list of
1077  *			named NFSD listeners;
1078  *			return code is the size in bytes of the string
1079  *	On error:	return code is zero or a negative errno value
1080  *
1081  * OR
1082  *
1083  * Input:
1084  *			buf:		C string containing an unsigned
1085  *					integer value representing a bound
1086  *					but unconnected socket that is to be
1087  *					used as an NFSD listener; listen(3)
1088  *					must be called for a SOCK_STREAM
1089  *					socket, otherwise it is ignored
1090  *			size:		non-zero length of C string in @buf
1091  * Output:
1092  *	On success:	NFS service is started;
1093  *			passed-in buffer filled with a '\n'-terminated C
1094  *			string containing a unique alphanumeric name of
1095  *			the listener;
1096  *			return code is the size in bytes of the string
1097  *	On error:	return code is a negative errno value
1098  *
1099  * OR
1100  *
1101  * Input:
1102  *			buf:		C string containing a "-" followed
1103  *					by an integer value representing a
1104  *					previously passed in socket file
1105  *					descriptor
1106  *			size:		non-zero length of C string in @buf
1107  * Output:
1108  *	On success:	NFS service no longer listens on that socket;
1109  *			passed-in buffer filled with a '\n'-terminated C
1110  *			string containing a unique name of the listener;
1111  *			return code is the size in bytes of the string
1112  *	On error:	return code is a negative errno value
1113  *
1114  * OR
1115  *
1116  * Input:
1117  *			buf:		C string containing a transport
1118  *					name and an unsigned integer value
1119  *					representing the port to listen on,
1120  *					separated by whitespace
1121  *			size:		non-zero length of C string in @buf
1122  * Output:
1123  *	On success:	returns zero; NFS service is started
1124  *	On error:	return code is a negative errno value
1125  *
1126  * OR
1127  *
1128  * Input:
1129  *			buf:		C string containing a "-" followed
1130  *					by a transport name and an unsigned
1131  *					integer value representing the port
1132  *					to listen on, separated by whitespace
1133  *			size:		non-zero length of C string in @buf
1134  * Output:
1135  *	On success:	returns zero; NFS service no longer listens
1136  *			on that transport
1137  *	On error:	return code is a negative errno value
1138  */
1139 static ssize_t write_ports(struct file *file, char *buf, size_t size)
1140 {
1141 	ssize_t rv;
1142 
1143 	mutex_lock(&nfsd_mutex);
1144 	rv = __write_ports(file, buf, size);
1145 	mutex_unlock(&nfsd_mutex);
1146 	return rv;
1147 }
1148 
1149 
1150 int nfsd_max_blksize;
1151 
1152 /**
1153  * write_maxblksize - Set or report the current NFS blksize
1154  *
1155  * Input:
1156  *			buf:		ignored
1157  *			size:		zero
1158  *
1159  * OR
1160  *
1161  * Input:
1162  * 			buf:		C string containing an unsigned
1163  * 					integer value representing the new
1164  * 					NFS blksize
1165  *			size:		non-zero length of C string in @buf
1166  * Output:
1167  *	On success:	passed-in buffer filled with '\n'-terminated C string
1168  *			containing numeric value of the current NFS blksize
1169  *			setting;
1170  *			return code is the size in bytes of the string
1171  *	On error:	return code is zero or a negative errno value
1172  */
1173 static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
1174 {
1175 	char *mesg = buf;
1176 	if (size > 0) {
1177 		int bsize;
1178 		int rv = get_int(&mesg, &bsize);
1179 		if (rv)
1180 			return rv;
1181 		/* force bsize into allowed range and
1182 		 * required alignment.
1183 		 */
1184 		if (bsize < 1024)
1185 			bsize = 1024;
1186 		if (bsize > NFSSVC_MAXBLKSIZE)
1187 			bsize = NFSSVC_MAXBLKSIZE;
1188 		bsize &= ~(1024-1);
1189 		mutex_lock(&nfsd_mutex);
1190 		if (nfsd_serv && nfsd_serv->sv_nrthreads) {
1191 			mutex_unlock(&nfsd_mutex);
1192 			return -EBUSY;
1193 		}
1194 		nfsd_max_blksize = bsize;
1195 		mutex_unlock(&nfsd_mutex);
1196 	}
1197 
1198 	return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n",
1199 							nfsd_max_blksize);
1200 }
1201 
1202 #ifdef CONFIG_NFSD_V4
1203 extern time_t nfs4_leasetime(void);
1204 
1205 static ssize_t __write_leasetime(struct file *file, char *buf, size_t size)
1206 {
1207 	/* if size > 10 seconds, call
1208 	 * nfs4_reset_lease() then write out the new lease (seconds) as reply
1209 	 */
1210 	char *mesg = buf;
1211 	int rv, lease;
1212 
1213 	if (size > 0) {
1214 		if (nfsd_serv)
1215 			return -EBUSY;
1216 		rv = get_int(&mesg, &lease);
1217 		if (rv)
1218 			return rv;
1219 		if (lease < 10 || lease > 3600)
1220 			return -EINVAL;
1221 		nfs4_reset_lease(lease);
1222 	}
1223 
1224 	return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%ld\n",
1225 							nfs4_lease_time());
1226 }
1227 
1228 /**
1229  * write_leasetime - Set or report the current NFSv4 lease time
1230  *
1231  * Input:
1232  *			buf:		ignored
1233  *			size:		zero
1234  *
1235  * OR
1236  *
1237  * Input:
1238  *			buf:		C string containing an unsigned
1239  *					integer value representing the new
1240  *					NFSv4 lease expiry time
1241  *			size:		non-zero length of C string in @buf
1242  * Output:
1243  *	On success:	passed-in buffer filled with '\n'-terminated C
1244  *			string containing unsigned integer value of the
1245  *			current lease expiry time;
1246  *			return code is the size in bytes of the string
1247  *	On error:	return code is zero or a negative errno value
1248  */
1249 static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
1250 {
1251 	ssize_t rv;
1252 
1253 	mutex_lock(&nfsd_mutex);
1254 	rv = __write_leasetime(file, buf, size);
1255 	mutex_unlock(&nfsd_mutex);
1256 	return rv;
1257 }
1258 
1259 extern char *nfs4_recoverydir(void);
1260 
1261 static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size)
1262 {
1263 	char *mesg = buf;
1264 	char *recdir;
1265 	int len, status;
1266 
1267 	if (size > 0) {
1268 		if (nfsd_serv)
1269 			return -EBUSY;
1270 		if (size > PATH_MAX || buf[size-1] != '\n')
1271 			return -EINVAL;
1272 		buf[size-1] = 0;
1273 
1274 		recdir = mesg;
1275 		len = qword_get(&mesg, recdir, size);
1276 		if (len <= 0)
1277 			return -EINVAL;
1278 
1279 		status = nfs4_reset_recoverydir(recdir);
1280 	}
1281 
1282 	return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%s\n",
1283 							nfs4_recoverydir());
1284 }
1285 
1286 /**
1287  * write_recoverydir - Set or report the pathname of the recovery directory
1288  *
1289  * Input:
1290  *			buf:		ignored
1291  *			size:		zero
1292  *
1293  * OR
1294  *
1295  * Input:
1296  *			buf:		C string containing the pathname
1297  *					of the directory on a local file
1298  *					system containing permanent NFSv4
1299  *					recovery data
1300  *			size:		non-zero length of C string in @buf
1301  * Output:
1302  *	On success:	passed-in buffer filled with '\n'-terminated C string
1303  *			containing the current recovery pathname setting;
1304  *			return code is the size in bytes of the string
1305  *	On error:	return code is zero or a negative errno value
1306  */
1307 static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
1308 {
1309 	ssize_t rv;
1310 
1311 	mutex_lock(&nfsd_mutex);
1312 	rv = __write_recoverydir(file, buf, size);
1313 	mutex_unlock(&nfsd_mutex);
1314 	return rv;
1315 }
1316 
1317 #endif
1318 
1319 /*----------------------------------------------------------------------------*/
1320 /*
1321  *	populating the filesystem.
1322  */
1323 
1324 static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
1325 {
1326 	static struct tree_descr nfsd_files[] = {
1327 		[NFSD_Svc] = {".svc", &transaction_ops, S_IWUSR},
1328 		[NFSD_Add] = {".add", &transaction_ops, S_IWUSR},
1329 		[NFSD_Del] = {".del", &transaction_ops, S_IWUSR},
1330 		[NFSD_Export] = {".export", &transaction_ops, S_IWUSR},
1331 		[NFSD_Unexport] = {".unexport", &transaction_ops, S_IWUSR},
1332 		[NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR},
1333 		[NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR},
1334 		[NFSD_List] = {"exports", &exports_operations, S_IRUGO},
1335 		[NFSD_FO_UnlockIP] = {"unlock_ip",
1336 					&transaction_ops, S_IWUSR|S_IRUSR},
1337 		[NFSD_FO_UnlockFS] = {"unlock_filesystem",
1338 					&transaction_ops, S_IWUSR|S_IRUSR},
1339 		[NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR},
1340 		[NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
1341 		[NFSD_Pool_Threads] = {"pool_threads", &transaction_ops, S_IWUSR|S_IRUSR},
1342 		[NFSD_Pool_Stats] = {"pool_stats", &pool_stats_operations, S_IRUGO},
1343 		[NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR},
1344 		[NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO},
1345 		[NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO},
1346 #ifdef CONFIG_NFSD_V4
1347 		[NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR},
1348 		[NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR},
1349 #endif
1350 		/* last one */ {""}
1351 	};
1352 	return simple_fill_super(sb, 0x6e667364, nfsd_files);
1353 }
1354 
1355 static int nfsd_get_sb(struct file_system_type *fs_type,
1356 	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
1357 {
1358 	return get_sb_single(fs_type, flags, data, nfsd_fill_super, mnt);
1359 }
1360 
1361 static struct file_system_type nfsd_fs_type = {
1362 	.owner		= THIS_MODULE,
1363 	.name		= "nfsd",
1364 	.get_sb		= nfsd_get_sb,
1365 	.kill_sb	= kill_litter_super,
1366 };
1367 
1368 #ifdef CONFIG_PROC_FS
1369 static int create_proc_exports_entry(void)
1370 {
1371 	struct proc_dir_entry *entry;
1372 
1373 	entry = proc_mkdir("fs/nfs", NULL);
1374 	if (!entry)
1375 		return -ENOMEM;
1376 	entry = proc_create("exports", 0, entry, &exports_operations);
1377 	if (!entry)
1378 		return -ENOMEM;
1379 	return 0;
1380 }
1381 #else /* CONFIG_PROC_FS */
1382 static int create_proc_exports_entry(void)
1383 {
1384 	return 0;
1385 }
1386 #endif
1387 
1388 static int __init init_nfsd(void)
1389 {
1390 	int retval;
1391 	printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n");
1392 
1393 	retval = nfs4_state_init(); /* nfs4 locking state */
1394 	if (retval)
1395 		return retval;
1396 	nfsd_stat_init();	/* Statistics */
1397 	retval = nfsd_reply_cache_init();
1398 	if (retval)
1399 		goto out_free_stat;
1400 	retval = nfsd_export_init();
1401 	if (retval)
1402 		goto out_free_cache;
1403 	nfsd_lockd_init();	/* lockd->nfsd callbacks */
1404 	retval = nfsd_idmap_init();
1405 	if (retval)
1406 		goto out_free_lockd;
1407 	retval = create_proc_exports_entry();
1408 	if (retval)
1409 		goto out_free_idmap;
1410 	retval = register_filesystem(&nfsd_fs_type);
1411 	if (retval)
1412 		goto out_free_all;
1413 	return 0;
1414 out_free_all:
1415 	remove_proc_entry("fs/nfs/exports", NULL);
1416 	remove_proc_entry("fs/nfs", NULL);
1417 out_free_idmap:
1418 	nfsd_idmap_shutdown();
1419 out_free_lockd:
1420 	nfsd_lockd_shutdown();
1421 	nfsd_export_shutdown();
1422 out_free_cache:
1423 	nfsd_reply_cache_shutdown();
1424 out_free_stat:
1425 	nfsd_stat_shutdown();
1426 	nfsd4_free_slabs();
1427 	return retval;
1428 }
1429 
1430 static void __exit exit_nfsd(void)
1431 {
1432 	nfsd_export_shutdown();
1433 	nfsd_reply_cache_shutdown();
1434 	remove_proc_entry("fs/nfs/exports", NULL);
1435 	remove_proc_entry("fs/nfs", NULL);
1436 	nfsd_stat_shutdown();
1437 	nfsd_lockd_shutdown();
1438 	nfsd_idmap_shutdown();
1439 	nfsd4_free_slabs();
1440 	unregister_filesystem(&nfsd_fs_type);
1441 }
1442 
1443 MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
1444 MODULE_LICENSE("GPL");
1445 module_init(init_nfsd)
1446 module_exit(exit_nfsd)
1447