aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Layton <jlayton@primarydata.com>2014-07-02 16:11:22 -0400
committerJ. Bruce Fields <bfields@redhat.com>2014-07-08 17:14:32 -0400
commit5b8db00bae39e5ecd9bafb05478cca5b42564ab1 (patch)
tree4a66658c431b3e93aa0bdd4aa9227867739b46c7
parent0f3a24b43bf75adf67df188a85594a8f43b9ee93 (diff)
nfsd: add a new /proc/fs/nfsd/max_connections file
Currently, the maximum number of connections that nfsd will allow is based on the number of threads spawned. While this is fine for a default, there really isn't a clear relationship between the two. The number of threads corresponds to the number of concurrent requests that we want to allow the server to process at any given time. The connection limit corresponds to the maximum number of clients that we want to allow the server to handle. These are two entirely different quantities. Break the dependency on increasing threads in order to allow for more connections, by adding a new per-net parameter that can be set to a non-zero value. The default is still to base it on the number of threads, so there should be no behavior change for anyone who doesn't use it. Cc: Trond Myklebust <trond.myklebust@primarydata.com> Signed-off-by: Jeff Layton <jlayton@primarydata.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r--fs/nfsd/netns.h6
-rw-r--r--fs/nfsd/nfsctl.c42
-rw-r--r--fs/nfsd/nfssvc.c5
3 files changed, 53 insertions, 0 deletions
diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
index d32b3aa6600d..113e1aa9b0e8 100644
--- a/fs/nfsd/netns.h
+++ b/fs/nfsd/netns.h
@@ -102,6 +102,12 @@ struct nfsd_net {
102 */ 102 */
103 struct timeval nfssvc_boot; 103 struct timeval nfssvc_boot;
104 104
105 /*
106 * Max number of connections this nfsd container will allow. Defaults
107 * to '0' which is means that it bases this on the number of threads.
108 */
109 unsigned int max_connections;
110
105 struct svc_serv *nfsd_serv; 111 struct svc_serv *nfsd_serv;
106}; 112};
107 113
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 6a6f65cc8b34..4e042105fb6e 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -39,6 +39,7 @@ enum {
39 NFSD_Versions, 39 NFSD_Versions,
40 NFSD_Ports, 40 NFSD_Ports,
41 NFSD_MaxBlkSize, 41 NFSD_MaxBlkSize,
42 NFSD_MaxConnections,
42 NFSD_SupportedEnctypes, 43 NFSD_SupportedEnctypes,
43 /* 44 /*
44 * The below MUST come last. Otherwise we leave a hole in nfsd_files[] 45 * The below MUST come last. Otherwise we leave a hole in nfsd_files[]
@@ -62,6 +63,7 @@ static ssize_t write_pool_threads(struct file *file, char *buf, size_t size);
62static ssize_t write_versions(struct file *file, char *buf, size_t size); 63static ssize_t write_versions(struct file *file, char *buf, size_t size);
63static ssize_t write_ports(struct file *file, char *buf, size_t size); 64static ssize_t write_ports(struct file *file, char *buf, size_t size);
64static ssize_t write_maxblksize(struct file *file, char *buf, size_t size); 65static ssize_t write_maxblksize(struct file *file, char *buf, size_t size);
66static ssize_t write_maxconn(struct file *file, char *buf, size_t size);
65#ifdef CONFIG_NFSD_V4 67#ifdef CONFIG_NFSD_V4
66static ssize_t write_leasetime(struct file *file, char *buf, size_t size); 68static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
67static ssize_t write_gracetime(struct file *file, char *buf, size_t size); 69static ssize_t write_gracetime(struct file *file, char *buf, size_t size);
@@ -77,6 +79,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
77 [NFSD_Versions] = write_versions, 79 [NFSD_Versions] = write_versions,
78 [NFSD_Ports] = write_ports, 80 [NFSD_Ports] = write_ports,
79 [NFSD_MaxBlkSize] = write_maxblksize, 81 [NFSD_MaxBlkSize] = write_maxblksize,
82 [NFSD_MaxConnections] = write_maxconn,
80#ifdef CONFIG_NFSD_V4 83#ifdef CONFIG_NFSD_V4
81 [NFSD_Leasetime] = write_leasetime, 84 [NFSD_Leasetime] = write_leasetime,
82 [NFSD_Gracetime] = write_gracetime, 85 [NFSD_Gracetime] = write_gracetime,
@@ -886,6 +889,44 @@ static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
886 nfsd_max_blksize); 889 nfsd_max_blksize);
887} 890}
888 891
892/**
893 * write_maxconn - Set or report the current max number of connections
894 *
895 * Input:
896 * buf: ignored
897 * size: zero
898 * OR
899 *
900 * Input:
901 * buf: C string containing an unsigned
902 * integer value representing the new
903 * number of max connections
904 * size: non-zero length of C string in @buf
905 * Output:
906 * On success: passed-in buffer filled with '\n'-terminated C string
907 * containing numeric value of max_connections setting
908 * for this net namespace;
909 * return code is the size in bytes of the string
910 * On error: return code is zero or a negative errno value
911 */
912static ssize_t write_maxconn(struct file *file, char *buf, size_t size)
913{
914 char *mesg = buf;
915 struct net *net = file->f_dentry->d_sb->s_fs_info;
916 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
917 unsigned int maxconn = nn->max_connections;
918
919 if (size > 0) {
920 int rv = get_uint(&mesg, &maxconn);
921
922 if (rv)
923 return rv;
924 nn->max_connections = maxconn;
925 }
926
927 return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%u\n", maxconn);
928}
929
889#ifdef CONFIG_NFSD_V4 930#ifdef CONFIG_NFSD_V4
890static ssize_t __nfsd4_write_time(struct file *file, char *buf, size_t size, 931static ssize_t __nfsd4_write_time(struct file *file, char *buf, size_t size,
891 time_t *time, struct nfsd_net *nn) 932 time_t *time, struct nfsd_net *nn)
@@ -1061,6 +1102,7 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
1061 [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR}, 1102 [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR},
1062 [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO}, 1103 [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO},
1063 [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO}, 1104 [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO},
1105 [NFSD_MaxConnections] = {"max_connections", &transaction_ops, S_IWUSR|S_IRUGO},
1064#if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE) 1106#if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE)
1065 [NFSD_SupportedEnctypes] = {"supported_krb5_enctypes", &supported_enctypes_ops, S_IRUGO}, 1107 [NFSD_SupportedEnctypes] = {"supported_krb5_enctypes", &supported_enctypes_ops, S_IRUGO},
1066#endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */ 1108#endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 209474174fe4..5d026dca00ca 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -405,6 +405,7 @@ int nfsd_create_serv(struct net *net)
405 if (nn->nfsd_serv == NULL) 405 if (nn->nfsd_serv == NULL)
406 return -ENOMEM; 406 return -ENOMEM;
407 407
408 nn->nfsd_serv->sv_maxconn = nn->max_connections;
408 error = svc_bind(nn->nfsd_serv, net); 409 error = svc_bind(nn->nfsd_serv, net);
409 if (error < 0) { 410 if (error < 0) {
410 svc_destroy(nn->nfsd_serv); 411 svc_destroy(nn->nfsd_serv);
@@ -563,6 +564,7 @@ nfsd(void *vrqstp)
563 struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp; 564 struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp;
564 struct svc_xprt *perm_sock = list_entry(rqstp->rq_server->sv_permsocks.next, typeof(struct svc_xprt), xpt_list); 565 struct svc_xprt *perm_sock = list_entry(rqstp->rq_server->sv_permsocks.next, typeof(struct svc_xprt), xpt_list);
565 struct net *net = perm_sock->xpt_net; 566 struct net *net = perm_sock->xpt_net;
567 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
566 int err; 568 int err;
567 569
568 /* Lock module and set up kernel thread */ 570 /* Lock module and set up kernel thread */
@@ -596,6 +598,9 @@ nfsd(void *vrqstp)
596 * The main request loop 598 * The main request loop
597 */ 599 */
598 for (;;) { 600 for (;;) {
601 /* Update sv_maxconn if it has changed */
602 rqstp->rq_server->sv_maxconn = nn->max_connections;
603
599 /* 604 /*
600 * Find a socket with data available and call its 605 * Find a socket with data available and call its
601 * recvfrom routine. 606 * recvfrom routine.