VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   33 Branches   57 Tags
b24413180f560 (Greg Kroah-Hartman   2017-11-01 15:07:57 +0100    1) // SPDX-License-Identifier: GPL-2.0
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700    2) /*
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700    3)  * Central processing for nfsd.
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700    4)  *
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700    5)  * Authors:	Olaf Kirch (okir@monad.swb.de)
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700    6)  *
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700    7)  * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700    8)  */
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700    9) 
3f07c0144132e (Ingo Molnar          2017-02-08 18:51:30 +0100   10) #include <linux/sched/signal.h>
831441862956f (Rafael J. Wysocki    2007-07-17 04:03:35 -0700   11) #include <linux/freezer.h>
143cb494cb666 (Paul Gortmaker       2011-07-01 14:23:34 -0400   12) #include <linux/module.h>
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700   13) #include <linux/fs_struct.h>
c3d06f9ce8544 (Andy Adamson         2009-04-03 08:28:18 +0300   14) #include <linux/swap.h>
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700   15) 
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700   16) #include <linux/sunrpc/stats.h>
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700   17) #include <linux/sunrpc/svcsock.h>
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500   18) #include <linux/sunrpc/svc_xprt.h>
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700   19) #include <linux/lockd/bind.h>
a257cdd0e2179 (Andreas Gruenbacher  2005-06-22 17:16:26 +0000   20) #include <linux/nfsacl.h>
ed2d8aed52212 (Ryusei Yamaguchi     2009-08-16 00:54:41 +0900   21) #include <linux/seq_file.h>
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500   22) #include <linux/inetdevice.h>
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500   23) #include <net/addrconf.h>
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500   24) #include <net/ipv6.h>
fc5d00b04a3a5 (Pavel Emelyanov      2010-09-29 16:03:50 +0400   25) #include <net/net_namespace.h>
9a74af21330c8 (Boaz Harrosh         2009-12-03 20:30:56 +0200   26) #include "nfsd.h"
9a74af21330c8 (Boaz Harrosh         2009-12-03 20:30:56 +0200   27) #include "cache.h"
0a3adadee42f2 (J. Bruce Fields      2009-11-04 18:12:35 -0500   28) #include "vfs.h"
2c2fe2909e124 (Stanislav Kinsbursky 2012-12-06 14:23:14 +0300   29) #include "netns.h"
65294c1f2c5e7 (Jeff Layton          2019-08-18 14:18:48 -0400   30) #include "filecache.h"
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700   31) 
0dfdad1c1d1b7 (Chuck Lever          2020-10-19 13:00:29 -0400   32) #include "trace.h"
0dfdad1c1d1b7 (Chuck Lever          2020-10-19 13:00:29 -0400   33) 
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700   34) #define NFSDDBG_FACILITY	NFSDDBG_SVC
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700   35) 
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700   36) extern struct svc_program	nfsd_program;
9867d76ca16b3 (Jeff Layton          2008-06-10 08:40:38 -0400   37) static int			nfsd(void *vrqstp);
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400   38) #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400   39) static int			nfsd_acl_rpcbind_set(struct net *,
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400   40) 						     const struct svc_program *,
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400   41) 						     u32, int,
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400   42) 						     unsigned short,
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400   43) 						     unsigned short);
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400   44) static __be32			nfsd_acl_init_request(struct svc_rqst *,
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400   45) 						const struct svc_program *,
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400   46) 						struct svc_process_info *);
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400   47) #endif
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400   48) static int			nfsd_rpcbind_set(struct net *,
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400   49) 						 const struct svc_program *,
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400   50) 						 u32, int,
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400   51) 						 unsigned short,
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400   52) 						 unsigned short);
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400   53) static __be32			nfsd_init_request(struct svc_rqst *,
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400   54) 						const struct svc_program *,
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400   55) 						struct svc_process_info *);
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700   56) 
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400   57) /*
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300   58)  * nfsd_mutex protects nn->nfsd_serv -- both the pointer itself and the members
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400   59)  * of the svc_serv struct. In particular, ->sv_nrthreads but also to some
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400   60)  * extent ->sv_temp_socks and ->sv_permsocks. It also protects nfsdstats.th_cnt
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400   61)  *
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300   62)  * If (out side the lock) nn->nfsd_serv is non-NULL, then it must point to a
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400   63)  * properly initialised 'struct svc_serv' with ->sv_nrthreads > 0. That number
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400   64)  * of nfsd threads must exist and each must listed in ->sp_all_threads in each
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400   65)  * entry of ->sv_pools[].
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400   66)  *
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400   67)  * Transitions of the thread count between zero and non-zero are of particular
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400   68)  * interest since the svc_serv needs to be created and initialized at that
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400   69)  * point, or freed.
3dd98a3bccb1b (Jeff Layton          2008-06-10 08:40:36 -0400   70)  *
3dd98a3bccb1b (Jeff Layton          2008-06-10 08:40:36 -0400   71)  * Finally, the nfsd_mutex also protects some of the global variables that are
3dd98a3bccb1b (Jeff Layton          2008-06-10 08:40:36 -0400   72)  * accessed when nfsd starts and that are settable via the write_* routines in
3dd98a3bccb1b (Jeff Layton          2008-06-10 08:40:36 -0400   73)  * nfsctl.c. In particular:
3dd98a3bccb1b (Jeff Layton          2008-06-10 08:40:36 -0400   74)  *
3dd98a3bccb1b (Jeff Layton          2008-06-10 08:40:36 -0400   75)  *	user_recovery_dirname
3dd98a3bccb1b (Jeff Layton          2008-06-10 08:40:36 -0400   76)  *	user_lease_time
3dd98a3bccb1b (Jeff Layton          2008-06-10 08:40:36 -0400   77)  *	nfsd_versions
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400   78)  */
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400   79) DEFINE_MUTEX(nfsd_mutex);
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400   80) 
4bd9b0f4afc76 (Andy Adamson         2009-06-24 15:37:45 -0400   81) /*
4bd9b0f4afc76 (Andy Adamson         2009-06-24 15:37:45 -0400   82)  * nfsd_drc_lock protects nfsd_drc_max_pages and nfsd_drc_pages_used.
4bd9b0f4afc76 (Andy Adamson         2009-06-24 15:37:45 -0400   83)  * nfsd_drc_max_pages limits the total amount of memory available for
4bd9b0f4afc76 (Andy Adamson         2009-06-24 15:37:45 -0400   84)  * version 4.1 DRC caches.
4bd9b0f4afc76 (Andy Adamson         2009-06-24 15:37:45 -0400   85)  * nfsd_drc_pages_used tracks the current version 4.1 DRC memory usage.
4bd9b0f4afc76 (Andy Adamson         2009-06-24 15:37:45 -0400   86)  */
b73ac6808b0f7 (Guobin Huang         2021-04-06 20:08:18 +0800   87) DEFINE_SPINLOCK(nfsd_drc_lock);
697ce9be7d5c7 (Zhang Yanfei         2013-02-22 16:35:47 -0800   88) unsigned long	nfsd_drc_max_mem;
697ce9be7d5c7 (Zhang Yanfei         2013-02-22 16:35:47 -0800   89) unsigned long	nfsd_drc_mem_used;
4bd9b0f4afc76 (Andy Adamson         2009-06-24 15:37:45 -0400   90) 
3fb803a990cd1 (Andreas Gruenbacher  2006-02-01 03:04:34 -0800   91) #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
3fb803a990cd1 (Andreas Gruenbacher  2006-02-01 03:04:34 -0800   92) static struct svc_stat	nfsd_acl_svcstats;
e9679189e34b2 (Christoph Hellwig    2017-05-12 16:21:37 +0200   93) static const struct svc_version *nfsd_acl_version[] = {
3fb803a990cd1 (Andreas Gruenbacher  2006-02-01 03:04:34 -0800   94) 	[2] = &nfsd_acl_version2,
3fb803a990cd1 (Andreas Gruenbacher  2006-02-01 03:04:34 -0800   95) 	[3] = &nfsd_acl_version3,
3fb803a990cd1 (Andreas Gruenbacher  2006-02-01 03:04:34 -0800   96) };
3fb803a990cd1 (Andreas Gruenbacher  2006-02-01 03:04:34 -0800   97) 
3fb803a990cd1 (Andreas Gruenbacher  2006-02-01 03:04:34 -0800   98) #define NFSD_ACL_MINVERS            2
e8c96f8c29d89 (Tobias Klauser       2006-03-24 03:15:34 -0800   99) #define NFSD_ACL_NRVERS		ARRAY_SIZE(nfsd_acl_version)
3fb803a990cd1 (Andreas Gruenbacher  2006-02-01 03:04:34 -0800  100) 
3fb803a990cd1 (Andreas Gruenbacher  2006-02-01 03:04:34 -0800  101) static struct svc_program	nfsd_acl_program = {
3fb803a990cd1 (Andreas Gruenbacher  2006-02-01 03:04:34 -0800  102) 	.pg_prog		= NFS_ACL_PROGRAM,
3fb803a990cd1 (Andreas Gruenbacher  2006-02-01 03:04:34 -0800  103) 	.pg_nvers		= NFSD_ACL_NRVERS,
7c149057d044c (J. Bruce Fields      2019-11-19 16:05:33 -0500  104) 	.pg_vers		= nfsd_acl_version,
1a8eff6d977c2 (NeilBrown            2007-01-26 00:56:58 -0800  105) 	.pg_name		= "nfsacl",
3fb803a990cd1 (Andreas Gruenbacher  2006-02-01 03:04:34 -0800  106) 	.pg_class		= "nfsd",
3fb803a990cd1 (Andreas Gruenbacher  2006-02-01 03:04:34 -0800  107) 	.pg_stats		= &nfsd_acl_svcstats,
3fb803a990cd1 (Andreas Gruenbacher  2006-02-01 03:04:34 -0800  108) 	.pg_authenticate	= &svc_set_client,
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  109) 	.pg_init_request	= nfsd_acl_init_request,
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  110) 	.pg_rpcbind_set		= nfsd_acl_rpcbind_set,
3fb803a990cd1 (Andreas Gruenbacher  2006-02-01 03:04:34 -0800  111) };
3fb803a990cd1 (Andreas Gruenbacher  2006-02-01 03:04:34 -0800  112) 
3fb803a990cd1 (Andreas Gruenbacher  2006-02-01 03:04:34 -0800  113) static struct svc_stat	nfsd_acl_svcstats = {
3fb803a990cd1 (Andreas Gruenbacher  2006-02-01 03:04:34 -0800  114) 	.program	= &nfsd_acl_program,
3fb803a990cd1 (Andreas Gruenbacher  2006-02-01 03:04:34 -0800  115) };
3fb803a990cd1 (Andreas Gruenbacher  2006-02-01 03:04:34 -0800  116) #endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
3fb803a990cd1 (Andreas Gruenbacher  2006-02-01 03:04:34 -0800  117) 
e9679189e34b2 (Christoph Hellwig    2017-05-12 16:21:37 +0200  118) static const struct svc_version *nfsd_version[] = {
70c3b76c28b01 (NeilBrown            2005-11-07 01:00:25 -0800  119) 	[2] = &nfsd_version2,
70c3b76c28b01 (NeilBrown            2005-11-07 01:00:25 -0800  120) #if defined(CONFIG_NFSD_V3)
70c3b76c28b01 (NeilBrown            2005-11-07 01:00:25 -0800  121) 	[3] = &nfsd_version3,
70c3b76c28b01 (NeilBrown            2005-11-07 01:00:25 -0800  122) #endif
70c3b76c28b01 (NeilBrown            2005-11-07 01:00:25 -0800  123) #if defined(CONFIG_NFSD_V4)
70c3b76c28b01 (NeilBrown            2005-11-07 01:00:25 -0800  124) 	[4] = &nfsd_version4,
70c3b76c28b01 (NeilBrown            2005-11-07 01:00:25 -0800  125) #endif
70c3b76c28b01 (NeilBrown            2005-11-07 01:00:25 -0800  126) };
70c3b76c28b01 (NeilBrown            2005-11-07 01:00:25 -0800  127) 
70c3b76c28b01 (NeilBrown            2005-11-07 01:00:25 -0800  128) #define NFSD_MINVERS    	2
e8c96f8c29d89 (Tobias Klauser       2006-03-24 03:15:34 -0800  129) #define NFSD_NRVERS		ARRAY_SIZE(nfsd_version)
70c3b76c28b01 (NeilBrown            2005-11-07 01:00:25 -0800  130) 
70c3b76c28b01 (NeilBrown            2005-11-07 01:00:25 -0800  131) struct svc_program		nfsd_program = {
3fb803a990cd1 (Andreas Gruenbacher  2006-02-01 03:04:34 -0800  132) #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
3fb803a990cd1 (Andreas Gruenbacher  2006-02-01 03:04:34 -0800  133) 	.pg_next		= &nfsd_acl_program,
3fb803a990cd1 (Andreas Gruenbacher  2006-02-01 03:04:34 -0800  134) #endif
70c3b76c28b01 (NeilBrown            2005-11-07 01:00:25 -0800  135) 	.pg_prog		= NFS_PROGRAM,		/* program number */
70c3b76c28b01 (NeilBrown            2005-11-07 01:00:25 -0800  136) 	.pg_nvers		= NFSD_NRVERS,		/* nr of entries in nfsd_version */
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  137) 	.pg_vers		= nfsd_version,		/* version table */
70c3b76c28b01 (NeilBrown            2005-11-07 01:00:25 -0800  138) 	.pg_name		= "nfsd",		/* program name */
70c3b76c28b01 (NeilBrown            2005-11-07 01:00:25 -0800  139) 	.pg_class		= "nfsd",		/* authentication class */
70c3b76c28b01 (NeilBrown            2005-11-07 01:00:25 -0800  140) 	.pg_stats		= &nfsd_svcstats,	/* version table */
70c3b76c28b01 (NeilBrown            2005-11-07 01:00:25 -0800  141) 	.pg_authenticate	= &svc_set_client,	/* export authentication */
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  142) 	.pg_init_request	= nfsd_init_request,
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  143) 	.pg_rpcbind_set		= nfsd_rpcbind_set,
70c3b76c28b01 (NeilBrown            2005-11-07 01:00:25 -0800  144) };
70c3b76c28b01 (NeilBrown            2005-11-07 01:00:25 -0800  145) 
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  146) static bool
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  147) nfsd_support_version(int vers)
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  148) {
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  149) 	if (vers >= NFSD_MINVERS && vers < NFSD_NRVERS)
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  150) 		return nfsd_version[vers] != NULL;
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  151) 	return false;
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  152) }
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  153) 
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  154) static bool *
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  155) nfsd_alloc_versions(void)
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  156) {
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  157) 	bool *vers = kmalloc_array(NFSD_NRVERS, sizeof(bool), GFP_KERNEL);
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  158) 	unsigned i;
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  159) 
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  160) 	if (vers) {
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  161) 		/* All compiled versions are enabled by default */
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  162) 		for (i = 0; i < NFSD_NRVERS; i++)
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  163) 			vers[i] = nfsd_support_version(i);
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  164) 	}
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  165) 	return vers;
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  166) }
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  167) 
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  168) static bool *
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  169) nfsd_alloc_minorversions(void)
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  170) {
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  171) 	bool *vers = kmalloc_array(NFSD_SUPPORTED_MINOR_VERSION + 1,
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  172) 			sizeof(bool), GFP_KERNEL);
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  173) 	unsigned i;
8daf220a6a83c (Benny Halevy         2009-04-03 08:28:59 +0300  174) 
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  175) 	if (vers) {
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  176) 		/* All minor versions are enabled by default */
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  177) 		for (i = 0; i <= NFSD_SUPPORTED_MINOR_VERSION; i++)
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  178) 			vers[i] = nfsd_support_version(4);
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  179) 	}
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  180) 	return vers;
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  181) }
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  182) 
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  183) void
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  184) nfsd_netns_free_versions(struct nfsd_net *nn)
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  185) {
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  186) 	kfree(nn->nfsd_versions);
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  187) 	kfree(nn->nfsd4_minorversions);
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  188) 	nn->nfsd_versions = NULL;
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  189) 	nn->nfsd4_minorversions = NULL;
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  190) }
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  191) 
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  192) static void
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  193) nfsd_netns_init_versions(struct nfsd_net *nn)
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  194) {
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  195) 	if (!nn->nfsd_versions) {
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  196) 		nn->nfsd_versions = nfsd_alloc_versions();
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  197) 		nn->nfsd4_minorversions = nfsd_alloc_minorversions();
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  198) 		if (!nn->nfsd_versions || !nn->nfsd4_minorversions)
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  199) 			nfsd_netns_free_versions(nn);
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  200) 	}
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  201) }
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  202) 
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  203) int nfsd_vers(struct nfsd_net *nn, int vers, enum vers_op change)
6658d3a7bbfd1 (NeilBrown            2006-10-02 02:17:46 -0700  204) {
6658d3a7bbfd1 (NeilBrown            2006-10-02 02:17:46 -0700  205) 	if (vers < NFSD_MINVERS || vers >= NFSD_NRVERS)
15ddb4aec5442 (Pavel Emelyanov      2010-05-14 15:33:36 +0400  206) 		return 0;
6658d3a7bbfd1 (NeilBrown            2006-10-02 02:17:46 -0700  207) 	switch(change) {
6658d3a7bbfd1 (NeilBrown            2006-10-02 02:17:46 -0700  208) 	case NFSD_SET:
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  209) 		if (nn->nfsd_versions)
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  210) 			nn->nfsd_versions[vers] = nfsd_support_version(vers);
1a8eff6d977c2 (NeilBrown            2007-01-26 00:56:58 -0800  211) 		break;
6658d3a7bbfd1 (NeilBrown            2006-10-02 02:17:46 -0700  212) 	case NFSD_CLEAR:
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  213) 		nfsd_netns_init_versions(nn);
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  214) 		if (nn->nfsd_versions)
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  215) 			nn->nfsd_versions[vers] = false;
6658d3a7bbfd1 (NeilBrown            2006-10-02 02:17:46 -0700  216) 		break;
6658d3a7bbfd1 (NeilBrown            2006-10-02 02:17:46 -0700  217) 	case NFSD_TEST:
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  218) 		if (nn->nfsd_versions)
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  219) 			return nn->nfsd_versions[vers];
df561f6688fef (Gustavo A. R. Silva  2020-08-23 17:36:59 -0500  220) 		fallthrough;
6658d3a7bbfd1 (NeilBrown            2006-10-02 02:17:46 -0700  221) 	case NFSD_AVAIL:
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  222) 		return nfsd_support_version(vers);
6658d3a7bbfd1 (NeilBrown            2006-10-02 02:17:46 -0700  223) 	}
6658d3a7bbfd1 (NeilBrown            2006-10-02 02:17:46 -0700  224) 	return 0;
6658d3a7bbfd1 (NeilBrown            2006-10-02 02:17:46 -0700  225) }
8daf220a6a83c (Benny Halevy         2009-04-03 08:28:59 +0300  226) 
d3635ff07e8ca (Trond Myklebust      2017-02-22 18:35:32 -0500  227) static void
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  228) nfsd_adjust_nfsd_versions4(struct nfsd_net *nn)
d3635ff07e8ca (Trond Myklebust      2017-02-22 18:35:32 -0500  229) {
d3635ff07e8ca (Trond Myklebust      2017-02-22 18:35:32 -0500  230) 	unsigned i;
d3635ff07e8ca (Trond Myklebust      2017-02-22 18:35:32 -0500  231) 
d3635ff07e8ca (Trond Myklebust      2017-02-22 18:35:32 -0500  232) 	for (i = 0; i <= NFSD_SUPPORTED_MINOR_VERSION; i++) {
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  233) 		if (nn->nfsd4_minorversions[i])
d3635ff07e8ca (Trond Myklebust      2017-02-22 18:35:32 -0500  234) 			return;
d3635ff07e8ca (Trond Myklebust      2017-02-22 18:35:32 -0500  235) 	}
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  236) 	nfsd_vers(nn, 4, NFSD_CLEAR);
d3635ff07e8ca (Trond Myklebust      2017-02-22 18:35:32 -0500  237) }
d3635ff07e8ca (Trond Myklebust      2017-02-22 18:35:32 -0500  238) 
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  239) int nfsd_minorversion(struct nfsd_net *nn, u32 minorversion, enum vers_op change)
8daf220a6a83c (Benny Halevy         2009-04-03 08:28:59 +0300  240) {
928c6fb3a9bfd (NeilBrown            2017-03-10 11:36:39 +1100  241) 	if (minorversion > NFSD_SUPPORTED_MINOR_VERSION &&
928c6fb3a9bfd (NeilBrown            2017-03-10 11:36:39 +1100  242) 	    change != NFSD_AVAIL)
8daf220a6a83c (Benny Halevy         2009-04-03 08:28:59 +0300  243) 		return -1;
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  244) 
8daf220a6a83c (Benny Halevy         2009-04-03 08:28:59 +0300  245) 	switch(change) {
8daf220a6a83c (Benny Halevy         2009-04-03 08:28:59 +0300  246) 	case NFSD_SET:
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  247) 		if (nn->nfsd4_minorversions) {
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  248) 			nfsd_vers(nn, 4, NFSD_SET);
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  249) 			nn->nfsd4_minorversions[minorversion] =
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  250) 				nfsd_vers(nn, 4, NFSD_TEST);
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  251) 		}
8daf220a6a83c (Benny Halevy         2009-04-03 08:28:59 +0300  252) 		break;
8daf220a6a83c (Benny Halevy         2009-04-03 08:28:59 +0300  253) 	case NFSD_CLEAR:
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  254) 		nfsd_netns_init_versions(nn);
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  255) 		if (nn->nfsd4_minorversions) {
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  256) 			nn->nfsd4_minorversions[minorversion] = false;
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  257) 			nfsd_adjust_nfsd_versions4(nn);
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  258) 		}
8daf220a6a83c (Benny Halevy         2009-04-03 08:28:59 +0300  259) 		break;
8daf220a6a83c (Benny Halevy         2009-04-03 08:28:59 +0300  260) 	case NFSD_TEST:
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  261) 		if (nn->nfsd4_minorversions)
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  262) 			return nn->nfsd4_minorversions[minorversion];
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  263) 		return nfsd_vers(nn, 4, NFSD_TEST);
8daf220a6a83c (Benny Halevy         2009-04-03 08:28:59 +0300  264) 	case NFSD_AVAIL:
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  265) 		return minorversion <= NFSD_SUPPORTED_MINOR_VERSION &&
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  266) 			nfsd_vers(nn, 4, NFSD_AVAIL);
8daf220a6a83c (Benny Halevy         2009-04-03 08:28:59 +0300  267) 	}
8daf220a6a83c (Benny Halevy         2009-04-03 08:28:59 +0300  268) 	return 0;
8daf220a6a83c (Benny Halevy         2009-04-03 08:28:59 +0300  269) }
8daf220a6a83c (Benny Halevy         2009-04-03 08:28:59 +0300  270) 
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  271) /*
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  272)  * Maximum number of nfsd processes
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  273)  */
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  274) #define	NFSD_MAXSERVS		8192
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  275) 
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  276) int nfsd_nrthreads(struct net *net)
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  277) {
c7d106c90ec40 (Neil Brown           2008-06-12 13:38:42 +1000  278) 	int rv = 0;
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  279) 	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  280) 
c7d106c90ec40 (Neil Brown           2008-06-12 13:38:42 +1000  281) 	mutex_lock(&nfsd_mutex);
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  282) 	if (nn->nfsd_serv)
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  283) 		rv = nn->nfsd_serv->sv_nrthreads;
c7d106c90ec40 (Neil Brown           2008-06-12 13:38:42 +1000  284) 	mutex_unlock(&nfsd_mutex);
c7d106c90ec40 (Neil Brown           2008-06-12 13:38:42 +1000  285) 	return rv;
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  286) }
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  287) 
4df493a260d4c (Trond Myklebust      2019-04-09 12:13:37 -0400  288) static int nfsd_init_socks(struct net *net, const struct cred *cred)
59db4a0c102e0 (J. Bruce Fields      2010-07-21 18:29:25 -0400  289) {
59db4a0c102e0 (J. Bruce Fields      2010-07-21 18:29:25 -0400  290) 	int error;
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  291) 	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  292) 
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  293) 	if (!list_empty(&nn->nfsd_serv->sv_permsocks))
59db4a0c102e0 (J. Bruce Fields      2010-07-21 18:29:25 -0400  294) 		return 0;
59db4a0c102e0 (J. Bruce Fields      2010-07-21 18:29:25 -0400  295) 
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  296) 	error = svc_create_xprt(nn->nfsd_serv, "udp", net, PF_INET, NFS_PORT,
4df493a260d4c (Trond Myklebust      2019-04-09 12:13:37 -0400  297) 					SVC_SOCK_DEFAULTS, cred);
59db4a0c102e0 (J. Bruce Fields      2010-07-21 18:29:25 -0400  298) 	if (error < 0)
59db4a0c102e0 (J. Bruce Fields      2010-07-21 18:29:25 -0400  299) 		return error;
59db4a0c102e0 (J. Bruce Fields      2010-07-21 18:29:25 -0400  300) 
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  301) 	error = svc_create_xprt(nn->nfsd_serv, "tcp", net, PF_INET, NFS_PORT,
4df493a260d4c (Trond Myklebust      2019-04-09 12:13:37 -0400  302) 					SVC_SOCK_DEFAULTS, cred);
59db4a0c102e0 (J. Bruce Fields      2010-07-21 18:29:25 -0400  303) 	if (error < 0)
59db4a0c102e0 (J. Bruce Fields      2010-07-21 18:29:25 -0400  304) 		return error;
59db4a0c102e0 (J. Bruce Fields      2010-07-21 18:29:25 -0400  305) 
59db4a0c102e0 (J. Bruce Fields      2010-07-21 18:29:25 -0400  306) 	return 0;
59db4a0c102e0 (J. Bruce Fields      2010-07-21 18:29:25 -0400  307) }
59db4a0c102e0 (J. Bruce Fields      2010-07-21 18:29:25 -0400  308) 
4539f14981ce0 (Stanislav Kinsbursky 2012-12-06 14:23:39 +0300  309) static int nfsd_users = 0;
4ad9a344be229 (Jeff Layton          2010-07-19 16:50:04 -0400  310) 
70c5307564035 (Vasily Averin        2021-04-15 15:00:58 +0300  311) static int nfsd_startup_generic(void)
bda9cac1db8ab (Stanislav Kinsbursky 2012-12-06 14:23:29 +0300  312) {
bda9cac1db8ab (Stanislav Kinsbursky 2012-12-06 14:23:29 +0300  313) 	int ret;
bda9cac1db8ab (Stanislav Kinsbursky 2012-12-06 14:23:29 +0300  314) 
4539f14981ce0 (Stanislav Kinsbursky 2012-12-06 14:23:39 +0300  315) 	if (nfsd_users++)
bda9cac1db8ab (Stanislav Kinsbursky 2012-12-06 14:23:29 +0300  316) 		return 0;
bda9cac1db8ab (Stanislav Kinsbursky 2012-12-06 14:23:29 +0300  317) 
65294c1f2c5e7 (Jeff Layton          2019-08-18 14:18:48 -0400  318) 	ret = nfsd_file_cache_init();
65294c1f2c5e7 (Jeff Layton          2019-08-18 14:18:48 -0400  319) 	if (ret)
65294c1f2c5e7 (Jeff Layton          2019-08-18 14:18:48 -0400  320) 		goto dec_users;
d9499a95716db (Kinglong Mee         2014-07-30 21:26:05 +0800  321) 
bda9cac1db8ab (Stanislav Kinsbursky 2012-12-06 14:23:29 +0300  322) 	ret = nfs4_state_start();
bda9cac1db8ab (Stanislav Kinsbursky 2012-12-06 14:23:29 +0300  323) 	if (ret)
501cb1849f865 (Jeff Layton          2019-08-18 14:18:56 -0400  324) 		goto out_file_cache;
bda9cac1db8ab (Stanislav Kinsbursky 2012-12-06 14:23:29 +0300  325) 	return 0;
bda9cac1db8ab (Stanislav Kinsbursky 2012-12-06 14:23:29 +0300  326) 
65294c1f2c5e7 (Jeff Layton          2019-08-18 14:18:48 -0400  327) out_file_cache:
65294c1f2c5e7 (Jeff Layton          2019-08-18 14:18:48 -0400  328) 	nfsd_file_cache_shutdown();
d9499a95716db (Kinglong Mee         2014-07-30 21:26:05 +0800  329) dec_users:
d9499a95716db (Kinglong Mee         2014-07-30 21:26:05 +0800  330) 	nfsd_users--;
bda9cac1db8ab (Stanislav Kinsbursky 2012-12-06 14:23:29 +0300  331) 	return ret;
bda9cac1db8ab (Stanislav Kinsbursky 2012-12-06 14:23:29 +0300  332) }
bda9cac1db8ab (Stanislav Kinsbursky 2012-12-06 14:23:29 +0300  333) 
bda9cac1db8ab (Stanislav Kinsbursky 2012-12-06 14:23:29 +0300  334) static void nfsd_shutdown_generic(void)
bda9cac1db8ab (Stanislav Kinsbursky 2012-12-06 14:23:29 +0300  335) {
4539f14981ce0 (Stanislav Kinsbursky 2012-12-06 14:23:39 +0300  336) 	if (--nfsd_users)
4539f14981ce0 (Stanislav Kinsbursky 2012-12-06 14:23:39 +0300  337) 		return;
4539f14981ce0 (Stanislav Kinsbursky 2012-12-06 14:23:39 +0300  338) 
bda9cac1db8ab (Stanislav Kinsbursky 2012-12-06 14:23:29 +0300  339) 	nfs4_state_shutdown();
65294c1f2c5e7 (Jeff Layton          2019-08-18 14:18:48 -0400  340) 	nfsd_file_cache_shutdown();
bda9cac1db8ab (Stanislav Kinsbursky 2012-12-06 14:23:29 +0300  341) }
bda9cac1db8ab (Stanislav Kinsbursky 2012-12-06 14:23:29 +0300  342) 
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  343) static bool nfsd_needs_lockd(struct nfsd_net *nn)
8ef667140c52e (Kinglong Mee         2013-12-31 13:17:30 +0800  344) {
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  345) 	return nfsd_vers(nn, 2, NFSD_TEST) || nfsd_vers(nn, 3, NFSD_TEST);
8ef667140c52e (Kinglong Mee         2013-12-31 13:17:30 +0800  346) }
8ef667140c52e (Kinglong Mee         2013-12-31 13:17:30 +0800  347) 
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  348) void nfsd_copy_boot_verifier(__be32 verf[2], struct nfsd_net *nn)
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  349) {
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  350) 	int seq = 0;
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  351) 
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  352) 	do {
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  353) 		read_seqbegin_or_lock(&nn->boot_lock, &seq);
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  354) 		/*
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  355) 		 * This is opaque to client, so no need to byte-swap. Use
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  356) 		 * __force to keep sparse happy. y2038 time_t overflow is
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  357) 		 * irrelevant in this usage
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  358) 		 */
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  359) 		verf[0] = (__force __be32)nn->nfssvc_boot.tv_sec;
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  360) 		verf[1] = (__force __be32)nn->nfssvc_boot.tv_nsec;
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  361) 	} while (need_seqretry(&nn->boot_lock, seq));
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  362) 	done_seqretry(&nn->boot_lock, seq);
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  363) }
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  364) 
65643f4c8217e (YueHaibing           2019-09-23 13:58:59 +0800  365) static void nfsd_reset_boot_verifier_locked(struct nfsd_net *nn)
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  366) {
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  367) 	ktime_get_real_ts64(&nn->nfssvc_boot);
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  368) }
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  369) 
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  370) void nfsd_reset_boot_verifier(struct nfsd_net *nn)
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  371) {
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  372) 	write_seqlock(&nn->boot_lock);
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  373) 	nfsd_reset_boot_verifier_locked(nn);
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  374) 	write_sequnlock(&nn->boot_lock);
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  375) }
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  376) 
70c5307564035 (Vasily Averin        2021-04-15 15:00:58 +0300  377) static int nfsd_startup_net(struct net *net, const struct cred *cred)
6ff50b3dea9a2 (Stanislav Kinsbursky 2012-12-06 14:23:09 +0300  378) {
2c2fe2909e124 (Stanislav Kinsbursky 2012-12-06 14:23:14 +0300  379) 	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
6ff50b3dea9a2 (Stanislav Kinsbursky 2012-12-06 14:23:09 +0300  380) 	int ret;
6ff50b3dea9a2 (Stanislav Kinsbursky 2012-12-06 14:23:09 +0300  381) 
2c2fe2909e124 (Stanislav Kinsbursky 2012-12-06 14:23:14 +0300  382) 	if (nn->nfsd_net_up)
2c2fe2909e124 (Stanislav Kinsbursky 2012-12-06 14:23:14 +0300  383) 		return 0;
2c2fe2909e124 (Stanislav Kinsbursky 2012-12-06 14:23:14 +0300  384) 
70c5307564035 (Vasily Averin        2021-04-15 15:00:58 +0300  385) 	ret = nfsd_startup_generic();
6ff50b3dea9a2 (Stanislav Kinsbursky 2012-12-06 14:23:09 +0300  386) 	if (ret)
6ff50b3dea9a2 (Stanislav Kinsbursky 2012-12-06 14:23:09 +0300  387) 		return ret;
4df493a260d4c (Trond Myklebust      2019-04-09 12:13:37 -0400  388) 	ret = nfsd_init_socks(net, cred);
903d9bf0edebc (Stanislav Kinsbursky 2012-12-06 14:23:34 +0300  389) 	if (ret)
903d9bf0edebc (Stanislav Kinsbursky 2012-12-06 14:23:34 +0300  390) 		goto out_socks;
8ef667140c52e (Kinglong Mee         2013-12-31 13:17:30 +0800  391) 
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  392) 	if (nfsd_needs_lockd(nn) && !nn->lockd_up) {
40373b125de6b (Trond Myklebust      2019-04-09 12:13:39 -0400  393) 		ret = lockd_up(net, cred);
8ef667140c52e (Kinglong Mee         2013-12-31 13:17:30 +0800  394) 		if (ret)
8ef667140c52e (Kinglong Mee         2013-12-31 13:17:30 +0800  395) 			goto out_socks;
e44b4bf2648ef (zhengbin             2019-12-25 11:19:36 +0800  396) 		nn->lockd_up = true;
8ef667140c52e (Kinglong Mee         2013-12-31 13:17:30 +0800  397) 	}
8ef667140c52e (Kinglong Mee         2013-12-31 13:17:30 +0800  398) 
9542e6a643fc6 (Trond Myklebust      2020-01-06 13:18:05 -0500  399) 	ret = nfsd_file_cache_start_net(net);
6ff50b3dea9a2 (Stanislav Kinsbursky 2012-12-06 14:23:09 +0300  400) 	if (ret)
6ff50b3dea9a2 (Stanislav Kinsbursky 2012-12-06 14:23:09 +0300  401) 		goto out_lockd;
9542e6a643fc6 (Trond Myklebust      2020-01-06 13:18:05 -0500  402) 	ret = nfs4_state_start_net(net);
9542e6a643fc6 (Trond Myklebust      2020-01-06 13:18:05 -0500  403) 	if (ret)
9542e6a643fc6 (Trond Myklebust      2020-01-06 13:18:05 -0500  404) 		goto out_filecache;
6ff50b3dea9a2 (Stanislav Kinsbursky 2012-12-06 14:23:09 +0300  405) 
2c2fe2909e124 (Stanislav Kinsbursky 2012-12-06 14:23:14 +0300  406) 	nn->nfsd_net_up = true;
6ff50b3dea9a2 (Stanislav Kinsbursky 2012-12-06 14:23:09 +0300  407) 	return 0;
6ff50b3dea9a2 (Stanislav Kinsbursky 2012-12-06 14:23:09 +0300  408) 
9542e6a643fc6 (Trond Myklebust      2020-01-06 13:18:05 -0500  409) out_filecache:
9542e6a643fc6 (Trond Myklebust      2020-01-06 13:18:05 -0500  410) 	nfsd_file_cache_shutdown_net(net);
6ff50b3dea9a2 (Stanislav Kinsbursky 2012-12-06 14:23:09 +0300  411) out_lockd:
8ef667140c52e (Kinglong Mee         2013-12-31 13:17:30 +0800  412) 	if (nn->lockd_up) {
8ef667140c52e (Kinglong Mee         2013-12-31 13:17:30 +0800  413) 		lockd_down(net);
e44b4bf2648ef (zhengbin             2019-12-25 11:19:36 +0800  414) 		nn->lockd_up = false;
8ef667140c52e (Kinglong Mee         2013-12-31 13:17:30 +0800  415) 	}
903d9bf0edebc (Stanislav Kinsbursky 2012-12-06 14:23:34 +0300  416) out_socks:
bda9cac1db8ab (Stanislav Kinsbursky 2012-12-06 14:23:29 +0300  417) 	nfsd_shutdown_generic();
4ad9a344be229 (Jeff Layton          2010-07-19 16:50:04 -0400  418) 	return ret;
4ad9a344be229 (Jeff Layton          2010-07-19 16:50:04 -0400  419) }
4ad9a344be229 (Jeff Layton          2010-07-19 16:50:04 -0400  420) 
6ff50b3dea9a2 (Stanislav Kinsbursky 2012-12-06 14:23:09 +0300  421) static void nfsd_shutdown_net(struct net *net)
6ff50b3dea9a2 (Stanislav Kinsbursky 2012-12-06 14:23:09 +0300  422) {
2c2fe2909e124 (Stanislav Kinsbursky 2012-12-06 14:23:14 +0300  423) 	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
2c2fe2909e124 (Stanislav Kinsbursky 2012-12-06 14:23:14 +0300  424) 
9542e6a643fc6 (Trond Myklebust      2020-01-06 13:18:05 -0500  425) 	nfsd_file_cache_shutdown_net(net);
6ff50b3dea9a2 (Stanislav Kinsbursky 2012-12-06 14:23:09 +0300  426) 	nfs4_state_shutdown_net(net);
8ef667140c52e (Kinglong Mee         2013-12-31 13:17:30 +0800  427) 	if (nn->lockd_up) {
8ef667140c52e (Kinglong Mee         2013-12-31 13:17:30 +0800  428) 		lockd_down(net);
e44b4bf2648ef (zhengbin             2019-12-25 11:19:36 +0800  429) 		nn->lockd_up = false;
8ef667140c52e (Kinglong Mee         2013-12-31 13:17:30 +0800  430) 	}
2c2fe2909e124 (Stanislav Kinsbursky 2012-12-06 14:23:14 +0300  431) 	nn->nfsd_net_up = false;
903d9bf0edebc (Stanislav Kinsbursky 2012-12-06 14:23:34 +0300  432) 	nfsd_shutdown_generic();
6ff50b3dea9a2 (Stanislav Kinsbursky 2012-12-06 14:23:09 +0300  433) }
6ff50b3dea9a2 (Stanislav Kinsbursky 2012-12-06 14:23:09 +0300  434) 
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  435) static int nfsd_inetaddr_event(struct notifier_block *this, unsigned long event,
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  436) 	void *ptr)
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  437) {
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  438) 	struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  439) 	struct net_device *dev = ifa->ifa_dev->dev;
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  440) 	struct net *net = dev_net(dev);
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  441) 	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  442) 	struct sockaddr_in sin;
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  443) 
2317dc557a3b6 (Vasily Averin        2017-11-10 10:19:35 +0300  444) 	if ((event != NETDEV_DOWN) ||
2317dc557a3b6 (Vasily Averin        2017-11-10 10:19:35 +0300  445) 	    !atomic_inc_not_zero(&nn->ntf_refcnt))
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  446) 		goto out;
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  447) 
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  448) 	if (nn->nfsd_serv) {
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  449) 		dprintk("nfsd_inetaddr_event: removed %pI4\n", &ifa->ifa_local);
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  450) 		sin.sin_family = AF_INET;
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  451) 		sin.sin_addr.s_addr = ifa->ifa_local;
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  452) 		svc_age_temp_xprts_now(nn->nfsd_serv, (struct sockaddr *)&sin);
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  453) 	}
2317dc557a3b6 (Vasily Averin        2017-11-10 10:19:35 +0300  454) 	atomic_dec(&nn->ntf_refcnt);
2317dc557a3b6 (Vasily Averin        2017-11-10 10:19:35 +0300  455) 	wake_up(&nn->ntf_wq);
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  456) 
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  457) out:
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  458) 	return NOTIFY_DONE;
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  459) }
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  460) 
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  461) static struct notifier_block nfsd_inetaddr_notifier = {
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  462) 	.notifier_call = nfsd_inetaddr_event,
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  463) };
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  464) 
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  465) #if IS_ENABLED(CONFIG_IPV6)
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  466) static int nfsd_inet6addr_event(struct notifier_block *this,
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  467) 	unsigned long event, void *ptr)
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  468) {
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  469) 	struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  470) 	struct net_device *dev = ifa->idev->dev;
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  471) 	struct net *net = dev_net(dev);
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  472) 	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  473) 	struct sockaddr_in6 sin6;
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  474) 
2317dc557a3b6 (Vasily Averin        2017-11-10 10:19:35 +0300  475) 	if ((event != NETDEV_DOWN) ||
2317dc557a3b6 (Vasily Averin        2017-11-10 10:19:35 +0300  476) 	    !atomic_inc_not_zero(&nn->ntf_refcnt))
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  477) 		goto out;
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  478) 
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  479) 	if (nn->nfsd_serv) {
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  480) 		dprintk("nfsd_inet6addr_event: removed %pI6\n", &ifa->addr);
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  481) 		sin6.sin6_family = AF_INET6;
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  482) 		sin6.sin6_addr = ifa->addr;
7b19824de685e (Scott Mayhew         2017-01-05 16:34:49 -0500  483) 		if (ipv6_addr_type(&sin6.sin6_addr) & IPV6_ADDR_LINKLOCAL)
7b19824de685e (Scott Mayhew         2017-01-05 16:34:49 -0500  484) 			sin6.sin6_scope_id = ifa->idev->dev->ifindex;
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  485) 		svc_age_temp_xprts_now(nn->nfsd_serv, (struct sockaddr *)&sin6);
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  486) 	}
2317dc557a3b6 (Vasily Averin        2017-11-10 10:19:35 +0300  487) 	atomic_dec(&nn->ntf_refcnt);
2317dc557a3b6 (Vasily Averin        2017-11-10 10:19:35 +0300  488) 	wake_up(&nn->ntf_wq);
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  489) out:
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  490) 	return NOTIFY_DONE;
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  491) }
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  492) 
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  493) static struct notifier_block nfsd_inet6addr_notifier = {
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  494) 	.notifier_call = nfsd_inet6addr_event,
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  495) };
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  496) #endif
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  497) 
1eca45f8a8409 (Vasily Averin        2016-09-21 15:33:05 +0300  498) /* Only used under nfsd_mutex, so this atomic may be overkill: */
1eca45f8a8409 (Vasily Averin        2016-09-21 15:33:05 +0300  499) static atomic_t nfsd_notifier_refcount = ATOMIC_INIT(0);
1eca45f8a8409 (Vasily Averin        2016-09-21 15:33:05 +0300  500) 
541e864f00d00 (Stanislav Kinsbursky 2012-12-06 14:23:44 +0300  501) static void nfsd_last_thread(struct svc_serv *serv, struct net *net)
4ad9a344be229 (Jeff Layton          2010-07-19 16:50:04 -0400  502) {
903d9bf0edebc (Stanislav Kinsbursky 2012-12-06 14:23:34 +0300  503) 	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
903d9bf0edebc (Stanislav Kinsbursky 2012-12-06 14:23:34 +0300  504) 
2317dc557a3b6 (Vasily Averin        2017-11-10 10:19:35 +0300  505) 	atomic_dec(&nn->ntf_refcnt);
1eca45f8a8409 (Vasily Averin        2016-09-21 15:33:05 +0300  506) 	/* check if the notifier still has clients */
1eca45f8a8409 (Vasily Averin        2016-09-21 15:33:05 +0300  507) 	if (atomic_dec_return(&nfsd_notifier_refcount) == 0) {
1eca45f8a8409 (Vasily Averin        2016-09-21 15:33:05 +0300  508) 		unregister_inetaddr_notifier(&nfsd_inetaddr_notifier);
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  509) #if IS_ENABLED(CONFIG_IPV6)
1eca45f8a8409 (Vasily Averin        2016-09-21 15:33:05 +0300  510) 		unregister_inet6addr_notifier(&nfsd_inet6addr_notifier);
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  511) #endif
1eca45f8a8409 (Vasily Averin        2016-09-21 15:33:05 +0300  512) 	}
2317dc557a3b6 (Vasily Averin        2017-11-10 10:19:35 +0300  513) 	wait_event(nn->ntf_wq, atomic_read(&nn->ntf_refcnt) == 0);
1eca45f8a8409 (Vasily Averin        2016-09-21 15:33:05 +0300  514) 
4ad9a344be229 (Jeff Layton          2010-07-19 16:50:04 -0400  515) 	/*
4ad9a344be229 (Jeff Layton          2010-07-19 16:50:04 -0400  516) 	 * write_ports can create the server without actually starting
4ad9a344be229 (Jeff Layton          2010-07-19 16:50:04 -0400  517) 	 * any threads--if we get shut down before any threads are
4ad9a344be229 (Jeff Layton          2010-07-19 16:50:04 -0400  518) 	 * started, then nfsd_last_thread will be run before any of this
691412b4438da (Kinglong Mee         2016-01-04 11:15:21 +0800  519) 	 * other initialization has been done except the rpcb information.
4ad9a344be229 (Jeff Layton          2010-07-19 16:50:04 -0400  520) 	 */
691412b4438da (Kinglong Mee         2016-01-04 11:15:21 +0800  521) 	svc_rpcb_cleanup(serv, net);
903d9bf0edebc (Stanislav Kinsbursky 2012-12-06 14:23:34 +0300  522) 	if (!nn->nfsd_net_up)
4ad9a344be229 (Jeff Layton          2010-07-19 16:50:04 -0400  523) 		return;
16d0587090ab9 (Stanislav Kinsbursky 2011-10-25 14:17:28 +0300  524) 
691412b4438da (Kinglong Mee         2016-01-04 11:15:21 +0800  525) 	nfsd_shutdown_net(net);
4420440c57892 (kazuo ito            2020-11-27 15:26:59 +0900  526) 	pr_info("nfsd: last server has exited, flushing export cache\n");
b3853e0ea1f2e (Stanislav Kinsbursky 2012-04-11 15:13:21 +0400  527) 	nfsd_export_flush(net);
bc591ccff27e6 (NeilBrown            2006-10-02 02:17:44 -0700  528) }
6658d3a7bbfd1 (NeilBrown            2006-10-02 02:17:46 -0700  529) 
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  530) void nfsd_reset_versions(struct nfsd_net *nn)
6658d3a7bbfd1 (NeilBrown            2006-10-02 02:17:46 -0700  531) {
6658d3a7bbfd1 (NeilBrown            2006-10-02 02:17:46 -0700  532) 	int i;
6658d3a7bbfd1 (NeilBrown            2006-10-02 02:17:46 -0700  533) 
800a938f0bf91 (NeilBrown            2017-03-10 11:36:39 +1100  534) 	for (i = 0; i < NFSD_NRVERS; i++)
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  535) 		if (nfsd_vers(nn, i, NFSD_TEST))
800a938f0bf91 (NeilBrown            2017-03-10 11:36:39 +1100  536) 			return;
6658d3a7bbfd1 (NeilBrown            2006-10-02 02:17:46 -0700  537) 
800a938f0bf91 (NeilBrown            2017-03-10 11:36:39 +1100  538) 	for (i = 0; i < NFSD_NRVERS; i++)
800a938f0bf91 (NeilBrown            2017-03-10 11:36:39 +1100  539) 		if (i != 4)
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  540) 			nfsd_vers(nn, i, NFSD_SET);
800a938f0bf91 (NeilBrown            2017-03-10 11:36:39 +1100  541) 		else {
800a938f0bf91 (NeilBrown            2017-03-10 11:36:39 +1100  542) 			int minor = 0;
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  543) 			while (nfsd_minorversion(nn, minor, NFSD_SET) >= 0)
800a938f0bf91 (NeilBrown            2017-03-10 11:36:39 +1100  544) 				minor++;
800a938f0bf91 (NeilBrown            2017-03-10 11:36:39 +1100  545) 		}
6658d3a7bbfd1 (NeilBrown            2006-10-02 02:17:46 -0700  546) }
6658d3a7bbfd1 (NeilBrown            2006-10-02 02:17:46 -0700  547) 
c3d06f9ce8544 (Andy Adamson         2009-04-03 08:28:18 +0300  548) /*
c3d06f9ce8544 (Andy Adamson         2009-04-03 08:28:18 +0300  549)  * Each session guarantees a negotiated per slot memory cache for replies
c3d06f9ce8544 (Andy Adamson         2009-04-03 08:28:18 +0300  550)  * which in turn consumes memory beyond the v2/v3/v4.0 server. A dedicated
c3d06f9ce8544 (Andy Adamson         2009-04-03 08:28:18 +0300  551)  * NFSv4.1 server might want to use more memory for a DRC than a machine
c3d06f9ce8544 (Andy Adamson         2009-04-03 08:28:18 +0300  552)  * with mutiple services.
c3d06f9ce8544 (Andy Adamson         2009-04-03 08:28:18 +0300  553)  *
c3d06f9ce8544 (Andy Adamson         2009-04-03 08:28:18 +0300  554)  * Impose a hard limit on the number of pages for the DRC which varies
c3d06f9ce8544 (Andy Adamson         2009-04-03 08:28:18 +0300  555)  * according to the machines free pages. This is of course only a default.
c3d06f9ce8544 (Andy Adamson         2009-04-03 08:28:18 +0300  556)  *
c3d06f9ce8544 (Andy Adamson         2009-04-03 08:28:18 +0300  557)  * For now this is a #defined shift which could be under admin control
c3d06f9ce8544 (Andy Adamson         2009-04-03 08:28:18 +0300  558)  * in the future.
c3d06f9ce8544 (Andy Adamson         2009-04-03 08:28:18 +0300  559)  */
c3d06f9ce8544 (Andy Adamson         2009-04-03 08:28:18 +0300  560) static void set_max_drc(void)
c3d06f9ce8544 (Andy Adamson         2009-04-03 08:28:18 +0300  561) {
44d8660d3bb0a (J. Bruce Fields      2017-09-19 20:51:31 -0400  562) 	#define NFSD_DRC_SIZE_SHIFT	7
0c193054a4c1c (Andy Adamson         2009-07-27 19:09:19 -0400  563) 	nfsd_drc_max_mem = (nr_free_buffer_pages()
0c193054a4c1c (Andy Adamson         2009-07-27 19:09:19 -0400  564) 					>> NFSD_DRC_SIZE_SHIFT) * PAGE_SIZE;
0c193054a4c1c (Andy Adamson         2009-07-27 19:09:19 -0400  565) 	nfsd_drc_mem_used = 0;
697ce9be7d5c7 (Zhang Yanfei         2013-02-22 16:35:47 -0800  566) 	dprintk("%s nfsd_drc_max_mem %lu \n", __func__, nfsd_drc_max_mem);
c3d06f9ce8544 (Andy Adamson         2009-04-03 08:28:18 +0300  567) }
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400  568) 
87b0fc7deb5fe (J. Bruce Fields      2012-01-30 16:18:35 -0500  569) static int nfsd_get_default_max_blksize(void)
02a375f0ac4bc (NeilBrown            2006-10-02 02:17:46 -0700  570) {
87b0fc7deb5fe (J. Bruce Fields      2012-01-30 16:18:35 -0500  571) 	struct sysinfo i;
87b0fc7deb5fe (J. Bruce Fields      2012-01-30 16:18:35 -0500  572) 	unsigned long long target;
87b0fc7deb5fe (J. Bruce Fields      2012-01-30 16:18:35 -0500  573) 	unsigned long ret;
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400  574) 
87b0fc7deb5fe (J. Bruce Fields      2012-01-30 16:18:35 -0500  575) 	si_meminfo(&i);
508f92275624f (J. Bruce Fields      2012-01-30 16:21:11 -0500  576) 	target = (i.totalram - i.totalhigh) << PAGE_SHIFT;
87b0fc7deb5fe (J. Bruce Fields      2012-01-30 16:18:35 -0500  577) 	/*
87b0fc7deb5fe (J. Bruce Fields      2012-01-30 16:18:35 -0500  578) 	 * Aim for 1/4096 of memory per thread This gives 1MB on 4Gig
87b0fc7deb5fe (J. Bruce Fields      2012-01-30 16:18:35 -0500  579) 	 * machines, but only uses 32K on 128M machines.  Bottom out at
87b0fc7deb5fe (J. Bruce Fields      2012-01-30 16:18:35 -0500  580) 	 * 8K on 32M and smaller.  Of course, this is only a default.
87b0fc7deb5fe (J. Bruce Fields      2012-01-30 16:18:35 -0500  581) 	 */
87b0fc7deb5fe (J. Bruce Fields      2012-01-30 16:18:35 -0500  582) 	target >>= 12;
87b0fc7deb5fe (J. Bruce Fields      2012-01-30 16:18:35 -0500  583) 
87b0fc7deb5fe (J. Bruce Fields      2012-01-30 16:18:35 -0500  584) 	ret = NFSSVC_MAXBLKSIZE;
87b0fc7deb5fe (J. Bruce Fields      2012-01-30 16:18:35 -0500  585) 	while (ret > target && ret >= 8*1024*2)
87b0fc7deb5fe (J. Bruce Fields      2012-01-30 16:18:35 -0500  586) 		ret /= 2;
87b0fc7deb5fe (J. Bruce Fields      2012-01-30 16:18:35 -0500  587) 	return ret;
87b0fc7deb5fe (J. Bruce Fields      2012-01-30 16:18:35 -0500  588) }
87b0fc7deb5fe (J. Bruce Fields      2012-01-30 16:18:35 -0500  589) 
afea5657c20b1 (Chuck Lever          2017-08-01 12:00:06 -0400  590) static const struct svc_serv_ops nfsd_thread_sv_ops = {
b9e13cdfac70e (Jeff Layton          2015-06-08 12:06:51 -0700  591) 	.svo_shutdown		= nfsd_last_thread,
b9e13cdfac70e (Jeff Layton          2015-06-08 12:06:51 -0700  592) 	.svo_function		= nfsd,
b9e13cdfac70e (Jeff Layton          2015-06-08 12:06:51 -0700  593) 	.svo_enqueue_xprt	= svc_xprt_do_enqueue,
598e2359090d3 (Jeff Layton          2015-06-08 12:08:33 -0700  594) 	.svo_setup		= svc_set_num_threads,
b9e13cdfac70e (Jeff Layton          2015-06-08 12:06:51 -0700  595) 	.svo_module		= THIS_MODULE,
ea126e7435345 (Jeff Layton          2015-06-08 12:03:32 -0700  596) };
ea126e7435345 (Jeff Layton          2015-06-08 12:03:32 -0700  597) 
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  598) static void nfsd_complete_shutdown(struct net *net)
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  599) {
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  600) 	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  601) 
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  602) 	WARN_ON(!mutex_is_locked(&nfsd_mutex));
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  603) 
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  604) 	nn->nfsd_serv = NULL;
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  605) 	complete(&nn->nfsd_shutdown_complete);
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  606) }
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  607) 
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  608) void nfsd_shutdown_threads(struct net *net)
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  609) {
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  610) 	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  611) 	struct svc_serv *serv;
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  612) 
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  613) 	mutex_lock(&nfsd_mutex);
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  614) 	serv = nn->nfsd_serv;
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  615) 	if (serv == NULL) {
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  616) 		mutex_unlock(&nfsd_mutex);
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  617) 		return;
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  618) 	}
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  619) 
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  620) 	svc_get(serv);
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  621) 	/* Kill outstanding nfsd threads */
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  622) 	serv->sv_ops->svo_setup(serv, NULL, 0);
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  623) 	nfsd_destroy(net);
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  624) 	mutex_unlock(&nfsd_mutex);
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  625) 	/* Wait for shutdown of nfsd_serv to complete */
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  626) 	wait_for_completion(&nn->nfsd_shutdown_complete);
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  627) }
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  628) 
44fb26c6b4c5a (Ma Feng              2020-05-11 20:07:08 +0800  629) bool i_am_nfsd(void)
28df3d1539de5 (J. Bruce Fields      2017-07-28 16:35:15 -0400  630) {
28df3d1539de5 (J. Bruce Fields      2017-07-28 16:35:15 -0400  631) 	return kthread_func(current) == nfsd;
28df3d1539de5 (J. Bruce Fields      2017-07-28 16:35:15 -0400  632) }
28df3d1539de5 (J. Bruce Fields      2017-07-28 16:35:15 -0400  633) 
6777436b0f072 (Stanislav Kinsbursky 2012-12-10 12:19:20 +0300  634) int nfsd_create_serv(struct net *net)
87b0fc7deb5fe (J. Bruce Fields      2012-01-30 16:18:35 -0500  635) {
9793f7c88937e (Stanislav Kinsbursky 2012-05-02 16:08:38 +0400  636) 	int error;
b9c0ef8571c6a (Stanislav Kinsbursky 2012-12-06 14:23:19 +0300  637) 	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
9793f7c88937e (Stanislav Kinsbursky 2012-05-02 16:08:38 +0400  638) 
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400  639) 	WARN_ON(!mutex_is_locked(&nfsd_mutex));
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  640) 	if (nn->nfsd_serv) {
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  641) 		svc_get(nn->nfsd_serv);
02a375f0ac4bc (NeilBrown            2006-10-02 02:17:46 -0700  642) 		return 0;
02a375f0ac4bc (NeilBrown            2006-10-02 02:17:46 -0700  643) 	}
87b0fc7deb5fe (J. Bruce Fields      2012-01-30 16:18:35 -0500  644) 	if (nfsd_max_blksize == 0)
87b0fc7deb5fe (J. Bruce Fields      2012-01-30 16:18:35 -0500  645) 		nfsd_max_blksize = nfsd_get_default_max_blksize();
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  646) 	nfsd_reset_versions(nn);
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  647) 	nn->nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize,
b9e13cdfac70e (Jeff Layton          2015-06-08 12:06:51 -0700  648) 						&nfsd_thread_sv_ops);
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  649) 	if (nn->nfsd_serv == NULL)
628b368728e23 (Jeff Layton          2010-07-21 16:40:08 -0400  650) 		return -ENOMEM;
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  651) 	init_completion(&nn->nfsd_shutdown_complete);
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400  652) 
5b8db00bae39e (Jeff Layton          2014-07-02 16:11:22 -0400  653) 	nn->nfsd_serv->sv_maxconn = nn->max_connections;
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  654) 	error = svc_bind(nn->nfsd_serv, net);
9793f7c88937e (Stanislav Kinsbursky 2012-05-02 16:08:38 +0400  655) 	if (error < 0) {
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  656) 		svc_destroy(nn->nfsd_serv);
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  657) 		nfsd_complete_shutdown(net);
9793f7c88937e (Stanislav Kinsbursky 2012-05-02 16:08:38 +0400  658) 		return error;
9793f7c88937e (Stanislav Kinsbursky 2012-05-02 16:08:38 +0400  659) 	}
9793f7c88937e (Stanislav Kinsbursky 2012-05-02 16:08:38 +0400  660) 
628b368728e23 (Jeff Layton          2010-07-21 16:40:08 -0400  661) 	set_max_drc();
1eca45f8a8409 (Vasily Averin        2016-09-21 15:33:05 +0300  662) 	/* check if the notifier is already set */
1eca45f8a8409 (Vasily Averin        2016-09-21 15:33:05 +0300  663) 	if (atomic_inc_return(&nfsd_notifier_refcount) == 1) {
1eca45f8a8409 (Vasily Averin        2016-09-21 15:33:05 +0300  664) 		register_inetaddr_notifier(&nfsd_inetaddr_notifier);
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  665) #if IS_ENABLED(CONFIG_IPV6)
1eca45f8a8409 (Vasily Averin        2016-09-21 15:33:05 +0300  666) 		register_inet6addr_notifier(&nfsd_inet6addr_notifier);
366849966f20a (Scott Mayhew         2015-12-11 16:45:59 -0500  667) #endif
1eca45f8a8409 (Vasily Averin        2016-09-21 15:33:05 +0300  668) 	}
2317dc557a3b6 (Vasily Averin        2017-11-10 10:19:35 +0300  669) 	atomic_inc(&nn->ntf_refcnt);
27c438f53e79b (Trond Myklebust      2019-09-02 13:02:56 -0400  670) 	nfsd_reset_boot_verifier(nn);
87b0fc7deb5fe (J. Bruce Fields      2012-01-30 16:18:35 -0500  671) 	return 0;
02a375f0ac4bc (NeilBrown            2006-10-02 02:17:46 -0700  672) }
02a375f0ac4bc (NeilBrown            2006-10-02 02:17:46 -0700  673) 
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  674) int nfsd_nrpools(struct net *net)
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  675) {
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  676) 	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  677) 
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  678) 	if (nn->nfsd_serv == NULL)
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  679) 		return 0;
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  680) 	else
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  681) 		return nn->nfsd_serv->sv_nrpools;
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  682) }
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  683) 
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  684) int nfsd_get_nrthreads(int n, int *nthreads, struct net *net)
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  685) {
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  686) 	int i = 0;
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  687) 	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  688) 
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  689) 	if (nn->nfsd_serv != NULL) {
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  690) 		for (i = 0; i < nn->nfsd_serv->sv_nrpools && i < n; i++)
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  691) 			nthreads[i] = nn->nfsd_serv->sv_pools[i].sp_nrthreads;
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  692) 	}
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  693) 
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  694) 	return 0;
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  695) }
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  696) 
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  697) void nfsd_destroy(struct net *net)
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  698) {
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  699) 	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  700) 	int destroy = (nn->nfsd_serv->sv_nrthreads == 1);
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  701) 
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  702) 	if (destroy)
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  703) 		svc_shutdown_net(nn->nfsd_serv, net);
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  704) 	svc_destroy(nn->nfsd_serv);
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  705) 	if (destroy)
c6c7f2a84da45 (Trond Myklebust      2021-03-13 16:08:47 -0500  706) 		nfsd_complete_shutdown(net);
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  707) }
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  708) 
3938a0d5eb5ef (Stanislav Kinsbursky 2012-12-10 12:19:30 +0300  709) int nfsd_set_nrthreads(int n, int *nthreads, struct net *net)
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  710) {
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  711) 	int i = 0;
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  712) 	int tot = 0;
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  713) 	int err = 0;
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  714) 	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  715) 
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400  716) 	WARN_ON(!mutex_is_locked(&nfsd_mutex));
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400  717) 
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  718) 	if (nn->nfsd_serv == NULL || n <= 0)
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  719) 		return 0;
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  720) 
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  721) 	if (n > nn->nfsd_serv->sv_nrpools)
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  722) 		n = nn->nfsd_serv->sv_nrpools;
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  723) 
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  724) 	/* enforce a global maximum number of threads */
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  725) 	tot = 0;
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  726) 	for (i = 0; i < n; i++) {
3c7aa15d2073d (Kinglong Mee         2014-06-10 18:08:19 +0800  727) 		nthreads[i] = min(nthreads[i], NFSD_MAXSERVS);
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  728) 		tot += nthreads[i];
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  729) 	}
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  730) 	if (tot > NFSD_MAXSERVS) {
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  731) 		/* total too large: scale down requested numbers */
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  732) 		for (i = 0; i < n && tot > 0; i++) {
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  733) 		    	int new = nthreads[i] * NFSD_MAXSERVS / tot;
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  734) 			tot -= (nthreads[i] - new);
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  735) 			nthreads[i] = new;
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  736) 		}
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  737) 		for (i = 0; i < n && tot > 0; i++) {
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  738) 			nthreads[i]--;
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  739) 			tot--;
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  740) 		}
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  741) 	}
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  742) 
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  743) 	/*
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  744) 	 * There must always be a thread in pool 0; the admin
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  745) 	 * can't shut down NFS completely using pool_threads.
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  746) 	 */
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  747) 	if (nthreads[0] == 0)
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  748) 		nthreads[0] = 1;
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  749) 
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  750) 	/* apply the new numbers */
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  751) 	svc_get(nn->nfsd_serv);
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  752) 	for (i = 0; i < n; i++) {
598e2359090d3 (Jeff Layton          2015-06-08 12:08:33 -0700  753) 		err = nn->nfsd_serv->sv_ops->svo_setup(nn->nfsd_serv,
598e2359090d3 (Jeff Layton          2015-06-08 12:08:33 -0700  754) 				&nn->nfsd_serv->sv_pools[i], nthreads[i]);
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  755) 		if (err)
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  756) 			break;
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  757) 	}
19f7e2ca44dfc (Stanislav Kinsbursky 2012-07-03 16:46:41 +0400  758) 	nfsd_destroy(net);
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  759) 	return err;
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  760) }
eed2965af1bae (Greg Banks           2006-10-02 02:18:02 -0700  761) 
ac77efbe2b4d2 (Jeff Layton          2010-07-20 14:10:22 -0400  762) /*
ac77efbe2b4d2 (Jeff Layton          2010-07-20 14:10:22 -0400  763)  * Adjust the number of threads and return the new number of threads.
ac77efbe2b4d2 (Jeff Layton          2010-07-20 14:10:22 -0400  764)  * This is also the function that starts the server if necessary, if
ac77efbe2b4d2 (Jeff Layton          2010-07-20 14:10:22 -0400  765)  * this is the first time nrservs is nonzero.
ac77efbe2b4d2 (Jeff Layton          2010-07-20 14:10:22 -0400  766)  */
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  767) int
4df493a260d4c (Trond Myklebust      2019-04-09 12:13:37 -0400  768) nfsd_svc(int nrservs, struct net *net, const struct cred *cred)
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  769) {
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  770) 	int	error;
774f8bbd9ef2e (J. Bruce Fields      2010-08-02 14:12:44 -0400  771) 	bool	nfsd_up_before;
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  772) 	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400  773) 
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400  774) 	mutex_lock(&nfsd_mutex);
6658d3a7bbfd1 (NeilBrown            2006-10-02 02:17:46 -0700  775) 	dprintk("nfsd: creating service\n");
3c7aa15d2073d (Kinglong Mee         2014-06-10 18:08:19 +0800  776) 
3c7aa15d2073d (Kinglong Mee         2014-06-10 18:08:19 +0800  777) 	nrservs = max(nrservs, 0);
3c7aa15d2073d (Kinglong Mee         2014-06-10 18:08:19 +0800  778) 	nrservs = min(nrservs, NFSD_MAXSERVS);
671e1fcf63fd1 (NeilBrown            2009-06-16 11:03:20 +1000  779) 	error = 0;
3c7aa15d2073d (Kinglong Mee         2014-06-10 18:08:19 +0800  780) 
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  781) 	if (nrservs == 0 && nn->nfsd_serv == NULL)
671e1fcf63fd1 (NeilBrown            2009-06-16 11:03:20 +1000  782) 		goto out;
671e1fcf63fd1 (NeilBrown            2009-06-16 11:03:20 +1000  783) 
7627d7dc79a8e (Scott Mayhew         2020-02-19 15:52:15 -0500  784) 	strlcpy(nn->nfsd_name, utsname()->nodename,
7627d7dc79a8e (Scott Mayhew         2020-02-19 15:52:15 -0500  785) 		sizeof(nn->nfsd_name));
7627d7dc79a8e (Scott Mayhew         2020-02-19 15:52:15 -0500  786) 
6777436b0f072 (Stanislav Kinsbursky 2012-12-10 12:19:20 +0300  787) 	error = nfsd_create_serv(net);
02a375f0ac4bc (NeilBrown            2006-10-02 02:17:46 -0700  788) 	if (error)
774f8bbd9ef2e (J. Bruce Fields      2010-08-02 14:12:44 -0400  789) 		goto out;
774f8bbd9ef2e (J. Bruce Fields      2010-08-02 14:12:44 -0400  790) 
903d9bf0edebc (Stanislav Kinsbursky 2012-12-06 14:23:34 +0300  791) 	nfsd_up_before = nn->nfsd_net_up;
774f8bbd9ef2e (J. Bruce Fields      2010-08-02 14:12:44 -0400  792) 
70c5307564035 (Vasily Averin        2021-04-15 15:00:58 +0300  793) 	error = nfsd_startup_net(net, cred);
af4718f3f9969 (J. Bruce Fields      2010-07-21 18:31:42 -0400  794) 	if (error)
af4718f3f9969 (J. Bruce Fields      2010-07-21 18:31:42 -0400  795) 		goto out_destroy;
598e2359090d3 (Jeff Layton          2015-06-08 12:08:33 -0700  796) 	error = nn->nfsd_serv->sv_ops->svo_setup(nn->nfsd_serv,
598e2359090d3 (Jeff Layton          2015-06-08 12:08:33 -0700  797) 			NULL, nrservs);
774f8bbd9ef2e (J. Bruce Fields      2010-08-02 14:12:44 -0400  798) 	if (error)
774f8bbd9ef2e (J. Bruce Fields      2010-08-02 14:12:44 -0400  799) 		goto out_shutdown;
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  800) 	/* We are holding a reference to nn->nfsd_serv which
af4718f3f9969 (J. Bruce Fields      2010-07-21 18:31:42 -0400  801) 	 * we don't want to count in the return value,
af4718f3f9969 (J. Bruce Fields      2010-07-21 18:31:42 -0400  802) 	 * so subtract 1
af4718f3f9969 (J. Bruce Fields      2010-07-21 18:31:42 -0400  803) 	 */
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300  804) 	error = nn->nfsd_serv->sv_nrthreads - 1;
4ad9a344be229 (Jeff Layton          2010-07-19 16:50:04 -0400  805) out_shutdown:
774f8bbd9ef2e (J. Bruce Fields      2010-08-02 14:12:44 -0400  806) 	if (error < 0 && !nfsd_up_before)
541e864f00d00 (Stanislav Kinsbursky 2012-12-06 14:23:44 +0300  807) 		nfsd_shutdown_net(net);
774f8bbd9ef2e (J. Bruce Fields      2010-08-02 14:12:44 -0400  808) out_destroy:
19f7e2ca44dfc (Stanislav Kinsbursky 2012-07-03 16:46:41 +0400  809) 	nfsd_destroy(net);		/* Release server */
4ad9a344be229 (Jeff Layton          2010-07-19 16:50:04 -0400  810) out:
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400  811) 	mutex_unlock(&nfsd_mutex);
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  812) 	return error;
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  813) }
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  814) 
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  815) #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  816) static bool
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  817) nfsd_support_acl_version(int vers)
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  818) {
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  819) 	if (vers >= NFSD_ACL_MINVERS && vers < NFSD_ACL_NRVERS)
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  820) 		return nfsd_acl_version[vers] != NULL;
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  821) 	return false;
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  822) }
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  823) 
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  824) static int
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  825) nfsd_acl_rpcbind_set(struct net *net, const struct svc_program *progp,
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  826) 		     u32 version, int family, unsigned short proto,
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  827) 		     unsigned short port)
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  828) {
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  829) 	if (!nfsd_support_acl_version(version) ||
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  830) 	    !nfsd_vers(net_generic(net, nfsd_net_id), version, NFSD_TEST))
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  831) 		return 0;
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  832) 	return svc_generic_rpcbind_set(net, progp, version, family,
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  833) 			proto, port);
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  834) }
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  835) 
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  836) static __be32
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  837) nfsd_acl_init_request(struct svc_rqst *rqstp,
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  838) 		      const struct svc_program *progp,
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  839) 		      struct svc_process_info *ret)
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  840) {
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  841) 	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  842) 	int i;
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  843) 
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  844) 	if (likely(nfsd_support_acl_version(rqstp->rq_vers) &&
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  845) 	    nfsd_vers(nn, rqstp->rq_vers, NFSD_TEST)))
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  846) 		return svc_generic_init_request(rqstp, progp, ret);
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  847) 
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  848) 	ret->mismatch.lovers = NFSD_ACL_NRVERS;
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  849) 	for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++) {
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  850) 		if (nfsd_support_acl_version(rqstp->rq_vers) &&
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  851) 		    nfsd_vers(nn, i, NFSD_TEST)) {
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  852) 			ret->mismatch.lovers = i;
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  853) 			break;
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  854) 		}
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  855) 	}
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  856) 	if (ret->mismatch.lovers == NFSD_ACL_NRVERS)
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  857) 		return rpc_prog_unavail;
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  858) 	ret->mismatch.hivers = NFSD_ACL_MINVERS;
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  859) 	for (i = NFSD_ACL_NRVERS - 1; i >= NFSD_ACL_MINVERS; i--) {
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  860) 		if (nfsd_support_acl_version(rqstp->rq_vers) &&
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  861) 		    nfsd_vers(nn, i, NFSD_TEST)) {
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  862) 			ret->mismatch.hivers = i;
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  863) 			break;
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  864) 		}
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  865) 	}
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  866) 	return rpc_prog_mismatch;
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  867) }
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  868) #endif
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  869) 
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  870) static int
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  871) nfsd_rpcbind_set(struct net *net, const struct svc_program *progp,
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  872) 		 u32 version, int family, unsigned short proto,
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  873) 		 unsigned short port)
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  874) {
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  875) 	if (!nfsd_vers(net_generic(net, nfsd_net_id), version, NFSD_TEST))
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  876) 		return 0;
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  877) 	return svc_generic_rpcbind_set(net, progp, version, family,
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  878) 			proto, port);
029be5d03357f (Trond Myklebust      2019-04-09 11:46:18 -0400  879) }
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  880) 
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  881) static __be32
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  882) nfsd_init_request(struct svc_rqst *rqstp,
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  883) 		  const struct svc_program *progp,
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  884) 		  struct svc_process_info *ret)
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  885) {
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  886) 	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  887) 	int i;
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  888) 
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  889) 	if (likely(nfsd_vers(nn, rqstp->rq_vers, NFSD_TEST)))
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  890) 		return svc_generic_init_request(rqstp, progp, ret);
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  891) 
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  892) 	ret->mismatch.lovers = NFSD_NRVERS;
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  893) 	for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) {
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  894) 		if (nfsd_vers(nn, i, NFSD_TEST)) {
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  895) 			ret->mismatch.lovers = i;
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  896) 			break;
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  897) 		}
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  898) 	}
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  899) 	if (ret->mismatch.lovers == NFSD_NRVERS)
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  900) 		return rpc_prog_unavail;
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  901) 	ret->mismatch.hivers = NFSD_MINVERS;
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  902) 	for (i = NFSD_NRVERS - 1; i >= NFSD_MINVERS; i--) {
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  903) 		if (nfsd_vers(nn, i, NFSD_TEST)) {
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  904) 			ret->mismatch.hivers = i;
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  905) 			break;
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  906) 		}
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  907) 	}
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  908) 	return rpc_prog_mismatch;
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  909) }
e333f3bbefe3e (Trond Myklebust      2019-04-09 11:46:19 -0400  910) 
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  911) /*
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  912)  * This is the NFS server kernel thread
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  913)  */
9867d76ca16b3 (Jeff Layton          2008-06-10 08:40:38 -0400  914) static int
9867d76ca16b3 (Jeff Layton          2008-06-10 08:40:38 -0400  915) nfsd(void *vrqstp)
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  916) {
9867d76ca16b3 (Jeff Layton          2008-06-10 08:40:38 -0400  917) 	struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp;
88c4766617198 (Stanislav Kinsbursky 2012-12-06 18:34:42 +0300  918) 	struct svc_xprt *perm_sock = list_entry(rqstp->rq_server->sv_permsocks.next, typeof(struct svc_xprt), xpt_list);
88c4766617198 (Stanislav Kinsbursky 2012-12-06 18:34:42 +0300  919) 	struct net *net = perm_sock->xpt_net;
5b8db00bae39e (Jeff Layton          2014-07-02 16:11:22 -0400  920) 	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
5b444cc9a4c97 (J. Bruce Fields      2012-08-17 21:47:53 -0400  921) 	int err;
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  922) 
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  923) 	/* Lock module and set up kernel thread */
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400  924) 	mutex_lock(&nfsd_mutex);
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  925) 
9867d76ca16b3 (Jeff Layton          2008-06-10 08:40:38 -0400  926) 	/* At this point, the thread shares current->fs
47057abde5151 (Andreas Gruenbacher  2016-01-12 20:24:14 +0100  927) 	 * with the init process. We need to create files with the
47057abde5151 (Andreas Gruenbacher  2016-01-12 20:24:14 +0100  928) 	 * umask as defined by the client instead of init's umask. */
3e93cd671813e (Al Viro              2009-03-29 19:00:13 -0400  929) 	if (unshare_fs_struct() < 0) {
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  930) 		printk("Unable to start nfsd thread: out of memory\n");
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  931) 		goto out;
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  932) 	}
3e93cd671813e (Al Viro              2009-03-29 19:00:13 -0400  933) 
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  934) 	current->fs->umask = 0;
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  935) 
9867d76ca16b3 (Jeff Layton          2008-06-10 08:40:38 -0400  936) 	/*
9867d76ca16b3 (Jeff Layton          2008-06-10 08:40:38 -0400  937) 	 * thread is spawned with all signals set to SIG_IGN, re-enable
100766f8347c1 (Jeff Layton          2008-06-30 14:09:46 -0400  938) 	 * the ones that will bring down the thread
9867d76ca16b3 (Jeff Layton          2008-06-10 08:40:38 -0400  939) 	 */
100766f8347c1 (Jeff Layton          2008-06-30 14:09:46 -0400  940) 	allow_signal(SIGKILL);
100766f8347c1 (Jeff Layton          2008-06-30 14:09:46 -0400  941) 	allow_signal(SIGHUP);
100766f8347c1 (Jeff Layton          2008-06-30 14:09:46 -0400  942) 	allow_signal(SIGINT);
100766f8347c1 (Jeff Layton          2008-06-30 14:09:46 -0400  943) 	allow_signal(SIGQUIT);
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400  944) 
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  945) 	nfsdstats.th_cnt++;
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400  946) 	mutex_unlock(&nfsd_mutex);
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400  947) 
831441862956f (Rafael J. Wysocki    2007-07-17 04:03:35 -0700  948) 	set_freezable();
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  949) 
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  950) 	/*
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  951) 	 * The main request loop
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  952) 	 */
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  953) 	for (;;) {
5b8db00bae39e (Jeff Layton          2014-07-02 16:11:22 -0400  954) 		/* Update sv_maxconn if it has changed */
5b8db00bae39e (Jeff Layton          2014-07-02 16:11:22 -0400  955) 		rqstp->rq_server->sv_maxconn = nn->max_connections;
5b8db00bae39e (Jeff Layton          2014-07-02 16:11:22 -0400  956) 
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  957) 		/*
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  958) 		 * Find a socket with data available and call its
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  959) 		 * recvfrom routine.
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  960) 		 */
6fb2b47fa16c8 (NeilBrown            2006-10-02 02:17:50 -0700  961) 		while ((err = svc_recv(rqstp, 60*60*HZ)) == -EAGAIN)
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  962) 			;
9867d76ca16b3 (Jeff Layton          2008-06-10 08:40:38 -0400  963) 		if (err == -EINTR)
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  964) 			break;
e0e817392b9ac (David Howells        2009-09-02 09:13:40 +0100  965) 		validate_process_creds();
6fb2b47fa16c8 (NeilBrown            2006-10-02 02:17:50 -0700  966) 		svc_process(rqstp);
e0e817392b9ac (David Howells        2009-09-02 09:13:40 +0100  967) 		validate_process_creds();
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  968) 	}
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  969) 
24e36663c375d (NeilBrown            2006-10-02 02:17:45 -0700  970) 	/* Clear signals before calling svc_exit_thread() */
9e416052f1462 (NeilBrown            2005-04-16 15:26:37 -0700  971) 	flush_signals(current);
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  972) 
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400  973) 	mutex_lock(&nfsd_mutex);
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  974) 	nfsdstats.th_cnt --;
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  975) 
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  976) out:
57c8b13e3cd0f (Stanislav Kinsbursky 2012-07-03 16:46:41 +0400  977) 	rqstp->rq_server = NULL;
786185b5f8abe (Stanislav Kinsbursky 2012-05-04 12:49:41 +0400  978) 
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  979) 	/* Release the thread */
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  980) 	svc_exit_thread(rqstp);
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  981) 
88c4766617198 (Stanislav Kinsbursky 2012-12-06 18:34:42 +0300  982) 	nfsd_destroy(net);
57c8b13e3cd0f (Stanislav Kinsbursky 2012-07-03 16:46:41 +0400  983) 
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  984) 	/* Release module */
bedbdd8bada19 (Neil Brown           2008-06-10 08:40:35 -0400  985) 	mutex_unlock(&nfsd_mutex);
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  986) 	module_put_and_exit(0);
9867d76ca16b3 (Jeff Layton          2008-06-10 08:40:38 -0400  987) 	return 0;
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  988) }
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700  989) 
383c440d4f14f (Chuck Lever          2020-10-01 18:59:23 -0400  990) /**
383c440d4f14f (Chuck Lever          2020-10-01 18:59:23 -0400  991)  * nfsd_dispatch - Process an NFS or NFSACL Request
383c440d4f14f (Chuck Lever          2020-10-01 18:59:23 -0400  992)  * @rqstp: incoming request
383c440d4f14f (Chuck Lever          2020-10-01 18:59:23 -0400  993)  * @statp: pointer to location of accept_stat field in RPC Reply buffer
383c440d4f14f (Chuck Lever          2020-10-01 18:59:23 -0400  994)  *
383c440d4f14f (Chuck Lever          2020-10-01 18:59:23 -0400  995)  * This RPC dispatcher integrates the NFS server's duplicate reply cache.
383c440d4f14f (Chuck Lever          2020-10-01 18:59:23 -0400  996)  *
383c440d4f14f (Chuck Lever          2020-10-01 18:59:23 -0400  997)  * Return values:
383c440d4f14f (Chuck Lever          2020-10-01 18:59:23 -0400  998)  *  %0: Processing complete; do not send a Reply
383c440d4f14f (Chuck Lever          2020-10-01 18:59:23 -0400  999)  *  %1: Processing complete; send Reply in rqstp->rq_res
383c440d4f14f (Chuck Lever          2020-10-01 18:59:23 -0400 1000)  */
383c440d4f14f (Chuck Lever          2020-10-01 18:59:23 -0400 1001) int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700 1002) {
4c96cb56eefa6 (Chuck Lever          2020-10-01 18:59:28 -0400 1003) 	const struct svc_procedure *proc = rqstp->rq_procinfo;
4c96cb56eefa6 (Chuck Lever          2020-10-01 18:59:28 -0400 1004) 	struct kvec *argv = &rqstp->rq_arg.head[0];
4c96cb56eefa6 (Chuck Lever          2020-10-01 18:59:28 -0400 1005) 	struct kvec *resv = &rqstp->rq_res.head[0];
cc028a10a48c3 (Chuck Lever          2020-10-02 15:52:44 -0400 1006) 	__be32 *p;
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700 1007) 
1091006c5eb15 (J. Bruce Fields      2011-01-24 12:11:02 -0500 1008) 	/*
1091006c5eb15 (J. Bruce Fields      2011-01-24 12:11:02 -0500 1009) 	 * Give the xdr decoder a chance to change this if it wants
1091006c5eb15 (J. Bruce Fields      2011-01-24 12:11:02 -0500 1010) 	 * (necessary in the NFSv4.0 compound case)
1091006c5eb15 (J. Bruce Fields      2011-01-24 12:11:02 -0500 1011) 	 */
1091006c5eb15 (J. Bruce Fields      2011-01-24 12:11:02 -0500 1012) 	rqstp->rq_cachetype = proc->pc_cachetype;
5191955d6fc65 (Chuck Lever          2020-11-05 11:19:42 -0500 1013) 
5191955d6fc65 (Chuck Lever          2020-11-05 11:19:42 -0500 1014) 	svcxdr_init_decode(rqstp);
85085aacefc62 (Chuck Lever          2020-10-01 18:59:33 -0400 1015) 	if (!proc->pc_decode(rqstp, argv->iov_base))
85085aacefc62 (Chuck Lever          2020-10-01 18:59:33 -0400 1016) 		goto out_decode_err;
1091006c5eb15 (J. Bruce Fields      2011-01-24 12:11:02 -0500 1017) 
1091006c5eb15 (J. Bruce Fields      2011-01-24 12:11:02 -0500 1018) 	switch (nfsd_cache_lookup(rqstp)) {
84c138e78d8ec (Chuck Lever          2020-10-01 18:59:18 -0400 1019) 	case RC_DOIT:
84c138e78d8ec (Chuck Lever          2020-10-01 18:59:18 -0400 1020) 		break;
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700 1021) 	case RC_REPLY:
85085aacefc62 (Chuck Lever          2020-10-01 18:59:33 -0400 1022) 		goto out_cached_reply;
84c138e78d8ec (Chuck Lever          2020-10-01 18:59:18 -0400 1023) 	case RC_DROPIT:
85085aacefc62 (Chuck Lever          2020-10-01 18:59:33 -0400 1024) 		goto out_dropit;
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700 1025) 	}
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700 1026) 
383c440d4f14f (Chuck Lever          2020-10-01 18:59:23 -0400 1027) 	/*
383c440d4f14f (Chuck Lever          2020-10-01 18:59:23 -0400 1028) 	 * Need to grab the location to store the status, as
383c440d4f14f (Chuck Lever          2020-10-01 18:59:23 -0400 1029) 	 * NFSv4 does some encoding while processing
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700 1030) 	 */
cc028a10a48c3 (Chuck Lever          2020-10-02 15:52:44 -0400 1031) 	p = resv->iov_base + resv->iov_len;
bddfdbcddbe26 (Chuck Lever          2020-10-27 15:53:42 -0400 1032) 	svcxdr_init_encode(rqstp);
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700 1033) 
cc028a10a48c3 (Chuck Lever          2020-10-02 15:52:44 -0400 1034) 	*statp = proc->pc_func(rqstp);
cc028a10a48c3 (Chuck Lever          2020-10-02 15:52:44 -0400 1035) 	if (*statp == rpc_drop_reply || test_bit(RQ_DROPME, &rqstp->rq_flags))
85085aacefc62 (Chuck Lever          2020-10-01 18:59:33 -0400 1036) 		goto out_update_drop;
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700 1037) 
cc028a10a48c3 (Chuck Lever          2020-10-02 15:52:44 -0400 1038) 	if (!proc->pc_encode(rqstp, p))
f0af22101d907 (Chuck Lever          2020-10-01 18:59:49 -0400 1039) 		goto out_encode_err;
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700 1040) 
57d276d71aef7 (J. Bruce Fields      2012-11-16 15:22:43 -0500 1041) 	nfsd_cache_update(rqstp, rqstp->rq_cachetype, statp + 1);
85085aacefc62 (Chuck Lever          2020-10-01 18:59:33 -0400 1042) out_cached_reply:
85085aacefc62 (Chuck Lever          2020-10-01 18:59:33 -0400 1043) 	return 1;
85085aacefc62 (Chuck Lever          2020-10-01 18:59:33 -0400 1044) 
85085aacefc62 (Chuck Lever          2020-10-01 18:59:33 -0400 1045) out_decode_err:
0dfdad1c1d1b7 (Chuck Lever          2020-10-19 13:00:29 -0400 1046) 	trace_nfsd_garbage_args_err(rqstp);
85085aacefc62 (Chuck Lever          2020-10-01 18:59:33 -0400 1047) 	*statp = rpc_garbage_args;
85085aacefc62 (Chuck Lever          2020-10-01 18:59:33 -0400 1048) 	return 1;
85085aacefc62 (Chuck Lever          2020-10-01 18:59:33 -0400 1049) 
85085aacefc62 (Chuck Lever          2020-10-01 18:59:33 -0400 1050) out_update_drop:
85085aacefc62 (Chuck Lever          2020-10-01 18:59:33 -0400 1051) 	nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
85085aacefc62 (Chuck Lever          2020-10-01 18:59:33 -0400 1052) out_dropit:
85085aacefc62 (Chuck Lever          2020-10-01 18:59:33 -0400 1053) 	return 0;
85085aacefc62 (Chuck Lever          2020-10-01 18:59:33 -0400 1054) 
85085aacefc62 (Chuck Lever          2020-10-01 18:59:33 -0400 1055) out_encode_err:
0dfdad1c1d1b7 (Chuck Lever          2020-10-19 13:00:29 -0400 1056) 	trace_nfsd_cant_encode_err(rqstp);
85085aacefc62 (Chuck Lever          2020-10-01 18:59:33 -0400 1057) 	nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
85085aacefc62 (Chuck Lever          2020-10-01 18:59:33 -0400 1058) 	*statp = rpc_system_err;
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700 1059) 	return 1;
^1da177e4c3f4 (Linus Torvalds       2005-04-16 15:20:36 -0700 1060) }
03cf6c9f49a8f (Greg Banks           2009-01-13 21:26:36 +1100 1061) 
788f7183fba86 (Chuck Lever          2020-11-05 14:48:29 -0500 1062) /**
788f7183fba86 (Chuck Lever          2020-11-05 14:48:29 -0500 1063)  * nfssvc_decode_voidarg - Decode void arguments
788f7183fba86 (Chuck Lever          2020-11-05 14:48:29 -0500 1064)  * @rqstp: Server RPC transaction context
788f7183fba86 (Chuck Lever          2020-11-05 14:48:29 -0500 1065)  * @p: buffer containing arguments to decode
788f7183fba86 (Chuck Lever          2020-11-05 14:48:29 -0500 1066)  *
788f7183fba86 (Chuck Lever          2020-11-05 14:48:29 -0500 1067)  * Return values:
788f7183fba86 (Chuck Lever          2020-11-05 14:48:29 -0500 1068)  *   %0: Arguments were not valid
788f7183fba86 (Chuck Lever          2020-11-05 14:48:29 -0500 1069)  *   %1: Decoding was successful
788f7183fba86 (Chuck Lever          2020-11-05 14:48:29 -0500 1070)  */
788f7183fba86 (Chuck Lever          2020-11-05 14:48:29 -0500 1071) int nfssvc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p)
788f7183fba86 (Chuck Lever          2020-11-05 14:48:29 -0500 1072) {
788f7183fba86 (Chuck Lever          2020-11-05 14:48:29 -0500 1073) 	return 1;
788f7183fba86 (Chuck Lever          2020-11-05 14:48:29 -0500 1074) }
788f7183fba86 (Chuck Lever          2020-11-05 14:48:29 -0500 1075) 
788f7183fba86 (Chuck Lever          2020-11-05 14:48:29 -0500 1076) /**
788f7183fba86 (Chuck Lever          2020-11-05 14:48:29 -0500 1077)  * nfssvc_encode_voidres - Encode void results
788f7183fba86 (Chuck Lever          2020-11-05 14:48:29 -0500 1078)  * @rqstp: Server RPC transaction context
788f7183fba86 (Chuck Lever          2020-11-05 14:48:29 -0500 1079)  * @p: buffer in which to encode results
788f7183fba86 (Chuck Lever          2020-11-05 14:48:29 -0500 1080)  *
788f7183fba86 (Chuck Lever          2020-11-05 14:48:29 -0500 1081)  * Return values:
788f7183fba86 (Chuck Lever          2020-11-05 14:48:29 -0500 1082)  *   %0: Local error while encoding
788f7183fba86 (Chuck Lever          2020-11-05 14:48:29 -0500 1083)  *   %1: Encoding was successful
788f7183fba86 (Chuck Lever          2020-11-05 14:48:29 -0500 1084)  */
788f7183fba86 (Chuck Lever          2020-11-05 14:48:29 -0500 1085) int nfssvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p)
788f7183fba86 (Chuck Lever          2020-11-05 14:48:29 -0500 1086) {
bddfdbcddbe26 (Chuck Lever          2020-10-27 15:53:42 -0400 1087) 	return 1;
788f7183fba86 (Chuck Lever          2020-11-05 14:48:29 -0500 1088) }
788f7183fba86 (Chuck Lever          2020-11-05 14:48:29 -0500 1089) 
03cf6c9f49a8f (Greg Banks           2009-01-13 21:26:36 +1100 1090) int nfsd_pool_stats_open(struct inode *inode, struct file *file)
03cf6c9f49a8f (Greg Banks           2009-01-13 21:26:36 +1100 1091) {
ed2d8aed52212 (Ryusei Yamaguchi     2009-08-16 00:54:41 +0900 1092) 	int ret;
11f779421a39b (Stanislav Kinsbursky 2013-02-01 15:56:12 +0300 1093) 	struct nfsd_net *nn = net_generic(inode->i_sb->s_fs_info, nfsd_net_id);
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300 1094) 
ed2d8aed52212 (Ryusei Yamaguchi     2009-08-16 00:54:41 +0900 1095) 	mutex_lock(&nfsd_mutex);
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300 1096) 	if (nn->nfsd_serv == NULL) {
ed2d8aed52212 (Ryusei Yamaguchi     2009-08-16 00:54:41 +0900 1097) 		mutex_unlock(&nfsd_mutex);
03cf6c9f49a8f (Greg Banks           2009-01-13 21:26:36 +1100 1098) 		return -ENODEV;
ed2d8aed52212 (Ryusei Yamaguchi     2009-08-16 00:54:41 +0900 1099) 	}
ed2d8aed52212 (Ryusei Yamaguchi     2009-08-16 00:54:41 +0900 1100) 	/* bump up the psudo refcount while traversing */
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300 1101) 	svc_get(nn->nfsd_serv);
9dd9845f084cd (Stanislav Kinsbursky 2012-12-06 14:23:24 +0300 1102) 	ret = svc_pool_stats_open(nn->nfsd_serv, file);
ed2d8aed52212 (Ryusei Yamaguchi     2009-08-16 00:54:41 +0900 1103) 	mutex_unlock(&nfsd_mutex);
ed2d8aed52212 (Ryusei Yamaguchi     2009-08-16 00:54:41 +0900 1104) 	return ret;
ed2d8aed52212 (Ryusei Yamaguchi     2009-08-16 00:54:41 +0900 1105) }
ed2d8aed52212 (Ryusei Yamaguchi     2009-08-16 00:54:41 +0900 1106) 
ed2d8aed52212 (Ryusei Yamaguchi     2009-08-16 00:54:41 +0900 1107) int nfsd_pool_stats_release(struct inode *inode, struct file *file)
ed2d8aed52212 (Ryusei Yamaguchi     2009-08-16 00:54:41 +0900 1108) {
ed2d8aed52212 (Ryusei Yamaguchi     2009-08-16 00:54:41 +0900 1109) 	int ret = seq_release(inode, file);
11f779421a39b (Stanislav Kinsbursky 2013-02-01 15:56:12 +0300 1110) 	struct net *net = inode->i_sb->s_fs_info;
786185b5f8abe (Stanislav Kinsbursky 2012-05-04 12:49:41 +0400 1111) 
ed2d8aed52212 (Ryusei Yamaguchi     2009-08-16 00:54:41 +0900 1112) 	mutex_lock(&nfsd_mutex);
ed2d8aed52212 (Ryusei Yamaguchi     2009-08-16 00:54:41 +0900 1113) 	/* this function really, really should have been called svc_put() */
19f7e2ca44dfc (Stanislav Kinsbursky 2012-07-03 16:46:41 +0400 1114) 	nfsd_destroy(net);
ed2d8aed52212 (Ryusei Yamaguchi     2009-08-16 00:54:41 +0900 1115) 	mutex_unlock(&nfsd_mutex);
ed2d8aed52212 (Ryusei Yamaguchi     2009-08-16 00:54:41 +0900 1116) 	return ret;
03cf6c9f49a8f (Greg Banks           2009-01-13 21:26:36 +1100 1117) }