]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
nfsd: add controls to set the minimum number of threads per pool
authorJeff Layton <jlayton@kernel.org>
Tue, 6 Jan 2026 18:59:50 +0000 (13:59 -0500)
committerChuck Lever <chuck.lever@oracle.com>
Wed, 28 Jan 2026 15:15:42 +0000 (10:15 -0500)
Add a new "min_threads" variable to the nfsd_net, along with the
corresponding netlink interface, to set that value from userland.
Pass that value to svc_set_pool_threads() and svc_set_num_threads().

Signed-off-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Documentation/netlink/specs/nfsd.yaml
fs/nfsd/netlink.c
fs/nfsd/netns.h
fs/nfsd/nfsctl.c
fs/nfsd/nfssvc.c
fs/nfsd/trace.h
include/uapi/linux/nfsd_netlink.h

index 100363029e82aed87295e34a008ab771a95d508c..badb2fe57c9859c6932c621a589da694782b0272 100644 (file)
@@ -78,6 +78,9 @@ attribute-sets:
       -
         name: scope
         type: string
+      -
+        name: min-threads
+        type: u32
   -
     name: version
     attributes:
@@ -159,6 +162,7 @@ operations:
             - gracetime
             - leasetime
             - scope
+            - min-threads
     -
       name: threads-get
       doc: get the number of running threads
@@ -170,6 +174,7 @@ operations:
             - gracetime
             - leasetime
             - scope
+            - min-threads
     -
       name: version-set
       doc: set nfs enabled versions
index ac51a44e1065ec3f1d88165f70a831a828b58394..887525964451e640304371e33aa4f415b4ff2848 100644 (file)
@@ -24,11 +24,12 @@ const struct nla_policy nfsd_version_nl_policy[NFSD_A_VERSION_ENABLED + 1] = {
 };
 
 /* NFSD_CMD_THREADS_SET - do */
-static const struct nla_policy nfsd_threads_set_nl_policy[NFSD_A_SERVER_SCOPE + 1] = {
+static const struct nla_policy nfsd_threads_set_nl_policy[NFSD_A_SERVER_MIN_THREADS + 1] = {
        [NFSD_A_SERVER_THREADS] = { .type = NLA_U32, },
        [NFSD_A_SERVER_GRACETIME] = { .type = NLA_U32, },
        [NFSD_A_SERVER_LEASETIME] = { .type = NLA_U32, },
        [NFSD_A_SERVER_SCOPE] = { .type = NLA_NUL_STRING, },
+       [NFSD_A_SERVER_MIN_THREADS] = { .type = NLA_U32, },
 };
 
 /* NFSD_CMD_VERSION_SET - do */
@@ -57,7 +58,7 @@ static const struct genl_split_ops nfsd_nl_ops[] = {
                .cmd            = NFSD_CMD_THREADS_SET,
                .doit           = nfsd_nl_threads_set_doit,
                .policy         = nfsd_threads_set_nl_policy,
-               .maxattr        = NFSD_A_SERVER_SCOPE,
+               .maxattr        = NFSD_A_SERVER_MIN_THREADS,
                .flags          = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
        },
        {
index d83c68872c4c3e53d9d251e93dcdcbdeb2aea6a9..9fa6006026585cc35fc3c28ec09941f0078f7b74 100644 (file)
@@ -129,6 +129,12 @@ struct nfsd_net {
        seqlock_t writeverf_lock;
        unsigned char writeverf[8];
 
+       /*
+        * Minimum number of threads to run per pool.  If 0 then the
+        * min == max requested number of threads.
+        */
+       unsigned int min_threads;
+
        u32 clientid_base;
        u32 clientid_counter;
        u32 clverifier_counter;
index 084fc517e9e160b56cba0c40ac0daa749be3ffcd..7a58e54760beb91431c80eec8c297d5578aa65e2 100644 (file)
@@ -1642,6 +1642,10 @@ int nfsd_nl_threads_set_doit(struct sk_buff *skb, struct genl_info *info)
                        scope = nla_data(attr);
        }
 
+       attr = info->attrs[NFSD_A_SERVER_MIN_THREADS];
+       if (attr)
+               nn->min_threads = nla_get_u32(attr);
+
        ret = nfsd_svc(nrpools, nthreads, net, get_current_cred(), scope);
        if (ret > 0)
                ret = 0;
@@ -1681,6 +1685,8 @@ int nfsd_nl_threads_get_doit(struct sk_buff *skb, struct genl_info *info)
                          nn->nfsd4_grace) ||
              nla_put_u32(skb, NFSD_A_SERVER_LEASETIME,
                          nn->nfsd4_lease) ||
+             nla_put_u32(skb, NFSD_A_SERVER_MIN_THREADS,
+                         nn->min_threads) ||
              nla_put_string(skb, NFSD_A_SERVER_SCOPE,
                          nn->nfsd_name);
        if (err)
index 1e2570e3c754cfbd3caf0335fb9f46b5e22b5d63..0887ee601d3cf5d4f20f1cef388d12e9db992690 100644 (file)
@@ -690,7 +690,7 @@ int nfsd_set_nrthreads(int n, int *nthreads, struct net *net)
 
        /* Special case: When n == 1, distribute threads equally among pools. */
        if (n == 1)
-               return svc_set_num_threads(nn->nfsd_serv, 0, nthreads[0]);
+               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;
@@ -718,7 +718,7 @@ int nfsd_set_nrthreads(int n, int *nthreads, struct net *net)
        for (i = 0; i < n; i++) {
                err = svc_set_pool_threads(nn->nfsd_serv,
                                           &nn->nfsd_serv->sv_pools[i],
-                                          0, nthreads[i]);
+                                          nn->min_threads, nthreads[i]);
                if (err)
                        goto out;
        }
index 8885fd9bead98ebf55379d68ab9c3701981a5150..d1d0b0dd054588a8c20e3386356dfa4e9632b8e0 100644 (file)
@@ -2164,6 +2164,25 @@ TRACE_EVENT(nfsd_ctl_maxblksize,
        )
 );
 
+TRACE_EVENT(nfsd_ctl_minthreads,
+       TP_PROTO(
+               const struct net *net,
+               int minthreads
+       ),
+       TP_ARGS(net, minthreads),
+       TP_STRUCT__entry(
+               __field(unsigned int, netns_ino)
+               __field(int, minthreads)
+       ),
+       TP_fast_assign(
+               __entry->netns_ino = net->ns.inum;
+               __entry->minthreads = minthreads
+       ),
+       TP_printk("minthreads=%d",
+               __entry->minthreads
+       )
+);
+
 TRACE_EVENT(nfsd_ctl_time,
        TP_PROTO(
                const struct net *net,
index e157e2009ea8c1ef805301261d536c82677821ef..e9efbc9e63d83ed25fcd790b7a877c0023638f15 100644 (file)
@@ -35,6 +35,7 @@ enum {
        NFSD_A_SERVER_GRACETIME,
        NFSD_A_SERVER_LEASETIME,
        NFSD_A_SERVER_SCOPE,
+       NFSD_A_SERVER_MIN_THREADS,
 
        __NFSD_A_SERVER_MAX,
        NFSD_A_SERVER_MAX = (__NFSD_A_SERVER_MAX - 1)