nfsd: add a new /proc/fs/nfsd/max_connections file
Subsystems (2)
PATCH 1/1 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.
--- fs/nfsd/netns.h | 6 ++++++ fs/nfsd/nfsctl.c | 42 ++++++++++++++++++++++++++++++++++++++++++ fs/nfsd/nfssvc.c | 5 +++++ 3 files changed, 53 insertions(+)
fs/nfsd/netns.h +6 -0
@@ -103,6 +103,12 @@ struct nfsd_net {/* Time of server startup */ struct timeval nfssvc_boot; +/* +* Max number of connections this nfsd container will allow. Defaults +* to '0' which is means that it bases this on the number of threads. +*/ +unsigned int max_connections; +u32 clientid_counter;struct svc_serv *nfsd_serv;
fs/nfsd/nfsctl.c +42 -0
72 lines not on this page · raw message
fs/nfsd/nfssvc.c +5 -0
@@ -405,6 +405,7 @@ int nfsd_create_serv(struct net *net)if (nn->nfsd_serv ==NULL )return -ENOMEM ; + nn->nfsd_serv->sv_maxconn = nn->max_connections; error =svc_bind (nn->nfsd_serv, net);if (error <0 ) {svc_destroy (nn->nfsd_serv);
@@ -563,6 +564,7 @@ nfsd(void *vrqstp)struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp; 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; +struct nfsd_net *nn =net_generic (net, nfsd_net_id);int err;/* Lock module and set up kernel thread */
@@ -596,6 +598,9 @@ nfsd(void *vrqstp)* The main request loop */ for (;;) { +/* Update sv_maxconn if it has changed */ + rqstp->rq_server->sv_maxconn = nn->max_connections; +/* * Find a socket with data available and call its * recvfrom routine.
Signature · 1 line
1.9.3
Quoted 10 lines · Jeff Layton
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.
Quoted 4 lines
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.
Makes sense to me, applying.
(Trivial conflict fixed up due to not having applied all the state locking patches yet.)
--b.
Quoted 140 lines
Cc Trond Myklebust <[email protected]>Signed-off-by Jeff Layton <[email protected]>--- fs/nfsd/netns.h | 6 ++++++ fs/nfsd/nfsctl.c | 42 ++++++++++++++++++++++++++++++++++++++++++ fs/nfsd/nfssvc.c | 5 +++++ 3 files changed, 53 insertions(+)fs/nfsd/netns.h +6
-0@@ -103,6 +103,12 @@ struct nfsd_net {/* Time of server startup */ struct timeval nfssvc_boot; +/* +* Max number of connections this nfsd container will allow. Defaults +* to '0' which is means that it bases this on the number of threads. +*/ +unsigned int max_connections; +u32 clientid_counter;struct svc_serv *nfsd_serv;fs/nfsd/nfsctl.c +42
-0@@ -39,6 +39,7 @@ enum { NFSD_Versions, NFSD_Ports, NFSD_MaxBlkSize, + NFSD_MaxConnections, NFSD_SupportedEnctypes,/* * 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);static ssize_t write_versions (struct file *file,char *buf,size_t size);static ssize_t write_ports (struct file *file,char *buf,size_t size);static ssize_t write_maxblksize (struct file *file,char *buf,size_t size); +static ssize_t write_maxconn (struct file *file,char *buf,size_t size);#ifdef CONFIG_NFSD_V4 static ssize_t write_leasetime (struct file *file,char *buf,size_t size);static 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) = { [NFSD_Versions] = write_versions, [NFSD_Ports] = write_ports, [NFSD_MaxBlkSize] = write_maxblksize, + [NFSD_MaxConnections] = write_maxconn, #ifdef CONFIG_NFSD_V4 [NFSD_Leasetime] = write_leasetime, [NFSD_Gracetime] = write_gracetime,@@ -886,6 +889,44 @@ static ssize_t write_maxblksize(struct file *file, char *buf, size_t size) nfsd_max_blksize); } +/** +* write_maxconn - Set or report the current max number of connections +* +* Input: +* buf: ignored +* size: zero +* OR +* +* Input: +* buf: C string containing an unsigned +* integer value representing the new +* number of max connections +* size: non-zero length of C string in @buf +* Output: +* On success: passed-in buffer filled with '\n'-terminated C string +* containing numeric value of max_connections setting +* for this net namespace; +* return code is the size in bytes of the string +* On error: return code is zero or a negative errno value +*/ +static ssize_t write_maxconn (struct file *file,char *buf,size_t size) +{ +char *mesg = buf; +struct net *net = file->f_dentry->d_sb->s_fs_info; +struct nfsd_net *nn =net_generic (net, nfsd_net_id); +unsigned int maxconn = nn->max_connections; + +if (size >0 ) { +int rv =get_uint (&mesg, &maxconn); + +if (rv) +return rv; + nn->max_connections = maxconn; + } + +return scnprintf (buf,SIMPLE_TRANSACTION_LIMIT ,"%u\n" , maxconn); +} +#ifdef CONFIG_NFSD_V4 static ssize_t __nfsd4_write_time (struct file *file,char *buf,size_t size,time_t *time,struct nfsd_net *nn)@@ -1061,6 +1102,7 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent) [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO}, [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO}, + [NFSD_MaxConnections] = {"max_connections" , &transaction_ops,S_IWUSR |S_IRUGO }, #if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE) [NFSD_SupportedEnctypes] = {"supported_krb5_enctypes", &supported_enctypes_ops, S_IRUGO}, #endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */fs/nfsd/nfssvc.c +5
-0@@ -405,6 +405,7 @@ int nfsd_create_serv(struct net *net)if (nn->nfsd_serv ==NULL )return -ENOMEM ; + nn->nfsd_serv->sv_maxconn = nn->max_connections; error =svc_bind (nn->nfsd_serv, net);if (error <0 ) {svc_destroy (nn->nfsd_serv);@@ -563,6 +564,7 @@ nfsd(void *vrqstp)struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp; 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; +struct nfsd_net *nn =net_generic (net, nfsd_net_id);int err;/* Lock module and set up kernel thread */ @@ -596,6 +598,9 @@ nfsd(void *vrqstp)* The main request loop */ for (;;) { +/* Update sv_maxconn if it has changed */ + rqstp->rq_server->sv_maxconn = nn->max_connections; +/* * Find a socket with data available and call its * recvfrom routine. Signature · 1 line
1.9.3