netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] nfsd/sunrpc: allow starting/stopping pooled NFS server via netlink
@ 2024-06-04 21:07 Jeff Layton
  2024-06-04 21:07 ` [PATCH 1/3] sunrpc: fix up the special handling of sv_nrpools == 1 Jeff Layton
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Jeff Layton @ 2024-06-04 21:07 UTC (permalink / raw)
  To: Chuck Lever, Neil Brown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: Trond Myklebust, Anna Schumaker, linux-nfs, linux-kernel, netdev,
	Jeff Layton

This patchset first attempts to detangle the pooled/non-pooled service
handling in the sunrpc layer, unifies the codepaths that start the
pooled vs. non-pooled nfsd, and then wires up the new netlink threads
interface to allow you to start a pooled server by specifying an
array of thread counts.

FWIW, eventually I'd like to wire up the pool_mode setting to netlink as
well. I took a stab at adding a pool_mode parameter to the set_threads
interface, but I think that's the wrong approach. By the time we call
set_threads, we've usually already allocated the serv. I think pool_mode
setting has to be done with new netlink call. I'll probably tackle that
in a later patchset.

Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
Jeff Layton (3):
      sunrpc: fix up the special handling of sv_nrpools == 1
      nfsd: make nfsd_svc call nfsd_set_nrthreads
      nfsd: allow passing in array of thread counts via netlink

 fs/nfsd/nfsctl.c           | 45 ++++++++++++++++++++++++++++++++-------------
 fs/nfsd/nfsd.h             |  3 ++-
 fs/nfsd/nfssvc.c           | 30 +++++++++++++-----------------
 include/linux/sunrpc/svc.h |  1 +
 net/sunrpc/svc.c           | 26 +++++++-------------------
 5 files changed, 55 insertions(+), 50 deletions(-)
---
base-commit: fec4124bac55ad92c47585fe537e646fe108b8fa
change-id: 20240604-nfsd-next-b04c0d2d89a9

Best regards,
-- 
Jeff Layton <jlayton@kernel.org>


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/3] sunrpc: fix up the special handling of sv_nrpools == 1
  2024-06-04 21:07 [PATCH 0/3] nfsd/sunrpc: allow starting/stopping pooled NFS server via netlink Jeff Layton
@ 2024-06-04 21:07 ` Jeff Layton
  2024-06-04 21:07 ` [PATCH 2/3] nfsd: make nfsd_svc call nfsd_set_nrthreads Jeff Layton
  2024-06-04 21:07 ` [PATCH 3/3] nfsd: allow passing in array of thread counts via netlink Jeff Layton
  2 siblings, 0 replies; 5+ messages in thread
From: Jeff Layton @ 2024-06-04 21:07 UTC (permalink / raw)
  To: Chuck Lever, Neil Brown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: Trond Myklebust, Anna Schumaker, linux-nfs, linux-kernel, netdev,
	Jeff Layton

Only pooled services take a reference to the svc_pool_map. The sunrpc
code has always used the sv_nrpools value to detect whether the service
is pooled.

The problem there is that nfsd is a pooled service, but when it's
running in "global" pool_mode, it doesn't take a reference to the pool
map because it has a sv_nrpools value of 1. This means that we have
two separate codepaths for starting the server, depending on whether
it's pooled or not.

Fix this by adding a new flag to the svc_serv, that indicates whether
the serv is pooled. With this we can have the nfsd service
unconditionally take a reference, regardless of pool_mode.

Ideally we should prevent anyone from changing the pool mode while the
server is running, and nfsd does this if the server is in percpu or
pernode mode. Previously, you could change the pool_mode even if there
were nfsd's already running in "global" mode. This fixes that problem as
well.

Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
 include/linux/sunrpc/svc.h |  1 +
 net/sunrpc/svc.c           | 26 +++++++-------------------
 2 files changed, 8 insertions(+), 19 deletions(-)

diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 23617da0e565..d0433e1642b3 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -85,6 +85,7 @@ struct svc_serv {
 	char *			sv_name;	/* service name */
 
 	unsigned int		sv_nrpools;	/* number of thread pools */
+	bool			sv_is_pooled;	/* is this a pooled service? */
 	struct svc_pool *	sv_pools;	/* array of thread pools */
 	int			(*sv_threadfn)(void *data);
 
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 2b4b1276d4e8..f80d94cbb8b1 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -250,10 +250,8 @@ svc_pool_map_get(void)
 	int npools = -1;
 
 	mutex_lock(&svc_pool_map_mutex);
-
 	if (m->count++) {
 		mutex_unlock(&svc_pool_map_mutex);
-		WARN_ON_ONCE(m->npools <= 1);
 		return m->npools;
 	}
 
@@ -275,32 +273,21 @@ svc_pool_map_get(void)
 		m->mode = SVC_POOL_GLOBAL;
 	}
 	m->npools = npools;
-
-	if (npools == 1)
-		/* service is unpooled, so doesn't hold a reference */
-		m->count--;
-
 	mutex_unlock(&svc_pool_map_mutex);
 	return npools;
 }
 
 /*
- * Drop a reference to the global map of cpus to pools, if
- * pools were in use, i.e. if npools > 1.
+ * Drop a reference to the global map of cpus to pools.
  * When the last reference is dropped, the map data is
- * freed; this allows the sysadmin to change the pool
- * mode using the pool_mode module option without
- * rebooting or re-loading sunrpc.ko.
+ * freed; this allows the sysadmin to change the pool.
  */
 static void
-svc_pool_map_put(int npools)
+svc_pool_map_put(void)
 {
 	struct svc_pool_map *m = &svc_pool_map;
 
-	if (npools <= 1)
-		return;
 	mutex_lock(&svc_pool_map_mutex);
-
 	if (!--m->count) {
 		kfree(m->to_pool);
 		m->to_pool = NULL;
@@ -308,7 +295,6 @@ svc_pool_map_put(int npools)
 		m->pool_to = NULL;
 		m->npools = 0;
 	}
-
 	mutex_unlock(&svc_pool_map_mutex);
 }
 
@@ -553,9 +539,10 @@ struct svc_serv *svc_create_pooled(struct svc_program *prog,
 	serv = __svc_create(prog, stats, bufsize, npools, threadfn);
 	if (!serv)
 		goto out_err;
+	serv->sv_is_pooled = true;
 	return serv;
 out_err:
-	svc_pool_map_put(npools);
+	svc_pool_map_put();
 	return NULL;
 }
 EXPORT_SYMBOL_GPL(svc_create_pooled);
@@ -585,7 +572,8 @@ svc_destroy(struct svc_serv **servp)
 
 	cache_clean_deferred(serv);
 
-	svc_pool_map_put(serv->sv_nrpools);
+	if (serv->sv_is_pooled)
+		svc_pool_map_put();
 
 	for (i = 0; i < serv->sv_nrpools; i++) {
 		struct svc_pool *pool = &serv->sv_pools[i];

-- 
2.45.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/3] nfsd: make nfsd_svc call nfsd_set_nrthreads
  2024-06-04 21:07 [PATCH 0/3] nfsd/sunrpc: allow starting/stopping pooled NFS server via netlink Jeff Layton
  2024-06-04 21:07 ` [PATCH 1/3] sunrpc: fix up the special handling of sv_nrpools == 1 Jeff Layton
@ 2024-06-04 21:07 ` Jeff Layton
  2024-06-04 21:07 ` [PATCH 3/3] nfsd: allow passing in array of thread counts via netlink Jeff Layton
  2 siblings, 0 replies; 5+ messages in thread
From: Jeff Layton @ 2024-06-04 21:07 UTC (permalink / raw)
  To: Chuck Lever, Neil Brown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: Trond Myklebust, Anna Schumaker, linux-nfs, linux-kernel, netdev,
	Jeff Layton

Now that the refcounting is fixed, rework nfsd_svc to use the same
thread setup as the pool_threads interface. Since the new netlink
interface doesn't have the same restriction as pool_threads, move the
guard against shutting down all threads to write_pool_threads.

Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
 fs/nfsd/nfsctl.c | 14 ++++++++++++--
 fs/nfsd/nfsd.h   |  3 ++-
 fs/nfsd/nfssvc.c | 18 ++----------------
 3 files changed, 16 insertions(+), 19 deletions(-)

diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 202140df8f82..121b866125d4 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -406,7 +406,7 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
 			return -EINVAL;
 		trace_nfsd_ctl_threads(net, newthreads);
 		mutex_lock(&nfsd_mutex);
-		rv = nfsd_svc(newthreads, net, file->f_cred, NULL);
+		rv = nfsd_svc(1, &newthreads, net, file->f_cred, NULL);
 		mutex_unlock(&nfsd_mutex);
 		if (rv < 0)
 			return rv;
@@ -481,6 +481,16 @@ static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
 				goto out_free;
 			trace_nfsd_ctl_pool_threads(net, i, nthreads[i]);
 		}
+
+		/*
+		 * There must always be a thread in pool 0; the admin
+		 * can't shut down NFS completely using pool_threads.
+		 *
+		 * FIXME: do we really need this?
+		 */
+		if (nthreads[0] == 0)
+			nthreads[0] = 1;
+
 		rv = nfsd_set_nrthreads(i, nthreads, net);
 		if (rv)
 			goto out_free;
@@ -1722,7 +1732,7 @@ int nfsd_nl_threads_set_doit(struct sk_buff *skb, struct genl_info *info)
 			scope = nla_data(attr);
 	}
 
-	ret = nfsd_svc(nthreads, net, get_current_cred(), scope);
+	ret = nfsd_svc(1, &nthreads, net, get_current_cred(), scope);
 
 out_unlock:
 	mutex_unlock(&nfsd_mutex);
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index 8f4f239d9f8a..cec8697b1cd6 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -103,7 +103,8 @@ bool		nfssvc_encode_voidres(struct svc_rqst *rqstp,
 /*
  * Function prototypes.
  */
-int		nfsd_svc(int nrservs, struct net *net, const struct cred *cred, const char *scope);
+int		nfsd_svc(int n, int *nservers, struct net *net,
+			 const struct cred *cred, const char *scope);
 int		nfsd_dispatch(struct svc_rqst *rqstp);
 
 int		nfsd_nrthreads(struct net *);
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index cd9a6a1a9fc8..076f35dc17e4 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -744,13 +744,6 @@ int nfsd_set_nrthreads(int n, int *nthreads, struct net *net)
 		}
 	}
 
-	/*
-	 * 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 */
 	for (i = 0; i < n; i++) {
 		err = svc_set_num_threads(nn->nfsd_serv,
@@ -768,7 +761,7 @@ int nfsd_set_nrthreads(int n, int *nthreads, struct net *net)
  * this is the first time nrservs is nonzero.
  */
 int
-nfsd_svc(int nrservs, struct net *net, const struct cred *cred, const char *scope)
+nfsd_svc(int n, int *nthreads, struct net *net, const struct cred *cred, const char *scope)
 {
 	int	error;
 	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
@@ -778,13 +771,6 @@ nfsd_svc(int nrservs, struct net *net, const struct cred *cred, const char *scop
 
 	dprintk("nfsd: creating service\n");
 
-	nrservs = max(nrservs, 0);
-	nrservs = min(nrservs, NFSD_MAXSERVS);
-	error = 0;
-
-	if (nrservs == 0 && nn->nfsd_serv == NULL)
-		goto out;
-
 	strscpy(nn->nfsd_name, scope ? scope : utsname()->nodename,
 		sizeof(nn->nfsd_name));
 
@@ -796,7 +782,7 @@ nfsd_svc(int nrservs, struct net *net, const struct cred *cred, const char *scop
 	error = nfsd_startup_net(net, cred);
 	if (error)
 		goto out_put;
-	error = svc_set_num_threads(serv, NULL, nrservs);
+	error = nfsd_set_nrthreads(n, nthreads, net);
 	if (error)
 		goto out_put;
 	error = serv->sv_nrthreads;

-- 
2.45.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/3] nfsd: allow passing in array of thread counts via netlink
  2024-06-04 21:07 [PATCH 0/3] nfsd/sunrpc: allow starting/stopping pooled NFS server via netlink Jeff Layton
  2024-06-04 21:07 ` [PATCH 1/3] sunrpc: fix up the special handling of sv_nrpools == 1 Jeff Layton
  2024-06-04 21:07 ` [PATCH 2/3] nfsd: make nfsd_svc call nfsd_set_nrthreads Jeff Layton
@ 2024-06-04 21:07 ` Jeff Layton
  2024-06-05 19:34   ` Simon Horman
  2 siblings, 1 reply; 5+ messages in thread
From: Jeff Layton @ 2024-06-04 21:07 UTC (permalink / raw)
  To: Chuck Lever, Neil Brown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: Trond Myklebust, Anna Schumaker, linux-nfs, linux-kernel, netdev,
	Jeff Layton

Now that nfsd_svc can handle an array of thread counts, fix up the
netlink threads interface to construct one from the netlink call
and pass it through so we can start a pooled server the same way we
would start a normal one.

Note that any unspecified values in the array are considered zeroes,
so it's possible to shut down a pooled server by passing in a short
array that has only zeros, or even an empty array.

Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
 fs/nfsd/nfsctl.c | 33 +++++++++++++++++++++------------
 fs/nfsd/nfssvc.c | 12 +++++++++++-
 2 files changed, 32 insertions(+), 13 deletions(-)

diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 121b866125d4..54b98e569740 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -1673,7 +1673,8 @@ int nfsd_nl_rpc_status_get_done(struct netlink_callback *cb)
  */
 int nfsd_nl_threads_set_doit(struct sk_buff *skb, struct genl_info *info)
 {
-	int nthreads = 0, count = 0, nrpools, ret = -EOPNOTSUPP, rem;
+	int *nthreads, count = 0, nrpools, ret = -EOPNOTSUPP;
+	int rem, i, total = 0;
 	struct net *net = genl_info_net(info);
 	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 	const struct nlattr *attr;
@@ -1690,15 +1691,22 @@ int nfsd_nl_threads_set_doit(struct sk_buff *skb, struct genl_info *info)
 
 	mutex_lock(&nfsd_mutex);
 
-	nrpools = nfsd_nrpools(net);
-	if (nrpools && count > nrpools)
-		count = nrpools;
-
-	/* XXX: make this handle non-global pool-modes */
-	if (count > 1)
+	nrpools = max(count, nfsd_nrpools(net));
+	nthreads = kcalloc(nrpools, sizeof(int), GFP_KERNEL);
+	if (!nthreads) {
+		ret = -ENOMEM;
 		goto out_unlock;
+	}
+
+	i = 0;
+	nlmsg_for_each_attr(attr, info->nlhdr, GENL_HDRLEN, rem) {
+		if (nla_type(attr) == NFSD_A_SERVER_THREADS) {
+			total += nthreads[i++] = nla_get_u32(attr);
+			if (i >= count)
+				break;
+		}
+	}
 
-	nthreads = nla_get_u32(info->attrs[NFSD_A_SERVER_THREADS]);
 	if (info->attrs[NFSD_A_SERVER_GRACETIME] ||
 	    info->attrs[NFSD_A_SERVER_LEASETIME] ||
 	    info->attrs[NFSD_A_SERVER_SCOPE]) {
@@ -1732,12 +1740,13 @@ int nfsd_nl_threads_set_doit(struct sk_buff *skb, struct genl_info *info)
 			scope = nla_data(attr);
 	}
 
-	ret = nfsd_svc(1, &nthreads, net, get_current_cred(), scope);
-
+	ret = nfsd_svc(nrpools, nthreads, net, get_current_cred(), scope);
+	if (ret > 0)
+		ret = 0;
 out_unlock:
 	mutex_unlock(&nfsd_mutex);
-
-	return ret == nthreads ? 0 : ret;
+	kfree(nthreads);
+	return ret;
 }
 
 /**
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 076f35dc17e4..6754cbc27c71 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -750,8 +750,18 @@ int nfsd_set_nrthreads(int n, int *nthreads, struct net *net)
 					  &nn->nfsd_serv->sv_pools[i],
 					  nthreads[i]);
 		if (err)
-			break;
+			goto out;
 	}
+
+	/* Anything undefined in array is considered to be 0 */
+	for (i = n; i < nn->nfsd_serv->sv_nrpools; ++i) {
+		err = svc_set_num_threads(nn->nfsd_serv,
+					  &nn->nfsd_serv->sv_pools[i],
+					  0);
+		if (err)
+			goto out;
+	}
+out:
 	return err;
 }
 

-- 
2.45.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 3/3] nfsd: allow passing in array of thread counts via netlink
  2024-06-04 21:07 ` [PATCH 3/3] nfsd: allow passing in array of thread counts via netlink Jeff Layton
@ 2024-06-05 19:34   ` Simon Horman
  0 siblings, 0 replies; 5+ messages in thread
From: Simon Horman @ 2024-06-05 19:34 UTC (permalink / raw)
  To: Jeff Layton
  Cc: Chuck Lever, Neil Brown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Trond Myklebust, Anna Schumaker, linux-nfs, linux-kernel, netdev

On Tue, Jun 04, 2024 at 05:07:56PM -0400, Jeff Layton wrote:
> Now that nfsd_svc can handle an array of thread counts, fix up the
> netlink threads interface to construct one from the netlink call
> and pass it through so we can start a pooled server the same way we
> would start a normal one.
> 
> Note that any unspecified values in the array are considered zeroes,
> so it's possible to shut down a pooled server by passing in a short
> array that has only zeros, or even an empty array.
> 
> Signed-off-by: Jeff Layton <jlayton@kernel.org>

...

> @@ -1690,15 +1691,22 @@ int nfsd_nl_threads_set_doit(struct sk_buff *skb, struct genl_info *info)
>  
>  	mutex_lock(&nfsd_mutex);
>  
> -	nrpools = nfsd_nrpools(net);
> -	if (nrpools && count > nrpools)
> -		count = nrpools;
> -
> -	/* XXX: make this handle non-global pool-modes */
> -	if (count > 1)
> +	nrpools = max(count, nfsd_nrpools(net));
> +	nthreads = kcalloc(nrpools, sizeof(int), GFP_KERNEL);
> +	if (!nthreads) {
> +		ret = -ENOMEM;
>  		goto out_unlock;
> +	}
> +
> +	i = 0;
> +	nlmsg_for_each_attr(attr, info->nlhdr, GENL_HDRLEN, rem) {
> +		if (nla_type(attr) == NFSD_A_SERVER_THREADS) {
> +			total += nthreads[i++] = nla_get_u32(attr);

Hi Jeff,

A minor nit from my side.

Total is set by otherwise unused in this function.

Flagged by clang-18 W=1 allmodconfig builds.

> +			if (i >= count)
> +				break;
> +		}
> +	}
>  
> -	nthreads = nla_get_u32(info->attrs[NFSD_A_SERVER_THREADS]);
>  	if (info->attrs[NFSD_A_SERVER_GRACETIME] ||
>  	    info->attrs[NFSD_A_SERVER_LEASETIME] ||
>  	    info->attrs[NFSD_A_SERVER_SCOPE]) {

...

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2024-06-05 19:34 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-06-04 21:07 [PATCH 0/3] nfsd/sunrpc: allow starting/stopping pooled NFS server via netlink Jeff Layton
2024-06-04 21:07 ` [PATCH 1/3] sunrpc: fix up the special handling of sv_nrpools == 1 Jeff Layton
2024-06-04 21:07 ` [PATCH 2/3] nfsd: make nfsd_svc call nfsd_set_nrthreads Jeff Layton
2024-06-04 21:07 ` [PATCH 3/3] nfsd: allow passing in array of thread counts via netlink Jeff Layton
2024-06-05 19:34   ` Simon Horman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).