From bc95fa240a1b8ae64d3dabe87cbe103b912afc45 Mon Sep 17 00:00:00 2001 From: Hans Holmberg Date: Mon, 18 May 2026 08:52:24 +0200 Subject: [PATCH 1/9] xfs: handle racing deletions in xfs_zone_gc_iter_irec Under heavy garbage collection pressure from RocksDB workloads, filesystem shutdowns can occur in xfs_zone_gc_iter_irec when xfs_iget() returns -EINVAL for deleted files. Fix this by handling -EINVAL just like we handle -ENOENT, allowing zone GC to safely ignore stale mappings. Fixes: 080d01c41d44 ("xfs: implement zoned garbage collection") Signed-off-by: Hans Holmberg Reviewed-by: Christoph Hellwig Signed-off-by: Carlos Maiolino --- fs/xfs/xfs_zone_gc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/xfs_zone_gc.c b/fs/xfs/xfs_zone_gc.c index c8a1d5c0332c..f03211e4354a 100644 --- a/fs/xfs/xfs_zone_gc.c +++ b/fs/xfs/xfs_zone_gc.c @@ -400,7 +400,7 @@ xfs_zone_gc_iter_irec( /* * If the inode was already deleted, skip over it. */ - if (error == -ENOENT) { + if (error == -ENOENT || error == -EINVAL) { iter->rec_idx++; goto retry; } From 97bdbf2613eb89428b739ce09d1a6e1c8435a286 Mon Sep 17 00:00:00 2001 From: Dai Ngo Date: Tue, 19 May 2026 17:32:58 -0700 Subject: [PATCH 2/9] xfs: fix use of uninitialized imap in xfs_fs_map_blocks error path xfs_fs_map_blocks() acquires the data map lock and then calls xfs_bmapi_read(). If xfs_bmapi_read() fails, the function currently still falls through to xfs_bmbt_to_iomap(), which consumes an uninitialized imap record and may return invalid data to the caller. Fix this by releasing the data map lock and returning immediately when xfs_bmapi_read() reports an error. This prevents xfs_bmbt_to_iomap() from being called with an uninitialized xfs_bmbt_irec. Fixes: 527851124d10f ("xfs: implement pNFS export operations") Signed-off-by: Dai Ngo Reviewed-by: Carlos Maiolino Reviewed-by: Christoph Hellwig Signed-off-by: Carlos Maiolino --- fs/xfs/xfs_pnfs.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_pnfs.c b/fs/xfs/xfs_pnfs.c index 221e55887a2a..b792e066b403 100644 --- a/fs/xfs/xfs_pnfs.c +++ b/fs/xfs/xfs_pnfs.c @@ -174,12 +174,15 @@ xfs_fs_map_blocks( lock_flags = xfs_ilock_data_map_shared(ip); error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, &imap, &nimaps, bmapi_flags); + if (error) { + xfs_iunlock(ip, lock_flags); + goto out_unlock; + } seq = xfs_iomap_inode_sequence(ip, 0); ASSERT(!nimaps || imap.br_startblock != DELAYSTARTBLOCK); - if (!error && write && - (!nimaps || imap.br_startblock == HOLESTARTBLOCK)) { + if (write && (!nimaps || imap.br_startblock == HOLESTARTBLOCK)) { if (offset + length > XFS_ISIZE(ip)) end_fsb = xfs_iomap_eof_align_last_fsb(ip, end_fsb); else if (nimaps && imap.br_startblock == HOLESTARTBLOCK) From 36ca6f11424a5b6d92b88df37c40bf2fe825d5a0 Mon Sep 17 00:00:00 2001 From: Dai Ngo Date: Tue, 19 May 2026 17:32:59 -0700 Subject: [PATCH 3/9] xfs: fix overlapping extents returned for pNFS LAYOUTGET xfs_fs_map_blocks() currently passes XFS_BMAPI_ENTIRE to xfs_bmapi_read(), which causes the bmap code to expand the mapping to cover the entire extent rather than the requested range. A single LAYOUTGET request from the client can cause the server to issue multiple calls to xfs_fs_map_blocks() for different offsets within the same extent. Because the use of XFS_BMAPI_ENTIRE flag, these calls can produce overlapping mappings. As a result, the LAYOUTGET reply sent to the NFS client may contain overlapping extents. This creates ambiguity in extent selection for a given file range, which can lead to incorrect device selection, inconsistent handling of datastate, and ultimately data corruption or protocol violations on the client side. Problem discovered with xfstest generic/075 test using NFSv4.2 mount with SCSI layout. Fix this by replacing the XFS_BMAPI_ENTIRE flag with '0' so that xfs_bmapi_read() returns only the mapping for the requested range. Fixes: cc6c40e09d7b1 ("NFSD/blocklayout: Support multiple extents per LAYOUTGET"). Signed-off-by: Dai Ngo Reviewed-by: Carlos Maiolino Reviewed-by: Christoph Hellwig Signed-off-by: Carlos Maiolino --- fs/xfs/xfs_pnfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_pnfs.c b/fs/xfs/xfs_pnfs.c index b792e066b403..d92993367ab6 100644 --- a/fs/xfs/xfs_pnfs.c +++ b/fs/xfs/xfs_pnfs.c @@ -118,7 +118,6 @@ xfs_fs_map_blocks( struct xfs_bmbt_irec imap; xfs_fileoff_t offset_fsb, end_fsb; loff_t limit; - int bmapi_flags = XFS_BMAPI_ENTIRE; int nimaps = 1; uint lock_flags; int error = 0; @@ -172,8 +171,9 @@ xfs_fs_map_blocks( offset_fsb = XFS_B_TO_FSBT(mp, offset); lock_flags = xfs_ilock_data_map_shared(ip); + /* request mappings for the specified range only */ error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, - &imap, &nimaps, bmapi_flags); + &imap, &nimaps, 0); if (error) { xfs_iunlock(ip, lock_flags); goto out_unlock; From fcf4faba9f986b3bb528da11913c9ec5d6e8f689 Mon Sep 17 00:00:00 2001 From: Yingjie Gao Date: Wed, 27 May 2026 12:31:33 +0800 Subject: [PATCH 4/9] xfs: fix error returns in CoW fork repair xrep_cow_find_bad() returns success after the cleanup labels even if AG setup, btree queries, or bitmap updates failed. This can make repair continue with an incomplete bad-file-offset bitmap instead of stopping at the original error. The force-rebuild path has a related cleanup problem. If xrep_cow_mark_file_range() fails, the function returns directly and skips the scrub AG context and perag cleanup. Let the force-rebuild path fall through to the existing cleanup code and return the saved error after cleanup. Fixes: dbbdbd008632 ("xfs: repair problems in CoW forks") Cc: # v6.8 Signed-off-by: Yingjie Gao Reviewed-by: "Darrick J. Wong" Signed-off-by: Carlos Maiolino --- fs/xfs/scrub/cow_repair.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/fs/xfs/scrub/cow_repair.c b/fs/xfs/scrub/cow_repair.c index bffc4666ce60..a6ff09ace43d 100644 --- a/fs/xfs/scrub/cow_repair.c +++ b/fs/xfs/scrub/cow_repair.c @@ -300,18 +300,15 @@ xrep_cow_find_bad( * on the debugging knob, replace everything in the CoW fork. */ if ((sc->sm->sm_flags & XFS_SCRUB_IFLAG_FORCE_REBUILD) || - XFS_TEST_ERROR(sc->mp, XFS_ERRTAG_FORCE_SCRUB_REPAIR)) { + XFS_TEST_ERROR(sc->mp, XFS_ERRTAG_FORCE_SCRUB_REPAIR)) error = xrep_cow_mark_file_range(xc, xc->irec.br_startblock, xc->irec.br_blockcount); - if (error) - return error; - } out_sa: xchk_ag_free(sc, &sc->sa); out_pag: xfs_perag_put(pag); - return 0; + return error; } /* From c3e073894379532c00cca7ba5762e18fafe29da8 Mon Sep 17 00:00:00 2001 From: Yingjie Gao Date: Wed, 27 May 2026 12:31:34 +0800 Subject: [PATCH 5/9] xfs: fix rtgroup cleanup in CoW fork repair xrep_cow_find_bad_rt() initializes scrub rtgroup state before the force-rebuild path calls xrep_cow_mark_file_range(). If that call fails, the code jumps directly to out_rtg, which skips the scrub rtgroup cleanup and only drops the local rtgroup reference. Remove the unnecessary jump so the function falls through to out_sr, ensuring the realtime cursors, lock state, and sr->rtg reference are released before returning. Fixes: fd97fe111208 ("xfs: fix CoW forks for realtime files") Cc: # v6.14 Signed-off-by: Yingjie Gao Reviewed-by: "Darrick J. Wong" Signed-off-by: Carlos Maiolino --- fs/xfs/scrub/cow_repair.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/fs/xfs/scrub/cow_repair.c b/fs/xfs/scrub/cow_repair.c index a6ff09ace43d..c25716fc4fee 100644 --- a/fs/xfs/scrub/cow_repair.c +++ b/fs/xfs/scrub/cow_repair.c @@ -382,12 +382,9 @@ xrep_cow_find_bad_rt( * CoW fork and then scan for staging extents in the refcountbt. */ if ((sc->sm->sm_flags & XFS_SCRUB_IFLAG_FORCE_REBUILD) || - XFS_TEST_ERROR(sc->mp, XFS_ERRTAG_FORCE_SCRUB_REPAIR)) { + XFS_TEST_ERROR(sc->mp, XFS_ERRTAG_FORCE_SCRUB_REPAIR)) error = xrep_cow_mark_file_range(xc, xc->irec.br_startblock, xc->irec.br_blockcount); - if (error) - goto out_rtg; - } out_sr: xchk_rtgroup_btcur_free(&sc->sr); From c316bb56bf4dda9bd3456a163c3a3856ca1b9498 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 27 May 2026 14:39:28 +0200 Subject: [PATCH 6/9] xfs: drop the RTG reference later in xfs_ioc_rtgroup_geometry Keep the rtgroup reference until after reporting the write pointer, as that uses it. Right now this is not a major issue as we don't support shrinking file systems in a way that makes RTGs go away, but let's stick to the proper reference counting to prepare for that. Fixes: c6ce65cb17aa ("xfs: add write pointer to xfs_rtgroup_geometry") Signed-off-by: Christoph Hellwig Reviewed-by: Carlos Maiolino Reviewed-by: Wilfred Mallawa Reviewed-by: Damien Le Moal Signed-off-by: Carlos Maiolino --- fs/xfs/xfs_ioctl.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 46e234863644..737afcb5652a 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -433,9 +433,8 @@ xfs_ioc_rtgroup_geometry( return -EINVAL; error = xfs_rtgroup_get_geometry(rtg, &rgeo); - xfs_rtgroup_put(rtg); if (error) - return error; + goto out_put_rtg; if (xfs_has_zoned(mp)) { xfs_rtgroup_lock(rtg, XFS_RTGLOCK_RMAP); @@ -453,8 +452,10 @@ xfs_ioc_rtgroup_geometry( } if (copy_to_user(arg, &rgeo, sizeof(rgeo))) - return -EFAULT; - return 0; + error = -EFAULT; +out_put_rtg: + xfs_rtgroup_put(rtg); + return error; } /* From 2fa29c1a167739fdef0fda9742ddeb15d9a6c7e4 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 27 May 2026 14:39:29 +0200 Subject: [PATCH 7/9] xfs: factor rtgroup geom write pointer reporting into a helper Sticks out a bit better if we add a separate helper for it. Signed-off-by: Christoph Hellwig Reviewed-by: Carlos Maiolino Reviewed-by: Wilfred Mallawa Reviewed-by: Damien Le Moal Signed-off-by: Carlos Maiolino --- fs/xfs/xfs_ioctl.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 737afcb5652a..96af6b62ce39 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -409,6 +409,26 @@ xfs_ioc_ag_geometry( return 0; } +static void +xfs_rtgroup_report_write_pointer( + struct xfs_rtgroup *rtg, + struct xfs_rtgroup_geometry *rgeo) +{ + xfs_rtgroup_lock(rtg, XFS_RTGLOCK_RMAP); + if (rtg->rtg_open_zone) { + rgeo->rg_writepointer = rtg->rtg_open_zone->oz_allocated; + } else { + xfs_rgblock_t highest_rgbno = xfs_rtrmap_highest_rgbno(rtg); + + if (highest_rgbno == NULLRGBLOCK) + rgeo->rg_writepointer = 0; + else + rgeo->rg_writepointer = highest_rgbno + 1; + } + xfs_rtgroup_unlock(rtg, XFS_RTGLOCK_RMAP); + rgeo->rg_flags |= XFS_RTGROUP_GEOM_WRITEPOINTER; +} + STATIC int xfs_ioc_rtgroup_geometry( struct xfs_mount *mp, @@ -416,7 +436,6 @@ xfs_ioc_rtgroup_geometry( { struct xfs_rtgroup *rtg; struct xfs_rtgroup_geometry rgeo; - xfs_rgblock_t highest_rgbno; int error; if (copy_from_user(&rgeo, arg, sizeof(rgeo))) @@ -435,21 +454,8 @@ xfs_ioc_rtgroup_geometry( error = xfs_rtgroup_get_geometry(rtg, &rgeo); if (error) goto out_put_rtg; - - if (xfs_has_zoned(mp)) { - xfs_rtgroup_lock(rtg, XFS_RTGLOCK_RMAP); - if (rtg->rtg_open_zone) { - rgeo.rg_writepointer = rtg->rtg_open_zone->oz_allocated; - } else { - highest_rgbno = xfs_rtrmap_highest_rgbno(rtg); - if (highest_rgbno == NULLRGBLOCK) - rgeo.rg_writepointer = 0; - else - rgeo.rg_writepointer = highest_rgbno + 1; - } - xfs_rtgroup_unlock(rtg, XFS_RTGLOCK_RMAP); - rgeo.rg_flags |= XFS_RTGROUP_GEOM_WRITEPOINTER; - } + if (xfs_has_zoned(mp)) + xfs_rtgroup_report_write_pointer(rtg, &rgeo); if (copy_to_user(arg, &rgeo, sizeof(rgeo))) error = -EFAULT; From 8070a50b88971f9fada55a3ae3330f529bef9adc Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 27 May 2026 14:32:37 +0200 Subject: [PATCH 8/9] xfs: abort mount if xfs_fs_reserve_ag_blocks fails xfs_mountfs currently ignores all errors from xfs_fs_reserve_ag_blocks, which can lead to the mount path continuing on corruption errors. Fix the check to only ignore -ENOSPC as in other callers, and unwind for all other errors. Fixes: 81ed94751b15 ("xfs: fix log intent recovery ENOSPC shutdowns when inactivating inodes") Signed-off-by: Christoph Hellwig Reviewed-by: "Darrick J. Wong" Signed-off-by: Carlos Maiolino --- fs/xfs/xfs_mount.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index b24195f570cd..7aa51826b1ca 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -1149,9 +1149,12 @@ xfs_mountfs( * blocks. */ error = xfs_fs_reserve_ag_blocks(mp); - if (error && error == -ENOSPC) + if (error) { + if (error != -ENOSPC) + goto out_rtunmount; xfs_warn(mp, - "ENOSPC reserving per-AG metadata pool, log recovery may fail."); +"ENOSPC reserving per-AG metadata pool, log recovery may fail."); + } error = xfs_log_mount_finish(mp); xfs_fs_unreserve_ag_blocks(mp); if (error) { From dabfaca8140f64535a79020f0f86ea56f5db5bb2 Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Tue, 26 May 2026 20:53:59 +0100 Subject: [PATCH 9/9] xfs: Remove mention of PageWriteback Update a comment to refer to folios instead of pages. Signed-off-by: Matthew Wilcox (Oracle) Reviewed-by: Christoph Hellwig Signed-off-by: Carlos Maiolino --- fs/xfs/xfs_reflink.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index db23a0f231d6..251dec48f0e3 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -949,16 +949,16 @@ xfs_reflink_end_cow( * repeatedly cycles the ILOCK to allocate one transaction per remapped * extent. * - * If we're being called by writeback then the pages will still - * have PageWriteback set, which prevents races with reflink remapping - * and truncate. Reflink remapping prevents races with writeback by - * taking the iolock and mmaplock before flushing the pages and - * remapping, which means there won't be any further writeback or page - * cache dirtying until the reflink completes. + * If we're being called by writeback then the folios will still + * have the writeback flag set, which prevents races with reflink + * remapping and truncate. Reflink remapping prevents races with + * writeback by taking the iolock and mmaplock before flushing + * the folios and remapping, which means there won't be any further + * writeback or page cache dirtying until the reflink completes. * * We should never have two threads issuing writeback for the same file * region. There are also have post-eof checks in the writeback - * preparation code so that we don't bother writing out pages that are + * preparation code so that we don't bother writing out folios that are * about to be truncated. * * If we're being called as part of directio write completion, the dio