Re: [PATCH v4 1/9] xfs: mark the inode preallocated for pNFS write layouts past EOF

From: Pankaj Raghav (Samsung)

Date: Thu Oct 22 2026 - 08:42:16 EST


On Tue, Oct 20, 2026 at 12:08:44PM +0900, Daejun Park wrote:
> xfs_fs_map_blocks() marks the inode XFS_DIFLAG_PREALLOC after it
> allocates blocks for a write layout, so that xfs_free_eofblocks() does
> not free blocks past EOF that a client may write to. But a write layout
> for a range past EOF where blocks are already allocated, such as the
> speculative preallocation of buffered writes, gets those blocks without
> an allocation, and the inode is not marked. blockgc, or the release of
> the file, then frees them without breaking the layout. The client still
> writes to them, and they may belong to another file by then.
>
> With pynfs as the client, a file grown to 1 MiB by two buffered writes
> on the server had 960 KiB preallocated past EOF, and an RW LAYOUTGET for
> that range got it as one INVALID_DATA extent, without the inode being
> marked. About 300 seconds later, with the default
> speculative_prealloc_lifetime, blockgc freed those blocks while the
> layout was still held. When the client then wrote through the layout and
> sent LAYOUTCOMMIT, xfs_fs_commit_blocks() found a hole where the
> unwritten extent had been, and xfs_iomap_write_unwritten() allocated for
> it with no blocks reserved:
>
> XFS (nvme0n1): Corruption of in-memory data (0x8) detected at
> xfs_trans_mod_sb+0x817/0x960 (fs/xfs/xfs_trans.c:351).
> Shutting down filesystem.
> ...
> xfs_trans_mod_sb+0x817/0x960
> xfs_alloc_vextent_finish+0x2e7/0x990
> xfs_alloc_vextent_start_ag+0x25d/0x720
> xfs_bmap_btalloc+0xdd2/0x1720
> xfs_bmapi_allocate+0x197/0xf90
> xfs_bmapi_write+0x4d0/0xb60
> xfs_iomap_write_unwritten+0x307/0x7e0
> xfs_fs_commit_blocks+0x1d9/0x630
> nfsd4_block_proc_layoutcommit+0x5c2/0x7d0
> nfsd4_layoutcommit+0x4b5/0xa20
>
> The client got NFS4ERR_IO, in six runs out of six. When small files were
> written on the server after blockgc, with a sync first so that the freed
> extents were no longer busy, they got those blocks, and the client's
> write through the layout replaced 978944 bytes of their data before the
> LAYOUTCOMMIT. A LAYOUTGET and LAYOUTCOMMIT 30 seconds apart, before
> blockgc runs, leave the client's data in place.
>
> Mark the inode also when a write mapping ends past EOF and nothing was
> allocated, the same way as for an allocation, before the blocks are
> handed out. With this, the same test keeps the blocks past blockgc, and
> the LAYOUTCOMMIT after 360 seconds succeeds with the data in place.
>
> To share the update with the allocation case, set a local update_inode
> flag in both cases, call xfs_fs_map_update_inode() in one place below
> them, and move the log force into xfs_fs_map_update_inode().
>
> Fixes: 527851124d10 ("xfs: implement pNFS export operations")
> Cc: stable@xxxxxxxxxxxxxxx
> Reported-by: Chuck Lever <cel@xxxxxxxxxx>
> Link: https://lore.kernel.org/r/4de5356f-bc4d-4f1a-9c81-fce09b1b46fd@slotpi15m67
> Signed-off-by: Daejun Park <daejun7.park@xxxxxxxxxxx>
> Reviewed-by: Christoph Hellwig <hch@xxxxxx>
> ---
> fs/xfs/xfs_pnfs.c | 34 +++++++++++++++++++++++++---------
> 1 file changed, 25 insertions(+), 9 deletions(-)

Looks good,
Reviewed-by: Pankaj Raghav <p.raghav@xxxxxxxxxxx>

--
Pankaj