Linux XFS filesystem development
 help / color / mirror / Atom feed
From: Dave Chinner <dgc@kernel.org>
To: Ran Hongyun <ranhongyun1@huawei.com>
Cc: catherine.hoang@oracle.com, chandan.babu@oracle.com,
	djwong@kernel.org, hch@lst.de, linux-xfs@vger.kernel.org,
	linux-kernel@vger.kernel.org, chengzhihao1@huawei.com,
	yangerkun@huawei.com, yi.zhang@huawei.com
Subject: Re: [QUESTION] xfs: Can we remove flush_workqueue from xlog_cil_push_now?
Date: Mon, 31 Aug 2026 07:56:27 +1000	[thread overview]
Message-ID: <apSnC9p0X04cKxDj@dread> (raw)
In-Reply-To: <20260827033654.1172495-1-ranhongyun1@huawei.com>

On Thu, Aug 27, 2026 at 11:36:52AM +0800, Ran Hongyun wrote:
> In xlog_cil_push_now(), we call flush_workqueue(cil->xc_push_wq) before
> queuing a new work item in sync mode. The intention is to start any
> pending background push and reduce the wait time for the new sync work.
> However, after commit 636b927eba5b ("workqueue: Make unbound workqueues
> to use per-cpu pool_workqueues"), flush_workqueue() iterates over all
> nr_cpus pool_workqueue entries, instead of per-NUMA nodes. On large SMP
> systems (e.g. 128 CPUs, 4 NUMA nodes), this adds significant overhead.
> Even after 85f0d8e39aff ("workqueue: Reduce expensive locks for unbound
> workqueue") reduced lock cost, the per-CPU iteration remains costly.
> This seems contrary to the original performance intent of the flush.
> 
> Below is a bpftrace test result on a 128-CPU system with 4 NUMA nodes,
> 16 threads doing sequential writes with fsync per write.
> 
> Function                    remove flush          with flush
>                             per-CPU pwqs     per-CPU      per-NUMA
> -------------------------  --------------   ----------   -----------
> xfs_fsync_flush_log          32-256 us      256-1000 us    32-256 us
> flush_workqueue_prep_pwqs      N/A           2-64 us        2-8 us
> 
> With flush_workqueue() removed, xfs_fsync_flush_log latency drops
> back to the per‑NUMA range (32‑256 us).

Ok, but how does the IO performance change? Does this result in a
measurable increase in RWF_OSYNC write throughput? (write + fsync ==
pwritev2(RWF_OSYNC)).

However, behavioural changes like this seem like an infrastructure
regression, and trying to modify callers to hide that regression is
a bandaid. This affects all UNBOUND workqueues, not just this one,
and we do not need per-cpu scheduling for workqueues with such low
work and concurrency counts - there can only be 4 pushs scheduled
and running concurrently at any time on this work queue. Hence we
don't even need NUMA queuing - a single global queue would work just
fine...

Hence it seems to me that this overhead problem should be fixed at
the WQ infra level, not worked around in the caller context...

> The removal relies on the assumption that flush_workqueue is just a
> performance optimization, not a correctness requirement. Without it,
> xlog_cil_force_seq already provides a reliable completion guarantee via
> xlog_wait(&cil->xc_commit_wait), which blocks until the target sequence
> has been committed. The caller will eventually observe the completion
> regardless of whether flush_workqueue was called. In addition, ordering
> is enforced by xlog_cil_order_write, which ensures all records are
> written in strict sequence order. Therefore, removing flush_workqueue
> does not weaken any ordering or completion semantics.

And wait latency goes up because now there is nothing to expedidite
the scheduling of the work we are waiting to complete.

i.e. you might see a drop in CPU time in flush heavy workloads by
removing it, but the trade off is an increase in wait time variance
and long tail latencies, especially under light load.

> If this analysis is correct, the change can be applied broadly to all
> sync force callers through xlog_cil_push_now(), as they all share the
> same completion and ordering guarantees provided by the existing CIL
> infrastructure. The per-CPU iteration overhead would be eliminated on
> every sync log force without affecting correctness.
> 
> But there are several concerns I'd like to confirm:
> 
> Is flush_workqueue just about performance, or does it hide any
> correctness dependency I'm missing?

It may well hide implicit correctness bugs.

> Without it, the "if (!ctx->commit_lsn) { goto restart; }" loop in
> xlog_cil_force_seq may be triggered more often. Is that acceptable,
> or is it a concern?

That's additional context switches and latency. i.e. CPU overhead
that we are trying to avoid...

> Are there any ordering guarantees provided by flush_workqueue that
> xc_push_lock + waitqueues don't already provide?

Removing the flush will change the order in which concurrent push
pipelines order in the journal. This could change the inherent order
of checkpoints in the journal, so there could be visible artifacts
during crash recovery compared to an flushing implementaiton. None
of that would be a correctness issue, but from an application POV it
would be like the concurrent fsync operations completing in a
different order across different kernel versions.

A lakc of flushing could also simply move the ordering latency
bottleneck to journal IO completion where checkpoints have to be
completed in ascending LSN order. Whether that causes a problem or
not is a complete unknown, but it could increase overall wait times
as waiting seqeunces always get woken in ascending order, and hence
everything will wait if a low sequeunce flush submission gets held
up because the kworker isn't scheduled immediately...

> I'd appreciate any thoughts on whether this change is safe.

Probably safe, but there is lots of potential for performance
regressions by removing it. Better would be to provide a low
overhead work queue implementation for callers that don't need
scale-out performance from their unbound workqueues....

-Dave.
-- 
Dave Chinner
dgc@kernel.org

  reply	other threads:[~2026-08-30 21:56 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-27  3:36 [QUESTION] xfs: Can we remove flush_workqueue from xlog_cil_push_now? Ran Hongyun
2026-08-30 21:56 ` Dave Chinner [this message]
2026-09-02  7:35   ` Christoph Hellwig
2026-09-02 14:23     ` Chuck Lever
2026-09-02 16:50       ` Tejun Heo

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=apSnC9p0X04cKxDj@dread \
    --to=dgc@kernel.org \
    --cc=catherine.hoang@oracle.com \
    --cc=chandan.babu@oracle.com \
    --cc=chengzhihao1@huawei.com \
    --cc=djwong@kernel.org \
    --cc=hch@lst.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-xfs@vger.kernel.org \
    --cc=ranhongyun1@huawei.com \
    --cc=yangerkun@huawei.com \
    --cc=yi.zhang@huawei.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox