* [PATCH v5 0/9] xfs: pNFS block layout fixes
@ 2026-10-29 2:22 Daejun Park via B4 Relay
2026-10-29 2:22 ` [PATCH v5 1/9] xfs: mark the inode preallocated for pNFS write layouts past EOF Daejun Park via B4 Relay
` (8 more replies)
0 siblings, 9 replies; 10+ messages in thread
From: Daejun Park via B4 Relay @ 2026-10-29 2:22 UTC (permalink / raw)
To: Carlos Maiolino, linux-xfs
Cc: Christoph Hellwig, Darrick J. Wong, Dave Chinner, Pankaj Raghav,
Chuck Lever, Jeff Layton, Dai Ngo, Sergey Bashirov,
Andrey Albershteyn, linux-nfs, linux-kernel, stable, Daejun Park
The XFS side of the pNFS block and SCSI layout fixes. A pNFS client
alone can trigger the bugs fixed by patches 1 and 3 to 6. Patch 7
closes a race with a local process writing to a shared mapping.
Patches 8 and 9 make a LAYOUTCOMMIT stable the way fdatasync does.
Patch 3 needs patch 2. Patch 4 should not go without patches 2 and 3,
and patch 6 not without patch 5. Patches 1 to 6 are marked for stable.
XFS_BMAPI_CONVERT_ONLY takes bit 12 of the bmapi flags, which the
fs-verity series [1] also uses.
Tested on nfsd-testing plus this series in QEMU guests. nfsd exported
XFS on an nvmet-tcp namespace to pynfs ([2] and local tests for patches
5 and 6) and the Linux client, with KASAN and lockdep and also with
XFS_DEBUG. fstests -g quick ran on a local XFS. Each patch builds with
W=1 on for-next.
[1] https://lore.kernel.org/r/20261002223705.2175542-14-aalbersh@kernel.org
[2] https://lore.kernel.org/r/20261014-pynfs-block-commit-v1-0-1723979f495f@samsung.com
---
Changes in v5:
- Cap the block count in xfs_iomap_write_direct() instead of
xfs_fs_map_blocks().
- Clamp the layout length with min_t(), as min() rejects u64 against
loff_t.
- Assert that XFS_BMAPI_CONVERT_ONLY allocated nothing.
- Shorter commit messages, with test results below the --- line.
Changes in v4:
- Limit a pNFS allocation to XFS_MAX_BMBT_EXTLEN blocks instead of
refusing a count whose reservation would wrap.
Changes in v3:
- Post the XFS pNFS patches as one series.
- Split XFS_BMAPI_CONVERT_ONLY from its pNFS user.
- Return -ENOSR when nothing is mapped, and commit the transaction
instead of cancelling it.
- Add the datasync arguments to xfs_log_force_inode() itself.
---
Daejun Park (9):
xfs: mark the inode preallocated for pNFS write layouts past EOF
xfs: add a flag to convert unwritten extents without allocating blocks
xfs: refuse a pNFS LAYOUTCOMMIT of a range without blocks
xfs: clamp a pNFS LAYOUTCOMMIT extent before computing its end
xfs: cap the block count of xfs_iomap_write_direct() at one extent
xfs: clamp the pNFS layout range to the maximum file size
xfs: take the invalidate lock while mapping a pNFS layout
xfs: add datasync and log_flushed arguments to xfs_log_force_inode()
xfs: make pNFS LAYOUTCOMMIT stable the way fdatasync does
fs/xfs/libxfs/xfs_bmap.c | 14 +++++++--
fs/xfs/libxfs/xfs_bmap.h | 10 +++++-
fs/xfs/xfs_export.c | 2 +-
fs/xfs/xfs_file.c | 52 +++---------------------------
fs/xfs/xfs_inode.c | 36 ++++++++++++++++++---
fs/xfs/xfs_inode.h | 3 +-
fs/xfs/xfs_ioend.c | 2 +-
fs/xfs/xfs_iomap.c | 28 +++++++++++++++--
fs/xfs/xfs_iomap.h | 3 +-
fs/xfs/xfs_pnfs.c | 82 +++++++++++++++++++++++++++++++++---------------
fs/xfs/xfs_zone_gc.c | 2 +-
11 files changed, 147 insertions(+), 87 deletions(-)
---
base-commit: ec8f62cc109a3f596b3c65dc0f1011c209239051
change-id: 20261015-xfs-pnfs-batch-85459210aeeb
Best regards,
--
Daejun Park <daejun7.park@samsung.com>
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v5 1/9] xfs: mark the inode preallocated for pNFS write layouts past EOF
2026-10-29 2:22 [PATCH v5 0/9] xfs: pNFS block layout fixes Daejun Park via B4 Relay
@ 2026-10-29 2:22 ` Daejun Park via B4 Relay
2026-10-29 2:22 ` [PATCH v5 2/9] xfs: add a flag to convert unwritten extents without allocating blocks Daejun Park via B4 Relay
` (7 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Daejun Park via B4 Relay @ 2026-10-29 2:22 UTC (permalink / raw)
To: Carlos Maiolino, linux-xfs
Cc: Christoph Hellwig, Darrick J. Wong, Dave Chinner, Pankaj Raghav,
Chuck Lever, Jeff Layton, Dai Ngo, Sergey Bashirov,
Andrey Albershteyn, linux-nfs, linux-kernel, stable, Daejun Park
From: Daejun Park <daejun7.park@samsung.com>
xfs_fs_map_blocks() marks the inode XFS_DIFLAG_PREALLOC only when it
allocates blocks for a write layout. A write layout past EOF can also
hand out allocated blocks, such as speculative preallocation. blockgc
then frees them under the layout, and another file may get them.
Mark the inode whenever a write mapping ends past EOF.
Fixes: 527851124d10 ("xfs: implement pNFS export operations")
Cc: stable@vger.kernel.org
Reported-by: Chuck Lever <cel@kernel.org>
Link: https://lore.kernel.org/r/4de5356f-bc4d-4f1a-9c81-fce09b1b46fd@slotpi15m67
Signed-off-by: Daejun Park <daejun7.park@samsung.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Pankaj Raghav <p.raghav@samsung.com>
---
Tested with pynfs: blockgc freed 960 KiB under an RW layout, and the
client's write then replaced 978944 bytes of files written meanwhile.
With this, the blocks stay and the LAYOUTCOMMIT succeeds.
---
fs/xfs/xfs_pnfs.c | 34 +++++++++++++++++++++++++---------
1 file changed, 25 insertions(+), 9 deletions(-)
diff --git a/fs/xfs/xfs_pnfs.c b/fs/xfs/xfs_pnfs.c
index ab38561700..a9f0b472f3 100644
--- a/fs/xfs/xfs_pnfs.c
+++ b/fs/xfs/xfs_pnfs.c
@@ -110,7 +110,15 @@ xfs_fs_map_update_inode(
ip->i_diflags |= XFS_DIFLAG_PREALLOC;
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
- return xfs_trans_commit(tp);
+ error = xfs_trans_commit(tp);
+ if (error)
+ return error;
+
+ /*
+ * Force the log so that the blocks handed out to the client are
+ * guaranteed to be present even after a server crash.
+ */
+ return xfs_log_force_inode(ip);
}
/*
@@ -134,6 +142,7 @@ xfs_fs_map_blocks(
uint lock_flags;
int error = 0;
u64 seq;
+ bool update_inode = false;
if (xfs_is_shutdown(mp))
return -EIO;
@@ -221,20 +230,27 @@ xfs_fs_map_blocks(
end_fsb - offset_fsb, 0, &imap, &seq);
if (error)
goto out_unlock;
+ update_inode = true;
+ } else {
+ xfs_iunlock(ip, lock_flags);
/*
- * Ensure the next transaction is committed synchronously so
- * that the blocks allocated and handed out to the client are
- * guaranteed to be present even after a server crash.
+ * Blocks past EOF that were allocated for buffered writes, such
+ * as speculative preallocation, can be freed by
+ * xfs_free_eofblocks() without breaking the layout unless the
+ * inode is marked as preallocated. Mark it before handing them
+ * out for writing, as for blocks allocated above.
*/
+ if (write && !(ip->i_diflags & XFS_DIFLAG_PREALLOC) &&
+ imap.br_startoff + imap.br_blockcount >
+ XFS_B_TO_FSB(mp, XFS_ISIZE(ip)))
+ update_inode = true;
+ }
+
+ if (update_inode) {
error = xfs_fs_map_update_inode(ip);
- if (!error)
- error = xfs_log_force_inode(ip);
if (error)
goto out_unlock;
-
- } else {
- xfs_iunlock(ip, lock_flags);
}
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
--
2.43.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v5 2/9] xfs: add a flag to convert unwritten extents without allocating blocks
2026-10-29 2:22 [PATCH v5 0/9] xfs: pNFS block layout fixes Daejun Park via B4 Relay
2026-10-29 2:22 ` [PATCH v5 1/9] xfs: mark the inode preallocated for pNFS write layouts past EOF Daejun Park via B4 Relay
@ 2026-10-29 2:22 ` Daejun Park via B4 Relay
2026-10-29 2:23 ` [PATCH v5 3/9] xfs: refuse a pNFS LAYOUTCOMMIT of a range without blocks Daejun Park via B4 Relay
` (6 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Daejun Park via B4 Relay @ 2026-10-29 2:22 UTC (permalink / raw)
To: Carlos Maiolino, linux-xfs
Cc: Christoph Hellwig, Darrick J. Wong, Dave Chinner, Pankaj Raghav,
Chuck Lever, Jeff Layton, Dai Ngo, Sergey Bashirov,
Andrey Albershteyn, linux-nfs, linux-kernel, stable, Daejun Park
From: Daejun Park <daejun7.park@samsung.com>
xfs_bmapi_write() with XFS_BMAPI_CONVERT also allocates blocks for
holes and delalloc extents in the range. Add XFS_BMAPI_CONVERT_ONLY for
callers that may only convert already allocated blocks. It stops at a
hole or delalloc extent, and returns -ENOSR if it stops before mapping
anything.
Marked for stable because "xfs: refuse a pNFS LAYOUTCOMMIT of a range
without blocks" needs it.
Suggested-by: Christoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/20261013120359.GB2944@lst.de
Cc: stable@vger.kernel.org
Signed-off-by: Daejun Park <daejun7.park@samsung.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Pankaj Raghav <p.raghav@samsung.com>
---
fs/xfs/libxfs/xfs_bmap.c | 14 ++++++++++++--
fs/xfs/libxfs/xfs_bmap.h | 10 +++++++++-
2 files changed, 21 insertions(+), 3 deletions(-)
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index ca49bf4a50..050522c58b 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -4130,6 +4130,8 @@ xfs_bmapi_finish(
* Returns a negative error code on failure, including -ENOSPC when it could not
* allocate any blocks and -ENOSR when it did allocate blocks to convert a
* delalloc range, but those blocks were before the passed in range.
+ * With XFS_BMAPI_CONVERT_ONLY, it stops at a hole or a delalloc extent instead
+ * of allocating blocks, and returns -ENOSR if it stops before mapping anything.
*/
int
xfs_bmapi_write(
@@ -4189,6 +4191,8 @@ xfs_bmapi_write(
*/
ASSERT((flags & (XFS_BMAPI_PREALLOC | XFS_BMAPI_ZERO)) !=
(XFS_BMAPI_PREALLOC | XFS_BMAPI_ZERO));
+ ASSERT(!(flags & XFS_BMAPI_CONVERT_ONLY) ||
+ (flags & XFS_BMAPI_CONVERT));
if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
XFS_TEST_ERROR(mp, XFS_ERRTAG_BMAPIFORMAT)) {
@@ -4237,6 +4241,9 @@ xfs_bmapi_write(
* that we found, if any.
*/
if (need_alloc || wasdelay) {
+ if (flags & XFS_BMAPI_CONVERT_ONLY)
+ break;
+
bma.eof = eof;
bma.conv = !!(flags & XFS_BMAPI_CONVERT);
bma.wasdel = wasdelay;
@@ -4332,10 +4339,13 @@ xfs_bmapi_write(
*
* To avoid a successful return with *nmap set to 0, return the magic
* -ENOSR error code for this particular case so that the caller can
- * handle it.
+ * handle it. The same goes for XFS_BMAPI_CONVERT_ONLY stopping at a
+ * hole or a delalloc extent at the start of the range, in which case
+ * nothing has been changed.
*/
if (!n) {
- ASSERT(bma.nallocs >= *nmap);
+ ASSERT((flags & XFS_BMAPI_CONVERT_ONLY) ? bma.nallocs == 0 :
+ bma.nallocs >= *nmap);
return -ENOSR;
}
*nmap = n;
diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h
index e9f5416e4c..fb7481e819 100644
--- a/fs/xfs/libxfs/xfs_bmap.h
+++ b/fs/xfs/libxfs/xfs_bmap.h
@@ -90,6 +90,13 @@ struct xfs_bmalloca {
/* Try to align allocations to the extent size hint */
#define XFS_BMAPI_EXTSZALIGN (1u << 11)
+/*
+ * Use with XFS_BMAPI_CONVERT to convert unwritten extents without allocating
+ * blocks. Stop at a hole or a delalloc extent: return the mappings found so
+ * far, or -ENOSR if there are none.
+ */
+#define XFS_BMAPI_CONVERT_ONLY (1u << 12)
+
#define XFS_BMAPI_FLAGS \
{ XFS_BMAPI_ENTIRE, "ENTIRE" }, \
{ XFS_BMAPI_METADATA, "METADATA" }, \
@@ -102,7 +109,8 @@ struct xfs_bmalloca {
{ XFS_BMAPI_COWFORK, "COWFORK" }, \
{ XFS_BMAPI_NODISCARD, "NODISCARD" }, \
{ XFS_BMAPI_NORMAP, "NORMAP" },\
- { XFS_BMAPI_EXTSZALIGN, "EXTSZALIGN" }
+ { XFS_BMAPI_EXTSZALIGN, "EXTSZALIGN" }, \
+ { XFS_BMAPI_CONVERT_ONLY, "CONVERT_ONLY" }
static inline int xfs_bmapi_aflag(int w)
--
2.43.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v5 3/9] xfs: refuse a pNFS LAYOUTCOMMIT of a range without blocks
2026-10-29 2:22 [PATCH v5 0/9] xfs: pNFS block layout fixes Daejun Park via B4 Relay
2026-10-29 2:22 ` [PATCH v5 1/9] xfs: mark the inode preallocated for pNFS write layouts past EOF Daejun Park via B4 Relay
2026-10-29 2:22 ` [PATCH v5 2/9] xfs: add a flag to convert unwritten extents without allocating blocks Daejun Park via B4 Relay
@ 2026-10-29 2:23 ` Daejun Park via B4 Relay
2026-10-29 2:23 ` [PATCH v5 4/9] xfs: clamp a pNFS LAYOUTCOMMIT extent before computing its end Daejun Park via B4 Relay
` (5 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Daejun Park via B4 Relay @ 2026-10-29 2:23 UTC (permalink / raw)
To: Carlos Maiolino, linux-xfs
Cc: Christoph Hellwig, Darrick J. Wong, Dave Chinner, Pankaj Raghav,
Chuck Lever, Jeff Layton, Dai Ngo, Sergey Bashirov,
Andrey Albershteyn, linux-nfs, linux-kernel, stable, Daejun Park
From: Daejun Park <daejun7.park@samsung.com>
A client can commit a hole in a LAYOUTCOMMIT, because nfsd does not
check the extents against its layouts. xfs_iomap_write_unwritten() then
allocates written blocks there. A large hole overruns the block
reservation and shuts XFS down. A small one exposes stale data.
Refuse such a range with -EIO, using XFS_BMAPI_CONVERT_ONLY.
Link: https://lore.kernel.org/r/20261014130834.GB15773@lst.de
Fixes: 527851124d10 ("xfs: implement pNFS export operations")
Cc: stable@vger.kernel.org
Signed-off-by: Daejun Park <daejun7.park@samsung.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
---
Tested with pynfs: committing a 64 KiB hole shut XFS down, and a 4 KiB
hole got NFS4_OK and a new block. Both now get NFS4ERR_IO, no block.
---
fs/xfs/xfs_file.c | 2 +-
fs/xfs/xfs_ioend.c | 2 +-
fs/xfs/xfs_iomap.c | 20 +++++++++++++++++---
fs/xfs/xfs_iomap.h | 3 ++-
fs/xfs/xfs_pnfs.c | 9 ++++++++-
5 files changed, 29 insertions(+), 7 deletions(-)
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 7d0c8a1975..720f4a9b40 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -666,7 +666,7 @@ xfs_dio_write_end_io(
* they are converted.
*/
if (flags & IOMAP_DIO_UNWRITTEN) {
- error = xfs_iomap_write_unwritten(ip, offset, size, true);
+ error = xfs_iomap_write_unwritten(ip, offset, size, true, 0);
goto out;
}
diff --git a/fs/xfs/xfs_ioend.c b/fs/xfs/xfs_ioend.c
index 48becc3bf6..7f4a4a95af 100644
--- a/fs/xfs/xfs_ioend.c
+++ b/fs/xfs/xfs_ioend.c
@@ -237,7 +237,7 @@ xfs_end_ioend_write(
if (ioend->io_flags & IOMAP_IOEND_SHARED)
error = xfs_reflink_end_cow(ip, offset, size);
else if (ioend->io_flags & IOMAP_IOEND_UNWRITTEN)
- error = xfs_iomap_write_unwritten(ip, offset, size, false);
+ error = xfs_iomap_write_unwritten(ip, offset, size, false, 0);
if (!error &&
!(ioend->io_flags & IOMAP_IOEND_DIRECT) &&
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 329c745e31..99d48081c5 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -614,7 +614,8 @@ xfs_iomap_write_unwritten(
xfs_inode_t *ip,
xfs_off_t offset,
xfs_off_t count,
- bool update_isize)
+ bool update_isize,
+ uint32_t bmapi_flags)
{
xfs_mount_t *mp = ip->i_mount;
xfs_fileoff_t offset_fsb;
@@ -676,8 +677,21 @@ xfs_iomap_write_unwritten(
*/
nimaps = 1;
error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb,
- XFS_BMAPI_CONVERT, resblks, &imap,
- &nimaps);
+ XFS_BMAPI_CONVERT | bmapi_flags,
+ resblks, &imap, &nimaps);
+ if (error == -ENOSR && (bmapi_flags & XFS_BMAPI_CONVERT_ONLY)) {
+ /*
+ * Nothing was mapped: the rest of the range starts
+ * with a hole or a delalloc extent. Nothing was
+ * changed either, but xfs_iext_count_extend() may
+ * have logged the inode, and cancelling a dirty
+ * transaction shuts the filesystem down. Commit it,
+ * as xfs_alloc_file_space() does on -ENOSR.
+ */
+ error = xfs_trans_commit(tp);
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+ return error ? error : -EIO;
+ }
if (error)
goto error_on_bmapi_transaction;
diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h
index f2520a9b3a..8fc0c6fc8b 100644
--- a/fs/xfs/xfs_iomap.h
+++ b/fs/xfs/xfs_iomap.h
@@ -15,7 +15,8 @@ struct xfs_zone_alloc_ctx;
int xfs_iomap_write_direct(struct xfs_inode *ip, xfs_fileoff_t offset_fsb,
xfs_fileoff_t count_fsb, unsigned int flags,
struct xfs_bmbt_irec *imap, u64 *sequence);
-int xfs_iomap_write_unwritten(struct xfs_inode *, xfs_off_t, xfs_off_t, bool);
+int xfs_iomap_write_unwritten(struct xfs_inode *ip, xfs_off_t offset,
+ xfs_off_t count, bool update_isize, uint32_t bmapi_flags);
xfs_fileoff_t xfs_iomap_eof_align_last_fsb(struct xfs_inode *ip,
xfs_fileoff_t end_fsb);
diff --git a/fs/xfs/xfs_pnfs.c b/fs/xfs/xfs_pnfs.c
index a9f0b472f3..7ff83274a5 100644
--- a/fs/xfs/xfs_pnfs.c
+++ b/fs/xfs/xfs_pnfs.c
@@ -344,7 +344,14 @@ xfs_fs_commit_blocks(
(end - 1) >> PAGE_SHIFT);
WARN_ON_ONCE(error);
- error = xfs_iomap_write_unwritten(ip, start, length, false);
+ /*
+ * A client may only write to blocks that a layout handed out,
+ * and xfs_fs_map_blocks() allocates blocks for any hole in a
+ * write layout, so refuse to allocate blocks for a hole or a
+ * delalloc extent in the committed range.
+ */
+ error = xfs_iomap_write_unwritten(ip, start, length, false,
+ XFS_BMAPI_CONVERT_ONLY);
if (error)
goto out_drop_iolock;
}
--
2.43.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v5 4/9] xfs: clamp a pNFS LAYOUTCOMMIT extent before computing its end
2026-10-29 2:22 [PATCH v5 0/9] xfs: pNFS block layout fixes Daejun Park via B4 Relay
` (2 preceding siblings ...)
2026-10-29 2:23 ` [PATCH v5 3/9] xfs: refuse a pNFS LAYOUTCOMMIT of a range without blocks Daejun Park via B4 Relay
@ 2026-10-29 2:23 ` Daejun Park via B4 Relay
2026-10-29 2:23 ` [PATCH v5 5/9] xfs: cap the block count of xfs_iomap_write_direct() at one extent Daejun Park via B4 Relay
` (4 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Daejun Park via B4 Relay @ 2026-10-29 2:23 UTC (permalink / raw)
To: Carlos Maiolino, linux-xfs
Cc: Christoph Hellwig, Darrick J. Wong, Dave Chinner, Pankaj Raghav,
Chuck Lever, Jeff Layton, Dai Ngo, Sergey Bashirov,
Andrey Albershteyn, linux-nfs, linux-kernel, stable, Daejun Park
From: Daejun Park <daejun7.park@samsung.com>
xfs_fs_commit_blocks() adds the client's length to the offset before it
clamps the end to the file size. A large length wraps the sum and
reaches xfs_iomap_write_unwritten() unclamped. With the previous two
patches the LAYOUTCOMMIT then fails with -EIO and converts nothing.
Clamp the length first.
Fixes: 527851124d10 ("xfs: implement pNFS export operations")
Cc: stable@vger.kernel.org
Signed-off-by: Daejun Park <daejun7.park@samsung.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Pankaj Raghav <p.raghav@samsung.com>
---
Tested with pynfs: a LAYOUTCOMMIT of 2^64 - 4 KiB at 4 KiB got
NFS4ERR_IO and a WARNING. Now it converts up to the hole, then fails.
---
fs/xfs/xfs_pnfs.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/fs/xfs/xfs_pnfs.c b/fs/xfs/xfs_pnfs.c
index 7ff83274a5..19eb18e129 100644
--- a/fs/xfs/xfs_pnfs.c
+++ b/fs/xfs/xfs_pnfs.c
@@ -328,9 +328,7 @@ xfs_fs_commit_blocks(
if (start > size)
continue;
- end = start + maps[i].length;
- if (end > size)
- end = size;
+ end = start + min_t(u64, maps[i].length, size - start);
length = end - start;
if (!length)
--
2.43.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v5 5/9] xfs: cap the block count of xfs_iomap_write_direct() at one extent
2026-10-29 2:22 [PATCH v5 0/9] xfs: pNFS block layout fixes Daejun Park via B4 Relay
` (3 preceding siblings ...)
2026-10-29 2:23 ` [PATCH v5 4/9] xfs: clamp a pNFS LAYOUTCOMMIT extent before computing its end Daejun Park via B4 Relay
@ 2026-10-29 2:23 ` Daejun Park via B4 Relay
2026-10-29 2:23 ` [PATCH v5 6/9] xfs: clamp the pNFS layout range to the maximum file size Daejun Park via B4 Relay
` (3 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Daejun Park via B4 Relay @ 2026-10-29 2:23 UTC (permalink / raw)
To: Carlos Maiolino, linux-xfs
Cc: Christoph Hellwig, Darrick J. Wong, Dave Chinner, Pankaj Raghav,
Chuck Lever, Jeff Layton, Dai Ngo, Sergey Bashirov,
Andrey Albershteyn, linux-nfs, linux-kernel, stable, Daejun Park
From: Daejun Park <daejun7.park@samsung.com>
xfs_iomap_write_direct() reserves blocks for the whole count in an
unsigned int. For a pNFS layout the client chooses that count, and an
RW LAYOUTGET for 16 TiB wraps the reservation and shuts XFS down.
xfs_bmapi_write() maps at most XFS_MAX_BMBT_EXTLEN blocks here, so cap
the count at that. nfsd asks again for the rest. The other callers get
the same mapping as before.
Suggested-by: Darrick J. Wong <djwong@kernel.org>
Link: https://lore.kernel.org/r/20261008154017.GO2705364@frogsfrogsfrogs
Suggested-by: Christoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/20261015060932.GD14035@lst.de
Suggested-by: Pankaj Raghav <p.raghav@samsung.com>
Link: https://lore.kernel.org/r/atoImJxtg70XcIjS@quentin
Fixes: 527851124d10 ("xfs: implement pNFS export operations")
Cc: stable@vger.kernel.org
Signed-off-by: Daejun Park <daejun7.park@samsung.com>
---
Tested with pynfs on a 32 GiB XFS: the 16 TiB RW LAYOUTGET shut XFS
down before, and gets NFS4ERR_NOSPC after with XFS still running.
Like one for 100 GiB, which allocated nothing before, it now leaves
about 24 GiB allocated past EOF.
---
fs/xfs/xfs_iomap.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 99d48081c5..c3465204b8 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -285,6 +285,14 @@ xfs_iomap_write_direct(
ASSERT(count_fsb > 0);
+ /*
+ * xfs_bmapi_write() maps at most XFS_MAX_BMBT_EXTLEN blocks in one
+ * mapping, so don't reserve blocks for more. A pNFS layout range
+ * comes from a client, and its block count may not even fit the
+ * 32-bit reservation. The caller maps the rest with a later call.
+ */
+ count_fsb = min_t(xfs_filblks_t, count_fsb, XFS_MAX_BMBT_EXTLEN);
+
resaligned = xfs_aligned_fsb_count(offset_fsb, count_fsb,
xfs_get_extsz_hint(ip));
if (unlikely(XFS_IS_REALTIME_INODE(ip))) {
--
2.43.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v5 6/9] xfs: clamp the pNFS layout range to the maximum file size
2026-10-29 2:22 [PATCH v5 0/9] xfs: pNFS block layout fixes Daejun Park via B4 Relay
` (4 preceding siblings ...)
2026-10-29 2:23 ` [PATCH v5 5/9] xfs: cap the block count of xfs_iomap_write_direct() at one extent Daejun Park via B4 Relay
@ 2026-10-29 2:23 ` Daejun Park via B4 Relay
2026-10-29 2:23 ` [PATCH v5 7/9] xfs: take the invalidate lock while mapping a pNFS layout Daejun Park via B4 Relay
` (2 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Daejun Park via B4 Relay @ 2026-10-29 2:23 UTC (permalink / raw)
To: Carlos Maiolino, linux-xfs
Cc: Christoph Hellwig, Darrick J. Wong, Dave Chinner, Pankaj Raghav,
Chuck Lever, Jeff Layton, Dai Ngo, Sergey Bashirov,
Andrey Albershteyn, linux-nfs, linux-kernel, stable, Daejun Park
From: Daejun Park <daejun7.park@samsung.com>
xfs_fs_map_blocks() lets two bad layout ranges through. An offset of
2^63 or more is negative and passes "offset > limit". A length above
the limit, such as NFS4_UINT64_MAX, wraps "offset > limit - length"
and stays unclamped. With NFS4_UINT64_MAX, a read layout is built from
an uninitialized mapping.
Reject a negative offset and one at the limit, and clamp the length.
This needs "xfs: cap the block count of xfs_iomap_write_direct() at one
extent".
Fixes: 527851124d10 ("xfs: implement pNFS export operations")
Cc: stable@vger.kernel.org
Signed-off-by: Daejun Park <daejun7.park@samsung.com>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Pankaj Raghav <p.raghav@samsung.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
---
Tested with pynfs: a READ LAYOUTGET for NFS4_UINT64_MAX bytes at
offset 0 and one for 4 KiB at 2^63 got NFS4ERR_IO before, and get
NFS4ERR_INVAL after. The first fails when nfsd asks again at 2^63,
after the last extent.
---
fs/xfs/xfs_pnfs.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/fs/xfs/xfs_pnfs.c b/fs/xfs/xfs_pnfs.c
index 19eb18e129..7153e7a1e1 100644
--- a/fs/xfs/xfs_pnfs.c
+++ b/fs/xfs/xfs_pnfs.c
@@ -176,10 +176,9 @@ xfs_fs_map_blocks(
if (!write)
limit = max(limit, round_up(i_size_read(inode),
inode->i_sb->s_blocksize));
- if (offset > limit)
+ if (offset < 0 || offset >= limit)
goto out_unlock;
- if (offset > limit - length)
- length = limit - offset;
+ length = min_t(u64, length, limit - offset);
error = filemap_write_and_wait(inode->i_mapping);
if (error)
--
2.43.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v5 7/9] xfs: take the invalidate lock while mapping a pNFS layout
2026-10-29 2:22 [PATCH v5 0/9] xfs: pNFS block layout fixes Daejun Park via B4 Relay
` (5 preceding siblings ...)
2026-10-29 2:23 ` [PATCH v5 6/9] xfs: clamp the pNFS layout range to the maximum file size Daejun Park via B4 Relay
@ 2026-10-29 2:23 ` Daejun Park via B4 Relay
2026-10-29 2:23 ` [PATCH v5 8/9] xfs: add datasync and log_flushed arguments to xfs_log_force_inode() Daejun Park via B4 Relay
2026-10-29 2:23 ` [PATCH v5 9/9] xfs: make pNFS LAYOUTCOMMIT stable the way fdatasync does Daejun Park via B4 Relay
8 siblings, 0 replies; 10+ messages in thread
From: Daejun Park via B4 Relay @ 2026-10-29 2:23 UTC (permalink / raw)
To: Carlos Maiolino, linux-xfs
Cc: Christoph Hellwig, Darrick J. Wong, Dave Chinner, Pankaj Raghav,
Chuck Lever, Jeff Layton, Dai Ngo, Sergey Bashirov,
Andrey Albershteyn, linux-nfs, linux-kernel, Daejun Park
From: Daejun Park <daejun7.park@samsung.com>
xfs_fs_map_blocks() flushes the page cache under the iolock, but a
write fault takes only the invalidate lock. A fault on a shared mapping
can then add a delalloc extent before the range is mapped. That trips
an ASSERT, or nfsd warns and refuses the layout.
Take the invalidate lock with the iolock, as __xfs_file_fallocate()
does. Not for stable: pNFS already leaves local writers to shared
mappings unsynchronized.
Suggested-by: Darrick J. Wong <djwong@kernel.org>
Link: https://lore.kernel.org/r/20260519145949.GH9555@frogsfrogsfrogs
Signed-off-by: Daejun Park <daejun7.park@samsung.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
---
fs/xfs/xfs_pnfs.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/fs/xfs/xfs_pnfs.c b/fs/xfs/xfs_pnfs.c
index 7153e7a1e1..c1a6409f00 100644
--- a/fs/xfs/xfs_pnfs.c
+++ b/fs/xfs/xfs_pnfs.c
@@ -168,8 +168,11 @@ xfs_fs_map_blocks(
* similar to direct I/O, except that the synchronization is much more
* complicated. See the comment near xfs_break_leased_layouts
* for a detailed explanation.
+ *
+ * Take the invalidate lock as well, so that page faults cannot add
+ * delalloc extents to the range while it is being mapped.
*/
- xfs_ilock(ip, XFS_IOLOCK_EXCL);
+ xfs_ilock(ip, XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL);
error = -EINVAL;
limit = mp->m_super->s_maxbytes;
@@ -251,13 +254,13 @@ xfs_fs_map_blocks(
if (error)
goto out_unlock;
}
- xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+ xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL);
error = xfs_bmbt_to_iomap(ip, iomap, &imap, 0, 0, seq);
*device_generation = mp->m_generation;
return error;
out_unlock:
- xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+ xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL);
return error;
}
--
2.43.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v5 8/9] xfs: add datasync and log_flushed arguments to xfs_log_force_inode()
2026-10-29 2:22 [PATCH v5 0/9] xfs: pNFS block layout fixes Daejun Park via B4 Relay
` (6 preceding siblings ...)
2026-10-29 2:23 ` [PATCH v5 7/9] xfs: take the invalidate lock while mapping a pNFS layout Daejun Park via B4 Relay
@ 2026-10-29 2:23 ` Daejun Park via B4 Relay
2026-10-29 2:23 ` [PATCH v5 9/9] xfs: make pNFS LAYOUTCOMMIT stable the way fdatasync does Daejun Park via B4 Relay
8 siblings, 0 replies; 10+ messages in thread
From: Daejun Park via B4 Relay @ 2026-10-29 2:23 UTC (permalink / raw)
To: Carlos Maiolino, linux-xfs
Cc: Christoph Hellwig, Darrick J. Wong, Dave Chinner, Pankaj Raghav,
Chuck Lever, Jeff Layton, Dai Ngo, Sergey Bashirov,
Andrey Albershteyn, linux-nfs, linux-kernel, Daejun Park
From: Daejun Park <daejun7.park@samsung.com>
Add datasync and log_flushed arguments to xfs_log_force_inode() and
move the body of xfs_fsync_flush_log() into it. The next patch needs a
datasync log force in the pNFS LAYOUTCOMMIT path. xfs_file_fsync()
calls it instead, and the other callers pass false and NULL. No
functional change.
Suggested-by: Christoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/20261014130124.GA15407@lst.de
Signed-off-by: Daejun Park <daejun7.park@samsung.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
---
fs/xfs/xfs_export.c | 2 +-
fs/xfs/xfs_file.c | 50 ++++----------------------------------------------
fs/xfs/xfs_inode.c | 36 ++++++++++++++++++++++++++++++++----
fs/xfs/xfs_inode.h | 3 ++-
fs/xfs/xfs_pnfs.c | 2 +-
fs/xfs/xfs_zone_gc.c | 2 +-
6 files changed, 41 insertions(+), 54 deletions(-)
diff --git a/fs/xfs/xfs_export.c b/fs/xfs/xfs_export.c
index 9afda52ed1..9dd6dd8c27 100644
--- a/fs/xfs/xfs_export.c
+++ b/fs/xfs/xfs_export.c
@@ -234,7 +234,7 @@ STATIC int
xfs_fs_nfs_commit_metadata(
struct inode *inode)
{
- return xfs_log_force_inode(XFS_I(inode));
+ return xfs_log_force_inode(XFS_I(inode), false, NULL);
}
const struct export_operations xfs_export_operations = {
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 720f4a9b40..27176a4808 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -76,49 +76,7 @@ xfs_dir_fsync(
struct xfs_inode *ip = XFS_I(file->f_mapping->host);
trace_xfs_dir_fsync(ip);
- return xfs_log_force_inode(ip);
-}
-
-/*
- * All metadata updates are logged, which means that we just have to push the
- * journal to the required sequence number than holds the updates. We track
- * datasync commits separately to full sync commits, and hence only need to
- * select the correct sequence number for the log force here.
- *
- * We don't have to serialise against concurrent modifications, as we do not
- * have to wait for modifications that have not yet completed. We define a
- * transaction commit as completing when the commit sequence number is updated,
- * hence if the sequence number has not updated, the sync operation has been
- * run before the commit completed and we don't have to wait for it.
- *
- * If we have concurrent fsync/fdatasync() calls, the sequence numbers remain
- * set on the log item until - at least - the journal flush completes. In
- * reality, they are only cleared when the inode is fully unpinned (i.e.
- * persistent in the journal and not dirty in the CIL), and so we rely on
- * xfs_log_force_seq() either skipping sequences that have been persisted or
- * waiting on sequences that are still in flight to correctly order concurrent
- * sync operations.
- */
-static int
-xfs_fsync_flush_log(
- struct xfs_inode *ip,
- bool datasync,
- int *log_flushed)
-{
- struct xfs_inode_log_item *iip = ip->i_itemp;
- xfs_csn_t seq = 0;
-
- spin_lock(&iip->ili_lock);
- if (datasync)
- seq = iip->ili_datasync_seq;
- else
- seq = iip->ili_commit_seq;
- spin_unlock(&iip->ili_lock);
-
- if (!seq)
- return 0;
-
- return xfs_log_force_seq(ip->i_mount, seq, XFS_LOG_SYNC, log_flushed);
+ return xfs_log_force_inode(ip, false, NULL);
}
STATIC int
@@ -151,7 +109,7 @@ xfs_file_fsync(
* no modifications to this inode that need to be pushed out.
*/
if (ip->i_itemp) {
- error = xfs_fsync_flush_log(ip, datasync, &log_flushed);
+ error = xfs_log_force_inode(ip, datasync, &log_flushed);
if (error)
return error;
}
@@ -1599,7 +1557,7 @@ __xfs_file_fallocate(
}
if (!error && xfs_file_sync_writes(file))
- error = xfs_log_force_inode(ip);
+ error = xfs_log_force_inode(ip, false, NULL);
out_unlock:
xfs_iunlock(ip, iolock);
@@ -1750,7 +1708,7 @@ xfs_file_remap_range(
goto out_unlock;
if (xfs_file_sync_writes(file_in) || xfs_file_sync_writes(file_out))
- xfs_log_force_inode(dest);
+ xfs_log_force_inode(dest, false, NULL);
out_unlock:
xfs_iunlock2_remapping(src, dest);
if (ret)
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 15b62574b8..0d1c9531cd 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -2669,11 +2669,36 @@ xfs_irele(
}
/*
- * Ensure all committed transactions touching the inode are written to the log.
+ * Ensure all committed transactions touching the inode are written to the log,
+ * or with @datasync only those that fdatasync has to wait for.
+ *
+ * All metadata updates are logged, which means that we just have to push the
+ * journal to the required sequence number that holds the updates. We track
+ * datasync commits separately to full sync commits, and hence only need to
+ * select the correct sequence number for the log force here.
+ *
+ * We don't have to serialise against concurrent modifications, as we do not
+ * have to wait for modifications that have not yet completed. We define a
+ * transaction commit as completing when the commit sequence number is updated,
+ * hence if the sequence number has not updated, the sync operation has been
+ * run before the commit completed and we don't have to wait for it.
+ *
+ * If we have concurrent fsync/fdatasync() calls, the sequence numbers remain
+ * set on the log item until - at least - the journal flush completes. In
+ * reality, they are only cleared when the inode is fully unpinned (i.e.
+ * persistent in the journal and not dirty in the CIL), and so we rely on
+ * xfs_log_force_seq() either skipping sequences that have been persisted or
+ * waiting on sequences that are still in flight to correctly order concurrent
+ * sync operations.
+ *
+ * If @log_flushed is not NULL, it is set when the log force wrote an iclog,
+ * which flushes the device caches before the log write.
*/
int
xfs_log_force_inode(
- struct xfs_inode *ip)
+ struct xfs_inode *ip,
+ bool datasync,
+ int *log_flushed)
{
struct xfs_inode_log_item *iip = ip->i_itemp;
xfs_csn_t seq = 0;
@@ -2682,12 +2707,15 @@ xfs_log_force_inode(
return 0;
spin_lock(&iip->ili_lock);
- seq = iip->ili_commit_seq;
+ if (datasync)
+ seq = iip->ili_datasync_seq;
+ else
+ seq = iip->ili_commit_seq;
spin_unlock(&iip->ili_lock);
if (!seq)
return 0;
- return xfs_log_force_seq(ip->i_mount, seq, XFS_LOG_SYNC, NULL);
+ return xfs_log_force_seq(ip->i_mount, seq, XFS_LOG_SYNC, log_flushed);
}
/*
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 1fa442b646..6dfd9271e6 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -595,7 +595,8 @@ int xfs_ifree(struct xfs_trans *, struct xfs_inode *);
int xfs_itruncate_extents_flags(struct xfs_trans **,
struct xfs_inode *, int, xfs_fsize_t, int);
-int xfs_log_force_inode(struct xfs_inode *ip);
+int xfs_log_force_inode(struct xfs_inode *ip, bool datasync,
+ int *log_flushed);
void xfs_iunpin_wait(xfs_inode_t *);
#define xfs_ipincount(ip) ((unsigned int) atomic_read(&ip->i_pincount))
diff --git a/fs/xfs/xfs_pnfs.c b/fs/xfs/xfs_pnfs.c
index c1a6409f00..f4c4a02e5c 100644
--- a/fs/xfs/xfs_pnfs.c
+++ b/fs/xfs/xfs_pnfs.c
@@ -118,7 +118,7 @@ xfs_fs_map_update_inode(
* Force the log so that the blocks handed out to the client are
* guaranteed to be present even after a server crash.
*/
- return xfs_log_force_inode(ip);
+ return xfs_log_force_inode(ip, false, NULL);
}
/*
diff --git a/fs/xfs/xfs_zone_gc.c b/fs/xfs/xfs_zone_gc.c
index 54b70ed292..cea5447a88 100644
--- a/fs/xfs/xfs_zone_gc.c
+++ b/fs/xfs/xfs_zone_gc.c
@@ -1018,7 +1018,7 @@ xfs_zone_gc_reset_zones(
struct xfs_gc_bio *chunk;
struct bio *bio;
- xfs_log_force_inode(rtg_rmap(rtg));
+ xfs_log_force_inode(rtg_rmap(rtg), false, NULL);
next = rtg_group(rtg)->xg_next_reset;
rtg_group(rtg)->xg_next_reset = NULL;
--
2.43.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v5 9/9] xfs: make pNFS LAYOUTCOMMIT stable the way fdatasync does
2026-10-29 2:22 [PATCH v5 0/9] xfs: pNFS block layout fixes Daejun Park via B4 Relay
` (7 preceding siblings ...)
2026-10-29 2:23 ` [PATCH v5 8/9] xfs: add datasync and log_flushed arguments to xfs_log_force_inode() Daejun Park via B4 Relay
@ 2026-10-29 2:23 ` Daejun Park via B4 Relay
8 siblings, 0 replies; 10+ messages in thread
From: Daejun Park via B4 Relay @ 2026-10-29 2:23 UTC (permalink / raw)
To: Carlos Maiolino, linux-xfs
Cc: Christoph Hellwig, Darrick J. Wong, Dave Chinner, Pankaj Raghav,
Chuck Lever, Jeff Layton, Dai Ngo, Sergey Bashirov,
Andrey Albershteyn, linux-nfs, linux-kernel, Daejun Park
From: Daejun Park <daejun7.park@samsung.com>
Every LAYOUTCOMMIT commits a synchronous transaction and forces the
log. fdatasync after the same overwrite does not, because timestamps
alone do not set ili_datasync_seq.
Do what fdatasync does. Commit without XFS_TRANS_SYNC, force the log up
to ili_datasync_seq, and flush the data device cache if that wrote no
iclog. Conversions and size changes still force the log. As with
fdatasync, a crash before the next log write can lose the new
timestamps and the change attribute that nfsd derives from the ctime.
Signed-off-by: Daejun Park <daejun7.park@samsung.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
---
With the block layout on NVMe/TCP in QEMU, 64 KiB overwrites of a
16 MiB file with fsync each took 473 ms instead of 800 ms. With 4
writers, one file each, 1011 ms instead of 1083 ms (medians of 5 runs).
---
fs/xfs/xfs_pnfs.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/fs/xfs/xfs_pnfs.c b/fs/xfs/xfs_pnfs.c
index f4c4a02e5c..065875c8b7 100644
--- a/fs/xfs/xfs_pnfs.c
+++ b/fs/xfs/xfs_pnfs.c
@@ -295,10 +295,12 @@ xfs_pnfs_validate_isize(
* converting any unwritten extents, flushing the disk cache and updating the
* time stamps.
*
- * Note that we rely on the caller to always send us a timestamp update so that
- * we always commit a transaction here. If that stops being true we will have
- * to manually flush the cache here similar to what the fsync code path does
- * for datasyncs on files that have no dirty metadata.
+ * Like fdatasync, a commit that only updates the timestamps does not force the
+ * log: they are logged as XFS_ILOG_TIMESTAMP and reach the disk with a later
+ * log write. The log is forced up to the last change that a datasync needs,
+ * such as the unwritten extent conversions or a new size, and the cache of the
+ * device holding the file data is flushed if that log force did not write an
+ * iclog itself.
*/
static int
xfs_fs_commit_blocks(
@@ -312,6 +314,7 @@ xfs_fs_commit_blocks(
struct xfs_trans *tp;
struct timespec64 now;
bool update_isize = false;
+ int log_flushed = 0;
int error, i;
loff_t size;
@@ -368,7 +371,8 @@ xfs_fs_commit_blocks(
xfs_ilock(ip, XFS_ILOCK_EXCL);
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
- xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+ xfs_trans_log_inode(tp, ip,
+ update_isize ? XFS_ILOG_CORE : XFS_ILOG_TIMESTAMP);
now = inode_set_ctime_current(inode);
inode_set_atime_to_ts(inode, now);
@@ -379,8 +383,13 @@ xfs_fs_commit_blocks(
ip->i_disk_size = new_size;
}
- xfs_trans_set_sync(tp);
error = xfs_trans_commit(tp);
+ if (error)
+ goto out_drop_iolock;
+
+ error = xfs_log_force_inode(ip, true, &log_flushed);
+ if (!error && !log_flushed)
+ error = blkdev_issue_flush(xfs_inode_buftarg(ip)->bt_bdev);
out_drop_iolock:
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
--
2.43.0
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-10-29 2:23 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-29 2:22 [PATCH v5 0/9] xfs: pNFS block layout fixes Daejun Park via B4 Relay
2026-10-29 2:22 ` [PATCH v5 1/9] xfs: mark the inode preallocated for pNFS write layouts past EOF Daejun Park via B4 Relay
2026-10-29 2:22 ` [PATCH v5 2/9] xfs: add a flag to convert unwritten extents without allocating blocks Daejun Park via B4 Relay
2026-10-29 2:23 ` [PATCH v5 3/9] xfs: refuse a pNFS LAYOUTCOMMIT of a range without blocks Daejun Park via B4 Relay
2026-10-29 2:23 ` [PATCH v5 4/9] xfs: clamp a pNFS LAYOUTCOMMIT extent before computing its end Daejun Park via B4 Relay
2026-10-29 2:23 ` [PATCH v5 5/9] xfs: cap the block count of xfs_iomap_write_direct() at one extent Daejun Park via B4 Relay
2026-10-29 2:23 ` [PATCH v5 6/9] xfs: clamp the pNFS layout range to the maximum file size Daejun Park via B4 Relay
2026-10-29 2:23 ` [PATCH v5 7/9] xfs: take the invalidate lock while mapping a pNFS layout Daejun Park via B4 Relay
2026-10-29 2:23 ` [PATCH v5 8/9] xfs: add datasync and log_flushed arguments to xfs_log_force_inode() Daejun Park via B4 Relay
2026-10-29 2:23 ` [PATCH v5 9/9] xfs: make pNFS LAYOUTCOMMIT stable the way fdatasync does Daejun Park via B4 Relay
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®