aboutsummaryrefslogtreecommitdiffstats
path: root/fs
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
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')
-rw-r--r--fs/nfsd/netns.h2
-rw-r--r--fs/nfsd/nfs4state.c14
-rw-r--r--fs/nfsd/nfsctl.c63
-rw-r--r--fs/nfsd/nfsd.h18
-rw-r--r--fs/nfsd/nfssvc.c91
5 files changed, 110 insertions, 78 deletions
diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
index 3b283eaab10d..1051bebff1b0 100644
--- a/fs/nfsd/netns.h
+++ b/fs/nfsd/netns.h
@@ -99,6 +99,8 @@ struct nfsd_net {
99 * Time of server startup 99 * Time of server startup
100 */ 100 */
101 struct timeval nfssvc_boot; 101 struct timeval nfssvc_boot;
102
103 struct svc_serv *nfsd_serv;
102}; 104};
103 105
104/* Simple check to find out if a given net was properly initialized */ 106/* Simple check to find out if a given net was properly initialized */
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 16e954c1c911..3d27f08e2297 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -743,9 +743,12 @@ out_free:
743 return NULL; 743 return NULL;
744} 744}
745 745
746static void init_forechannel_attrs(struct nfsd4_channel_attrs *new, struct nfsd4_channel_attrs *req, int numslots, int slotsize) 746static void init_forechannel_attrs(struct nfsd4_channel_attrs *new,
747 struct nfsd4_channel_attrs *req,
748 int numslots, int slotsize,
749 struct nfsd_net *nn)
747{ 750{
748 u32 maxrpc = nfsd_serv->sv_max_mesg; 751 u32 maxrpc = nn->nfsd_serv->sv_max_mesg;
749 752
750 new->maxreqs = numslots; 753 new->maxreqs = numslots;
751 new->maxresp_cached = min_t(u32, req->maxresp_cached, 754 new->maxresp_cached = min_t(u32, req->maxresp_cached,
@@ -883,7 +886,8 @@ void nfsd4_put_session(struct nfsd4_session *ses)
883 spin_unlock(&nn->client_lock); 886 spin_unlock(&nn->client_lock);
884} 887}
885 888
886static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fchan) 889static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fchan,
890 struct nfsd_net *nn)
887{ 891{
888 struct nfsd4_session *new; 892 struct nfsd4_session *new;
889 int numslots, slotsize; 893 int numslots, slotsize;
@@ -904,7 +908,7 @@ static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fchan)
904 nfsd4_put_drc_mem(slotsize, fchan->maxreqs); 908 nfsd4_put_drc_mem(slotsize, fchan->maxreqs);
905 return NULL; 909 return NULL;
906 } 910 }
907 init_forechannel_attrs(&new->se_fchannel, fchan, numslots, slotsize); 911 init_forechannel_attrs(&new->se_fchannel, fchan, numslots, slotsize, nn);
908 return new; 912 return new;
909} 913}
910 914
@@ -1776,7 +1780,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
1776 return nfserr_inval; 1780 return nfserr_inval;
1777 if (check_forechannel_attrs(cr_ses->fore_channel)) 1781 if (check_forechannel_attrs(cr_ses->fore_channel))
1778 return nfserr_toosmall; 1782 return nfserr_toosmall;
1779 new = alloc_session(&cr_ses->fore_channel); 1783 new = alloc_session(&cr_ses->fore_channel, nn);
1780 if (!new) 1784 if (!new)
1781 return nfserr_jukebox; 1785 return nfserr_jukebox;
1782 status = nfserr_jukebox; 1786 status = nfserr_jukebox;
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 8536100b7fc1..74934284d9a7 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -409,7 +409,7 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
409 if (rv < 0) 409 if (rv < 0)
410 return rv; 410 return rv;
411 } else 411 } else
412 rv = nfsd_nrthreads(); 412 rv = nfsd_nrthreads(net);
413 413
414 return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n", rv); 414 return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n", rv);
415} 415}
@@ -450,7 +450,7 @@ static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
450 struct net *net = &init_net; 450 struct net *net = &init_net;
451 451
452 mutex_lock(&nfsd_mutex); 452 mutex_lock(&nfsd_mutex);
453 npools = nfsd_nrpools(); 453 npools = nfsd_nrpools(net);
454 if (npools == 0) { 454 if (npools == 0) {
455 /* 455 /*
456 * NFS is shut down. The admin can start it by 456 * NFS is shut down. The admin can start it by
@@ -483,7 +483,7 @@ static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
483 goto out_free; 483 goto out_free;
484 } 484 }
485 485
486 rv = nfsd_get_nrthreads(npools, nthreads); 486 rv = nfsd_get_nrthreads(npools, nthreads, net);
487 if (rv) 487 if (rv)
488 goto out_free; 488 goto out_free;
489 489
@@ -510,11 +510,13 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)
510 unsigned minor; 510 unsigned minor;
511 ssize_t tlen = 0; 511 ssize_t tlen = 0;
512 char *sep; 512 char *sep;
513 struct net *net = &init_net;
514 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
513 515
514 if (size>0) { 516 if (size>0) {
515 if (nfsd_serv) 517 if (nn->nfsd_serv)
516 /* Cannot change versions without updating 518 /* Cannot change versions without updating
517 * nfsd_serv->sv_xdrsize, and reallocing 519 * nn->nfsd_serv->sv_xdrsize, and reallocing
518 * rq_argp and rq_resp 520 * rq_argp and rq_resp
519 */ 521 */
520 return -EBUSY; 522 return -EBUSY;
@@ -645,11 +647,13 @@ static ssize_t write_versions(struct file *file, char *buf, size_t size)
645 * Zero-length write. Return a list of NFSD's current listener 647 * Zero-length write. Return a list of NFSD's current listener
646 * transports. 648 * transports.
647 */ 649 */
648static ssize_t __write_ports_names(char *buf) 650static ssize_t __write_ports_names(char *buf, struct net *net)
649{ 651{
650 if (nfsd_serv == NULL) 652 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
653
654 if (nn->nfsd_serv == NULL)
651 return 0; 655 return 0;
652 return svc_xprt_names(nfsd_serv, buf, SIMPLE_TRANSACTION_LIMIT); 656 return svc_xprt_names(nn->nfsd_serv, buf, SIMPLE_TRANSACTION_LIMIT);
653} 657}
654 658
655/* 659/*
@@ -661,6 +665,7 @@ static ssize_t __write_ports_addfd(char *buf, struct net *net)
661{ 665{
662 char *mesg = buf; 666 char *mesg = buf;
663 int fd, err; 667 int fd, err;
668 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
664 669
665 err = get_int(&mesg, &fd); 670 err = get_int(&mesg, &fd);
666 if (err != 0 || fd < 0) 671 if (err != 0 || fd < 0)
@@ -670,14 +675,14 @@ static ssize_t __write_ports_addfd(char *buf, struct net *net)
670 if (err != 0) 675 if (err != 0)
671 return err; 676 return err;
672 677
673 err = svc_addsock(nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT); 678 err = svc_addsock(nn->nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT);
674 if (err < 0) { 679 if (err < 0) {
675 nfsd_destroy(net); 680 nfsd_destroy(net);
676 return err; 681 return err;
677 } 682 }
678 683
679 /* Decrease the count, but don't shut down the service */ 684 /* Decrease the count, but don't shut down the service */
680 nfsd_serv->sv_nrthreads--; 685 nn->nfsd_serv->sv_nrthreads--;
681 return err; 686 return err;
682} 687}
683 688
@@ -690,6 +695,7 @@ static ssize_t __write_ports_addxprt(char *buf, struct net *net)
690 char transport[16]; 695 char transport[16];
691 struct svc_xprt *xprt; 696 struct svc_xprt *xprt;
692 int port, err; 697 int port, err;
698 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
693 699
694 if (sscanf(buf, "%15s %5u", transport, &port) != 2) 700 if (sscanf(buf, "%15s %5u", transport, &port) != 2)
695 return -EINVAL; 701 return -EINVAL;
@@ -701,21 +707,21 @@ static ssize_t __write_ports_addxprt(char *buf, struct net *net)
701 if (err != 0) 707 if (err != 0)
702 return err; 708 return err;
703 709
704 err = svc_create_xprt(nfsd_serv, transport, net, 710 err = svc_create_xprt(nn->nfsd_serv, transport, net,
705 PF_INET, port, SVC_SOCK_ANONYMOUS); 711 PF_INET, port, SVC_SOCK_ANONYMOUS);
706 if (err < 0) 712 if (err < 0)
707 goto out_err; 713 goto out_err;
708 714
709 err = svc_create_xprt(nfsd_serv, transport, net, 715 err = svc_create_xprt(nn->nfsd_serv, transport, net,
710 PF_INET6, port, SVC_SOCK_ANONYMOUS); 716 PF_INET6, port, SVC_SOCK_ANONYMOUS);
711 if (err < 0 && err != -EAFNOSUPPORT) 717 if (err < 0 && err != -EAFNOSUPPORT)
712 goto out_close; 718 goto out_close;
713 719
714 /* Decrease the count, but don't shut down the service */ 720 /* Decrease the count, but don't shut down the service */
715 nfsd_serv->sv_nrthreads--; 721 nn->nfsd_serv->sv_nrthreads--;
716 return 0; 722 return 0;
717out_close: 723out_close:
718 xprt = svc_find_xprt(nfsd_serv, transport, net, PF_INET, port); 724 xprt = svc_find_xprt(nn->nfsd_serv, transport, net, PF_INET, port);
719 if (xprt != NULL) { 725 if (xprt != NULL) {
720 svc_close_xprt(xprt); 726 svc_close_xprt(xprt);
721 svc_xprt_put(xprt); 727 svc_xprt_put(xprt);
@@ -729,7 +735,7 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size,
729 struct net *net) 735 struct net *net)
730{ 736{
731 if (size == 0) 737 if (size == 0)
732 return __write_ports_names(buf); 738 return __write_ports_names(buf, net);
733 739
734 if (isdigit(buf[0])) 740 if (isdigit(buf[0]))
735 return __write_ports_addfd(buf, net); 741 return __write_ports_addfd(buf, net);
@@ -821,6 +827,9 @@ int nfsd_max_blksize;
821static ssize_t write_maxblksize(struct file *file, char *buf, size_t size) 827static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
822{ 828{
823 char *mesg = buf; 829 char *mesg = buf;
830 struct net *net = &init_net;
831 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
832
824 if (size > 0) { 833 if (size > 0) {
825 int bsize; 834 int bsize;
826 int rv = get_int(&mesg, &bsize); 835 int rv = get_int(&mesg, &bsize);
@@ -835,7 +844,7 @@ static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
835 bsize = NFSSVC_MAXBLKSIZE; 844 bsize = NFSSVC_MAXBLKSIZE;
836 bsize &= ~(1024-1); 845 bsize &= ~(1024-1);
837 mutex_lock(&nfsd_mutex); 846 mutex_lock(&nfsd_mutex);
838 if (nfsd_serv) { 847 if (nn->nfsd_serv) {
839 mutex_unlock(&nfsd_mutex); 848 mutex_unlock(&nfsd_mutex);
840 return -EBUSY; 849 return -EBUSY;
841 } 850 }
@@ -848,13 +857,14 @@ static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
848} 857}
849 858
850#ifdef CONFIG_NFSD_V4 859#ifdef CONFIG_NFSD_V4
851static ssize_t __nfsd4_write_time(struct file *file, char *buf, size_t size, time_t *time) 860static ssize_t __nfsd4_write_time(struct file *file, char *buf, size_t size,
861 time_t *time, struct nfsd_net *nn)
852{ 862{
853 char *mesg = buf; 863 char *mesg = buf;
854 int rv, i; 864 int rv, i;
855 865
856 if (size > 0) { 866 if (size > 0) {
857 if (nfsd_serv) 867 if (nn->nfsd_serv)
858 return -EBUSY; 868 return -EBUSY;
859 rv = get_int(&mesg, &i); 869 rv = get_int(&mesg, &i);
860 if (rv) 870 if (rv)
@@ -879,12 +889,13 @@ static ssize_t __nfsd4_write_time(struct file *file, char *buf, size_t size, tim
879 return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%ld\n", *time); 889 return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%ld\n", *time);
880} 890}
881 891
882static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size, time_t *time) 892static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size,
893 time_t *time, struct nfsd_net *nn)
883{ 894{
884 ssize_t rv; 895 ssize_t rv;
885 896
886 mutex_lock(&nfsd_mutex); 897 mutex_lock(&nfsd_mutex);
887 rv = __nfsd4_write_time(file, buf, size, time); 898 rv = __nfsd4_write_time(file, buf, size, time, nn);
888 mutex_unlock(&nfsd_mutex); 899 mutex_unlock(&nfsd_mutex);
889 return rv; 900 return rv;
890} 901}
@@ -913,7 +924,7 @@ static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size, time_
913static ssize_t write_leasetime(struct file *file, char *buf, size_t size) 924static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
914{ 925{
915 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); 926 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
916 return nfsd4_write_time(file, buf, size, &nn->nfsd4_lease); 927 return nfsd4_write_time(file, buf, size, &nn->nfsd4_lease, nn);
917} 928}
918 929
919/** 930/**
@@ -929,17 +940,18 @@ static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
929static ssize_t write_gracetime(struct file *file, char *buf, size_t size) 940static ssize_t write_gracetime(struct file *file, char *buf, size_t size)
930{ 941{
931 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); 942 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
932 return nfsd4_write_time(file, buf, size, &nn->nfsd4_grace); 943 return nfsd4_write_time(file, buf, size, &nn->nfsd4_grace, nn);
933} 944}
934 945
935static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size) 946static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size,
947 struct nfsd_net *nn)
936{ 948{
937 char *mesg = buf; 949 char *mesg = buf;
938 char *recdir; 950 char *recdir;
939 int len, status; 951 int len, status;
940 952
941 if (size > 0) { 953 if (size > 0) {
942 if (nfsd_serv) 954 if (nn->nfsd_serv)
943 return -EBUSY; 955 return -EBUSY;
944 if (size > PATH_MAX || buf[size-1] != '\n') 956 if (size > PATH_MAX || buf[size-1] != '\n')
945 return -EINVAL; 957 return -EINVAL;
@@ -983,9 +995,10 @@ static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size)
983static ssize_t write_recoverydir(struct file *file, char *buf, size_t size) 995static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
984{ 996{
985 ssize_t rv; 997 ssize_t rv;
998 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
986 999
987 mutex_lock(&nfsd_mutex); 1000 mutex_lock(&nfsd_mutex);
988 rv = __write_recoverydir(file, buf, size); 1001 rv = __write_recoverydir(file, buf, size, nn);
989 mutex_unlock(&nfsd_mutex); 1002 mutex_unlock(&nfsd_mutex);
990 return rv; 1003 return rv;
991} 1004}
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index 71ba60d36234..de23db255c69 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -55,7 +55,6 @@ extern struct svc_version nfsd_version2, nfsd_version3,
55 nfsd_version4; 55 nfsd_version4;
56extern u32 nfsd_supported_minorversion; 56extern u32 nfsd_supported_minorversion;
57extern struct mutex nfsd_mutex; 57extern struct mutex nfsd_mutex;
58extern struct svc_serv *nfsd_serv;
59extern spinlock_t nfsd_drc_lock; 58extern spinlock_t nfsd_drc_lock;
60extern unsigned int nfsd_drc_max_mem; 59extern unsigned int nfsd_drc_max_mem;
61extern unsigned int nfsd_drc_mem_used; 60extern unsigned int nfsd_drc_mem_used;
@@ -68,23 +67,14 @@ extern const struct seq_operations nfs_exports_op;
68int nfsd_svc(int nrservs, struct net *net); 67int nfsd_svc(int nrservs, struct net *net);
69int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp); 68int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp);
70 69
71int nfsd_nrthreads(void); 70int nfsd_nrthreads(struct net *);
72int nfsd_nrpools(void); 71int nfsd_nrpools(struct net *);
73int nfsd_get_nrthreads(int n, int *); 72int nfsd_get_nrthreads(int n, int *, struct net *);
74int nfsd_set_nrthreads(int n, int *, struct net *); 73int nfsd_set_nrthreads(int n, int *, struct net *);
75int nfsd_pool_stats_open(struct inode *, struct file *); 74int nfsd_pool_stats_open(struct inode *, struct file *);
76int nfsd_pool_stats_release(struct inode *, struct file *); 75int nfsd_pool_stats_release(struct inode *, struct file *);
77 76
78static inline void nfsd_destroy(struct net *net) 77void nfsd_destroy(struct net *net);
79{
80 int destroy = (nfsd_serv->sv_nrthreads == 1);
81
82 if (destroy)
83 svc_shutdown_net(nfsd_serv, net);
84 svc_destroy(nfsd_serv);
85 if (destroy)
86 nfsd_serv = NULL;
87}
88 78
89#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) 79#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
90#ifdef CONFIG_NFSD_V2_ACL 80#ifdef CONFIG_NFSD_V2_ACL
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}