From: Chuck Lever <cel@kernel.org>
To: NeilBrown <neil@brown.name>, Jeff Layton <jlayton@kernel.org>,
Olga Kornievskaia <okorniev@redhat.com>,
Dai Ngo <dai.ngo@oracle.com>, Tom Talpey <tom@talpey.com>
Cc: <linux-nfs@vger.kernel.org>
Subject: [PATCH 2/5] NFSD: Eliminate percpu counter contention in DRC memory accounting
Date: Thu, 16 Jul 2026 20:12:29 -0400 [thread overview]
Message-ID: <20260717001232.438792-3-cel@kernel.org> (raw)
In-Reply-To: <20260717001232.438792-1-cel@kernel.org>
The DRC memory usage counter (NFSD_STATS_DRC_MEM_USAGE) tracks
bytes, but percpu_counter_add() uses the global percpu_counter_batch
threshold of max(32, 2*nr_cpus). Each DRC entry add or removal
updates the counter by sizeof(struct nfsd_cacherep) (~144 bytes),
which always exceeds the batch threshold. percpu_counter_add()
then acquires the counter's global spinlock on every update,
serializing all nfsd threads.
On a 10-CPU NFS server handling a high rate of non-idempotent
NFSv3 operations, this lock accounts for a measurable fraction
of total spin lock overhead because nfsd_cache_lookup() both
inserts a new entry and prunes up to three old entries per RPC,
producing 4-7 global lock acquisitions per operation.
Switch to percpu_counter_add_local() and percpu_counter_sub_local(),
which batch with INT_MAX so that updates always remain on the per-CPU
fast path regardless of the amount. The only reader of this counter uses
percpu_counter_sum_positive(), which sums the per-CPU deltas under the
global lock, so read accuracy is unaffected.
Signed-off-by: Chuck Lever <cel@kernel.org>
---
fs/nfsd/stats.h | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/fs/nfsd/stats.h b/fs/nfsd/stats.h
index 87736b7fbf28..15d30c045dc3 100644
--- a/fs/nfsd/stats.h
+++ b/fs/nfsd/stats.h
@@ -60,14 +60,32 @@ static inline void nfsd_stats_payload_misses_inc(struct nfsd_net *nn)
percpu_counter_inc(&nn->counter[NFSD_STATS_PAYLOAD_MISSES]);
}
+/**
+ * nfsd_stats_drc_mem_usage_add - Add memory used by a cache item
+ * @nn: target network namespace
+ * @amount: byte count
+ *
+ * percpu_counter_add_local() keeps updates on the per-CPU fast
+ * path. The sole reader, percpu_counter_sum_positive(), sums the
+ * per-CPU deltas, so batching locally does not lose accuracy.
+ */
static inline void nfsd_stats_drc_mem_usage_add(struct nfsd_net *nn, s64 amount)
{
- percpu_counter_add(&nn->counter[NFSD_STATS_DRC_MEM_USAGE], amount);
+ percpu_counter_add_local(&nn->counter[NFSD_STATS_DRC_MEM_USAGE],
+ amount);
}
+/**
+ * nfsd_stats_drc_mem_usage_sub - Subtract memory used by a cache item
+ * @nn: target network namespace
+ * @amount: byte count
+ *
+ * See nfsd_stats_drc_mem_usage_add() for batching rationale.
+ */
static inline void nfsd_stats_drc_mem_usage_sub(struct nfsd_net *nn, s64 amount)
{
- percpu_counter_sub(&nn->counter[NFSD_STATS_DRC_MEM_USAGE], amount);
+ percpu_counter_sub_local(&nn->counter[NFSD_STATS_DRC_MEM_USAGE],
+ amount);
}
#ifdef CONFIG_NFSD_V4
--
2.54.0
next prev parent reply other threads:[~2026-07-17 0:12 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-17 0:12 [PATCH 0/5] Minor NFSD global DRC clean-ups Chuck Lever
2026-07-17 0:12 ` [PATCH 1/5] NFSD: Fix off-by-one in DRC bucket pruning limit Chuck Lever
2026-07-17 0:12 ` Chuck Lever [this message]
2026-07-17 0:12 ` [PATCH 3/5] NFSD: Eliminate percpu counter contention in reply cache statistics Chuck Lever
2026-07-17 0:12 ` [PATCH 4/5] NFSD: Eliminate percpu counter contention in IO byte accounting Chuck Lever
2026-07-17 0:12 ` [PATCH 5/5] NFSD: Document reply_cache_stats ABI Chuck Lever
2026-07-17 4:44 ` [PATCH 0/5] Minor NFSD global DRC clean-ups NeilBrown
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=20260717001232.438792-3-cel@kernel.org \
--to=cel@kernel.org \
--cc=dai.ngo@oracle.com \
--cc=jlayton@kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=neil@brown.name \
--cc=okorniev@redhat.com \
--cc=tom@talpey.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.