Blame view
fs/nfsd/nfssvc.c
20 KB
1da177e4c Linux-2.6.12-rc2 |
1 |
/* |
1da177e4c Linux-2.6.12-rc2 |
2 3 4 5 6 7 |
* Central processing for nfsd. * * Authors: Olaf Kirch (okir@monad.swb.de) * * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de> */ |
e8edc6e03 Detach sched.h fr... |
8 |
#include <linux/sched.h> |
831441862 Freezer: make ker... |
9 |
#include <linux/freezer.h> |
143cb494c fs: add module.h ... |
10 |
#include <linux/module.h> |
1da177e4c Linux-2.6.12-rc2 |
11 |
#include <linux/fs_struct.h> |
c3d06f9ce nfsd41: hard page... |
12 |
#include <linux/swap.h> |
1da177e4c Linux-2.6.12-rc2 |
13 |
|
1da177e4c Linux-2.6.12-rc2 |
14 |
#include <linux/sunrpc/stats.h> |
1da177e4c Linux-2.6.12-rc2 |
15 |
#include <linux/sunrpc/svcsock.h> |
366849966 nfsd: Register ca... |
16 |
#include <linux/sunrpc/svc_xprt.h> |
1da177e4c Linux-2.6.12-rc2 |
17 |
#include <linux/lockd/bind.h> |
a257cdd0e [PATCH] NFSD: Add... |
18 |
#include <linux/nfsacl.h> |
ed2d8aed5 knfsd: Replace lo... |
19 |
#include <linux/seq_file.h> |
366849966 nfsd: Register ca... |
20 21 22 |
#include <linux/inetdevice.h> #include <net/addrconf.h> #include <net/ipv6.h> |
fc5d00b04 sunrpc: Add net a... |
23 |
#include <net/net_namespace.h> |
9a74af213 nfsd: Move privat... |
24 25 |
#include "nfsd.h" #include "cache.h" |
0a3adadee nfsd: make fs/nfs... |
26 |
#include "vfs.h" |
2c2fe2909 nfsd: per-net NFS... |
27 |
#include "netns.h" |
1da177e4c Linux-2.6.12-rc2 |
28 29 |
#define NFSDDBG_FACILITY NFSDDBG_SVC |
1da177e4c Linux-2.6.12-rc2 |
30 |
extern struct svc_program nfsd_program; |
9867d76ca knfsd: convert kn... |
31 |
static int nfsd(void *vrqstp); |
1da177e4c Linux-2.6.12-rc2 |
32 |
|
bedbdd8ba knfsd: Replace lo... |
33 |
/* |
9dd9845f0 nfsd: make NFSd s... |
34 |
* nfsd_mutex protects nn->nfsd_serv -- both the pointer itself and the members |
bedbdd8ba knfsd: Replace lo... |
35 36 37 |
* of the svc_serv struct. In particular, ->sv_nrthreads but also to some * extent ->sv_temp_socks and ->sv_permsocks. It also protects nfsdstats.th_cnt * |
9dd9845f0 nfsd: make NFSd s... |
38 |
* If (out side the lock) nn->nfsd_serv is non-NULL, then it must point to a |
bedbdd8ba knfsd: Replace lo... |
39 40 41 42 43 44 45 |
* properly initialised 'struct svc_serv' with ->sv_nrthreads > 0. That number * of nfsd threads must exist and each must listed in ->sp_all_threads in each * entry of ->sv_pools[]. * * Transitions of the thread count between zero and non-zero are of particular * interest since the svc_serv needs to be created and initialized at that * point, or freed. |
3dd98a3bc knfsd: clean up n... |
46 47 48 49 50 51 52 53 |
* * Finally, the nfsd_mutex also protects some of the global variables that are * accessed when nfsd starts and that are settable via the write_* routines in * nfsctl.c. In particular: * * user_recovery_dirname * user_lease_time * nfsd_versions |
bedbdd8ba knfsd: Replace lo... |
54 55 |
*/ DEFINE_MUTEX(nfsd_mutex); |
bedbdd8ba knfsd: Replace lo... |
56 |
|
4bd9b0f4a nfsd41: use globa... |
57 58 59 60 61 62 63 |
/* * nfsd_drc_lock protects nfsd_drc_max_pages and nfsd_drc_pages_used. * nfsd_drc_max_pages limits the total amount of memory available for * version 4.1 DRC caches. * nfsd_drc_pages_used tracks the current version 4.1 DRC memory usage. */ spinlock_t nfsd_drc_lock; |
697ce9be7 fs/nfsd: change t... |
64 65 |
unsigned long nfsd_drc_max_mem; unsigned long nfsd_drc_mem_used; |
4bd9b0f4a nfsd41: use globa... |
66 |
|
3fb803a99 [PATCH] knfsd: Re... |
67 68 69 70 71 72 73 74 |
#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) static struct svc_stat nfsd_acl_svcstats; static struct svc_version * nfsd_acl_version[] = { [2] = &nfsd_acl_version2, [3] = &nfsd_acl_version3, }; #define NFSD_ACL_MINVERS 2 |
e8c96f8c2 [PATCH] fs: Use A... |
75 |
#define NFSD_ACL_NRVERS ARRAY_SIZE(nfsd_acl_version) |
3fb803a99 [PATCH] knfsd: Re... |
76 77 78 79 80 81 |
static struct svc_version *nfsd_acl_versions[NFSD_ACL_NRVERS]; static struct svc_program nfsd_acl_program = { .pg_prog = NFS_ACL_PROGRAM, .pg_nvers = NFSD_ACL_NRVERS, .pg_vers = nfsd_acl_versions, |
1a8eff6d9 [PATCH] knfsd: fi... |
82 |
.pg_name = "nfsacl", |
3fb803a99 [PATCH] knfsd: Re... |
83 84 85 86 87 88 89 90 91 |
.pg_class = "nfsd", .pg_stats = &nfsd_acl_svcstats, .pg_authenticate = &svc_set_client, }; static struct svc_stat nfsd_acl_svcstats = { .program = &nfsd_acl_program, }; #endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */ |
70c3b76c2 [PATCH] knfsd: Al... |
92 93 94 95 96 97 98 99 100 101 102 |
static struct svc_version * nfsd_version[] = { [2] = &nfsd_version2, #if defined(CONFIG_NFSD_V3) [3] = &nfsd_version3, #endif #if defined(CONFIG_NFSD_V4) [4] = &nfsd_version4, #endif }; #define NFSD_MINVERS 2 |
e8c96f8c2 [PATCH] fs: Use A... |
103 |
#define NFSD_NRVERS ARRAY_SIZE(nfsd_version) |
70c3b76c2 [PATCH] knfsd: Al... |
104 105 106 |
static struct svc_version *nfsd_versions[NFSD_NRVERS]; struct svc_program nfsd_program = { |
3fb803a99 [PATCH] knfsd: Re... |
107 108 109 |
#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) .pg_next = &nfsd_acl_program, #endif |
70c3b76c2 [PATCH] knfsd: Al... |
110 111 112 113 114 115 116 117 118 |
.pg_prog = NFS_PROGRAM, /* program number */ .pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */ .pg_vers = nfsd_versions, /* version table */ .pg_name = "nfsd", /* program name */ .pg_class = "nfsd", /* authentication class */ .pg_stats = &nfsd_svcstats, /* version table */ .pg_authenticate = &svc_set_client, /* export authentication */ }; |
35f7a14fc nfsd4: fix minorv... |
119 120 121 |
static bool nfsd_supported_minorversions[NFSD_SUPPORTED_MINOR_VERSION + 1] = { [0] = 1, [1] = 1, |
c23ae6017 nfsd: default NFS... |
122 |
[2] = 1, |
35f7a14fc nfsd4: fix minorv... |
123 |
}; |
8daf220a6 nfsd41: control n... |
124 |
|
6658d3a7b [PATCH] knfsd: re... |
125 126 127 |
int nfsd_vers(int vers, enum vers_op change) { if (vers < NFSD_MINVERS || vers >= NFSD_NRVERS) |
15ddb4aec NFSD: don't repor... |
128 |
return 0; |
6658d3a7b [PATCH] knfsd: re... |
129 130 131 |
switch(change) { case NFSD_SET: nfsd_versions[vers] = nfsd_version[vers]; |
6658d3a7b [PATCH] knfsd: re... |
132 133 |
#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) if (vers < NFSD_ACL_NRVERS) |
1a8eff6d9 [PATCH] knfsd: fi... |
134 |
nfsd_acl_versions[vers] = nfsd_acl_version[vers]; |
6658d3a7b [PATCH] knfsd: re... |
135 |
#endif |
1a8eff6d9 [PATCH] knfsd: fi... |
136 |
break; |
6658d3a7b [PATCH] knfsd: re... |
137 138 139 140 |
case NFSD_CLEAR: nfsd_versions[vers] = NULL; #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) if (vers < NFSD_ACL_NRVERS) |
1a8eff6d9 [PATCH] knfsd: fi... |
141 |
nfsd_acl_versions[vers] = NULL; |
6658d3a7b [PATCH] knfsd: re... |
142 143 144 145 146 147 148 149 150 |
#endif break; case NFSD_TEST: return nfsd_versions[vers] != NULL; case NFSD_AVAIL: return nfsd_version[vers] != NULL; } return 0; } |
8daf220a6 nfsd41: control n... |
151 152 153 154 155 156 157 |
int nfsd_minorversion(u32 minorversion, enum vers_op change) { if (minorversion > NFSD_SUPPORTED_MINOR_VERSION) return -1; switch(change) { case NFSD_SET: |
35f7a14fc nfsd4: fix minorv... |
158 |
nfsd_supported_minorversions[minorversion] = true; |
8daf220a6 nfsd41: control n... |
159 160 |
break; case NFSD_CLEAR: |
35f7a14fc nfsd4: fix minorv... |
161 |
nfsd_supported_minorversions[minorversion] = false; |
8daf220a6 nfsd41: control n... |
162 163 |
break; case NFSD_TEST: |
35f7a14fc nfsd4: fix minorv... |
164 |
return nfsd_supported_minorversions[minorversion]; |
8daf220a6 nfsd41: control n... |
165 166 167 168 169 |
case NFSD_AVAIL: return minorversion <= NFSD_SUPPORTED_MINOR_VERSION; } return 0; } |
1da177e4c Linux-2.6.12-rc2 |
170 171 172 173 |
/* * Maximum number of nfsd processes */ #define NFSD_MAXSERVS 8192 |
9dd9845f0 nfsd: make NFSd s... |
174 |
int nfsd_nrthreads(struct net *net) |
1da177e4c Linux-2.6.12-rc2 |
175 |
{ |
c7d106c90 nfsd: fix race in... |
176 |
int rv = 0; |
9dd9845f0 nfsd: make NFSd s... |
177 |
struct nfsd_net *nn = net_generic(net, nfsd_net_id); |
c7d106c90 nfsd: fix race in... |
178 |
mutex_lock(&nfsd_mutex); |
9dd9845f0 nfsd: make NFSd s... |
179 180 |
if (nn->nfsd_serv) rv = nn->nfsd_serv->sv_nrthreads; |
c7d106c90 nfsd: fix race in... |
181 182 |
mutex_unlock(&nfsd_mutex); return rv; |
1da177e4c Linux-2.6.12-rc2 |
183 |
} |
db6e182c1 nfsd: pass net to... |
184 |
static int nfsd_init_socks(struct net *net) |
59db4a0c1 nfsd: move more i... |
185 186 |
{ int error; |
9dd9845f0 nfsd: make NFSd s... |
187 188 189 |
struct nfsd_net *nn = net_generic(net, nfsd_net_id); if (!list_empty(&nn->nfsd_serv->sv_permsocks)) |
59db4a0c1 nfsd: move more i... |
190 |
return 0; |
9dd9845f0 nfsd: make NFSd s... |
191 |
error = svc_create_xprt(nn->nfsd_serv, "udp", net, PF_INET, NFS_PORT, |
59db4a0c1 nfsd: move more i... |
192 193 194 |
SVC_SOCK_DEFAULTS); if (error < 0) return error; |
9dd9845f0 nfsd: make NFSd s... |
195 |
error = svc_create_xprt(nn->nfsd_serv, "tcp", net, PF_INET, NFS_PORT, |
59db4a0c1 nfsd: move more i... |
196 197 198 199 200 201 |
SVC_SOCK_DEFAULTS); if (error < 0) return error; return 0; } |
4539f1498 nfsd: replace boo... |
202 |
static int nfsd_users = 0; |
4ad9a344b nfsd4: fix v4 sta... |
203 |
|
bda9cac1d nfsd: introduce h... |
204 205 206 |
static int nfsd_startup_generic(int nrservs) { int ret; |
4539f1498 nfsd: replace boo... |
207 |
if (nfsd_users++) |
bda9cac1d nfsd: introduce h... |
208 209 210 211 212 213 214 215 216 |
return 0; /* * Readahead param cache - will no-op if it already exists. * (Note therefore results will be suboptimal if number of * threads is modified after nfsd start.) */ ret = nfsd_racache_init(2*nrservs); if (ret) |
d9499a957 NFSD: Decrease nf... |
217 |
goto dec_users; |
bda9cac1d nfsd: introduce h... |
218 219 220 221 222 223 224 |
ret = nfs4_state_start(); if (ret) goto out_racache; return 0; out_racache: nfsd_racache_shutdown(); |
d9499a957 NFSD: Decrease nf... |
225 226 |
dec_users: nfsd_users--; |
bda9cac1d nfsd: introduce h... |
227 228 229 230 231 |
return ret; } static void nfsd_shutdown_generic(void) { |
4539f1498 nfsd: replace boo... |
232 233 |
if (--nfsd_users) return; |
bda9cac1d nfsd: introduce h... |
234 235 236 |
nfs4_state_shutdown(); nfsd_racache_shutdown(); } |
8ef667140 NFSD: Don't start... |
237 238 |
static bool nfsd_needs_lockd(void) { |
ff88825fb NFSD: fix compile... |
239 |
#if defined(CONFIG_NFSD_V3) |
8ef667140 NFSD: Don't start... |
240 |
return (nfsd_versions[2] != NULL) || (nfsd_versions[3] != NULL); |
ff88825fb NFSD: fix compile... |
241 242 243 |
#else return (nfsd_versions[2] != NULL); #endif |
8ef667140 NFSD: Don't start... |
244 |
} |
903d9bf0e nfsd: simplify NF... |
245 |
static int nfsd_startup_net(int nrservs, struct net *net) |
6ff50b3de nfsd: move per-ne... |
246 |
{ |
2c2fe2909 nfsd: per-net NFS... |
247 |
struct nfsd_net *nn = net_generic(net, nfsd_net_id); |
6ff50b3de nfsd: move per-ne... |
248 |
int ret; |
2c2fe2909 nfsd: per-net NFS... |
249 250 |
if (nn->nfsd_net_up) return 0; |
903d9bf0e nfsd: simplify NF... |
251 |
ret = nfsd_startup_generic(nrservs); |
6ff50b3de nfsd: move per-ne... |
252 253 |
if (ret) return ret; |
903d9bf0e nfsd: simplify NF... |
254 255 256 |
ret = nfsd_init_socks(net); if (ret) goto out_socks; |
8ef667140 NFSD: Don't start... |
257 258 259 260 261 262 263 |
if (nfsd_needs_lockd() && !nn->lockd_up) { ret = lockd_up(net); if (ret) goto out_socks; nn->lockd_up = 1; } |
6ff50b3de nfsd: move per-ne... |
264 265 266 |
ret = nfs4_state_start_net(net); if (ret) goto out_lockd; |
2c2fe2909 nfsd: per-net NFS... |
267 |
nn->nfsd_net_up = true; |
6ff50b3de nfsd: move per-ne... |
268 269 270 |
return 0; out_lockd: |
8ef667140 NFSD: Don't start... |
271 272 273 274 |
if (nn->lockd_up) { lockd_down(net); nn->lockd_up = 0; } |
903d9bf0e nfsd: simplify NF... |
275 |
out_socks: |
bda9cac1d nfsd: introduce h... |
276 |
nfsd_shutdown_generic(); |
4ad9a344b nfsd4: fix v4 sta... |
277 278 |
return ret; } |
6ff50b3de nfsd: move per-ne... |
279 280 |
static void nfsd_shutdown_net(struct net *net) { |
2c2fe2909 nfsd: per-net NFS... |
281 |
struct nfsd_net *nn = net_generic(net, nfsd_net_id); |
6ff50b3de nfsd: move per-ne... |
282 |
nfs4_state_shutdown_net(net); |
8ef667140 NFSD: Don't start... |
283 284 285 286 |
if (nn->lockd_up) { lockd_down(net); nn->lockd_up = 0; } |
2c2fe2909 nfsd: per-net NFS... |
287 |
nn->nfsd_net_up = false; |
903d9bf0e nfsd: simplify NF... |
288 |
nfsd_shutdown_generic(); |
6ff50b3de nfsd: move per-ne... |
289 |
} |
366849966 nfsd: Register ca... |
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 |
static int nfsd_inetaddr_event(struct notifier_block *this, unsigned long event, void *ptr) { struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; struct net_device *dev = ifa->ifa_dev->dev; struct net *net = dev_net(dev); struct nfsd_net *nn = net_generic(net, nfsd_net_id); struct sockaddr_in sin; if (event != NETDEV_DOWN) goto out; if (nn->nfsd_serv) { dprintk("nfsd_inetaddr_event: removed %pI4 ", &ifa->ifa_local); sin.sin_family = AF_INET; sin.sin_addr.s_addr = ifa->ifa_local; svc_age_temp_xprts_now(nn->nfsd_serv, (struct sockaddr *)&sin); } out: return NOTIFY_DONE; } static struct notifier_block nfsd_inetaddr_notifier = { .notifier_call = nfsd_inetaddr_event, }; #if IS_ENABLED(CONFIG_IPV6) static int nfsd_inet6addr_event(struct notifier_block *this, unsigned long event, void *ptr) { struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr; struct net_device *dev = ifa->idev->dev; struct net *net = dev_net(dev); struct nfsd_net *nn = net_generic(net, nfsd_net_id); struct sockaddr_in6 sin6; if (event != NETDEV_DOWN) goto out; if (nn->nfsd_serv) { dprintk("nfsd_inet6addr_event: removed %pI6 ", &ifa->addr); sin6.sin6_family = AF_INET6; sin6.sin6_addr = ifa->addr; svc_age_temp_xprts_now(nn->nfsd_serv, (struct sockaddr *)&sin6); } out: return NOTIFY_DONE; } static struct notifier_block nfsd_inet6addr_notifier = { .notifier_call = nfsd_inet6addr_event, }; #endif |
1eca45f8a NFSD: fix corrupt... |
347 348 |
/* Only used under nfsd_mutex, so this atomic may be overkill: */ static atomic_t nfsd_notifier_refcount = ATOMIC_INIT(0); |
541e864f0 nfsd: simplify se... |
349 |
static void nfsd_last_thread(struct svc_serv *serv, struct net *net) |
4ad9a344b nfsd4: fix v4 sta... |
350 |
{ |
903d9bf0e nfsd: simplify NF... |
351 |
struct nfsd_net *nn = net_generic(net, nfsd_net_id); |
1eca45f8a NFSD: fix corrupt... |
352 353 354 |
/* check if the notifier still has clients */ if (atomic_dec_return(&nfsd_notifier_refcount) == 0) { unregister_inetaddr_notifier(&nfsd_inetaddr_notifier); |
366849966 nfsd: Register ca... |
355 |
#if IS_ENABLED(CONFIG_IPV6) |
1eca45f8a NFSD: fix corrupt... |
356 |
unregister_inet6addr_notifier(&nfsd_inet6addr_notifier); |
366849966 nfsd: Register ca... |
357 |
#endif |
1eca45f8a NFSD: fix corrupt... |
358 |
} |
4ad9a344b nfsd4: fix v4 sta... |
359 360 361 362 |
/* * write_ports can create the server without actually starting * any threads--if we get shut down before any threads are * started, then nfsd_last_thread will be run before any of this |
691412b44 nfsd: Fix nfsd le... |
363 |
* other initialization has been done except the rpcb information. |
4ad9a344b nfsd4: fix v4 sta... |
364 |
*/ |
691412b44 nfsd: Fix nfsd le... |
365 |
svc_rpcb_cleanup(serv, net); |
903d9bf0e nfsd: simplify NF... |
366 |
if (!nn->nfsd_net_up) |
4ad9a344b nfsd4: fix v4 sta... |
367 |
return; |
16d058709 NFSd: call svc rp... |
368 |
|
691412b44 nfsd: Fix nfsd le... |
369 |
nfsd_shutdown_net(net); |
e096bbc64 knfsd: remove spe... |
370 371 372 |
printk(KERN_WARNING "nfsd: last server has exited, flushing export " "cache "); |
b3853e0ea nfsd: make export... |
373 |
nfsd_export_flush(net); |
bc591ccff [PATCH] knfsd: ad... |
374 |
} |
6658d3a7b [PATCH] knfsd: re... |
375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 |
void nfsd_reset_versions(void) { int found_one = 0; int i; for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) { if (nfsd_program.pg_vers[i]) found_one = 1; } if (!found_one) { for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) nfsd_program.pg_vers[i] = nfsd_version[i]; #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++) nfsd_acl_program.pg_vers[i] = nfsd_acl_version[i]; #endif } } |
c3d06f9ce nfsd41: hard page... |
396 397 398 399 400 401 402 403 404 405 406 407 408 409 |
/* * Each session guarantees a negotiated per slot memory cache for replies * which in turn consumes memory beyond the v2/v3/v4.0 server. A dedicated * NFSv4.1 server might want to use more memory for a DRC than a machine * with mutiple services. * * Impose a hard limit on the number of pages for the DRC which varies * according to the machines free pages. This is of course only a default. * * For now this is a #defined shift which could be under admin control * in the future. */ static void set_max_drc(void) { |
6a14dd1a4 nfsd41: reserve l... |
410 |
#define NFSD_DRC_SIZE_SHIFT 10 |
0c193054a nfsd41: hange fro... |
411 412 413 |
nfsd_drc_max_mem = (nr_free_buffer_pages() >> NFSD_DRC_SIZE_SHIFT) * PAGE_SIZE; nfsd_drc_mem_used = 0; |
4bd9b0f4a nfsd41: use globa... |
414 |
spin_lock_init(&nfsd_drc_lock); |
697ce9be7 fs/nfsd: change t... |
415 416 |
dprintk("%s nfsd_drc_max_mem %lu ", __func__, nfsd_drc_max_mem); |
c3d06f9ce nfsd41: hard page... |
417 |
} |
bedbdd8ba knfsd: Replace lo... |
418 |
|
87b0fc7de nfsd: cleanup set... |
419 |
static int nfsd_get_default_max_blksize(void) |
02a375f0a [PATCH] knfsd: se... |
420 |
{ |
87b0fc7de nfsd: cleanup set... |
421 422 423 |
struct sysinfo i; unsigned long long target; unsigned long ret; |
bedbdd8ba knfsd: Replace lo... |
424 |
|
87b0fc7de nfsd: cleanup set... |
425 |
si_meminfo(&i); |
508f92275 nfsd: fix default... |
426 |
target = (i.totalram - i.totalhigh) << PAGE_SHIFT; |
87b0fc7de nfsd: cleanup set... |
427 428 429 430 431 432 433 434 435 436 437 438 |
/* * Aim for 1/4096 of memory per thread This gives 1MB on 4Gig * machines, but only uses 32K on 128M machines. Bottom out at * 8K on 32M and smaller. Of course, this is only a default. */ target >>= 12; ret = NFSSVC_MAXBLKSIZE; while (ret > target && ret >= 8*1024*2) ret /= 2; return ret; } |
b9e13cdfa nfsd/sunrpc: turn... |
439 440 441 442 |
static struct svc_serv_ops nfsd_thread_sv_ops = { .svo_shutdown = nfsd_last_thread, .svo_function = nfsd, .svo_enqueue_xprt = svc_xprt_do_enqueue, |
598e23590 nfsd/sunrpc: abst... |
443 |
.svo_setup = svc_set_num_threads, |
b9e13cdfa nfsd/sunrpc: turn... |
444 |
.svo_module = THIS_MODULE, |
ea126e743 nfsd/sunrpc: add ... |
445 |
}; |
6777436b0 nfsd: pass net to... |
446 |
int nfsd_create_serv(struct net *net) |
87b0fc7de nfsd: cleanup set... |
447 |
{ |
9793f7c88 SUNRPC: new svc_b... |
448 |
int error; |
b9c0ef857 nfsd: make NFSd s... |
449 |
struct nfsd_net *nn = net_generic(net, nfsd_net_id); |
9793f7c88 SUNRPC: new svc_b... |
450 |
|
bedbdd8ba knfsd: Replace lo... |
451 |
WARN_ON(!mutex_is_locked(&nfsd_mutex)); |
9dd9845f0 nfsd: make NFSd s... |
452 453 |
if (nn->nfsd_serv) { svc_get(nn->nfsd_serv); |
02a375f0a [PATCH] knfsd: se... |
454 455 |
return 0; } |
87b0fc7de nfsd: cleanup set... |
456 457 |
if (nfsd_max_blksize == 0) nfsd_max_blksize = nfsd_get_default_max_blksize(); |
e844a7b98 nfsd: initialize ... |
458 |
nfsd_reset_versions(); |
9dd9845f0 nfsd: make NFSd s... |
459 |
nn->nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize, |
b9e13cdfa nfsd/sunrpc: turn... |
460 |
&nfsd_thread_sv_ops); |
9dd9845f0 nfsd: make NFSd s... |
461 |
if (nn->nfsd_serv == NULL) |
628b36872 nfsd: clean up nf... |
462 |
return -ENOMEM; |
bedbdd8ba knfsd: Replace lo... |
463 |
|
5b8db00ba nfsd: add a new /... |
464 |
nn->nfsd_serv->sv_maxconn = nn->max_connections; |
9dd9845f0 nfsd: make NFSd s... |
465 |
error = svc_bind(nn->nfsd_serv, net); |
9793f7c88 SUNRPC: new svc_b... |
466 |
if (error < 0) { |
9dd9845f0 nfsd: make NFSd s... |
467 |
svc_destroy(nn->nfsd_serv); |
9793f7c88 SUNRPC: new svc_b... |
468 469 |
return error; } |
628b36872 nfsd: clean up nf... |
470 |
set_max_drc(); |
1eca45f8a NFSD: fix corrupt... |
471 472 473 |
/* check if the notifier is already set */ if (atomic_inc_return(&nfsd_notifier_refcount) == 1) { register_inetaddr_notifier(&nfsd_inetaddr_notifier); |
366849966 nfsd: Register ca... |
474 |
#if IS_ENABLED(CONFIG_IPV6) |
1eca45f8a NFSD: fix corrupt... |
475 |
register_inet6addr_notifier(&nfsd_inet6addr_notifier); |
366849966 nfsd: Register ca... |
476 |
#endif |
1eca45f8a NFSD: fix corrupt... |
477 |
} |
b9c0ef857 nfsd: make NFSd s... |
478 |
do_gettimeofday(&nn->nfssvc_boot); /* record boot time */ |
87b0fc7de nfsd: cleanup set... |
479 |
return 0; |
02a375f0a [PATCH] knfsd: se... |
480 |
} |
9dd9845f0 nfsd: make NFSd s... |
481 |
int nfsd_nrpools(struct net *net) |
eed2965af [PATCH] knfsd: al... |
482 |
{ |
9dd9845f0 nfsd: make NFSd s... |
483 484 485 |
struct nfsd_net *nn = net_generic(net, nfsd_net_id); if (nn->nfsd_serv == NULL) |
eed2965af [PATCH] knfsd: al... |
486 487 |
return 0; else |
9dd9845f0 nfsd: make NFSd s... |
488 |
return nn->nfsd_serv->sv_nrpools; |
eed2965af [PATCH] knfsd: al... |
489 |
} |
9dd9845f0 nfsd: make NFSd s... |
490 |
int nfsd_get_nrthreads(int n, int *nthreads, struct net *net) |
eed2965af [PATCH] knfsd: al... |
491 492 |
{ int i = 0; |
9dd9845f0 nfsd: make NFSd s... |
493 |
struct nfsd_net *nn = net_generic(net, nfsd_net_id); |
eed2965af [PATCH] knfsd: al... |
494 |
|
9dd9845f0 nfsd: make NFSd s... |
495 496 497 |
if (nn->nfsd_serv != NULL) { for (i = 0; i < nn->nfsd_serv->sv_nrpools && i < n; i++) nthreads[i] = nn->nfsd_serv->sv_pools[i].sp_nrthreads; |
eed2965af [PATCH] knfsd: al... |
498 499 500 501 |
} return 0; } |
9dd9845f0 nfsd: make NFSd s... |
502 503 504 505 506 507 508 509 510 511 512 |
void nfsd_destroy(struct net *net) { struct nfsd_net *nn = net_generic(net, nfsd_net_id); int destroy = (nn->nfsd_serv->sv_nrthreads == 1); if (destroy) svc_shutdown_net(nn->nfsd_serv, net); svc_destroy(nn->nfsd_serv); if (destroy) nn->nfsd_serv = NULL; } |
3938a0d5e nfsd: pass net to... |
513 |
int nfsd_set_nrthreads(int n, int *nthreads, struct net *net) |
eed2965af [PATCH] knfsd: al... |
514 515 516 517 |
{ int i = 0; int tot = 0; int err = 0; |
9dd9845f0 nfsd: make NFSd s... |
518 |
struct nfsd_net *nn = net_generic(net, nfsd_net_id); |
eed2965af [PATCH] knfsd: al... |
519 |
|
bedbdd8ba knfsd: Replace lo... |
520 |
WARN_ON(!mutex_is_locked(&nfsd_mutex)); |
9dd9845f0 nfsd: make NFSd s... |
521 |
if (nn->nfsd_serv == NULL || n <= 0) |
eed2965af [PATCH] knfsd: al... |
522 |
return 0; |
9dd9845f0 nfsd: make NFSd s... |
523 524 |
if (n > nn->nfsd_serv->sv_nrpools) n = nn->nfsd_serv->sv_nrpools; |
eed2965af [PATCH] knfsd: al... |
525 526 527 528 |
/* enforce a global maximum number of threads */ tot = 0; for (i = 0; i < n; i++) { |
3c7aa15d2 NFSD: Using min/m... |
529 |
nthreads[i] = min(nthreads[i], NFSD_MAXSERVS); |
eed2965af [PATCH] knfsd: al... |
530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 |
tot += nthreads[i]; } if (tot > NFSD_MAXSERVS) { /* total too large: scale down requested numbers */ for (i = 0; i < n && tot > 0; i++) { int new = nthreads[i] * NFSD_MAXSERVS / tot; tot -= (nthreads[i] - new); nthreads[i] = new; } for (i = 0; i < n && tot > 0; i++) { nthreads[i]--; tot--; } } /* * There must always be a thread in pool 0; the admin * can't shut down NFS completely using pool_threads. */ if (nthreads[0] == 0) nthreads[0] = 1; /* apply the new numbers */ |
9dd9845f0 nfsd: make NFSd s... |
553 |
svc_get(nn->nfsd_serv); |
eed2965af [PATCH] knfsd: al... |
554 |
for (i = 0; i < n; i++) { |
598e23590 nfsd/sunrpc: abst... |
555 556 |
err = nn->nfsd_serv->sv_ops->svo_setup(nn->nfsd_serv, &nn->nfsd_serv->sv_pools[i], nthreads[i]); |
eed2965af [PATCH] knfsd: al... |
557 558 559 |
if (err) break; } |
19f7e2ca4 NFSd: introduce n... |
560 |
nfsd_destroy(net); |
eed2965af [PATCH] knfsd: al... |
561 562 |
return err; } |
ac77efbe2 nfsd: just keep s... |
563 564 565 566 567 |
/* * Adjust the number of threads and return the new number of threads. * This is also the function that starts the server if necessary, if * this is the first time nrservs is nonzero. */ |
1da177e4c Linux-2.6.12-rc2 |
568 |
int |
d41a9417c nfsd: pass net to... |
569 |
nfsd_svc(int nrservs, struct net *net) |
1da177e4c Linux-2.6.12-rc2 |
570 571 |
{ int error; |
774f8bbd9 nfsd: fix startup... |
572 |
bool nfsd_up_before; |
9dd9845f0 nfsd: make NFSd s... |
573 |
struct nfsd_net *nn = net_generic(net, nfsd_net_id); |
bedbdd8ba knfsd: Replace lo... |
574 575 |
mutex_lock(&nfsd_mutex); |
6658d3a7b [PATCH] knfsd: re... |
576 577 |
dprintk("nfsd: creating service "); |
3c7aa15d2 NFSD: Using min/m... |
578 579 580 |
nrservs = max(nrservs, 0); nrservs = min(nrservs, NFSD_MAXSERVS); |
671e1fcf6 nfsd: optimise th... |
581 |
error = 0; |
3c7aa15d2 NFSD: Using min/m... |
582 |
|
9dd9845f0 nfsd: make NFSd s... |
583 |
if (nrservs == 0 && nn->nfsd_serv == NULL) |
671e1fcf6 nfsd: optimise th... |
584 |
goto out; |
6777436b0 nfsd: pass net to... |
585 |
error = nfsd_create_serv(net); |
02a375f0a [PATCH] knfsd: se... |
586 |
if (error) |
774f8bbd9 nfsd: fix startup... |
587 |
goto out; |
903d9bf0e nfsd: simplify NF... |
588 |
nfsd_up_before = nn->nfsd_net_up; |
774f8bbd9 nfsd: fix startup... |
589 |
|
903d9bf0e nfsd: simplify NF... |
590 |
error = nfsd_startup_net(nrservs, net); |
af4718f3f nfsd: minor nfsd_... |
591 592 |
if (error) goto out_destroy; |
598e23590 nfsd/sunrpc: abst... |
593 594 |
error = nn->nfsd_serv->sv_ops->svo_setup(nn->nfsd_serv, NULL, nrservs); |
774f8bbd9 nfsd: fix startup... |
595 596 |
if (error) goto out_shutdown; |
9dd9845f0 nfsd: make NFSd s... |
597 |
/* We are holding a reference to nn->nfsd_serv which |
af4718f3f nfsd: minor nfsd_... |
598 599 600 |
* we don't want to count in the return value, * so subtract 1 */ |
9dd9845f0 nfsd: make NFSd s... |
601 |
error = nn->nfsd_serv->sv_nrthreads - 1; |
4ad9a344b nfsd4: fix v4 sta... |
602 |
out_shutdown: |
774f8bbd9 nfsd: fix startup... |
603 |
if (error < 0 && !nfsd_up_before) |
541e864f0 nfsd: simplify se... |
604 |
nfsd_shutdown_net(net); |
774f8bbd9 nfsd: fix startup... |
605 |
out_destroy: |
19f7e2ca4 NFSd: introduce n... |
606 |
nfsd_destroy(net); /* Release server */ |
4ad9a344b nfsd4: fix v4 sta... |
607 |
out: |
bedbdd8ba knfsd: Replace lo... |
608 |
mutex_unlock(&nfsd_mutex); |
1da177e4c Linux-2.6.12-rc2 |
609 610 |
return error; } |
1da177e4c Linux-2.6.12-rc2 |
611 612 613 614 |
/* * This is the NFS server kernel thread */ |
9867d76ca knfsd: convert kn... |
615 616 |
static int nfsd(void *vrqstp) |
1da177e4c Linux-2.6.12-rc2 |
617 |
{ |
9867d76ca knfsd: convert kn... |
618 |
struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp; |
88c476661 nfsd: pass proper... |
619 620 |
struct svc_xprt *perm_sock = list_entry(rqstp->rq_server->sv_permsocks.next, typeof(struct svc_xprt), xpt_list); struct net *net = perm_sock->xpt_net; |
5b8db00ba nfsd: add a new /... |
621 |
struct nfsd_net *nn = net_generic(net, nfsd_net_id); |
5b444cc9a svcrpc: remove ha... |
622 |
int err; |
1da177e4c Linux-2.6.12-rc2 |
623 624 |
/* Lock module and set up kernel thread */ |
bedbdd8ba knfsd: Replace lo... |
625 |
mutex_lock(&nfsd_mutex); |
1da177e4c Linux-2.6.12-rc2 |
626 |
|
9867d76ca knfsd: convert kn... |
627 |
/* At this point, the thread shares current->fs |
1da177e4c Linux-2.6.12-rc2 |
628 629 |
* with the init process. We need to create files with a * umask of 0 instead of init's umask. */ |
3e93cd671 Take fs_struct ha... |
630 |
if (unshare_fs_struct() < 0) { |
1da177e4c Linux-2.6.12-rc2 |
631 632 633 634 |
printk("Unable to start nfsd thread: out of memory "); goto out; } |
3e93cd671 Take fs_struct ha... |
635 |
|
1da177e4c Linux-2.6.12-rc2 |
636 |
current->fs->umask = 0; |
9867d76ca knfsd: convert kn... |
637 638 |
/* * thread is spawned with all signals set to SIG_IGN, re-enable |
100766f83 nfsd: treat all s... |
639 |
* the ones that will bring down the thread |
9867d76ca knfsd: convert kn... |
640 |
*/ |
100766f83 nfsd: treat all s... |
641 642 643 644 |
allow_signal(SIGKILL); allow_signal(SIGHUP); allow_signal(SIGINT); allow_signal(SIGQUIT); |
bedbdd8ba knfsd: Replace lo... |
645 |
|
1da177e4c Linux-2.6.12-rc2 |
646 |
nfsdstats.th_cnt++; |
bedbdd8ba knfsd: Replace lo... |
647 |
mutex_unlock(&nfsd_mutex); |
831441862 Freezer: make ker... |
648 |
set_freezable(); |
1da177e4c Linux-2.6.12-rc2 |
649 650 651 652 653 |
/* * The main request loop */ for (;;) { |
5b8db00ba nfsd: add a new /... |
654 655 |
/* Update sv_maxconn if it has changed */ rqstp->rq_server->sv_maxconn = nn->max_connections; |
1da177e4c Linux-2.6.12-rc2 |
656 657 658 659 |
/* * Find a socket with data available and call its * recvfrom routine. */ |
6fb2b47fa [PATCH] knfsd: Dr... |
660 |
while ((err = svc_recv(rqstp, 60*60*HZ)) == -EAGAIN) |
1da177e4c Linux-2.6.12-rc2 |
661 |
; |
9867d76ca knfsd: convert kn... |
662 |
if (err == -EINTR) |
1da177e4c Linux-2.6.12-rc2 |
663 |
break; |
e0e817392 CRED: Add some co... |
664 |
validate_process_creds(); |
6fb2b47fa [PATCH] knfsd: Dr... |
665 |
svc_process(rqstp); |
e0e817392 CRED: Add some co... |
666 |
validate_process_creds(); |
1da177e4c Linux-2.6.12-rc2 |
667 |
} |
24e36663c [PATCH] knfsd: be... |
668 |
/* Clear signals before calling svc_exit_thread() */ |
9e416052f [PATCH] nfsd: cle... |
669 |
flush_signals(current); |
1da177e4c Linux-2.6.12-rc2 |
670 |
|
bedbdd8ba knfsd: Replace lo... |
671 |
mutex_lock(&nfsd_mutex); |
1da177e4c Linux-2.6.12-rc2 |
672 673 674 |
nfsdstats.th_cnt --; out: |
57c8b13e3 NFSd: set nfsd_se... |
675 |
rqstp->rq_server = NULL; |
786185b5f SUNRPC: move per-... |
676 |
|
1da177e4c Linux-2.6.12-rc2 |
677 678 |
/* Release the thread */ svc_exit_thread(rqstp); |
88c476661 nfsd: pass proper... |
679 |
nfsd_destroy(net); |
57c8b13e3 NFSd: set nfsd_se... |
680 |
|
1da177e4c Linux-2.6.12-rc2 |
681 |
/* Release module */ |
bedbdd8ba knfsd: Replace lo... |
682 |
mutex_unlock(&nfsd_mutex); |
1da177e4c Linux-2.6.12-rc2 |
683 |
module_put_and_exit(0); |
9867d76ca knfsd: convert kn... |
684 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
685 |
} |
32c1eb0cd knfsd: nfsd4: ret... |
686 687 688 689 690 691 692 693 |
static __be32 map_new_errors(u32 vers, __be32 nfserr) { if (nfserr == nfserr_jukebox && vers == 2) return nfserr_dropit; if (nfserr == nfserr_wrongsec && vers < 4) return nfserr_acces; return nfserr; } |
1da177e4c Linux-2.6.12-rc2 |
694 |
int |
c7afef1f9 [PATCH] nfsd: mis... |
695 |
nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp) |
1da177e4c Linux-2.6.12-rc2 |
696 697 698 |
{ struct svc_procedure *proc; kxdrproc_t xdr; |
ad451d389 [PATCH] xdr annot... |
699 700 |
__be32 nfserr; __be32 *nfserrp; |
1da177e4c Linux-2.6.12-rc2 |
701 702 703 704 705 |
dprintk("nfsd_dispatch: vers %d proc %d ", rqstp->rq_vers, rqstp->rq_proc); proc = rqstp->rq_procinfo; |
1091006c5 nfsd: turn on rep... |
706 707 708 709 710 711 712 713 714 715 716 717 718 719 |
/* * Give the xdr decoder a chance to change this if it wants * (necessary in the NFSv4.0 compound case) */ rqstp->rq_cachetype = proc->pc_cachetype; /* Decode arguments */ xdr = proc->pc_decode; if (xdr && !xdr(rqstp, (__be32*)rqstp->rq_arg.head[0].iov_base, rqstp->rq_argp)) { dprintk("nfsd: failed to decode arguments! "); *statp = rpc_garbage_args; return 1; } |
1da177e4c Linux-2.6.12-rc2 |
720 |
/* Check whether we have this call in the cache. */ |
1091006c5 nfsd: turn on rep... |
721 |
switch (nfsd_cache_lookup(rqstp)) { |
1da177e4c Linux-2.6.12-rc2 |
722 723 724 725 726 727 728 |
case RC_DROPIT: return 0; case RC_REPLY: return 1; case RC_DOIT:; /* do it */ } |
1da177e4c Linux-2.6.12-rc2 |
729 730 731 732 733 |
/* need to grab the location to store the status, as * nfsv4 does some encoding while processing */ nfserrp = rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len; |
ad451d389 [PATCH] xdr annot... |
734 |
rqstp->rq_res.head[0].iov_len += sizeof(__be32); |
1da177e4c Linux-2.6.12-rc2 |
735 736 737 |
/* Now call the procedure handler, and encode NFS status. */ nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp); |
32c1eb0cd knfsd: nfsd4: ret... |
738 |
nfserr = map_new_errors(rqstp->rq_vers, nfserr); |
78b65eb3f sunrpc: move rq_d... |
739 |
if (nfserr == nfserr_dropit || test_bit(RQ_DROPME, &rqstp->rq_flags)) { |
45457e091 nfsd: tone down i... |
740 741 |
dprintk("nfsd: Dropping request; may be revisited later "); |
1da177e4c Linux-2.6.12-rc2 |
742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 |
nfsd_cache_update(rqstp, RC_NOCACHE, NULL); return 0; } if (rqstp->rq_proc != 0) *nfserrp++ = nfserr; /* Encode result. * For NFSv2, additional info is never returned in case of an error. */ if (!(nfserr && rqstp->rq_vers == 2)) { xdr = proc->pc_encode; if (xdr && !xdr(rqstp, nfserrp, rqstp->rq_resp)) { /* Failed to encode result. Release cache entry */ dprintk("nfsd: failed to encode result! "); nfsd_cache_update(rqstp, RC_NOCACHE, NULL); *statp = rpc_system_err; return 1; } } /* Store reply in cache. */ |
57d276d71 nfsd: fix v4 repl... |
766 |
nfsd_cache_update(rqstp, rqstp->rq_cachetype, statp + 1); |
1da177e4c Linux-2.6.12-rc2 |
767 768 |
return 1; } |
03cf6c9f4 knfsd: add file t... |
769 770 771 |
int nfsd_pool_stats_open(struct inode *inode, struct file *file) { |
ed2d8aed5 knfsd: Replace lo... |
772 |
int ret; |
11f779421 nfsd: containeriz... |
773 |
struct nfsd_net *nn = net_generic(inode->i_sb->s_fs_info, nfsd_net_id); |
9dd9845f0 nfsd: make NFSd s... |
774 |
|
ed2d8aed5 knfsd: Replace lo... |
775 |
mutex_lock(&nfsd_mutex); |
9dd9845f0 nfsd: make NFSd s... |
776 |
if (nn->nfsd_serv == NULL) { |
ed2d8aed5 knfsd: Replace lo... |
777 |
mutex_unlock(&nfsd_mutex); |
03cf6c9f4 knfsd: add file t... |
778 |
return -ENODEV; |
ed2d8aed5 knfsd: Replace lo... |
779 780 |
} /* bump up the psudo refcount while traversing */ |
9dd9845f0 nfsd: make NFSd s... |
781 782 |
svc_get(nn->nfsd_serv); ret = svc_pool_stats_open(nn->nfsd_serv, file); |
ed2d8aed5 knfsd: Replace lo... |
783 784 785 786 787 788 789 |
mutex_unlock(&nfsd_mutex); return ret; } int nfsd_pool_stats_release(struct inode *inode, struct file *file) { int ret = seq_release(inode, file); |
11f779421 nfsd: containeriz... |
790 |
struct net *net = inode->i_sb->s_fs_info; |
786185b5f SUNRPC: move per-... |
791 |
|
ed2d8aed5 knfsd: Replace lo... |
792 793 |
mutex_lock(&nfsd_mutex); /* this function really, really should have been called svc_put() */ |
19f7e2ca4 NFSd: introduce n... |
794 |
nfsd_destroy(net); |
ed2d8aed5 knfsd: Replace lo... |
795 796 |
mutex_unlock(&nfsd_mutex); return ret; |
03cf6c9f4 knfsd: add file t... |
797 |
} |