From: Jeff Layton <jlayton@kernel.org>
To: NeilBrown <neil@brown.name>
Cc: Trond Myklebust <trondmy@kernel.org>,
Anna Schumaker <anna@kernel.org>,
Olga Kornievskaia <okorniev@redhat.com>,
Dai Ngo <Dai.Ngo@oracle.com>, Tom Talpey <tom@talpey.com>,
Chuck Lever <cel@kernel.org>,
linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v5 5/5] sunrpc: derive the pool count instead of caching it in sv_nrpools
Date: Wed, 08 Jul 2026 06:40:17 -0400 [thread overview]
Message-ID: <6f703524141a195ad1e4f16b1b1d16ffa2073189.camel@kernel.org> (raw)
In-Reply-To: <178348882124.3371781.3092732814258907420@noble.neil.brown.name>
On Wed, 2026-07-08 at 15:33 +1000, NeilBrown wrote:
> On Tue, 07 Jul 2026, Jeff Layton wrote:
> > On Tue, 2026-07-07 at 08:50 +1000, NeilBrown wrote:
> > > On Mon, 06 Jul 2026, Jeff Layton wrote:
> > > > Now that the pool mode is always pernode, svc_serv.sv_nrpools is
> > > > redundant with sv_is_pooled: an unpooled service always has a single
> > > > pool, and a pooled service has svc_pool_map.npools pools (which is one on
> > > > a single-node host). sv_nrpools cannot distinguish an unpooled service
> > > > from a pooled service that happens to have one pool, so it is sv_nrpools,
> > > > not sv_is_pooled, that carries no unique information.
> > > >
> > > > Replace the cached field with a svc_serv_nrpools() helper that derives
> > > > the count from sv_is_pooled and the pool map, and convert all readers to
> > > > it. svc_pool_map is file-local to svc.c, so export the helper for the
> > > > svc_xprt.c and nfsd callers.
> > > >
> > > > Reading svc_pool_map.npools without svc_pool_map_mutex is safe: the
> > > > mutex protects only svc_pool_map.count, and npools is already read
> > > > locklessly in svc_pool_for_cpu().
> > > >
> > > > A pooled service holds a map reference for its whole lifetime, so npools
> > > > is stable while any reader could observe it. The hot path
> > > > (svc_pool_for_cpu()) already dereferences svc_pool_map for to_pool, and
> > > > npools shares that cacheline, so there is no new locking or coherence
> > > > cost.
> > > >
> > > > __svc_create() keeps using its local npools argument for the sv_pools[]
> > > > allocation, since sv_is_pooled is not set until svc_create_pooled() has
> > > > returned from it.
> > > >
> > > > Doing this also removes a modulus operation from svc_pool_for_cpu(),
> > > > which should make for more efficient RPC queueing.
> > > >
> > > > Assisted-by: Claude:claude-opus-4-8
> > > > Suggested-by: NeilBrown <neilb@ownmail.net>
> > > > Signed-off-by: Jeff Layton <jlayton@kernel.org>
> > > > ---
> > > > fs/nfsd/nfsctl.c | 2 +-
> > > > fs/nfsd/nfssvc.c | 10 ++++-----
> > > > include/linux/sunrpc/svc.h | 2 +-
> > > > net/sunrpc/svc.c | 52 ++++++++++++++++++++++++++++++++--------------
> > > > net/sunrpc/svc_xprt.c | 6 +++---
> > > > 5 files changed, 46 insertions(+), 26 deletions(-)
> > > >
> > > > diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
> > > > index bc16fc7ca24f..0543e5bb842f 100644
> > > > --- a/fs/nfsd/nfsctl.c
> > > > +++ b/fs/nfsd/nfsctl.c
> > > > @@ -1526,7 +1526,7 @@ int nfsd_nl_rpc_status_get_dumpit(struct sk_buff *skb,
> > > >
> > > > rcu_read_lock();
> > > >
> > > > - for (i = 0; i < nn->nfsd_serv->sv_nrpools; i++) {
> > > > + for (i = 0; i < svc_serv_nrpools(nn->nfsd_serv); i++) {
> > > > struct svc_rqst *rqstp;
> > > > long thread_skip = 0;
> > > >
> > > > diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
> > > > index a8ea4dbfa56b..2edf716ea022 100644
> > > > --- a/fs/nfsd/nfssvc.c
> > > > +++ b/fs/nfsd/nfssvc.c
> > > > @@ -655,7 +655,7 @@ int nfsd_nrpools(struct net *net)
> > > > if (nn->nfsd_serv == NULL)
> > > > return 0;
> > > > else
> > > > - return nn->nfsd_serv->sv_nrpools;
> > > > + return svc_serv_nrpools(nn->nfsd_serv);
> > > > }
> > > >
> > > > int nfsd_get_nrthreads(int n, int *nthreads, struct net *net)
> > > > @@ -665,7 +665,7 @@ int nfsd_get_nrthreads(int n, int *nthreads, struct net *net)
> > > > int i;
> > > >
> > > > if (serv)
> > > > - for (i = 0; i < serv->sv_nrpools && i < n; i++)
> > > > + for (i = 0; i < svc_serv_nrpools(serv) && i < n; i++)
> > > > nthreads[i] = serv->sv_pools[i].sp_nrthrmax;
> > > > return 0;
> > > > }
> > > > @@ -699,8 +699,8 @@ int nfsd_set_nrthreads(int n, int *nthreads, struct net *net)
> > > > if (n == 1)
> > > > return svc_set_num_threads(nn->nfsd_serv, nn->min_threads, nthreads[0]);
> > > >
> > > > - if (n > nn->nfsd_serv->sv_nrpools)
> > > > - n = nn->nfsd_serv->sv_nrpools;
> > > > + if (n > svc_serv_nrpools(nn->nfsd_serv))
> > > > + n = svc_serv_nrpools(nn->nfsd_serv);
> > > >
> > > > /* enforce a global maximum number of threads */
> > > > tot = 0;
> > > > @@ -731,7 +731,7 @@ int nfsd_set_nrthreads(int n, int *nthreads, struct net *net)
> > > > }
> > > >
> > > > /* Anything undefined in array is considered to be 0 */
> > > > - for (i = n; i < nn->nfsd_serv->sv_nrpools; ++i) {
> > > > + for (i = n; i < svc_serv_nrpools(nn->nfsd_serv); ++i) {
> > > > err = svc_set_pool_threads(nn->nfsd_serv,
> > > > &nn->nfsd_serv->sv_pools[i],
> > > > 0, 0);
> > > > diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
> > > > index 3a0152d926fb..3c885ab6ad41 100644
> > > > --- a/include/linux/sunrpc/svc.h
> > > > +++ b/include/linux/sunrpc/svc.h
> > > > @@ -85,7 +85,6 @@ 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);
> > > > @@ -480,6 +479,7 @@ void svc_wake_up(struct svc_serv *);
> > > > void svc_reserve(struct svc_rqst *rqstp, int space);
> > > > void svc_pool_wake_idle_thread(struct svc_pool *pool);
> > > > struct svc_pool *svc_pool_for_cpu(struct svc_serv *serv);
> > > > +unsigned int svc_serv_nrpools(const struct svc_serv *serv);
> > > > char * svc_print_addr(struct svc_rqst *, char *, size_t);
> > > > const char * svc_proc_name(const struct svc_rqst *rqstp);
> > > > int svc_encode_result_payload(struct svc_rqst *rqstp,
> > > > diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
> > > > index ece69cb0138a..800514a14f17 100644
> > > > --- a/net/sunrpc/svc.c
> > > > +++ b/net/sunrpc/svc.c
> > > > @@ -224,7 +224,7 @@ svc_pool_map_set_cpumask(struct task_struct *task, unsigned int pidx)
> > > > unsigned int node = m->pool_to[pidx];
> > > >
> > > > /*
> > > > - * The caller checks for sv_nrpools > 1, which
> > > > + * The caller checks for more than one pool, which
> > > > * implies that we've been initialized.
> > > > */
> > > > WARN_ON_ONCE(m->count == 0);
> > > > @@ -234,6 +234,24 @@ svc_pool_map_set_cpumask(struct task_struct *task, unsigned int pidx)
> > > > set_cpus_allowed_ptr(task, cpumask_of_node(node));
> > > > }
> > > >
> > > > +/**
> > > > + * svc_serv_nrpools - number of thread pools backing a service
> > > > + * @serv: An RPC service
> > > > + *
> > > > + * Pooled services all share the global svc_pool_map, so their pool count
> > > > + * is svc_pool_map.npools. Unpooled services have a single pool. Reading
> > > > + * npools without svc_pool_map_mutex is safe: a pooled service holds a map
> > > > + * reference for its whole lifetime, so npools is stable once set.
> > > > + *
> > > > + * Return value:
> > > > + * The number of pools in @serv
> > > > + */
> > > > +unsigned int svc_serv_nrpools(const struct svc_serv *serv)
> > > > +{
> > > > + return serv->sv_is_pooled ? svc_pool_map.npools : 1;
> > > > +}
> > > > +EXPORT_SYMBOL_GPL(svc_serv_nrpools);
> > >
> > > I would make this a static-inline.
> > >
> >
> > That would mean that we would have to export svc_pool_map, which is
> > currently private to svc.c.
>
> Why is exporting svc_pool_map more problematic than exporting svc_serv_nrpools?
> I think it would be good for at least the code in svc_pool_for_cpu() to
> inline the function. Maybe it already does? Or maybe marking it
> "inline" but still exporting it would work.
>
> Thanks,
> NeilBrown
>
Doing what you suggest would increase the interface "surface" between
sunrpc.ko and nfsd.ko.
Currently struct svc_pool_map is only defined in net/sunrpc/svc.c, so
we'd not only need to export the symbol, but also we'd have to make
that definition public.
Why expose so many internal details to other modules when all we need
is this one accessor? I think keeping this interface small is
preferable.
--
Jeff Layton <jlayton@kernel.org>
next prev parent reply other threads:[~2026-07-08 10:40 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-06 13:29 [PATCH v5 0/5] sunrpc: hardcode pool_mode to pernode, remove other modes Jeff Layton
2026-07-06 13:29 ` [PATCH v5 1/5] sunrpc: route to a populated pool in svc_pool_for_cpu() Jeff Layton
2026-07-06 13:29 ` [PATCH v5 2/5] sunrpc: hardcode pool_mode to pernode, remove other modes Jeff Layton
2026-07-06 13:29 ` [PATCH v5 3/5] sunrpc: guarantee a thread per pool when auto-distributing Jeff Layton
2026-07-06 13:29 ` [PATCH v5 4/5] sunrpc: tear down pool counters before dropping the pool map reference Jeff Layton
2026-07-06 13:29 ` [PATCH v5 5/5] sunrpc: derive the pool count instead of caching it in sv_nrpools Jeff Layton
2026-07-06 22:50 ` NeilBrown
2026-07-06 22:59 ` Jeff Layton
2026-07-08 5:33 ` NeilBrown
2026-07-08 10:40 ` Jeff Layton [this message]
2026-07-08 22:51 ` NeilBrown
2026-07-08 23:37 ` Jeff Layton
2026-07-06 20:50 ` [PATCH v5 0/5] sunrpc: hardcode pool_mode to pernode, remove other modes Chuck Lever
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=6f703524141a195ad1e4f16b1b1d16ffa2073189.camel@kernel.org \
--to=jlayton@kernel.org \
--cc=Dai.Ngo@oracle.com \
--cc=anna@kernel.org \
--cc=cel@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=neil@brown.name \
--cc=okorniev@redhat.com \
--cc=tom@talpey.com \
--cc=trondmy@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome