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