From: Christoph Hellwig <hch@lst.de>
To: Dave Chinner <dgc@kernel.org>
Cc: Ran Hongyun <ranhongyun1@huawei.com>,
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,
Wangyang Guo <wangyang.guo@intel.com>,
Tim Chen <tim.c.chen@linux.intel.com>,
Lai Jiangshan <jiangshanlai@gmail.com>,
Chuck Lever <cel@kernel.org>
Subject: Re: [QUESTION] xfs: Can we remove flush_workqueue from xlog_cil_push_now?
Date: Wed, 2 Sep 2026 09:35:56 +0200 [thread overview]
Message-ID: <20260902073556.GA27223@lst.de> (raw)
In-Reply-To: <apSnC9p0X04cKxDj@dread>
On Mon, Aug 31, 2026 at 07:56:27AM +1000, Dave Chinner wrote:
> > 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.
Adding the authors/reviwers and maintainers relevant to this commit and
Chuck as he has been looking into different unbound workqueue overhead
lately.
> >
> > 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...
Yeah, a lot of the recent workqueue changes had a lot of adverse effects.
We really need to come up with a way to queue work to task context (or a
different task context) that doesn't require reverse engineering "smart"
behavior in the backend. This has become a never ending whack-a-mole
unfortunately.
Not sure what we can do here, but a simply "just queue things up on a
fixed queue" interface would be really helpful. Even better with just a
double or even singly linked list as overhead, as the work_struct is
way to big due to the function pointer not even needed in most cases
as typically every item in the queue uses the same one.
[leaving the rest of the context in place for the new readers]
> 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
---end quoted text---
next prev parent reply other threads:[~2026-09-02 7:36 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
2026-09-02 7:35 ` Christoph Hellwig [this message]
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=20260902073556.GA27223@lst.de \
--to=hch@lst.de \
--cc=catherine.hoang@oracle.com \
--cc=cel@kernel.org \
--cc=chandan.babu@oracle.com \
--cc=chengzhihao1@huawei.com \
--cc=dgc@kernel.org \
--cc=djwong@kernel.org \
--cc=jiangshanlai@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-xfs@vger.kernel.org \
--cc=ranhongyun1@huawei.com \
--cc=tim.c.chen@linux.intel.com \
--cc=wangyang.guo@intel.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