From: Ojaswin Mujoo <ojaswin@linux.ibm.com>
To: Christian Brauner <brauner@kernel.org>, linux-fsdevel@vger.kernel.org
Cc: "Darrick J . Wong" <djwong@kernel.org>,
Carlos Maiolino <cem@kernel.org>,
Alexander Viro <viro@zeniv.linux.org.uk>, Jan Kara <jack@suse.cz>,
Matthew Wilcox <willy@infradead.org>,
Andrew Morton <akpm@linux-foundation.org>,
Ritesh Harjani <ritesh.list@gmail.com>,
Zhang Yi <yi.zhang@huawei.com>, Christoph Hellwig <hch@lst.de>,
Dave Chinner <dchinner@redhat.com>,
Daniel Gomez <da.gomez@kernel.org>,
Pankaj Raghav <pankaj.raghav@linux.dev>,
Theodore Tso <tytso@mit.edu>,
linux-xfs@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-mm@kvack.org, Andres Freund <andres@anarazel.de>
Subject: [RFC PATCH v4 06/12] xfs: Add RWF_WRITETHROUGH support to xfs
Date: Mon, 28 Sep 2026 17:33:07 +0530 [thread overview]
Message-ID: <d4bde7d19c5da922cd7c378db269b10ed841f93a.1790596383.git.ojaswin@linux.ibm.com> (raw)
In-Reply-To: <cover.1790596383.git.ojaswin@linux.ibm.com>
Add the boilerplate needed to start supporting RWF_WRITETHROUGH in XFS.
We use the direct write ->iomap_begin() functions to ensure the range
under write through always has a real non-delalloc extent. We reuse the xfs
dio's end IO function to perform extent conversion and i_size handling
for us.
*Note on COW extent over DATA hole case*
In case of an unmapped COW extent over a DATA hole
(due to COW preallocations), leave the extent unmapped until we are just
about to send IO. At that time, use the ->writethrough_submit() call
back to convert the COW extent to written.
We initially tried converting during iomap_begin() time (like dio does)
but that results in a stale data exposure as follows:
1. iomap_begin() - converts COW extent over DATA hole to written and
marks IOMAP_F_NEW to handle zeroing.
2. During iomap_write_begin() -> realise extent is stale and return back
without zeroing.
3. iomap_begin() - Again sees the same COW extent but it's written
this time so we don't mark IOMAP_F_NEW
4. Since IOMAP_F_NEW is unmarked, we never zeroout and hence expose
stale data.
To avoid the above, take the buffered IO approach of converting the
extent just before IO, when we are sure to have zeroed out the folio.
Co-developed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
Signed-off-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
Signed-off-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
---
fs/xfs/xfs_file.c | 95 ++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 89 insertions(+), 6 deletions(-)
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index d53a329b6a58..3e25baca22c2 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -690,6 +690,48 @@ static const struct iomap_dio_ops xfs_dio_write_ops = {
.end_io = xfs_dio_write_end_io,
};
+static int
+xfs_writethrough_end_io(
+ struct iomap_writethrough_ctx *wt_ctx,
+ ssize_t size,
+ int error,
+ unsigned int flags)
+{
+ struct xfs_inode *ip = XFS_I(wt_ctx->inode);
+ xfs_off_t offset = wt_ctx->iocb->ki_pos;
+
+ if (unlikely(error))
+ goto error;
+
+ /*
+ * writethrough completions are handled same as dio with the exception
+ * that we need to explicitly change the i_disk_size. This is because
+ * unlike dio, we have already updated the i_size and hence the
+ * (i_disk_size < i_size) check will fail in dio code
+ */
+ error = xfs_dio_write_end_io(wt_ctx->iocb, size, error, flags);
+ if (error)
+ goto error;
+ if (!size)
+ goto out;
+
+ /* Fast lockless check similar to how we do in buffered endio */
+ if (offset + size > ip->i_disk_size) {
+ error = xfs_setfilesize(ip, offset, size);
+ if (error)
+ goto error;
+ }
+
+ return 0;
+
+error:
+ if (wt_ctx->flags & IOMAP_DIO_COW)
+ xfs_reflink_cancel_cow_range(ip, offset, size, true);
+
+out:
+ return error;
+}
+
static void
xfs_dio_zoned_submit_io(
const struct iomap_iter *iter,
@@ -1021,6 +1063,39 @@ xfs_file_dax_write(
return ret;
}
+static int
+xfs_writethrough_submit(
+ struct inode *inode,
+ struct iomap *iomap,
+ loff_t offset,
+ u64 count)
+{
+ int error = 0;
+ unsigned int nofs_flag;
+
+ /*
+ * Convert CoW extents to regular.
+ *
+ * We are under writethrough context with folio lock possibly held. To
+ * avoid memory allocation deadlocks, set the task-wide nofs context.
+ */
+ if (iomap->flags & IOMAP_F_SHARED) {
+ nofs_flag = memalloc_nofs_save();
+ error = xfs_reflink_convert_cow(XFS_I(inode), offset, count);
+ memalloc_nofs_restore(nofs_flag);
+ }
+
+ return error;
+}
+
+const struct iomap_writethrough_ops xfs_writethrough_ops = {
+ .ops = &xfs_direct_write_iomap_ops,
+ .write_ops = &xfs_iomap_write_ops,
+ .end_io = xfs_writethrough_end_io,
+ .writethrough_submit = &xfs_writethrough_submit
+};
+
+
STATIC ssize_t
xfs_file_buffered_write(
struct kiocb *iocb,
@@ -1043,9 +1118,13 @@ xfs_file_buffered_write(
goto out;
trace_xfs_file_buffered_write(iocb, from);
- ret = iomap_file_buffered_write(iocb, from,
- &xfs_buffered_write_iomap_ops, &xfs_iomap_write_ops,
- NULL);
+ if (iocb->ki_flags & IOCB_WRITETHROUGH) {
+ ret = iomap_file_writethrough_write(iocb, from,
+ &xfs_writethrough_ops, NULL);
+ } else
+ ret = iomap_file_buffered_write(iocb, from,
+ &xfs_buffered_write_iomap_ops,
+ &xfs_iomap_write_ops, NULL);
/*
* If we hit a space limit, try to free up some lingering preallocated
@@ -1080,8 +1159,12 @@ xfs_file_buffered_write(
if (ret > 0) {
XFS_STATS_ADD(ip->i_mount, xs_write_bytes, ret);
- /* Handle various SYNC-type writes */
- ret = generic_write_sync(iocb, ret);
+ /*
+ * Handle various SYNC-type writes.
+ * For writethrough, we handle sync during completion.
+ */
+ if (!(iocb->ki_flags & IOCB_WRITETHROUGH))
+ ret = generic_write_sync(iocb, ret);
}
return ret;
}
@@ -2176,7 +2259,7 @@ const struct file_operations xfs_file_operations = {
.remap_file_range = xfs_file_remap_range,
.fop_flags = FOP_MMAP_SYNC | FOP_BUFFER_RASYNC |
FOP_BUFFER_WASYNC | FOP_DIO_PARALLEL_WRITE |
- FOP_DONTCACHE,
+ FOP_DONTCACHE | FOP_WRITETHROUGH,
.setlease = generic_setlease,
};
--
2.55.0
next prev parent reply other threads:[~2026-09-28 12:04 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-28 12:03 [RFC PATCH v4 00/13] Add RWF_WRITETHROUGH support to iomap & xfs Ojaswin Mujoo
2026-09-28 12:03 ` [RFC PATCH v4 01/12] xfs: reexpand iter to original count when upgrading to excl ILOCK Ojaswin Mujoo
2026-09-28 12:03 ` [RFC PATCH v4 02/12] fs: Add counter to track inflight writes that need stable pages Ojaswin Mujoo
2026-09-28 12:03 ` [RFC PATCH v4 03/12] mm: Refactor folio_clear_dirty_for_io() Ojaswin Mujoo
2026-09-28 12:03 ` [RFC PATCH v4 04/12] iomap: Add helper to revert iomap iter Ojaswin Mujoo
2026-09-28 12:03 ` [RFC PATCH v4 05/12] iomap: Add initial support for buffered RWF_WRITETHROUGH Ojaswin Mujoo
2026-09-28 12:03 ` Ojaswin Mujoo [this message]
2026-09-28 12:03 ` [RFC PATCH v4 07/12] iomap: Add aio support to RWF_WRITETHROUGH Ojaswin Mujoo
2026-09-28 12:03 ` [RFC PATCH v4 08/12] iomap: Add DSYNC " Ojaswin Mujoo
2026-09-28 12:03 ` [RFC PATCH v4 09/12] fs: Introduce RWF_NOSERIAL flag to indicate parallel reads/writes Ojaswin Mujoo
2026-09-28 12:03 ` [RFC PATCH v4 10/12] xfs: Implement RWF_NOSERIAL to parallelize RWF_WRITETHROUGH writes Ojaswin Mujoo
2026-09-28 12:03 ` [RFC PATCH v4 11/12] iomap: Avoid folio dirtying in case of RWF_WRITETHROUGH Ojaswin Mujoo
2026-09-28 12:03 ` [RFC PATCH v4 12/12] iomap: Handle deadlock due to repeating folios in RWF_WRITETHROUGH Ojaswin Mujoo
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=d4bde7d19c5da922cd7c378db269b10ed841f93a.1790596383.git.ojaswin@linux.ibm.com \
--to=ojaswin@linux.ibm.com \
--cc=akpm@linux-foundation.org \
--cc=andres@anarazel.de \
--cc=brauner@kernel.org \
--cc=cem@kernel.org \
--cc=da.gomez@kernel.org \
--cc=dchinner@redhat.com \
--cc=djwong@kernel.org \
--cc=hch@lst.de \
--cc=jack@suse.cz \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-xfs@vger.kernel.org \
--cc=pankaj.raghav@linux.dev \
--cc=ritesh.list@gmail.com \
--cc=tytso@mit.edu \
--cc=viro@zeniv.linux.org.uk \
--cc=willy@infradead.org \
--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
all inboxes | Powered by JetHome®