From nobody Sat Jul 25 05:27:10 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 673F03B6C0C; Fri, 17 Jul 2026 11:09:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784286563; cv=none; b=ILFxBB9Plm6sbWq5aPu1PYM9AOiLushl/xrYC/OwCGVQR/emagcgJSYPTu9u24fNri2P/SPn5JxHrnaoS6FqKySaNjAoRkZK8SyftrDC2D8OhgLwJRdg8GSGnENyzUbpAAnxpV55jsLlY0Pid/rcmdNqP98mHVcKNYZKPiGEP3I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784286563; c=relaxed/simple; bh=F1LpEO6cHFt1uYeB1id8tH5t6HSMNhfH/uOVtWxB0/A=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=I52z3Jz8N/uA2kCc7I5SUCwCU2zqDSSKfD6akchI6dhuoMV6TR6mDjQf+rl6UcywOERWDCDac3Uds7yqihS7oL5ztVsj387SLnC7hIzj4F/G2gcK7veREkVFC0/fkLkZby+2Fw4ViA0Vyf56tZNmuwNzfndhaIoJbLM5pZnl+2Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=j5qtlRVJ; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="j5qtlRVJ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B5C631F00A3E; Fri, 17 Jul 2026 11:09:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784286550; bh=U+eZHGx05hGweQx8OCBjR81epQ4Yh2S7o/N4mWZmMWg=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=j5qtlRVJAhvSrsKfzL/HenC3z+j4h+fk7dq0EKIqcSFE2nI1o2GzebFnrJX4WrNME 3b21hKBGKHSxKqw9asacpwUnKp0QN/imHIY9a1etshcc8eP5njHN03JR0KM5tHqPGT qc7zpPhbNIjCJjdoJNn/aTUp2j2IeuRqVm7ZYD8JznMu0KY0Ox5366aisGgUYLQlTN Q7KRVzPozZqyFnU6965Jq5gUpQ9gdKcPLQXZdqCumXT2d3oPA37nijG8rlPf0l3pQd JCQmstfqz7uLVg6xQAicYANEsw6cHdNKF+sCWN6XynvNq5EWWSus2iJ8IXFmiaS3nK IZPb2NynpMzbQ== From: Jeff Layton Date: Fri, 17 Jul 2026 07:08:53 -0400 Subject: [PATCH v7 1/6] sunrpc: add per-netns per-procedure call counts to svc_stat Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260717-exportd-netlink-v7-1-b7ce17b83b60@kernel.org> References: <20260717-exportd-netlink-v7-0-b7ce17b83b60@kernel.org> In-Reply-To: <20260717-exportd-netlink-v7-0-b7ce17b83b60@kernel.org> To: NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey , Chuck Lever Cc: Trond Myklebust , Anna Schumaker , Steve Dickson , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=5098; i=jlayton@kernel.org; h=from:subject:message-id; bh=F1LpEO6cHFt1uYeB1id8tH5t6HSMNhfH/uOVtWxB0/A=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBqWg1SPDzvnaIGnI2Js7yvgCLLupPiI2X5TozMK IyRjXk9k1CJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaloNUgAKCRAADmhBGVaC FU8uD/4yAbk7kH7iwD00t90nUui3vYucDVC5el057C6SATO8W3IiO4cWoQ4BxPqZMhqoDDVKrvB Du36Y9uzODwbso3zVdVIA5UPcKxLZuzFh2O2o+3kEDfl6kP9sBeQBYHtWeh5DC/8fZS/PX1uWmM 40BZFtH385stIkOufbthXOn3vcZLFks9yDWJaCBOePkTMdDPPi8uMYPdUVgGxKtJU0q+b0io+Ik 3WFaRPbZgppIpNx02H6LKsVyIMeMyeBhCeYgk0zafIDblDBsNCcNd+taNuo60AMRnVSV7EB/JRE hZ8I4puN/+SgNiRRh2mrTim1SeUqgGu2lMwSfL4ZaTRQ9SXcX0VbgvZqEyIYrJyEkjFZrRAEHb4 RYb2/P6//qdt8EfA9gnWe1sGru4vRcHLeP73/Y6dFtF3LD5RD8sARZ4WyXWM0VQNE005SBRfXnm 6hTEZ1s2eVtJxcnGAnXrjyjcg/m6NDWf7jV91aWd5dgAQcVxpO+enQpTCEGj2i9TIpJ9CWX7jYF x0acrJemklO/QD5efZe7Bt8njKvfgzNSOIGZ0VNIr6cXMJE94A2ddCzXpHxm891YeDGvO1DSvpV WhmEYHtCHz8rTOiAaWXaGKIhHeE8iZlNWqlR+6yAmLfCGuvEyO9tk9TgMmJripqnw8RbBUudpLg GfJKCyJDUIe2Law== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 The existing per-procedure call counts live in global svc_version->vs_count[] arrays which are not network-namespace-aware. Add per-netns equivalents in struct svc_stat so the upcoming netlink stats interface can return namespace-scoped statistics. Add a vs_count pointer array to struct svc_stat, along with svc_stat_alloc_counts() and svc_stat_free_counts() helpers to manage per-version percpu call count arrays. Increment the per-net counter alongside the global one in svc_generic_init_request(). Call the alloc/free helpers from nfsd_net_init() and nfsd_net_exit(). Assisted-by: LLM Signed-off-by: Jeff Layton --- fs/nfsd/nfsctl.c | 8 +++++- include/linux/sunrpc/stats.h | 6 +++++ net/sunrpc/svc.c | 62 ++++++++++++++++++++++++++++++++++++++++= ++++ 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 7e1d5a5d6511..ae5a7f1ad917 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -2516,9 +2516,12 @@ static __net_init int nfsd_net_init(struct net *net) =20 memset(&nn->nfsd_svcstats, 0, sizeof(nn->nfsd_svcstats)); nn->nfsd_svcstats.program =3D &nfsd_programs[0]; + retval =3D svc_stat_alloc_counts(&nn->nfsd_svcstats); + if (retval) + goto out_proc_error; if (!nfsd_proc_stat_init(net)) { retval =3D -ENOMEM; - goto out_proc_error; + goto out_svcstats_error; } =20 for (i =3D 0; i < sizeof(nn->nfsd_versions); i++) @@ -2536,6 +2539,8 @@ static __net_init int nfsd_net_init(struct net *net) #endif return 0; =20 +out_svcstats_error: + svc_stat_free_counts(&nn->nfsd_svcstats); out_proc_error: percpu_counter_destroy_many(nn->counter, NFSD_STATS_COUNTERS_NUM); out_repcache_error: @@ -2576,6 +2581,7 @@ static __net_exit void nfsd_net_exit(struct net *net) kfree_sensitive(nn->fh_key); nfsd_net_cb_shutdown(nn); nfsd_proc_stat_shutdown(net); + svc_stat_free_counts(&nn->nfsd_svcstats); percpu_counter_destroy_many(nn->counter, NFSD_STATS_COUNTERS_NUM); nfsd_idmap_shutdown(net); nfsd_export_shutdown(net); diff --git a/include/linux/sunrpc/stats.h b/include/linux/sunrpc/stats.h index 3ce1550d1beb..087ade905e29 100644 --- a/include/linux/sunrpc/stats.h +++ b/include/linux/sunrpc/stats.h @@ -37,9 +37,15 @@ struct svc_stat { rpcbadfmt, rpcbadauth, rpcbadclnt; + + /* Per-version per-procedure call counts (per-cpu, per-netns) */ + unsigned long __percpu **vs_count; }; =20 struct net; +int svc_stat_alloc_counts(struct svc_stat *statp); +void svc_stat_free_counts(struct svc_stat *statp); + #ifdef CONFIG_PROC_FS int rpc_proc_init(struct net *); void rpc_proc_exit(struct net *); diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index d59e078f39d6..aef6406bab65 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -1348,6 +1348,14 @@ svc_generic_init_request(struct svc_rqst *rqstp, /* Bump per-procedure stats counter */ this_cpu_inc(versp->vs_count[rqstp->rq_proc]); =20 + /* Bump per-net per-procedure stats counter */ + if (rqstp->rq_server->sv_stats && + rqstp->rq_server->sv_stats->program =3D=3D progp && + rqstp->rq_server->sv_stats->vs_count && + rqstp->rq_server->sv_stats->vs_count[rqstp->rq_vers]) + this_cpu_inc(rqstp->rq_server->sv_stats->vs_count + [rqstp->rq_vers][rqstp->rq_proc]); + ret->dispatch =3D versp->vs_dispatch; return rpc_success; err_bad_vers: @@ -1359,6 +1367,60 @@ svc_generic_init_request(struct svc_rqst *rqstp, } EXPORT_SYMBOL_GPL(svc_generic_init_request); =20 +/** + * svc_stat_alloc_counts - allocate per-netns per-version call count arrays + * @statp: svc_stat whose vs_count arrays should be allocated + * + * statp->program must be set before calling this. + * + * Returns zero on success, or a negative errno otherwise. + */ +int svc_stat_alloc_counts(struct svc_stat *statp) +{ + struct svc_program *prog =3D statp->program; + unsigned int i; + + statp->vs_count =3D kcalloc(prog->pg_nvers, + sizeof(unsigned long __percpu *), + GFP_KERNEL); + if (!statp->vs_count) + return -ENOMEM; + + for (i =3D 0; i < prog->pg_nvers; i++) { + if (!prog->pg_vers[i]) + continue; + statp->vs_count[i] =3D __alloc_percpu(prog->pg_vers[i]->vs_nproc * + sizeof(unsigned long), + sizeof(unsigned long)); + if (!statp->vs_count[i]) + goto err; + } + return 0; +err: + svc_stat_free_counts(statp); + return -ENOMEM; +} +EXPORT_SYMBOL_GPL(svc_stat_alloc_counts); + +/** + * svc_stat_free_counts - free per-netns per-version call count arrays + * @statp: svc_stat whose vs_count arrays should be freed + */ +void svc_stat_free_counts(struct svc_stat *statp) +{ + struct svc_program *prog =3D statp->program; + unsigned int i; + + if (!statp->vs_count) + return; + + for (i =3D 0; i < prog->pg_nvers; i++) + free_percpu(statp->vs_count[i]); + kfree(statp->vs_count); + statp->vs_count =3D NULL; +} +EXPORT_SYMBOL_GPL(svc_stat_free_counts); + /* * Common routine for processing the RPC request. */ --=20 2.55.0 From nobody Sat Jul 25 05:27:10 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 695D53E92B5; Fri, 17 Jul 2026 11:09:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784286565; cv=none; b=TcFtgC66bezZaN1ThetJr3Yq7OcvoOZfw9FGoYTH2dRbpk8mmQlCY3dNQRUDIHxKH/vKZBQTEteEsBgMRxLbGKioNa0Cm62LdRgyVPsxF4vrh+LZqxqUtj+mWXVVawPx9gT3fkRTepwMrT1w2s4nvliRIpDXVdeRjio+Bd/waaA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784286565; c=relaxed/simple; bh=LgX43C5w6ErEJtn9G9F480eMc9PQ5s0RHgGS80lklNY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ZmQKBPV5pLZCK9Jdz/7KG56KwwC+x5cuUkOu6RqBe1rPBUgLp+dCwaPi116sQoNTpgyHh0Br69dUHoyOxSOk3AclJ1bglyGywP1WlZN1eB8Z9N3r0cfzYRNhFqYqERBL/FtBCqvCvS0W0lOm1rvQj39uAbwq7SoxGkbZ2YyNV50= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QZGbZ3OL; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="QZGbZ3OL" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BFA0B1F00ACA; Fri, 17 Jul 2026 11:09:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784286551; bh=U0eL/g1AAcmWX9GDVXpdXWwHQhg+pyE8z8K4+jPAEoE=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=QZGbZ3OLhNr74SbSk6dqnRx2M6Syi1X2BmnCEqph5yJMZxiMUaJYTnOdUwZtO9/y4 /7ks4UWE6eVmq/Jdcscl7Z36VJqUyrxRVxuxM6LxkOvrAF1tSoFgYnJOs7HRqhScTK n8O/moDqAZeEfz/42XyuifigliZ45GBbKOr/vr3/HgT2GT16UEl4lpa0uUX8wHfTCn 5StcgTgQTxhdPy6xXRPazLKEYU5hw+FmkVnOIKUkz61NMotCUlbbhVDfq+apPlmOaY x9JtddMHi9PLozofyb9t6LkIb3zpMvdhWOC0o4sEjXJiIjc+8uvjO90FaJplsyYNDd UE5FZLedPtqNw== From: Jeff Layton Date: Fri, 17 Jul 2026 07:08:54 -0400 Subject: [PATCH v7 2/6] sunrpc: use per-net counts in svc_seq_show() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260717-exportd-netlink-v7-2-b7ce17b83b60@kernel.org> References: <20260717-exportd-netlink-v7-0-b7ce17b83b60@kernel.org> In-Reply-To: <20260717-exportd-netlink-v7-0-b7ce17b83b60@kernel.org> To: NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey , Chuck Lever Cc: Trond Myklebust , Anna Schumaker , Steve Dickson , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=1024; i=jlayton@kernel.org; h=from:subject:message-id; bh=LgX43C5w6ErEJtn9G9F480eMc9PQ5s0RHgGS80lklNY=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBqWg1SD6uT33Oy6u/qbWQj89M9n1W/lxkpfjcp2 peTvIyjKlWJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaloNUgAKCRAADmhBGVaC FXrdD/9Bd1W90I21ePfUsVPtH+0UdY+e03NcFQG6zn9NTepueFwFqELZIrH4uDwzTrHyt4TW7F7 Jp7IaDdsi7UAvIxpJysvtZHteVg8BpbrO4j8naPpEKLYqjkxHe6pO1/maBeAQlqePhyI+aB+o/B DOluXU5I01areEfQf98ZpimNNo6XeeUiHJN6wEzNQ7r58hr69xT3Cqg+lq/qMO3H8Yd/iPQPDd2 kNQNC3Gxe6WrF2n0YxbNA2tj831dYEhHRtYyOiWzcabcge3jBvJiK7uGsXl0YxsV/g3nhIH/FT1 /xzl4DFaiN7mEjJbRKtTgKNEZqq+ig7E5vxlBalIqLDrUB20DxNQ74v3EVRLV1++WzMkVUCiucT C+HcYCJLwfkJ0r11jEZKe79GloCf+5YSdEcdYXoMsyimOUFqsXLUP2dRZN+4n41TbdMhW06j6Zk oM1zNqq2cOM6RP5L3l7rY4jVWlKUH0/lniExTUQfLfHZXoPdu03W8S1tciabQk4x0TmchmxRyvU 1Sg4k7Lu5OabRC+Qcg75yF1b0qGHT3rQ4cd6TRsTuq0Pc1JU2kD0I0tU7TR3wIKY/XwiHM38KoU RwX+XOkn6LbI0Y4jojTLU3kWfdNBoNUi1/HVZIefR52LSwXqyI5UwW/i1W0fkfntpfE6GfHbMsI YliOPKT/1hA0oRA== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 Update svc_seq_show() to read from the per-netns statp->vs_count[] arrays instead of the global svc_version->vs_count[]. The only caller is nfsd, which always allocates vs_count via svc_stat_alloc_counts() in nfsd_net_init(), so the per-netns arrays are always available. This makes /proc/net/rpc/nfsd report per-network-namespace procedure call counts. Assisted-by: LLM Signed-off-by: Jeff Layton --- net/sunrpc/stats.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c index 7093e18ac26c..d08711bee18e 100644 --- a/net/sunrpc/stats.c +++ b/net/sunrpc/stats.c @@ -108,7 +108,7 @@ void svc_seq_show(struct seq_file *seq, const struct sv= c_stat *statp) for (j =3D 0; j < vers->vs_nproc; j++) { count =3D 0; for_each_possible_cpu(k) - count +=3D per_cpu(vers->vs_count[j], k); + count +=3D per_cpu(statp->vs_count[i][j], k); seq_printf(seq, " %lu", count); } seq_putc(seq, '\n'); --=20 2.55.0 From nobody Sat Jul 25 05:27:10 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 347193F787E; Fri, 17 Jul 2026 11:09:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784286561; cv=none; b=TbSU5IkjAi1+ua3MQElXp/6x35XJ0Qf/qptg60kbohQi8BNNFILJtSvFAcXl7BvH4sSE2yrl5G/5pWO/0jxAtnzmSV1WxA23+Z7zQ7BbFSNmKmvk8HRCjiXgsoCb8dAfdofrMN9NnYaQQL8oH/v9x9ekKv/INeZo1JqnDYRrbmM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784286561; c=relaxed/simple; bh=59tnNmI81A+TE/ri3pJnS4uQdabX+PWqmK4HXTejSio=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ocxRIkQXjFJkkDxn6KrZiR5srmRHcLuqovzOsYARlC3sCi73SeZqEREEqT2Ckp09qZp2YkKDkkmHEJCh7fi7JGhOtVB20Rpgv2N3JsNTpVQ8DHj2Zdv48V3NPni7kumPWfH/8HpZEnWE0oDUmcaNFkjq7WPl/arhswaDR9AQ/YQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RJ68CZux; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="RJ68CZux" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C9CEF1F00A3D; Fri, 17 Jul 2026 11:09:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784286552; bh=qb1GlZisphJPQAbQd86M/SHe8tJzUUNE1J4JJINpITA=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=RJ68CZuxWKw+VU7359fPEB5Vm4q3PIQmShAH5+/k9pKM3W1JVl+QBRkcWjYMp73lh IrKPl8bKCnAk+EwAp6dUhkR2yLkMdB340BKv2AhbkCyJg0CNoO1nZefgNknJcMaArD 3DvPLYGqbN5oZ8fNaANG/v1rAUIlPiu+pOkXMhIC8/XipQHQ8N/zJW9q5hEGLj3EIw S4x+YKg/urNTLUsPgdLM2ZZvaYwTLgAxPn08TFeyUeORyJKYFION1PYP0NokicWvFZ jxAl8WP0sj8wsOIQMDPeX2ym3ohI7W8SAlL+q7CvpDq0o0n/h2lspN01p0c4UZrX+V 6K8tbBeWwlL5A== From: Jeff Layton Date: Fri, 17 Jul 2026 07:08:55 -0400 Subject: [PATCH v7 3/6] nfsd: implement server-stats-get netlink handler Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260717-exportd-netlink-v7-3-b7ce17b83b60@kernel.org> References: <20260717-exportd-netlink-v7-0-b7ce17b83b60@kernel.org> In-Reply-To: <20260717-exportd-netlink-v7-0-b7ce17b83b60@kernel.org> To: NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey , Chuck Lever Cc: Trond Myklebust , Anna Schumaker , Steve Dickson , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=14529; i=jlayton@kernel.org; h=from:subject:message-id; bh=59tnNmI81A+TE/ri3pJnS4uQdabX+PWqmK4HXTejSio=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBqWg1TG/kIsAgi+zgk9UE9UKtOeg960vrYEyS9n cBTvqN0NFWJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaloNUwAKCRAADmhBGVaC FdhfD/sG0Lbmrs7w47m1wfxaniwnnoN1Y7gbnIZgROv4I4rGrsQc8GVCbfY4g9yaM/QrW85pUdf R8DQckdsWdJQOo1xHWJCcdxDRNqH59l7XpGTPzXKYRDs5YU/BpUU5pofNUinL1oUDlqpUFZT3Ii 26+ztMk8By/hOsSbLv0ul6P/XZmoCJJv1JV9ro1pOv9JnaCKXbivTdlfLYITtAzMmlWKeUIhZwg 4O8zoS4xTd39LISvscxb9/h0nwuFbLb4lh82ib6iMRPVPGR+822bB02eSngYVhzmeZS0wkunVLE HvkBsp96a03sgooJeZS5Jt31dm+F/j2Tat3UyrRJrcdYOv6Q96VgUNSAmEC9yYxLN0CKveRSsIm wgtsbmEUX7vsirCoDbVoEkCP/0pMn7zO795XzWO8t2LquaeR+bA8AmW4YowFY0fuvLb4j3rr/MN tAJ06gGWVFfHQfAd2F4f/YmL9Wbo2jO3pmBEg5H0gGRDSFTC57rSx8Ggv3hO7CQve1yPHz4DOnx uTwZMrIUm0FnF7V8GH55Ckd32XR8W18T1Vns7Rfdgy/PlubMFrKRFDF6qjDd4GTs6x3dmZougqg YnpHbcnuWQQpNggNH+PNjPA/aR58REG9cuegE/7lgNDsz/0jm9qvCezdNyuYXHCKOuQb4C5xchW w20bIocEmh8bcxw== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 Implement nfsd_nl_server_stats_get_dumpit() which exposes the NFS server statistics currently available via /proc/net/rpc/nfsd through the nfsd generic netlink family. The handler uses a dump operation to stream statistics across one or more netlink messages. The reply is divided into sections that are emitted in order: - scalar stats (reply cache, filehandle, IO, network, RPC), emitted once in the first message, then - per-version procedure counts (proc2/3/4-ops) and the NFSv4 per-operation counts (proc4ops-ops), using the per-netns vs_count arrays. cb->args[0] tracks the current section and cb->args[1] the entry index within it, so a section that does not fit in the current message is closed and resumed in the next one. This matters because the first dump message is allocated at NLMSG_GOODSIZE (a single page on most architectures) regardless of the client's receive buffer; packing every counter into one message would overflow it and fail the dump with -EMSGSIZE. Userspace merges the attributes from every message. This allows nfsstat to retrieve server statistics via netlink with a procfs fallback for older kernels. Assisted-by: LLM Signed-off-by: Jeff Layton --- Documentation/netlink/specs/nfsd.yaml | 105 ++++++++++++++++ fs/nfsd/netlink.c | 5 + fs/nfsd/netlink.h | 2 + fs/nfsd/nfsctl.c | 222 ++++++++++++++++++++++++++++++= ++++ include/uapi/linux/nfsd_netlink.h | 35 ++++++ 5 files changed, 369 insertions(+) diff --git a/Documentation/netlink/specs/nfsd.yaml b/Documentation/netlink/= specs/nfsd.yaml index 8f36fadd68f7..2a89d355ee7b 100644 --- a/Documentation/netlink/specs/nfsd.yaml +++ b/Documentation/netlink/specs/nfsd.yaml @@ -330,6 +330,86 @@ attribute-sets: of which client holds the state. Intended for use after all clients have been unexported from a given path, enabling the underlying filesystem to be unmounted. + - + name: server-proc-entry + attributes: + - + name: op + type: u32 + - + name: count + type: u64 + - + name: pad + type: pad + - + name: server-stats + attributes: + - + name: rc-hits + type: u64 + - + name: rc-misses + type: u64 + - + name: rc-nocache + type: u64 + - + name: pad + type: pad + - + name: fh-stale + type: u64 + - + name: io-read + type: u64 + - + name: io-write + type: u64 + - + name: netcnt + type: u32 + - + name: netudpcnt + type: u32 + - + name: nettcpcnt + type: u32 + - + name: nettcpconn + type: u32 + - + name: rpccnt + type: u32 + - + name: rpcbadfmt + type: u32 + - + name: rpcbadauth + type: u32 + - + name: rpcbadclnt + type: u32 + - + name: proc2-ops + type: nest + nested-attributes: server-proc-entry + multi-attr: true + - + name: proc3-ops + type: nest + nested-attributes: server-proc-entry + multi-attr: true + - + name: proc4-ops + type: nest + nested-attributes: server-proc-entry + multi-attr: true + - + name: proc4ops-ops + type: nest + nested-attributes: server-proc-entry + multi-attr: true =20 operations: list: @@ -516,6 +596,31 @@ operations: request: attributes: - path + - + name: server-stats-get + doc: dump NFS server statistics + attribute-set: server-stats + dump: + reply: + attributes: + - rc-hits + - rc-misses + - rc-nocache + - fh-stale + - io-read + - io-write + - netcnt + - netudpcnt + - nettcpcnt + - nettcpconn + - rpccnt + - rpcbadfmt + - rpcbadauth + - rpcbadclnt + - proc2-ops + - proc3-ops + - proc4-ops + - proc4ops-ops =20 mcast-groups: list: diff --git a/fs/nfsd/netlink.c b/fs/nfsd/netlink.c index fbee3676d253..eba8b353f412 100644 --- a/fs/nfsd/netlink.c +++ b/fs/nfsd/netlink.c @@ -225,6 +225,11 @@ static const struct genl_split_ops nfsd_nl_ops[] =3D { .maxattr =3D NFSD_A_UNLOCK_EXPORT_PATH, .flags =3D GENL_ADMIN_PERM | GENL_CMD_CAP_DO, }, + { + .cmd =3D NFSD_CMD_SERVER_STATS_GET, + .dumpit =3D nfsd_nl_server_stats_get_dumpit, + .flags =3D GENL_CMD_CAP_DUMP, + }, }; =20 static const struct genl_multicast_group nfsd_nl_mcgrps[] =3D { diff --git a/fs/nfsd/netlink.h b/fs/nfsd/netlink.h index af41aa0d4a65..027e2953db26 100644 --- a/fs/nfsd/netlink.h +++ b/fs/nfsd/netlink.h @@ -42,6 +42,8 @@ int nfsd_nl_cache_flush_doit(struct sk_buff *skb, struct = genl_info *info); int nfsd_nl_unlock_ip_doit(struct sk_buff *skb, struct genl_info *info); int nfsd_nl_unlock_filesystem_doit(struct sk_buff *skb, struct genl_info *= info); int nfsd_nl_unlock_export_doit(struct sk_buff *skb, struct genl_info *info= ); +int nfsd_nl_server_stats_get_dumpit(struct sk_buff *skb, + struct netlink_callback *cb); =20 enum { NFSD_NLGRP_NONE, diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index ae5a7f1ad917..7731051105c9 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -2331,6 +2331,228 @@ int nfsd_nl_cache_flush_doit(struct sk_buff *skb, s= truct genl_info *info) return 0; } =20 +/* Emit a single server-proc-entry nest: { op, count }. */ +static int nfsd_nl_put_proc_entry(struct sk_buff *skb, int attr, + u32 op, u64 count) +{ + struct nlattr *nest; + + nest =3D nla_nest_start(skb, attr); + if (!nest) + return -EMSGSIZE; + if (nla_put_u32(skb, NFSD_A_SERVER_PROC_ENTRY_OP, op) || + nla_put_u64_64bit(skb, NFSD_A_SERVER_PROC_ENTRY_COUNT, + count, NFSD_A_SERVER_PROC_ENTRY_PAD)) { + nla_nest_cancel(skb, nest); + return -EMSGSIZE; + } + nla_nest_end(skb, nest); + return 0; +} + +/* Emit the scalar server-stats counters. Only ever called on a fresh skb.= */ +static int nfsd_nl_server_stats_scalars(struct sk_buff *skb, + struct nfsd_net *nn, + struct svc_stat *statp) +{ + if (nla_put_u64_64bit(skb, NFSD_A_SERVER_STATS_RC_HITS, + percpu_counter_sum_positive(&nn->counter[NFSD_STATS_RC_HITS]), + NFSD_A_SERVER_STATS_PAD) || + nla_put_u64_64bit(skb, NFSD_A_SERVER_STATS_RC_MISSES, + percpu_counter_sum_positive(&nn->counter[NFSD_STATS_RC_MISSES]), + NFSD_A_SERVER_STATS_PAD) || + nla_put_u64_64bit(skb, NFSD_A_SERVER_STATS_RC_NOCACHE, + percpu_counter_sum_positive(&nn->counter[NFSD_STATS_RC_NOCACHE]), + NFSD_A_SERVER_STATS_PAD)) + return -EMSGSIZE; + + if (nla_put_u64_64bit(skb, NFSD_A_SERVER_STATS_FH_STALE, + percpu_counter_sum_positive(&nn->counter[NFSD_STATS_FH_STALE]), + NFSD_A_SERVER_STATS_PAD)) + return -EMSGSIZE; + + if (nla_put_u64_64bit(skb, NFSD_A_SERVER_STATS_IO_READ, + percpu_counter_sum_positive(&nn->counter[NFSD_STATS_IO_READ]), + NFSD_A_SERVER_STATS_PAD) || + nla_put_u64_64bit(skb, NFSD_A_SERVER_STATS_IO_WRITE, + percpu_counter_sum_positive(&nn->counter[NFSD_STATS_IO_WRITE]), + NFSD_A_SERVER_STATS_PAD)) + return -EMSGSIZE; + + if (nla_put_u32(skb, NFSD_A_SERVER_STATS_NETCNT, statp->netcnt) || + nla_put_u32(skb, NFSD_A_SERVER_STATS_NETUDPCNT, statp->netudpcnt) || + nla_put_u32(skb, NFSD_A_SERVER_STATS_NETTCPCNT, statp->nettcpcnt) || + nla_put_u32(skb, NFSD_A_SERVER_STATS_NETTCPCONN, statp->nettcpconn)) + return -EMSGSIZE; + + if (nla_put_u32(skb, NFSD_A_SERVER_STATS_RPCCNT, statp->rpccnt) || + nla_put_u32(skb, NFSD_A_SERVER_STATS_RPCBADFMT, statp->rpcbadfmt) || + nla_put_u32(skb, NFSD_A_SERVER_STATS_RPCBADAUTH, statp->rpcbadauth) || + nla_put_u32(skb, NFSD_A_SERVER_STATS_RPCBADCLNT, statp->rpcbadclnt)) + return -EMSGSIZE; + + return 0; +} + +/* + * Emit per-version procedure counts for one NFS version, resuming at *idx. + * Returns 0 when the version has been fully emitted (or is not present), = or + * -EMSGSIZE when @skb filled up, leaving *idx at the entry still to emit. + */ +static int nfsd_nl_server_stats_proc(struct sk_buff *skb, + struct svc_stat *statp, + struct svc_program *prog, + unsigned int ver, int attr, int *idx) +{ + unsigned long __percpu *counts; + unsigned int nproc; + + if (!statp->vs_count || ver >=3D prog->pg_nvers || + !prog->pg_vers[ver] || !statp->vs_count[ver]) + return 0; + + counts =3D statp->vs_count[ver]; + nproc =3D prog->pg_vers[ver]->vs_nproc; + + for (; *idx < nproc; (*idx)++) { + unsigned long count =3D 0; + int cpu; + + for_each_possible_cpu(cpu) + count +=3D per_cpu(counts[*idx], cpu); + + if (!count) + continue; + if (nfsd_nl_put_proc_entry(skb, attr, *idx, count)) + return -EMSGSIZE; + } + + return 0; +} + +#ifdef CONFIG_NFSD_V4 +/* + * Emit NFSv4 per-operation counts, resuming at *idx. Same return conventi= on + * as nfsd_nl_server_stats_proc(). + */ +static int nfsd_nl_server_stats_nfs4ops(struct sk_buff *skb, + struct nfsd_net *nn, int *idx) +{ + for (; *idx <=3D LAST_NFS4_OP; (*idx)++) { + u64 cnt =3D percpu_counter_sum_positive( + &nn->counter[NFSD_STATS_NFS4_OP(*idx)]); + + if (!cnt) + continue; + if (nfsd_nl_put_proc_entry(skb, NFSD_A_SERVER_STATS_PROC4OPS_OPS, + *idx, cnt)) + return -EMSGSIZE; + } + + return 0; +} +#endif + +/* Sections of the server-stats dump, emitted in order across messages. */ +enum { + NFSD_SERVER_STATS_SCALARS =3D 0, + NFSD_SERVER_STATS_PROC2, + NFSD_SERVER_STATS_PROC3, + NFSD_SERVER_STATS_PROC4, + NFSD_SERVER_STATS_PROC4OPS, + NFSD_SERVER_STATS_DONE, +}; + +/** + * nfsd_nl_server_stats_get_dumpit - dump NFS server statistics + * @skb: reply buffer + * @cb: netlink metadata and command arguments + * + * The server-stats object is emitted across one or more netlink messages. + * cb->args[0] tracks the current section and cb->args[1] the entry index + * within it, so a section that does not fit in the current message is res= umed + * in the next one. The scalar counters are small and emitted once, in the + * first message; userspace merges the attributes from every message. + * + * Returns the size of the reply or a negative errno. + */ +int nfsd_nl_server_stats_get_dumpit(struct sk_buff *skb, + struct netlink_callback *cb) +{ + struct net *net =3D sock_net(skb->sk); + struct nfsd_net *nn =3D net_generic(net, nfsd_net_id); + struct svc_stat *statp =3D &nn->nfsd_svcstats; + struct svc_program *prog =3D statp->program; + int section =3D cb->args[0]; + int idx =3D cb->args[1]; + void *hdr; + + if (section >=3D NFSD_SERVER_STATS_DONE) + return 0; + + hdr =3D genlmsg_put(skb, NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, &nfsd_nl_family, + NLM_F_MULTI, NFSD_CMD_SERVER_STATS_GET); + if (!hdr) + return -ENOBUFS; + + /* Scalar stats fit easily and are emitted in the first message. */ + if (section =3D=3D NFSD_SERVER_STATS_SCALARS) { + if (nfsd_nl_server_stats_scalars(skb, nn, statp)) + goto err_cancel; + section =3D NFSD_SERVER_STATS_PROC2; + idx =3D 0; + } + + /* + * Emit as many of the remaining sections as fit. A section returning + * -EMSGSIZE means the message is full: close it and resume from the + * same section/index on the next call with a fresh skb. Each entry is + * small enough to fit in a fresh skb, so forward progress is assured. + */ + while (section < NFSD_SERVER_STATS_DONE) { + int ret =3D 0; + + switch (section) { + case NFSD_SERVER_STATS_PROC2: + ret =3D nfsd_nl_server_stats_proc(skb, statp, prog, 2, + NFSD_A_SERVER_STATS_PROC2_OPS, &idx); + break; + case NFSD_SERVER_STATS_PROC3: + ret =3D nfsd_nl_server_stats_proc(skb, statp, prog, 3, + NFSD_A_SERVER_STATS_PROC3_OPS, &idx); + break; + case NFSD_SERVER_STATS_PROC4: + ret =3D nfsd_nl_server_stats_proc(skb, statp, prog, 4, + NFSD_A_SERVER_STATS_PROC4_OPS, &idx); + break; +#ifdef CONFIG_NFSD_V4 + case NFSD_SERVER_STATS_PROC4OPS: + ret =3D nfsd_nl_server_stats_nfs4ops(skb, nn, &idx); + break; +#endif + } + + if (ret =3D=3D -EMSGSIZE) + goto out; + if (ret) + goto err_cancel; + + section++; + idx =3D 0; + } + +out: + genlmsg_end(skb, hdr); + cb->args[0] =3D section; + cb->args[1] =3D idx; + return skb->len; + +err_cancel: + genlmsg_cancel(skb, hdr); + return -EMSGSIZE; +} + int nfsd_cache_notify(struct cache_detail *cd, struct cache_head *h, u32 c= ache_type) { struct genlmsghdr *hdr; diff --git a/include/uapi/linux/nfsd_netlink.h b/include/uapi/linux/nfsd_ne= tlink.h index f5b75d5caba9..3d076d173b1d 100644 --- a/include/uapi/linux/nfsd_netlink.h +++ b/include/uapi/linux/nfsd_netlink.h @@ -225,6 +225,40 @@ enum { NFSD_A_UNLOCK_EXPORT_MAX =3D (__NFSD_A_UNLOCK_EXPORT_MAX - 1) }; =20 +enum { + NFSD_A_SERVER_PROC_ENTRY_OP =3D 1, + NFSD_A_SERVER_PROC_ENTRY_COUNT, + NFSD_A_SERVER_PROC_ENTRY_PAD, + + __NFSD_A_SERVER_PROC_ENTRY_MAX, + NFSD_A_SERVER_PROC_ENTRY_MAX =3D (__NFSD_A_SERVER_PROC_ENTRY_MAX - 1) +}; + +enum { + NFSD_A_SERVER_STATS_RC_HITS =3D 1, + NFSD_A_SERVER_STATS_RC_MISSES, + NFSD_A_SERVER_STATS_RC_NOCACHE, + NFSD_A_SERVER_STATS_PAD, + NFSD_A_SERVER_STATS_FH_STALE, + NFSD_A_SERVER_STATS_IO_READ, + NFSD_A_SERVER_STATS_IO_WRITE, + NFSD_A_SERVER_STATS_NETCNT, + NFSD_A_SERVER_STATS_NETUDPCNT, + NFSD_A_SERVER_STATS_NETTCPCNT, + NFSD_A_SERVER_STATS_NETTCPCONN, + NFSD_A_SERVER_STATS_RPCCNT, + NFSD_A_SERVER_STATS_RPCBADFMT, + NFSD_A_SERVER_STATS_RPCBADAUTH, + NFSD_A_SERVER_STATS_RPCBADCLNT, + NFSD_A_SERVER_STATS_PROC2_OPS, + NFSD_A_SERVER_STATS_PROC3_OPS, + NFSD_A_SERVER_STATS_PROC4_OPS, + NFSD_A_SERVER_STATS_PROC4OPS_OPS, + + __NFSD_A_SERVER_STATS_MAX, + NFSD_A_SERVER_STATS_MAX =3D (__NFSD_A_SERVER_STATS_MAX - 1) +}; + enum { NFSD_CMD_RPC_STATUS_GET =3D 1, NFSD_CMD_THREADS_SET, @@ -244,6 +278,7 @@ enum { NFSD_CMD_UNLOCK_IP, NFSD_CMD_UNLOCK_FILESYSTEM, NFSD_CMD_UNLOCK_EXPORT, + NFSD_CMD_SERVER_STATS_GET, =20 __NFSD_CMD_MAX, NFSD_CMD_MAX =3D (__NFSD_CMD_MAX - 1) --=20 2.55.0 From nobody Sat Jul 25 05:27:10 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2228A3F12FF; Fri, 17 Jul 2026 11:09:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784286568; cv=none; b=FrKEDYzC9Ae2TowokH7RUgaSlFZXOJyDd+8MxpBVk3oGRf62B0sA6R1h84LeTaR2OK2m8zb7KkHt2EbXzUJNh7L8azinpeQW3glFu6cHKBL5cYGyV8ZWBU8Hyrzr7/w+2RGHHZVimnzHQZDjSGGicYTQ0ppO5cb8utdL6uzpy3I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784286568; c=relaxed/simple; bh=t+edDh7vC6y6C+llhD2v9/sleK0nVagF/WTYzlvlGQ8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=CcIFypT4l72v2G5OnvKHUDeHiSUrMa7Hv/GoBrnd5zAdADOIPpV3cpJmG/Jcmh1amIox+ZKvBzZQi0lqD6naw9rqeL1FUw1R2u/IhVK3QP9a/eewYpj3AWNY14osPxnUga9m3Cqpd5npzzpqHzbC/FMStZ/R/jS4mh6ZtjNQlZI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=DQhI6k8p; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="DQhI6k8p" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E4C151F00ADB; Fri, 17 Jul 2026 11:09:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784286553; bh=k6RYcfGZkUX2Hqij4QyKPo896OF6IKWI93y/j5tfSJc=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=DQhI6k8pTlpgp03PQWSt5MY2WCMpCULvWdg6kKKn5ZJpMsDEIXxeb0cZxz5Hl5mWN +NW7K4eA3CtSPOU4CW2eBUNcKbp1k0Bumzb5cUjrPXQCBGmyEIWtg7hNYGFMGw2Ylr z7X9gpAVQ14M1mbvpUzQOZD0tglQ48J439fJncxdmZODE+ztPcHrewd4c6Dz5dF6/0 ZT2Jbweg/JxDUmsvFrY+PrCizKfYfTRXycrj22/071CeUZQxr9heLo9zaqcglLZ1Pz Klgt5wsJy0ASraxWgnnyxiYo2jm2iuhAOJ6yr/TJPmhFPMxts3UIK4jRROlZ0KbByx rA2nkJ0Hl2X9w== From: Jeff Layton Date: Fri, 17 Jul 2026 07:08:56 -0400 Subject: [PATCH v7 4/6] sunrpc: remove unused svc_version vs_count field Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260717-exportd-netlink-v7-4-b7ce17b83b60@kernel.org> References: <20260717-exportd-netlink-v7-0-b7ce17b83b60@kernel.org> In-Reply-To: <20260717-exportd-netlink-v7-0-b7ce17b83b60@kernel.org> To: NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey , Chuck Lever Cc: Trond Myklebust , Anna Schumaker , Steve Dickson , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=8466; i=jlayton@kernel.org; h=from:subject:message-id; bh=t+edDh7vC6y6C+llhD2v9/sleK0nVagF/WTYzlvlGQ8=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBqWg1TkZUKTx1UlDjWh25zKGxtxo/eEJgFhgH1L kc/s9b2EpOJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaloNUwAKCRAADmhBGVaC Fd6LEACTNhDnB+dXW5yfHsShP0N7/gNKHw7WlcUoetkk9lB2viCxvzJL1gLoc9fnIZDjCUUn7GD cZSQeQv6tgFQcca0jVCgeDLdD+ZnQnx4Q+Ju+3abMlt9ElgPqDohjm66Zgiq2A4DUCJOp+hQERS 3fi5RiU0zxKVgQRJ1sCkeG1od+NH0QUwyYRBCF8Ord3MN1+GWaN5J6ct57EQdFg0IfNPgM5elxT w4RUNz9+CYvw2AJk1gcgbsCtf6uDvzKxON2SKZDm5XOkXQDuf7PUC1DPxp/YdccdjlQP4YOKxC1 +N61go741o4KIp9sKIYtOjEO6803dhqsUYYcZoz4kCrZw1XF+bonBRgw1qulXEyxpFmzhku+xcZ Kzx39hA1xHJ/9XptcDik3C/FNOVb4JcFeiwpL2V2J4LfLO07ylwzQjlnZiSPjfMBGa6tF7kNk0W Wp9GXUAr/Ooc1fTVLKTCoe+ZMqbX8XOIRpxEsPg1a93XT8P9Z+owlj8ojj3rjirwcCHvAK8alUY Gil1jo3SuG2magSoPxbAqiWBPM1D8V48VKtTvrJ7pygrhxf3re3rG+x+UmmS6/0IflOCjk8RbCa 0Nvz1+VO7J+NVJP/I4s0TqTcjTpKt26002CgeF30bdCFo8qH12UUmilgHfjvuKHNjPKoLKBw+xo XIjBGGFDXN1q0EQ== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 Now that svc_seq_show() and the nfsd netlink stats handler both use the per-netns svc_stat vs_count arrays, the global per-version vs_count percpu counters are no longer read by anything. Remove the vs_count field from struct svc_version and all the associated DEFINE_PER_CPU_ALIGNED arrays and initializers across nfsd, lockd, and the NFS client callback service. Assisted-by: LLM Signed-off-by: Jeff Layton --- fs/lockd/svc4proc.c | 4 ---- fs/lockd/svcproc.c | 7 ------- fs/nfs/callback_xdr.c | 6 ------ fs/nfsd/localio.c | 3 --- fs/nfsd/nfs2acl.c | 3 --- fs/nfsd/nfs3acl.c | 3 --- fs/nfsd/nfs3proc.c | 3 --- fs/nfsd/nfs4proc.c | 3 --- fs/nfsd/nfsproc.c | 3 --- include/linux/sunrpc/svc.h | 1 - net/sunrpc/svc.c | 3 --- 11 files changed, 39 deletions(-) diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c index 5a70dbe9c6a4..03c5554ca579 100644 --- a/fs/lockd/svc4proc.c +++ b/fs/lockd/svc4proc.c @@ -1423,14 +1423,10 @@ union nlm4svc_xdrstore { struct nlm4_shareres_wrapper shareres; }; =20 -static DEFINE_PER_CPU_ALIGNED(unsigned long, - nlm4svc_call_counters[ARRAY_SIZE(nlm4svc_procedures)]); - const struct svc_version nlmsvc_version4 =3D { .vs_vers =3D 4, .vs_nproc =3D ARRAY_SIZE(nlm4svc_procedures), .vs_proc =3D nlm4svc_procedures, - .vs_count =3D nlm4svc_call_counters, .vs_dispatch =3D nlmsvc_dispatch, .vs_xdrsize =3D sizeof(union nlm4svc_xdrstore), }; diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index 7ba628939cff..a8b5195c2c6b 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c @@ -1436,25 +1436,18 @@ union nlmsvc_xdrstore { * NLMv1 defines only procedures 1 - 15. Linux lockd also implements * procedures 0 (NULL) and 16 (SM_NOTIFY). */ -static DEFINE_PER_CPU_ALIGNED(unsigned long, nlm1svc_call_counters[17]); - const struct svc_version nlmsvc_version1 =3D { .vs_vers =3D 1, .vs_nproc =3D 17, .vs_proc =3D nlmsvc_procedures, - .vs_count =3D nlm1svc_call_counters, .vs_dispatch =3D nlmsvc_dispatch, .vs_xdrsize =3D sizeof(union nlmsvc_xdrstore), }; =20 -static DEFINE_PER_CPU_ALIGNED(unsigned long, - nlm3svc_call_counters[ARRAY_SIZE(nlmsvc_procedures)]); - const struct svc_version nlmsvc_version3 =3D { .vs_vers =3D 3, .vs_nproc =3D ARRAY_SIZE(nlmsvc_procedures), .vs_proc =3D nlmsvc_procedures, - .vs_count =3D nlm3svc_call_counters, .vs_dispatch =3D nlmsvc_dispatch, .vs_xdrsize =3D sizeof(union nlmsvc_xdrstore), }; diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c index 4382baddc9ee..eec6040556c9 100644 --- a/fs/nfs/callback_xdr.c +++ b/fs/nfs/callback_xdr.c @@ -1090,26 +1090,20 @@ static const struct svc_procedure nfs4_callback_pro= cedures1[] =3D { } }; =20 -static DEFINE_PER_CPU_ALIGNED(unsigned long, - nfs4_callback_count1[ARRAY_SIZE(nfs4_callback_procedures1)]); const struct svc_version nfs4_callback_version1 =3D { .vs_vers =3D 1, .vs_nproc =3D ARRAY_SIZE(nfs4_callback_procedures1), .vs_proc =3D nfs4_callback_procedures1, - .vs_count =3D nfs4_callback_count1, .vs_xdrsize =3D NFS4_CALLBACK_XDRSIZE, .vs_dispatch =3D nfs_callback_dispatch, .vs_hidden =3D true, .vs_need_cong_ctrl =3D true, }; =20 -static DEFINE_PER_CPU_ALIGNED(unsigned long, - nfs4_callback_count4[ARRAY_SIZE(nfs4_callback_procedures1)]); const struct svc_version nfs4_callback_version4 =3D { .vs_vers =3D 4, .vs_nproc =3D ARRAY_SIZE(nfs4_callback_procedures1), .vs_proc =3D nfs4_callback_procedures1, - .vs_count =3D nfs4_callback_count4, .vs_xdrsize =3D NFS4_CALLBACK_XDRSIZE, .vs_dispatch =3D nfs_callback_dispatch, .vs_hidden =3D true, diff --git a/fs/nfsd/localio.c b/fs/nfsd/localio.c index c3eb0557b3e1..c458c01e9478 100644 --- a/fs/nfsd/localio.c +++ b/fs/nfsd/localio.c @@ -210,14 +210,11 @@ static const struct svc_procedure localio_procedures1= [] =3D { }; =20 #define LOCALIO_NR_PROCEDURES ARRAY_SIZE(localio_procedures1) -static DEFINE_PER_CPU_ALIGNED(unsigned long, - localio_count[LOCALIO_NR_PROCEDURES]); const struct svc_version localio_version1 =3D { .vs_vers =3D 1, .vs_nproc =3D LOCALIO_NR_PROCEDURES, .vs_proc =3D localio_procedures1, .vs_dispatch =3D nfsd_dispatch, - .vs_count =3D localio_count, .vs_xdrsize =3D XDR_QUADLEN(UUID_SIZE), .vs_hidden =3D true, }; diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c index 2998640f259d..190f5a001900 100644 --- a/fs/nfsd/nfs2acl.c +++ b/fs/nfsd/nfs2acl.c @@ -388,13 +388,10 @@ static const struct svc_procedure nfsd_acl_procedures= 2[5] =3D { }, }; =20 -static DEFINE_PER_CPU_ALIGNED(unsigned long, - nfsd_acl_count2[ARRAY_SIZE(nfsd_acl_procedures2)]); const struct svc_version nfsd_acl_version2 =3D { .vs_vers =3D 2, .vs_nproc =3D ARRAY_SIZE(nfsd_acl_procedures2), .vs_proc =3D nfsd_acl_procedures2, - .vs_count =3D nfsd_acl_count2, .vs_dispatch =3D nfsd_dispatch, .vs_xdrsize =3D NFS3_SVC_XDRSIZE, }; diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c index a87f9d7f32be..6b6b289db636 100644 --- a/fs/nfsd/nfs3acl.c +++ b/fs/nfsd/nfs3acl.c @@ -278,13 +278,10 @@ static const struct svc_procedure nfsd_acl_procedures= 3[3] =3D { }, }; =20 -static DEFINE_PER_CPU_ALIGNED(unsigned long, - nfsd_acl_count3[ARRAY_SIZE(nfsd_acl_procedures3)]); const struct svc_version nfsd_acl_version3 =3D { .vs_vers =3D 3, .vs_nproc =3D ARRAY_SIZE(nfsd_acl_procedures3), .vs_proc =3D nfsd_acl_procedures3, - .vs_count =3D nfsd_acl_count3, .vs_dispatch =3D nfsd_dispatch, .vs_xdrsize =3D NFS3_SVC_XDRSIZE, }; diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c index bbaef884f893..0904d953d10e 100644 --- a/fs/nfsd/nfs3proc.c +++ b/fs/nfsd/nfs3proc.c @@ -1108,13 +1108,10 @@ static const struct svc_procedure nfsd_procedures3[= 22] =3D { }, }; =20 -static DEFINE_PER_CPU_ALIGNED(unsigned long, - nfsd_count3[ARRAY_SIZE(nfsd_procedures3)]); const struct svc_version nfsd_version3 =3D { .vs_vers =3D 3, .vs_nproc =3D ARRAY_SIZE(nfsd_procedures3), .vs_proc =3D nfsd_procedures3, .vs_dispatch =3D nfsd_dispatch, - .vs_count =3D nfsd_count3, .vs_xdrsize =3D NFS3_SVC_XDRSIZE, }; diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 13292f38cf3d..50c07561e31f 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -4262,13 +4262,10 @@ static const struct svc_procedure nfsd_procedures4[= 2] =3D { }, }; =20 -static DEFINE_PER_CPU_ALIGNED(unsigned long, - nfsd_count4[ARRAY_SIZE(nfsd_procedures4)]); const struct svc_version nfsd_version4 =3D { .vs_vers =3D 4, .vs_nproc =3D ARRAY_SIZE(nfsd_procedures4), .vs_proc =3D nfsd_procedures4, - .vs_count =3D nfsd_count4, .vs_dispatch =3D nfsd_dispatch, .vs_xdrsize =3D NFS4_SVC_XDRSIZE, .vs_rpcb_optnl =3D true, diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index f60043632575..e2b5f8a241be 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c @@ -845,13 +845,10 @@ static const struct svc_procedure nfsd_procedures2[18= ] =3D { }, }; =20 -static DEFINE_PER_CPU_ALIGNED(unsigned long, - nfsd_count2[ARRAY_SIZE(nfsd_procedures2)]); const struct svc_version nfsd_version2 =3D { .vs_vers =3D 2, .vs_nproc =3D ARRAY_SIZE(nfsd_procedures2), .vs_proc =3D nfsd_procedures2, - .vs_count =3D nfsd_count2, .vs_dispatch =3D nfsd_dispatch, .vs_xdrsize =3D NFS2_SVC_XDRSIZE, }; diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 3c885ab6ad41..2db1b9ec5658 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -407,7 +407,6 @@ struct svc_version { u32 vs_vers; /* version number */ u32 vs_nproc; /* number of procedures */ const struct svc_procedure *vs_proc; /* per-procedure info */ - unsigned long __percpu *vs_count; /* call counts */ u32 vs_xdrsize; /* xdrsize needed for this version */ =20 /* Don't register with rpcbind */ diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index aef6406bab65..53c6a42d7f45 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -1345,9 +1345,6 @@ svc_generic_init_request(struct svc_rqst *rqstp, memset(rqstp->rq_argp, 0, procp->pc_argzero); memset(rqstp->rq_resp, 0, procp->pc_ressize); =20 - /* Bump per-procedure stats counter */ - this_cpu_inc(versp->vs_count[rqstp->rq_proc]); - /* Bump per-net per-procedure stats counter */ if (rqstp->rq_server->sv_stats && rqstp->rq_server->sv_stats->program =3D=3D progp && --=20 2.55.0 From nobody Sat Jul 25 05:27:10 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CE29C3F7A84; Fri, 17 Jul 2026 11:09:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784286569; cv=none; b=ZfYi5YKTwte4tzHvxHIFC23yf8GbA6avUv413Dy9PrZ/b3xEse2MAf7mBzx9ONSzwq4ZRbjCbvfwXf6eMcbS40KVtny2fr82DeQbktETDyrL/wj2hlG78iV52L0dWXZFXLonfrjKNBw8h0L2p7QIkzHa9Wg1DG92aBZbIufHZZU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784286569; c=relaxed/simple; bh=94d9mX1D850XINaow+l8oCCpvB+Sgb1At8dp3vkNX4I=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=DmyP6GG9xcEw4sGHCpD3w+LouOtaLFcEY9YHRM++TlHPkDA70GkZmD4kImGSYYNFDmyYB0avwwCtCN0f7iX7vBzadNUm7oQcHCdx/u2gWFESQEP3oz0q/KVQSQs0jkjy7eoNi/quTL2nYHX3K/TIANLzzxexiLAj3e1hRH0LNz8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=MHvY5tdG; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="MHvY5tdG" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EDF9B1F00A3F; Fri, 17 Jul 2026 11:09:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784286554; bh=RmnOPpqWq+Y2NvO0zZHAQlg+r+KmZLUR8nv7/fBKQMs=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=MHvY5tdG2D/tiM+qEda0oKhIMj+hD79OwJvgcQsbrV5PoQEjQZkS9Hdo4EB7eh22Q RwckhkjtFXqfV6SiV6kyERRbBUV2Xp8xndfowyswmvXMNHv6hCTSX4FV4YraLKTjo7 o2jdqcsbbclVzLvCFRiMyNGpCVjZCVL+B+r07qL/OwJLCti/iv7DAFRy2gvn1ggzcs Ga0uptLQykB9lb3NLWkt2RNLPuI/CDL+YB3FC40MuHm2ubZSFtLQ6PjZ5x4O7QnQFk X/QaWRZ6xL0hvM38GqeFsRSZrzYlsnIAYUumeXkbLVB3HYLSsApUmKS93JCKmhQZaD PBYOor2Y5o+aQ== From: Jeff Layton Date: Fri, 17 Jul 2026 07:08:57 -0400 Subject: [PATCH v7 5/6] nfsd: count NFSv4 callback operations per netns Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260717-exportd-netlink-v7-5-b7ce17b83b60@kernel.org> References: <20260717-exportd-netlink-v7-0-b7ce17b83b60@kernel.org> In-Reply-To: <20260717-exportd-netlink-v7-0-b7ce17b83b60@kernel.org> To: NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey , Chuck Lever Cc: Trond Myklebust , Anna Schumaker , Steve Dickson , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=7453; i=jlayton@kernel.org; h=from:subject:message-id; bh=94d9mX1D850XINaow+l8oCCpvB+Sgb1At8dp3vkNX4I=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBqWg1TLuaNs/5eBM0011Q2lZOVjfIoKYWZqpS99 xIRF39w1E2JAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaloNUwAKCRAADmhBGVaC FYMbD/4l2vFACzBz33TCx+B0gnYIbEsp37qSbFPWlgRdjnQU+2hcW9KbiLQphhGAf6UJSUkOsqI NXvAJxPFbGXF2MvPcny3eJPMQxTAjFdBGF8Ub122UqVzJ03ONklwJabnXNwqCKqFxS4K1jQ9wxw u8NM15KATYRdLeWlalbwlrx7cXNiUR6QbYG7+wYl86htx2VVEaxEO9D0y2mJOd0gsTm5gsLLMeH MCF0DlBbZdfgAocq7ffsm2u587tXPAMA89ZNrr9wLIrxbH6y3nXlKn+JWxLV500657WlbIcBC16 lJle1vy8tnN7caVp2SnjMxKL3MGu10zn47N1PvN3El/TNFXWw8HqESwWa3WijsJ2nro0YUy+Upy EqobUcW9rQko+27ae8jWQ+BvT8QrO6KzT6mgSm7p5G/aTLoq8dMhGkDBiZOo13u3parbIGaVmgd WmioYvOCrD++xBcBHR6UnMxa2Q41TxXTZXsMkTPu4IezI6eFE0pPSuuNkEw0tI8N8gYhgNQaGru jlyw4lo0XHG4WOmAOTFuMRwyj2hmiZHJzbYP1C59LC+ae3URSsNmeo910ULXmg/5XP4PhzPO0V+ Vl7ytyQGXoK9Q6lj0UtHRbcFFpuUGf4IZShOLEd6ktSsdLP2W/CsENPHakPwV6UJvDdRWDT+cI0 qZJVhONHhiVKn1g== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 The NFS server tracks per-operation call counts for the forward channel (proc4ops) but keeps no statistics for the NFSv4 backchannel (callback) operations it sends to clients. Add a per-netns array of percpu counters for callback operations, indexed by RFC 8881 callback opcode (OP_CB_GETATTR..OP_CB_OFFLOAD), and bump the relevant counter in nfsd4_run_cb(), which is hit exactly once per callback that is actually queued. CB_GETATTR is sent when a GETATTR conflicts with an outstanding write delegation, which is roughly what the dedicated wdeleg_getattr counter tracked. The two are not identical: the old counter incremented on every such conflict, whereas the CB_GETATTR counter only counts callbacks that are actually queued, so concurrent conflicts that coalesce onto an already in-flight CB_GETATTR are now counted once rather than once per conflict. Report the procfs "wdeleg_getattr" line from the CB_GETATTR counter and drop the now-redundant NFSD_STATS_WDELEG_GETATTR counter, its helper, and its increment site. Assisted-by: LLM Signed-off-by: Jeff Layton --- fs/nfsd/netns.h | 12 +++++++++++- fs/nfsd/nfs4callback.c | 22 +++++++++++++++++++++- fs/nfsd/nfs4state.c | 2 -- fs/nfsd/nfsctl.c | 14 ++++++++++++++ fs/nfsd/stats.c | 2 +- fs/nfsd/stats.h | 5 +++-- 6 files changed, 50 insertions(+), 7 deletions(-) diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h index a7bd7b67fa4f..71eebfea020d 100644 --- a/fs/nfsd/netns.h +++ b/fs/nfsd/netns.h @@ -53,11 +53,16 @@ enum { NFSD_STATS_FIRST_NFS4_OP, /* count of individual nfsv4 operations */ NFSD_STATS_LAST_NFS4_OP =3D NFSD_STATS_FIRST_NFS4_OP + LAST_NFS4_OP, #define NFSD_STATS_NFS4_OP(op) (NFSD_STATS_FIRST_NFS4_OP + (op)) - NFSD_STATS_WDELEG_GETATTR, /* count of getattr conflict with wdeleg */ #endif NFSD_STATS_COUNTERS_NUM }; =20 +/* + * Per-netns NFSv4 callback (backchannel) per-operation counters, indexed + * directly by RFC 8881 callback opcode (OP_CB_GETATTR..OP_CB_OFFLOAD). + */ +#define NFSD_STATS_CB_OPS_NUM (OP_CB_OFFLOAD + 1) + /* * Represents a nfsd "container". With respect to nfsv4 state tracking, the * fields of interest are the *_id_hashtbls and the *_name_tree. These tra= ck @@ -200,6 +205,11 @@ struct nfsd_net { /* Per-netns stats counters */ struct percpu_counter counter[NFSD_STATS_COUNTERS_NUM]; =20 +#ifdef CONFIG_NFSD_V4 + /* Per-netns NFSv4 callback (backchannel) per-operation counters */ + struct percpu_counter cb_counter[NFSD_STATS_CB_OPS_NUM]; +#endif + /* sunrpc svc stats */ struct svc_stat nfsd_svcstats; =20 diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index 71dcb448fa0a..a901bbe67e03 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c @@ -39,6 +39,7 @@ #include "nfsd.h" #include "state.h" #include "netns.h" +#include "stats.h" #include "trace.h" #include "xdr4cb.h" #include "xdr4.h" @@ -1921,12 +1922,31 @@ void nfsd4_init_cb(struct nfsd4_callback *cb, struc= t nfs4_client *clp, bool nfsd4_run_cb(struct nfsd4_callback *cb) { struct nfs4_client *clp =3D cb->cb_clp; + struct nfsd_net *nn =3D net_generic(clp->net, nfsd_net_id); + const struct nfsd4_callback_ops *ops =3D cb->cb_ops; + u32 minorversion =3D clp->cl_minorversion; bool queued; =20 nfsd41_cb_inflight_begin(clp); queued =3D nfsd4_queue_cb(cb); - if (!queued) + if (queued) { + if (ops) { + nfsd_stats_cb_op_inc(nn, ops->opcode); + /* + * Minorversion > 0 callbacks prepend a CB_SEQUENCE op + * (see encode_cb_sequence4args()); count it like the + * forechannel counts SEQUENCE, so it isn't perpetually + * reported as zero. CB_NULL probes (ops =3D=3D NULL) carry + * no CB_SEQUENCE -- and on 4.1+ they are dropped without + * sending any RPC (see nfsd4_run_cb_work()) -- so they + * must not be counted here. + */ + if (minorversion > 0) + nfsd_stats_cb_op_inc(nn, OP_CB_SEQUENCE); + } + } else { nfsd41_cb_inflight_end(clp); + } return queued; } =20 diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 19810419f457..18e17232cf94 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -10122,7 +10122,6 @@ __be32 nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_delegation **pdp) { - struct nfsd_net *nn =3D net_generic(SVC_NET(rqstp), nfsd_net_id); struct nfsd_thread_local_info *ntli =3D rqstp->rq_private; struct file_lock_context *ctx; struct nfs4_delegation *dp =3D NULL; @@ -10162,7 +10161,6 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp= , struct dentry *dentry, return 0; } =20 - nfsd_stats_wdeleg_getattr_inc(nn); refcount_inc(&dp->dl_stid.sc_count); ncf =3D &dp->dl_cb_fattr; nfs4_cb_getattr(&dp->dl_cb_fattr); diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 7731051105c9..93e18426039d 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -2736,6 +2736,13 @@ static __net_init int nfsd_net_init(struct net *net) if (retval) goto out_repcache_error; =20 +#ifdef CONFIG_NFSD_V4 + retval =3D percpu_counter_init_many(nn->cb_counter, 0, GFP_KERNEL, + NFSD_STATS_CB_OPS_NUM); + if (retval) + goto out_cb_counter_error; +#endif + memset(&nn->nfsd_svcstats, 0, sizeof(nn->nfsd_svcstats)); nn->nfsd_svcstats.program =3D &nfsd_programs[0]; retval =3D svc_stat_alloc_counts(&nn->nfsd_svcstats); @@ -2764,6 +2771,10 @@ static __net_init int nfsd_net_init(struct net *net) out_svcstats_error: svc_stat_free_counts(&nn->nfsd_svcstats); out_proc_error: +#ifdef CONFIG_NFSD_V4 + percpu_counter_destroy_many(nn->cb_counter, NFSD_STATS_CB_OPS_NUM); +out_cb_counter_error: +#endif percpu_counter_destroy_many(nn->counter, NFSD_STATS_COUNTERS_NUM); out_repcache_error: nfsd_idmap_shutdown(net); @@ -2804,6 +2815,9 @@ static __net_exit void nfsd_net_exit(struct net *net) nfsd_net_cb_shutdown(nn); nfsd_proc_stat_shutdown(net); svc_stat_free_counts(&nn->nfsd_svcstats); +#ifdef CONFIG_NFSD_V4 + percpu_counter_destroy_many(nn->cb_counter, NFSD_STATS_CB_OPS_NUM); +#endif percpu_counter_destroy_many(nn->counter, NFSD_STATS_COUNTERS_NUM); nfsd_idmap_shutdown(net); nfsd_export_shutdown(net); diff --git a/fs/nfsd/stats.c b/fs/nfsd/stats.c index 9a03e097cfe5..f16559813292 100644 --- a/fs/nfsd/stats.c +++ b/fs/nfsd/stats.c @@ -65,7 +65,7 @@ static int nfsd_show(struct seq_file *seq, void *v) percpu_counter_sum_positive(&nn->counter[NFSD_STATS_NFS4_OP(i)])); } seq_printf(seq, "\nwdeleg_getattr %lld", - percpu_counter_sum_positive(&nn->counter[NFSD_STATS_WDELEG_GETATTR])); + percpu_counter_sum_positive(&nn->cb_counter[OP_CB_GETATTR])); =20 seq_putc(seq, '\n'); #endif diff --git a/fs/nfsd/stats.h b/fs/nfsd/stats.h index 87736b7fbf28..70eaf5f20bda 100644 --- a/fs/nfsd/stats.h +++ b/fs/nfsd/stats.h @@ -71,9 +71,10 @@ static inline void nfsd_stats_drc_mem_usage_sub(struct n= fsd_net *nn, s64 amount) } =20 #ifdef CONFIG_NFSD_V4 -static inline void nfsd_stats_wdeleg_getattr_inc(struct nfsd_net *nn) +static inline void nfsd_stats_cb_op_inc(struct nfsd_net *nn, u32 opcode) { - percpu_counter_inc(&nn->counter[NFSD_STATS_WDELEG_GETATTR]); + if (opcode >=3D OP_CB_GETATTR && opcode <=3D OP_CB_OFFLOAD) + percpu_counter_inc(&nn->cb_counter[opcode]); } #endif #endif /* _NFSD_STATS_H */ --=20 2.55.0 From nobody Sat Jul 25 05:27:10 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 21C313BFACC; Fri, 17 Jul 2026 11:09:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784286570; cv=none; b=Rf9NdwoaQMOCO5EYbkQTaPnrgbaCyn/p5ARZJBB/TPCzHIMFLtCryHTqSqQhJ/mQ/wPI68ykuJmLrwlqpSnQPo3OEd5aD72XydiuO8fxGMAz9XOUg67xe5qYOdyY/l9sRQDKkZvBKXa/EEndxhgFpCxdR4BCVFH3wLLCfT7sf2U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784286570; c=relaxed/simple; bh=CS8zI+qB91zpGRQIqSxDi2oHVm0zXoSDFRWk/S3h27w=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=fXC6lk317TBVVUEmZi7L7u2zxrE+crBEkbkca+BJNPwyjJXWavCeAYnEQ0Et4Dh0W4kNKZFsgSp5u+gNPL5EWaNeQytffLiR2y62ZqNXXi+c4C0gqsc23KNvxsVA7C3U6+reahd6i+j61iXH5LjhahA4qYxTOAyzFRq9EAdUa1E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UiGurzF/; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="UiGurzF/" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 037D31F00AC4; Fri, 17 Jul 2026 11:09:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784286555; bh=DCDIhE7c9pAvgc6YoJGBa4Coz73mEKhv06cmrK3JWGo=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=UiGurzF/P0ebFMnF4UNTTjkKHMC/NgxP99mLR8amo9EQRsgb9pTJZ8P09Ey5NdfON n56Cf4owqgP+BUIDoTMpmib4Kx0DZ5IexlUQcf4rn4P1JzeNp4ABhgUCW5Au5n9iso DZeAJxoAL0Qol+BMBDAg+Q/AXTGmfuvKKXhk7OYJhGHDg4k2dGgCuDBK5iHYAEdsHf wMvzsoVQV+Ft9idn0DljVQR0cgBvEzcicnk/NHAcRVgp2UhpcBG7McM2PGkify8/gl M7gg/LwSSSRt1Ezb9bZ3tZa12xL7LSdOfCf7RhZ6DCyQdYSTaaTLODH2cnUKyOM6EW VSdqZfV/uFkzA== From: Jeff Layton Date: Fri, 17 Jul 2026 07:08:58 -0400 Subject: [PATCH v7 6/6] nfsd: export NFSv4 callback op stats via netlink Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260717-exportd-netlink-v7-6-b7ce17b83b60@kernel.org> References: <20260717-exportd-netlink-v7-0-b7ce17b83b60@kernel.org> In-Reply-To: <20260717-exportd-netlink-v7-0-b7ce17b83b60@kernel.org> To: NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey , Chuck Lever Cc: Trond Myklebust , Anna Schumaker , Steve Dickson , linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=3474; i=jlayton@kernel.org; h=from:subject:message-id; bh=CS8zI+qB91zpGRQIqSxDi2oHVm0zXoSDFRWk/S3h27w=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBqWg1UjK5p8uMIJjJMZQ6vPmWD1b6JxHDDF1I0z cdKNk9F6FSJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaloNVAAKCRAADmhBGVaC FTupD/oDam6qvgMY/4pxVGN/zOhn1+QCfnTkp967ECsT1AJlaWgG4PYntQdnAQvbJM4lv0vhlNO +YtkVU8WbB1Sq0mjqt1Z9I8bxolhoMj75EMLD3CWZglC0REjWwaoTq2eYxuQPRhzqY/gvi1FYsF Ws0p809x5NJzIbMWm/yDo75+q8in0DSiyHRAkGYebTPTQFbbRJd5UBdnxZQrQymV5Iu6bn7O4ce My9V8yTfJ+OKPixQUMdURGNj2BDu8z0AE3HstQqC5bOe3s21EXI0izuSiWX/8FcSWXw5aFoCLD4 Bmff7ndNkNvXVO+hsDius2Jew3bGC+zJTi/7Qc2eJEkoYLxgw1bQ0cHfkqkceyywxHKP4OWyelH ymFAXs25qhtRIrKY2PYksQMf2nRXMtfd/vlRUAweOeAsX1rZH7AofIcgYvYGcFP/+fwJaeebHfR 9Hq5fV2cqRIo7lzFEfcO3VP9KN66J3Wi0sAX0sKGAKtrB30PzwowYThVDHHEAbqn00ksSWTJMpL mDwi5LRXq1ODN0k3JXMBi1j1iukdEmUGFbxObwxBZ7MdPRvDvulUdFlNtUxzktMa+6+FYR+s9gc f7BYobF81/i2L9Sb8gXmoO4+8mOHh7SaSjkPcJBuXSgzEIfYFN7/PLaQGl1Rg4LzCcIni/dFQ+l lgPkioVDkv4DDAg== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 Add a proc4cb-ops nested attribute to the server-stats netlink dump, reusing the existing server-proc-entry (op/count) layout. The dump gains a callback section that emits one entry per callback opcode (OP_CB_GETATTR..OP_CB_OFFLOAD) from the per-netns callback counters, paged across messages like the other per-operation sections. This lets nfsstat report NFSv4 backchannel operation counts over netlink, including CB_GETATTR which corresponds to the procfs wdeleg_getattr line. Assisted-by: LLM Signed-off-by: Jeff Layton --- Documentation/netlink/specs/nfsd.yaml | 6 ++++++ fs/nfsd/nfsctl.c | 27 +++++++++++++++++++++++++++ include/uapi/linux/nfsd_netlink.h | 1 + 3 files changed, 34 insertions(+) diff --git a/Documentation/netlink/specs/nfsd.yaml b/Documentation/netlink/= specs/nfsd.yaml index 2a89d355ee7b..642268819c6f 100644 --- a/Documentation/netlink/specs/nfsd.yaml +++ b/Documentation/netlink/specs/nfsd.yaml @@ -410,6 +410,11 @@ attribute-sets: type: nest nested-attributes: server-proc-entry multi-attr: true + - + name: proc4cb-ops + type: nest + nested-attributes: server-proc-entry + multi-attr: true =20 operations: list: @@ -621,6 +626,7 @@ operations: - proc3-ops - proc4-ops - proc4ops-ops + - proc4cb-ops =20 mcast-groups: list: diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 93e18426039d..adb032b7311a 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -2451,6 +2451,29 @@ static int nfsd_nl_server_stats_nfs4ops(struct sk_bu= ff *skb, =20 return 0; } + +/* + * Emit NFSv4 callback (backchannel) per-operation counts, resuming at *id= x, + * which counts from OP_CB_GETATTR. Same return convention as + * nfsd_nl_server_stats_proc(). + */ +static int nfsd_nl_server_stats_cbops(struct sk_buff *skb, + struct nfsd_net *nn, int *idx) +{ + int op; + + for (op =3D OP_CB_GETATTR + *idx; op <=3D OP_CB_OFFLOAD; op++, (*idx)++) { + u64 cnt =3D percpu_counter_sum_positive(&nn->cb_counter[op]); + + if (!cnt) + continue; + if (nfsd_nl_put_proc_entry(skb, NFSD_A_SERVER_STATS_PROC4CB_OPS, + op, cnt)) + return -EMSGSIZE; + } + + return 0; +} #endif =20 /* Sections of the server-stats dump, emitted in order across messages. */ @@ -2459,6 +2482,7 @@ enum { NFSD_SERVER_STATS_PROC2, NFSD_SERVER_STATS_PROC3, NFSD_SERVER_STATS_PROC4, + NFSD_SERVER_STATS_PROC4CB, NFSD_SERVER_STATS_PROC4OPS, NFSD_SERVER_STATS_DONE, }; @@ -2527,6 +2551,9 @@ int nfsd_nl_server_stats_get_dumpit(struct sk_buff *s= kb, NFSD_A_SERVER_STATS_PROC4_OPS, &idx); break; #ifdef CONFIG_NFSD_V4 + case NFSD_SERVER_STATS_PROC4CB: + ret =3D nfsd_nl_server_stats_cbops(skb, nn, &idx); + break; case NFSD_SERVER_STATS_PROC4OPS: ret =3D nfsd_nl_server_stats_nfs4ops(skb, nn, &idx); break; diff --git a/include/uapi/linux/nfsd_netlink.h b/include/uapi/linux/nfsd_ne= tlink.h index 3d076d173b1d..87da1d0bb21e 100644 --- a/include/uapi/linux/nfsd_netlink.h +++ b/include/uapi/linux/nfsd_netlink.h @@ -254,6 +254,7 @@ enum { NFSD_A_SERVER_STATS_PROC3_OPS, NFSD_A_SERVER_STATS_PROC4_OPS, NFSD_A_SERVER_STATS_PROC4OPS_OPS, + NFSD_A_SERVER_STATS_PROC4CB_OPS, =20 __NFSD_A_SERVER_STATS_MAX, NFSD_A_SERVER_STATS_MAX =3D (__NFSD_A_SERVER_STATS_MAX - 1) --=20 2.55.0