From: Christoph Hellwig <hch@lst.de>
To: Carlos Maiolino <cem@kernel.org>
Cc: linux-xfs@vger.kernel.org
Subject: [PATCH 6/6] xfs: flush multiple device caches in parallel in xlog_write_iclog
Date: Wed, 2 Sep 2026 08:49:20 +0300 [thread overview]
Message-ID: <20260902054942.111988-7-hch@lst.de> (raw)
In-Reply-To: <20260902054942.111988-1-hch@lst.de>
When xlog_write_iclog needs to flush the cache for more than one devices,
the current implementations does this sequentially, which adds up the
flush latency for all devices. Switch to kicking off all cache flushes
in parallel so that only the longest latency bounds the time of the log
I/O. This removes the REQ_PREFLUSH optimization for the log device,
but as that flag is never passed on to the device and just very slightly
reduce the latency by queueing the following write from a lower-level
context it is trivially shadowed by the latency improvements of the
parallel flush commands.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/xfs/xfs_log.c | 78 +++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 71 insertions(+), 7 deletions(-)
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index a5870877baed..b392a45d38c6 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -1538,6 +1538,47 @@ xlog_bio_end_io(
&iclog->ic_end_io_work);
}
+struct xlog_flush_done {
+ atomic_t pending;
+ blk_status_t status;
+ struct completion done;
+};
+
+static void
+xlog_flush_done(
+ struct xlog_flush_done *done)
+{
+ if (atomic_dec_and_test(&done->pending))
+ complete(&done->done);
+}
+
+static void
+xlog_flush_end_io(
+ struct bio *bio)
+{
+ struct xlog_flush_done *done = bio->bi_private;
+
+ if (bio->bi_status)
+ cmpxchg(&done->status, 0, bio->bi_status);
+ xlog_flush_done(done);
+ bio_put(bio);
+}
+
+static void
+xlog_flush_async(
+ struct xlog_flush_done *done,
+ struct block_device *bdev)
+{
+ struct bio *bio;
+
+ bio = bio_alloc(bdev, 0, REQ_OP_WRITE | REQ_PREFLUSH | REQ_SYNC,
+ GFP_NOFS);
+ bio->bi_private = done;
+ bio->bi_end_io = xlog_flush_end_io;
+ atomic_inc(&done->pending);
+ submit_bio(bio);
+}
+
/*
* When using multiple devices, we also need to flush the data and RT device
* caches first to ensure that all metadata writeback covered by the LSN in
@@ -1551,17 +1592,39 @@ xlog_bio_end_io(
*/
static int
xlog_flush_data_caches(
- struct xlog *log)
+ struct xlog *log,
+ struct xlog_in_core *iclog)
{
struct xfs_mount *mp = log->l_mp;
+ struct xlog_flush_done done = {
+ .pending = ATOMIC_INIT(1),
+ .done = COMPLETION_INITIALIZER_ONSTACK(done.done),
+ };
+ bool did_flush = false;
- if (log->l_targ != mp->m_ddev_targp) {
- if (blkdev_issue_flush(mp->m_ddev_targp->bt_bdev))
- return -EIO;
+ if (mp->m_ddev_targp != log->l_targ &&
+ bdev_write_cache(mp->m_ddev_targp->bt_bdev)) {
+ xlog_flush_async(&done, mp->m_ddev_targp->bt_bdev);
+ did_flush = true;
+ }
+ if (mp->m_rtdev_targp && mp->m_rtdev_targp != mp->m_ddev_targp &&
+ bdev_write_cache(mp->m_rtdev_targp->bt_bdev)) {
+ xlog_flush_async(&done, mp->m_rtdev_targp->bt_bdev);
+ did_flush = true;
}
- if (mp->m_rtdev_targp && mp->m_rtdev_targp != mp->m_ddev_targp) {
- if (blkdev_issue_flush(mp->m_rtdev_targp->bt_bdev))
+
+ if (did_flush) {
+ /*
+ * If we flushed any other device, also use an async flush for
+ * the log device so that all flushes happen in parallel.
+ */
+ xlog_flush_async(&done, log->l_targ->bt_bdev);
+
+ xlog_flush_done(&done);
+ wait_for_completion(&done.done);
+ if (done.status)
return -EIO;
+ iclog->ic_flags &= ~XLOG_ICL_NEED_FLUSH;
}
return 0;
@@ -1611,8 +1674,9 @@ xlog_write_iclog(
iclog->ic_bio.bi_private = iclog;
if (iclog->ic_flags & XLOG_ICL_NEED_FLUSH) {
- if (xlog_flush_data_caches(log))
+ if (xlog_flush_data_caches(log, iclog))
goto shutdown;
+ /* xlog_flush_data_caches may clear XLOG_ICL_NEED_FLUSH */
}
if (iclog->ic_flags & (XLOG_ICL_NEED_FLUSH | XLOG_ICL_NEED_FLUSH_LOG))
iclog->ic_bio.bi_opf |= REQ_PREFLUSH;
--
2.53.0
next prev parent reply other threads:[~2026-09-02 5:50 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-02 5:49 fix and then optimize cache flushes for the RT device Christoph Hellwig
2026-09-02 5:49 ` [PATCH 1/6] xfs: also flush the RT device cache in xlog_write_iclog Christoph Hellwig
2026-09-02 16:01 ` Darrick J. Wong
2026-09-02 5:49 ` [PATCH 2/6] xfs: don't continue on error in xfs_fsync Christoph Hellwig
2026-09-02 16:07 ` Darrick J. Wong
2026-09-02 5:49 ` [PATCH 3/6] xfs: clean up xfs_fsync_flush_log a bit Christoph Hellwig
2026-09-02 16:07 ` Darrick J. Wong
2026-09-02 5:49 ` [PATCH 4/6] xfs: avoid extra cache flushes for multi-device file systems in xfs_fsync Christoph Hellwig
2026-09-02 16:12 ` Darrick J. Wong
2026-09-02 5:49 ` [PATCH 5/6] xfs: optimize cache flushing for CIL commits on multi-device file systems Christoph Hellwig
2026-09-02 16:15 ` Darrick J. Wong
2026-09-02 5:49 ` Christoph Hellwig [this message]
2026-09-02 16:18 ` [PATCH 6/6] xfs: flush multiple device caches in parallel in xlog_write_iclog Darrick J. Wong
2026-09-03 5:44 ` Christoph Hellwig
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=20260902054942.111988-7-hch@lst.de \
--to=hch@lst.de \
--cc=cem@kernel.org \
--cc=linux-xfs@vger.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