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) }