aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfssvc.c
diff options
context:
space:
mode:
authorStanislav Kinsbursky <skinsbursky@parallels.com>2012-12-06 06:23:24 -0500
committerJ. Bruce Fields <bfields@redhat.com>2012-12-10 16:25:39 -0500
commit9dd9845f084cda07ce00cca32a5ba8fbcbbfbcaf (patch)
tree1746b995da1b4f203373d72a41909b0eebdbecf6 /fs/nfsd/nfssvc.c
parentb9c0ef8571c6ae33465dcf41d496ce2ad783c49d (diff)
nfsd: make NFSd service structure allocated per net
This patch makes main step in NFSd containerisation. There could be different approaches to how to make NFSd able to handle incoming RPC request from different network namespaces. The two main options are: 1) Share NFSd kthreads betwween all network namespaces. 2) Create separated pool of threads for each namespace. While first approach looks more flexible, second one is simpler and non-racy. This patch implements the second option. To make it possible to allocate separate pools of threads, we have to make it possible to allocate separate NFSd service structures per net. Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd/nfssvc.c')
-rw-r--r--fs/nfsd/nfssvc.c91
1 files changed, 57 insertions, 34 deletions
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 40992cd5bff9..0e8622a4341c 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -29,11 +29,11 @@ extern struct svc_program nfsd_program;
29static int nfsd(void *vrqstp); 29static int nfsd(void *vrqstp);
30 30
31/* 31/*
32 * nfsd_mutex protects nfsd_serv -- both the pointer itself and the members 32 * nfsd_mutex protects nn->nfsd_serv -- both the pointer itself and the members
33 * of the svc_serv struct. In particular, ->sv_nrthreads but also to some 33 * of the svc_serv struct. In particular, ->sv_nrthreads but also to some
34 * extent ->sv_temp_socks and ->sv_permsocks. It also protects nfsdstats.th_cnt 34 * extent ->sv_temp_socks and ->sv_permsocks. It also protects nfsdstats.th_cnt
35 * 35 *
36 * If (out side the lock) nfsd_serv is non-NULL, then it must point to a 36 * If (out side the lock) nn->nfsd_serv is non-NULL, then it must point to a
37 * properly initialised 'struct svc_serv' with ->sv_nrthreads > 0. That number 37 * properly initialised 'struct svc_serv' with ->sv_nrthreads > 0. That number
38 * of nfsd threads must exist and each must listed in ->sp_all_threads in each 38 * of nfsd threads must exist and each must listed in ->sp_all_threads in each
39 * entry of ->sv_pools[]. 39 * entry of ->sv_pools[].
@@ -51,7 +51,6 @@ static int nfsd(void *vrqstp);
51 * nfsd_versions 51 * nfsd_versions
52 */ 52 */
53DEFINE_MUTEX(nfsd_mutex); 53DEFINE_MUTEX(nfsd_mutex);
54struct svc_serv *nfsd_serv;
55 54
56/* 55/*
57 * nfsd_drc_lock protects nfsd_drc_max_pages and nfsd_drc_pages_used. 56 * nfsd_drc_lock protects nfsd_drc_max_pages and nfsd_drc_pages_used.
@@ -172,12 +171,14 @@ int nfsd_minorversion(u32 minorversion, enum vers_op change)
172 */ 171 */
173#define NFSD_MAXSERVS 8192 172#define NFSD_MAXSERVS 8192
174 173
175int nfsd_nrthreads(void) 174int nfsd_nrthreads(struct net *net)
176{ 175{
177 int rv = 0; 176 int rv = 0;
177 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
178
178 mutex_lock(&nfsd_mutex); 179 mutex_lock(&nfsd_mutex);
179 if (nfsd_serv) 180 if (nn->nfsd_serv)
180 rv = nfsd_serv->sv_nrthreads; 181 rv = nn->nfsd_serv->sv_nrthreads;
181 mutex_unlock(&nfsd_mutex); 182 mutex_unlock(&nfsd_mutex);
182 return rv; 183 return rv;
183} 184}
@@ -185,15 +186,17 @@ int nfsd_nrthreads(void)
185static int nfsd_init_socks(struct net *net) 186static int nfsd_init_socks(struct net *net)
186{ 187{
187 int error; 188 int error;
188 if (!list_empty(&nfsd_serv->sv_permsocks)) 189 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
190
191 if (!list_empty(&nn->nfsd_serv->sv_permsocks))
189 return 0; 192 return 0;
190 193
191 error = svc_create_xprt(nfsd_serv, "udp", net, PF_INET, NFS_PORT, 194 error = svc_create_xprt(nn->nfsd_serv, "udp", net, PF_INET, NFS_PORT,
192 SVC_SOCK_DEFAULTS); 195 SVC_SOCK_DEFAULTS);
193 if (error < 0) 196 if (error < 0)
194 return error; 197 return error;
195 198
196 error = svc_create_xprt(nfsd_serv, "tcp", net, PF_INET, NFS_PORT, 199 error = svc_create_xprt(nn->nfsd_serv, "tcp", net, PF_INET, NFS_PORT,
197 SVC_SOCK_DEFAULTS); 200 SVC_SOCK_DEFAULTS);
198 if (error < 0) 201 if (error < 0)
199 return error; 202 return error;
@@ -369,21 +372,21 @@ int nfsd_create_serv(struct net *net)
369 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 372 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
370 373
371 WARN_ON(!mutex_is_locked(&nfsd_mutex)); 374 WARN_ON(!mutex_is_locked(&nfsd_mutex));
372 if (nfsd_serv) { 375 if (nn->nfsd_serv) {
373 svc_get(nfsd_serv); 376 svc_get(nn->nfsd_serv);
374 return 0; 377 return 0;
375 } 378 }
376 if (nfsd_max_blksize == 0) 379 if (nfsd_max_blksize == 0)
377 nfsd_max_blksize = nfsd_get_default_max_blksize(); 380 nfsd_max_blksize = nfsd_get_default_max_blksize();
378 nfsd_reset_versions(); 381 nfsd_reset_versions();
379 nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize, 382 nn->nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize,
380 nfsd_last_thread, nfsd, THIS_MODULE); 383 nfsd_last_thread, nfsd, THIS_MODULE);
381 if (nfsd_serv == NULL) 384 if (nn->nfsd_serv == NULL)
382 return -ENOMEM; 385 return -ENOMEM;
383 386
384 error = svc_bind(nfsd_serv, net); 387 error = svc_bind(nn->nfsd_serv, net);
385 if (error < 0) { 388 if (error < 0) {
386 svc_destroy(nfsd_serv); 389 svc_destroy(nn->nfsd_serv);
387 return error; 390 return error;
388 } 391 }
389 392
@@ -392,39 +395,55 @@ int nfsd_create_serv(struct net *net)
392 return 0; 395 return 0;
393} 396}
394 397
395int nfsd_nrpools(void) 398int nfsd_nrpools(struct net *net)
396{ 399{
397 if (nfsd_serv == NULL) 400 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
401
402 if (nn->nfsd_serv == NULL)
398 return 0; 403 return 0;
399 else 404 else
400 return nfsd_serv->sv_nrpools; 405 return nn->nfsd_serv->sv_nrpools;
401} 406}
402 407
403int nfsd_get_nrthreads(int n, int *nthreads) 408int nfsd_get_nrthreads(int n, int *nthreads, struct net *net)
404{ 409{
405 int i = 0; 410 int i = 0;
411 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
406 412
407 if (nfsd_serv != NULL) { 413 if (nn->nfsd_serv != NULL) {
408 for (i = 0; i < nfsd_serv->sv_nrpools && i < n; i++) 414 for (i = 0; i < nn->nfsd_serv->sv_nrpools && i < n; i++)
409 nthreads[i] = nfsd_serv->sv_pools[i].sp_nrthreads; 415 nthreads[i] = nn->nfsd_serv->sv_pools[i].sp_nrthreads;
410 } 416 }
411 417
412 return 0; 418 return 0;
413} 419}
414 420
421void nfsd_destroy(struct net *net)
422{
423 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
424 int destroy = (nn->nfsd_serv->sv_nrthreads == 1);
425
426 if (destroy)
427 svc_shutdown_net(nn->nfsd_serv, net);
428 svc_destroy(nn->nfsd_serv);
429 if (destroy)
430 nn->nfsd_serv = NULL;
431}
432
415int nfsd_set_nrthreads(int n, int *nthreads, struct net *net) 433int nfsd_set_nrthreads(int n, int *nthreads, struct net *net)
416{ 434{
417 int i = 0; 435 int i = 0;
418 int tot = 0; 436 int tot = 0;
419 int err = 0; 437 int err = 0;
438 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
420 439
421 WARN_ON(!mutex_is_locked(&nfsd_mutex)); 440 WARN_ON(!mutex_is_locked(&nfsd_mutex));
422 441
423 if (nfsd_serv == NULL || n <= 0) 442 if (nn->nfsd_serv == NULL || n <= 0)
424 return 0; 443 return 0;
425 444
426 if (n > nfsd_serv->sv_nrpools) 445 if (n > nn->nfsd_serv->sv_nrpools)
427 n = nfsd_serv->sv_nrpools; 446 n = nn->nfsd_serv->sv_nrpools;
428 447
429 /* enforce a global maximum number of threads */ 448 /* enforce a global maximum number of threads */
430 tot = 0; 449 tot = 0;
@@ -454,9 +473,9 @@ int nfsd_set_nrthreads(int n, int *nthreads, struct net *net)
454 nthreads[0] = 1; 473 nthreads[0] = 1;
455 474
456 /* apply the new numbers */ 475 /* apply the new numbers */
457 svc_get(nfsd_serv); 476 svc_get(nn->nfsd_serv);
458 for (i = 0; i < n; i++) { 477 for (i = 0; i < n; i++) {
459 err = svc_set_num_threads(nfsd_serv, &nfsd_serv->sv_pools[i], 478 err = svc_set_num_threads(nn->nfsd_serv, &nn->nfsd_serv->sv_pools[i],
460 nthreads[i]); 479 nthreads[i]);
461 if (err) 480 if (err)
462 break; 481 break;
@@ -475,6 +494,7 @@ nfsd_svc(int nrservs, struct net *net)
475{ 494{
476 int error; 495 int error;
477 bool nfsd_up_before; 496 bool nfsd_up_before;
497 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
478 498
479 mutex_lock(&nfsd_mutex); 499 mutex_lock(&nfsd_mutex);
480 dprintk("nfsd: creating service\n"); 500 dprintk("nfsd: creating service\n");
@@ -483,7 +503,7 @@ nfsd_svc(int nrservs, struct net *net)
483 if (nrservs > NFSD_MAXSERVS) 503 if (nrservs > NFSD_MAXSERVS)
484 nrservs = NFSD_MAXSERVS; 504 nrservs = NFSD_MAXSERVS;
485 error = 0; 505 error = 0;
486 if (nrservs == 0 && nfsd_serv == NULL) 506 if (nrservs == 0 && nn->nfsd_serv == NULL)
487 goto out; 507 goto out;
488 508
489 error = nfsd_create_serv(net); 509 error = nfsd_create_serv(net);
@@ -495,14 +515,14 @@ nfsd_svc(int nrservs, struct net *net)
495 error = nfsd_startup(nrservs, net); 515 error = nfsd_startup(nrservs, net);
496 if (error) 516 if (error)
497 goto out_destroy; 517 goto out_destroy;
498 error = svc_set_num_threads(nfsd_serv, NULL, nrservs); 518 error = svc_set_num_threads(nn->nfsd_serv, NULL, nrservs);
499 if (error) 519 if (error)
500 goto out_shutdown; 520 goto out_shutdown;
501 /* We are holding a reference to nfsd_serv which 521 /* We are holding a reference to nn->nfsd_serv which
502 * we don't want to count in the return value, 522 * we don't want to count in the return value,
503 * so subtract 1 523 * so subtract 1
504 */ 524 */
505 error = nfsd_serv->sv_nrthreads - 1; 525 error = nn->nfsd_serv->sv_nrthreads - 1;
506out_shutdown: 526out_shutdown:
507 if (error < 0 && !nfsd_up_before) 527 if (error < 0 && !nfsd_up_before)
508 nfsd_shutdown(net); 528 nfsd_shutdown(net);
@@ -681,14 +701,17 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
681int nfsd_pool_stats_open(struct inode *inode, struct file *file) 701int nfsd_pool_stats_open(struct inode *inode, struct file *file)
682{ 702{
683 int ret; 703 int ret;
704 struct net *net = &init_net;
705 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
706
684 mutex_lock(&nfsd_mutex); 707 mutex_lock(&nfsd_mutex);
685 if (nfsd_serv == NULL) { 708 if (nn->nfsd_serv == NULL) {
686 mutex_unlock(&nfsd_mutex); 709 mutex_unlock(&nfsd_mutex);
687 return -ENODEV; 710 return -ENODEV;
688 } 711 }
689 /* bump up the psudo refcount while traversing */ 712 /* bump up the psudo refcount while traversing */
690 svc_get(nfsd_serv); 713 svc_get(nn->nfsd_serv);
691 ret = svc_pool_stats_open(nfsd_serv, file); 714 ret = svc_pool_stats_open(nn->nfsd_serv, file);
692 mutex_unlock(&nfsd_mutex); 715 mutex_unlock(&nfsd_mutex);
693 return ret; 716 return ret;
694} 717}