From: Mike Snitzer <snitzer@kernel.org>
To: Anna Schumaker <anna@kernel.org>, Trond Myklebust <trondmy@kernel.org>
Cc: linux-nfs@vger.kernel.org,
Jonathan Flynn <jonathan.flynn@hammerspace.com>
Subject: [PATCH 06/11] NFSv4/flexfiles: pair the in-flight count with the layoutstats updates
Date: Mon, 2 Nov 2026 14:11:04 -0500 [thread overview]
Message-ID: <20261102191109.13470-7-snitzer@kernel.org> (raw)
In-Reply-To: <20261102191109.13470-1-snitzer@kernel.org>
From: Mike Snitzer <snitzer@hammerspace.com>
The busy timer's in-flight op count and the requested-side statistics are
two halves of the same accounting, but they lived in two helpers that the
callers invoked back to back. Nothing stopped a new requested-side path
from updating one and missing the other.
Fold nfs4_ff_layout_stat_io_update_requested() into
nfs4_ff_layoutstat_start_io() so both happen in one place, and rename
nfs4_ff_layout_stat_io_update_completed() to nfs4_ff_layoutstat_end_io()
for symmetry -- it already dropped the in-flight count alongside the
completed-side statistics.
Rename nfs4_ff_busy_timer::n_ops to ops_in_flight while here. It is what
the field holds, and it makes its relationship to the op counters legible
at the point of use.
Both helpers now take the stripe rather than mirror + dss_id, which lets
them assert the lock they run under. Since the previous patch made
ops_in_flight a plain int, that lock is the only thing keeping it
consistent, so assert it rather than document it; lockdep_assert_held()
compiles out without CONFIG_PROVE_LOCKING. The callers get a dss_info
local, which is what they were open coding.
No functional change.
Signed-off-by: Mike Snitzer <snitzer@hammerspace.com>
---
fs/nfs/flexfilelayout/flexfilelayout.c | 104 ++++++++++++++-----------
fs/nfs/flexfilelayout/flexfilelayout.h | 2 +-
2 files changed, 58 insertions(+), 48 deletions(-)
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c
index 6a474fa7b0446..bfe8288a14a08 100644
--- a/fs/nfs/flexfilelayout/flexfilelayout.c
+++ b/fs/nfs/flexfilelayout/flexfilelayout.c
@@ -711,7 +711,7 @@ static void
nfs4_ff_start_busy_timer(struct nfs4_ff_busy_timer *timer, ktime_t now)
{
/* first IO request? */
- if (++timer->n_ops == 1)
+ if (++timer->ops_in_flight == 1)
timer->start_time = now;
}
@@ -720,7 +720,7 @@ nfs4_ff_end_busy_timer(struct nfs4_ff_busy_timer *timer, ktime_t now)
{
ktime_t start;
- WARN_ON_ONCE(--timer->n_ops < 0);
+ WARN_ON_ONCE(--timer->ops_in_flight < 0);
start = timer->start_time;
timer->start_time = now;
@@ -743,18 +743,31 @@ nfs4_ff_layoutstat_set_start_time(struct nfs4_ff_layout_ds_stripe *dss_info,
try_cmpxchg64(&dss_info->start_time, &unset, now);
}
+/*
+ * Account for an I/O about to be sent to this stripe, and return true if a
+ * LAYOUTSTATS report is due.
+ *
+ * The in-flight count and the requested-side counters are bumped here
+ * together, so a new requested-side path cannot update one and miss the
+ * other.
+ */
static bool
-nfs4_ff_layoutstat_start_io(struct nfs4_ff_layout_mirror *mirror,
- u32 dss_id,
+nfs4_ff_layoutstat_start_io(struct nfs4_ff_layout_ds_stripe *dss_info,
struct nfs4_ff_layoutstat *layoutstat,
- ktime_t now)
+ __u64 requested, ktime_t now)
{
- s64 report_interval = FF_LAYOUTSTATS_REPORT_INTERVAL;
+ struct nfs4_ff_layout_mirror *mirror = dss_info->mirror;
struct nfs4_flexfile_layout *ffl = FF_LAYOUT_FROM_HDR(mirror->layout);
+ s64 report_interval = FF_LAYOUTSTATS_REPORT_INTERVAL;
ktime_t last_report;
+ lockdep_assert_held(&dss_info->lock);
+
nfs4_ff_start_busy_timer(&layoutstat->busy_timer, now);
- nfs4_ff_layoutstat_set_start_time(&mirror->dss[dss_id], now);
+ layoutstat->io_stat.ops_requested++;
+ layoutstat->io_stat.bytes_requested += requested;
+
+ nfs4_ff_layoutstat_set_start_time(dss_info, now);
if (mirror->report_interval != 0)
report_interval = (s64)mirror->report_interval * 1000LL;
else if (layoutstats_timer != 0)
@@ -772,27 +785,25 @@ nfs4_ff_layoutstat_start_io(struct nfs4_ff_layout_mirror *mirror,
return try_cmpxchg64(&ffl->last_report_time, &last_report, now);
}
+/*
+ * Account for an I/O that has completed on this stripe. The in-flight count
+ * is dropped here, alongside the completed-side counters, for the same reason
+ * it is bumped in nfs4_ff_layoutstat_start_io().
+ */
static void
-nfs4_ff_layout_stat_io_update_requested(struct nfs4_ff_layoutstat *layoutstat,
- __u64 requested)
-{
- struct nfs4_ff_io_stat *iostat = &layoutstat->io_stat;
-
- iostat->ops_requested++;
- iostat->bytes_requested += requested;
-}
-
-static void
-nfs4_ff_layout_stat_io_update_completed(struct nfs4_ff_layoutstat *layoutstat,
- __u64 requested,
- __u64 completed,
- ktime_t time_completed,
- ktime_t time_started)
+nfs4_ff_layoutstat_end_io(struct nfs4_ff_layout_ds_stripe *dss_info,
+ struct nfs4_ff_layoutstat *layoutstat,
+ __u64 requested,
+ __u64 completed,
+ ktime_t time_completed,
+ ktime_t time_started)
{
struct nfs4_ff_io_stat *iostat = &layoutstat->io_stat;
ktime_t completion_time = ktime_sub(time_completed, time_started);
ktime_t timer;
+ lockdep_assert_held(&dss_info->lock);
+
iostat->ops_completed++;
iostat->bytes_completed += completed;
iostat->bytes_not_delivered += requested - completed;
@@ -811,14 +822,13 @@ nfs4_ff_layout_stat_io_start_read(struct inode *inode,
u32 dss_id,
__u64 requested, ktime_t now)
{
+ struct nfs4_ff_layout_ds_stripe *dss_info = &mirror->dss[dss_id];
bool report;
- spin_lock(&mirror->dss[dss_id].lock);
- report = nfs4_ff_layoutstat_start_io(
- mirror, dss_id, &mirror->dss[dss_id].read_stat, now);
- nfs4_ff_layout_stat_io_update_requested(
- &mirror->dss[dss_id].read_stat, requested);
- spin_unlock(&mirror->dss[dss_id].lock);
+ spin_lock(&dss_info->lock);
+ report = nfs4_ff_layoutstat_start_io(dss_info, &dss_info->read_stat,
+ requested, now);
+ spin_unlock(&dss_info->lock);
set_bit(NFS4_FF_MIRROR_STAT_AVAIL, &mirror->flags);
if (report)
@@ -832,11 +842,13 @@ nfs4_ff_layout_stat_io_end_read(struct rpc_task *task,
__u64 requested,
__u64 completed)
{
- spin_lock(&mirror->dss[dss_id].lock);
- nfs4_ff_layout_stat_io_update_completed(&mirror->dss[dss_id].read_stat,
- requested, completed,
- ktime_get(), task->tk_start);
- spin_unlock(&mirror->dss[dss_id].lock);
+ struct nfs4_ff_layout_ds_stripe *dss_info = &mirror->dss[dss_id];
+
+ spin_lock(&dss_info->lock);
+ nfs4_ff_layoutstat_end_io(dss_info, &dss_info->read_stat,
+ requested, completed,
+ ktime_get(), task->tk_start);
+ spin_unlock(&dss_info->lock);
set_bit(NFS4_FF_MIRROR_STAT_AVAIL, &mirror->flags);
}
@@ -846,18 +858,13 @@ nfs4_ff_layout_stat_io_start_write(struct inode *inode,
u32 dss_id,
__u64 requested, ktime_t now)
{
+ struct nfs4_ff_layout_ds_stripe *dss_info = &mirror->dss[dss_id];
bool report;
- spin_lock(&mirror->dss[dss_id].lock);
- report = nfs4_ff_layoutstat_start_io(
- mirror,
- dss_id,
- &mirror->dss[dss_id].write_stat,
- now);
- nfs4_ff_layout_stat_io_update_requested(
- &mirror->dss[dss_id].write_stat,
- requested);
- spin_unlock(&mirror->dss[dss_id].lock);
+ spin_lock(&dss_info->lock);
+ report = nfs4_ff_layoutstat_start_io(dss_info, &dss_info->write_stat,
+ requested, now);
+ spin_unlock(&dss_info->lock);
set_bit(NFS4_FF_MIRROR_STAT_AVAIL, &mirror->flags);
if (report)
@@ -872,13 +879,16 @@ nfs4_ff_layout_stat_io_end_write(struct rpc_task *task,
__u64 completed,
enum nfs3_stable_how committed)
{
+ struct nfs4_ff_layout_ds_stripe *dss_info = &mirror->dss[dss_id];
+
if (committed == NFS_UNSTABLE)
requested = completed = 0;
- spin_lock(&mirror->dss[dss_id].lock);
- nfs4_ff_layout_stat_io_update_completed(&mirror->dss[dss_id].write_stat,
- requested, completed, ktime_get(), task->tk_start);
- spin_unlock(&mirror->dss[dss_id].lock);
+ spin_lock(&dss_info->lock);
+ nfs4_ff_layoutstat_end_io(dss_info, &dss_info->write_stat,
+ requested, completed,
+ ktime_get(), task->tk_start);
+ spin_unlock(&dss_info->lock);
set_bit(NFS4_FF_MIRROR_STAT_AVAIL, &mirror->flags);
}
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.h b/fs/nfs/flexfilelayout/flexfilelayout.h
index d97001abc0d22..b0653a652d3b8 100644
--- a/fs/nfs/flexfilelayout/flexfilelayout.h
+++ b/fs/nfs/flexfilelayout/flexfilelayout.h
@@ -70,7 +70,7 @@ struct nfs4_ff_io_stat {
*/
struct nfs4_ff_busy_timer {
ktime_t start_time;
- int n_ops;
+ int ops_in_flight;
};
struct nfs4_ff_layoutstat {
--
2.52.0
next prev parent reply other threads:[~2026-11-02 19:11 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-02 19:10 [PATCH 00/11] NFSv4/flexfiles: scale layoutstats for striped layouts Mike Snitzer
2026-11-02 19:10 ` [PATCH 01/11] NFSv4/flexfiles: move layoutstats accounting to a per-stripe lock Mike Snitzer
2026-11-02 19:11 ` [PATCH 02/11] NFSv4/flexfiles: drop the now-unused per-mirror lock Mike Snitzer
2026-11-02 19:11 ` [PATCH 03/11] NFSv4/flexfiles: cacheline align the per-stripe layoutstats Mike Snitzer
2026-11-02 19:11 ` [PATCH 04/11] NFSv4/flexfiles: make dss_info->start_time write-once Mike Snitzer
2026-11-02 19:11 ` [PATCH 05/11] NFSv4/flexfiles: drop the redundant atomic from the busy timer Mike Snitzer
2026-11-02 19:11 ` Mike Snitzer [this message]
2026-11-02 19:11 ` [PATCH 07/11] NFSv4/flexfiles: derive ffil_ops_requested rather than storing it Mike Snitzer
2026-11-02 19:11 ` [PATCH 08/11] NFSv4/flexfiles: give each direction its own lock and cacheline Mike Snitzer
2026-11-02 19:11 ` [PATCH 09/11] NFSv4/flexfiles: drop NFS4_FF_MIRROR_STAT_AVAIL Mike Snitzer
2026-11-02 19:11 ` [PATCH 10/11] NFSv4/flexfiles: rotate LAYOUTSTATS reporting across a mirror's stripes Mike Snitzer
2026-11-02 19:11 ` [PATCH 11/11] NFSv4/flexfiles: take the report decision out of the critical section Mike Snitzer
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=20261102191109.13470-7-snitzer@kernel.org \
--to=snitzer@kernel.org \
--cc=anna@kernel.org \
--cc=jonathan.flynn@hammerspace.com \
--cc=linux-nfs@vger.kernel.org \
--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