From 2145f447b79ab522667cbdbdab4525c903759f7c Mon Sep 17 00:00:00 2001 From: Chaitanya Kulkarni Date: Mon, 24 Nov 2025 15:48:06 -0800 Subject: [PATCH 1/7] xfs: ignore discard return value __blkdev_issue_discard() always returns 0, making all error checking in XFS discard functions dead code. Change xfs_discard_extents() return type to void, remove error variable, error checking, and error logging for the __blkdev_issue_discard() call in same function. Update xfs_trim_perag_extents() and xfs_trim_rtgroup_extents() to ignore the xfs_discard_extents() return value and error checking code. Update xfs_discard_rtdev_extents() to ignore __blkdev_issue_discard() return value and error checking code. Reviewed-by: Johannes Thumshirn Reviewed-by: Christoph Hellwig Signed-off-by: Chaitanya Kulkarni Signed-off-by: Carlos Maiolino --- fs/xfs/xfs_discard.c | 27 +++++---------------------- fs/xfs/xfs_discard.h | 2 +- 2 files changed, 6 insertions(+), 23 deletions(-) diff --git a/fs/xfs/xfs_discard.c b/fs/xfs/xfs_discard.c index 6917de832191..b6ffe4807a11 100644 --- a/fs/xfs/xfs_discard.c +++ b/fs/xfs/xfs_discard.c @@ -108,7 +108,7 @@ xfs_discard_endio( * list. We plug and chain the bios so that we only need a single completion * call to clear all the busy extents once the discards are complete. */ -int +void xfs_discard_extents( struct xfs_mount *mp, struct xfs_busy_extents *extents) @@ -116,7 +116,6 @@ xfs_discard_extents( struct xfs_extent_busy *busyp; struct bio *bio = NULL; struct blk_plug plug; - int error = 0; blk_start_plug(&plug); list_for_each_entry(busyp, &extents->extent_list, list) { @@ -126,18 +125,10 @@ xfs_discard_extents( trace_xfs_discard_extent(xg, busyp->bno, busyp->length); - error = __blkdev_issue_discard(btp->bt_bdev, + __blkdev_issue_discard(btp->bt_bdev, xfs_gbno_to_daddr(xg, busyp->bno), XFS_FSB_TO_BB(mp, busyp->length), GFP_KERNEL, &bio); - if (error && error != -EOPNOTSUPP) { - xfs_info(mp, - "discard failed for extent [0x%llx,%u], error %d", - (unsigned long long)busyp->bno, - busyp->length, - error); - break; - } } if (bio) { @@ -148,8 +139,6 @@ xfs_discard_extents( xfs_discard_endio_work(&extents->endio_work); } blk_finish_plug(&plug); - - return error; } /* @@ -385,9 +374,7 @@ xfs_trim_perag_extents( * list after this function call, as it may have been freed by * the time control returns to us. */ - error = xfs_discard_extents(pag_mount(pag), extents); - if (error) - break; + xfs_discard_extents(pag_mount(pag), extents); if (xfs_trim_should_stop()) break; @@ -496,12 +483,10 @@ xfs_discard_rtdev_extents( trace_xfs_discard_rtextent(mp, busyp->bno, busyp->length); - error = __blkdev_issue_discard(bdev, + __blkdev_issue_discard(bdev, xfs_rtb_to_daddr(mp, busyp->bno), XFS_FSB_TO_BB(mp, busyp->length), GFP_NOFS, &bio); - if (error) - break; } xfs_discard_free_rtdev_extents(tr); @@ -741,9 +726,7 @@ xfs_trim_rtgroup_extents( * list after this function call, as it may have been freed by * the time control returns to us. */ - error = xfs_discard_extents(rtg_mount(rtg), tr.extents); - if (error) - break; + xfs_discard_extents(rtg_mount(rtg), tr.extents); low = tr.restart_rtx; } while (!xfs_trim_should_stop() && low <= high); diff --git a/fs/xfs/xfs_discard.h b/fs/xfs/xfs_discard.h index 2b1a85223a56..8c5cc4af6a07 100644 --- a/fs/xfs/xfs_discard.h +++ b/fs/xfs/xfs_discard.h @@ -6,7 +6,7 @@ struct fstrim_range; struct xfs_mount; struct xfs_busy_extents; -int xfs_discard_extents(struct xfs_mount *mp, struct xfs_busy_extents *busy); +void xfs_discard_extents(struct xfs_mount *mp, struct xfs_busy_extents *busy); int xfs_ioc_trim(struct xfs_mount *mp, struct fstrim_range __user *fstrim); #endif /* XFS_DISCARD_H */ From 5990fd756943836978ad184aac980e2b36ab7e01 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 4 Dec 2025 13:43:50 -0800 Subject: [PATCH 2/7] xfs: fix a UAF problem in xattr repair The xchk_setup_xattr_buf function can allocate a new value buffer, which means that any reference to ab->value before the call could become a dangling pointer. Fix this by moving an assignment to after the buffer setup. Cc: stable@vger.kernel.org # v6.10 Fixes: e47dcf113ae348 ("xfs: repair extended attributes") Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig Signed-off-by: Carlos Maiolino --- fs/xfs/scrub/attr_repair.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/scrub/attr_repair.c b/fs/xfs/scrub/attr_repair.c index c7eb94069caf..09d63aa10314 100644 --- a/fs/xfs/scrub/attr_repair.c +++ b/fs/xfs/scrub/attr_repair.c @@ -333,7 +333,6 @@ xrep_xattr_salvage_remote_attr( .attr_filter = ent->flags & XFS_ATTR_NSP_ONDISK_MASK, .namelen = rentry->namelen, .name = rentry->name, - .value = ab->value, .valuelen = be32_to_cpu(rentry->valuelen), }; unsigned int namesize; @@ -363,6 +362,7 @@ xrep_xattr_salvage_remote_attr( error = -EDEADLOCK; if (error) return error; + args.value = ab->value; /* Look up the remote value and stash it for reconstruction. */ error = xfs_attr3_leaf_getvalue(leaf_bp, &args); From f06725052098d7b1133ac3846d693c383dc427a2 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 4 Dec 2025 13:44:15 -0800 Subject: [PATCH 3/7] xfs: fix stupid compiler warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gcc 14.2 warns about: xfs_attr_item.c: In function ‘xfs_attr_recover_work’: xfs_attr_item.c:785:9: warning: ‘ip’ may be used uninitialized [-Wmaybe-uninitialized] 785 | xfs_trans_ijoin(tp, ip, 0); | ^~~~~~~~~~~~~~~~~~~~~~~~~~ xfs_attr_item.c:740:42: note: ‘ip’ was declared here 740 | struct xfs_inode *ip; | ^~ I think this is bogus since xfs_attri_recover_work either returns a real pointer having initialized ip or an ERR_PTR having not touched it, but the tools are smarter than me so let's just null-init the variable anyway. Cc: stable@vger.kernel.org # v6.8 Fixes: e70fb328d52772 ("xfs: recreate work items when recovering intent items") Signed-off-by: Darrick J. Wong Reviewed-by: Carlos Maiolino Reviewed-by: Christoph Hellwig Signed-off-by: Carlos Maiolino --- fs/xfs/xfs_attr_item.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/xfs_attr_item.c b/fs/xfs/xfs_attr_item.c index c3a593319bee..e8fa326ac995 100644 --- a/fs/xfs/xfs_attr_item.c +++ b/fs/xfs/xfs_attr_item.c @@ -737,7 +737,7 @@ xfs_attr_recover_work( struct xfs_attri_log_item *attrip = ATTRI_ITEM(lip); struct xfs_attr_intent *attr; struct xfs_mount *mp = lip->li_log->l_mp; - struct xfs_inode *ip; + struct xfs_inode *ip = NULL; struct xfs_da_args *args; struct xfs_trans *tp; struct xfs_trans_res resv; From fc40459de82543b565ebc839dca8f7987f16f62e Mon Sep 17 00:00:00 2001 From: Haoxiang Li Date: Wed, 10 Dec 2025 17:06:01 +0800 Subject: [PATCH 4/7] xfs: fix a memory leak in xfs_buf_item_init() xfs_buf_item_get_format() may allocate memory for bip->bli_formats, free the memory in the error path. Fixes: c3d5f0c2fb85 ("xfs: complain if anyone tries to create a too-large buffer log item") Cc: stable@vger.kernel.org Signed-off-by: Haoxiang Li Reviewed-by: Christoph Hellwig Reviewed-by: Carlos Maiolino Signed-off-by: Carlos Maiolino --- fs/xfs/xfs_buf_item.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 8d85b5eee444..f4c5be67826e 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c @@ -896,6 +896,7 @@ xfs_buf_item_init( map_size = DIV_ROUND_UP(chunks, NBWORD); if (map_size > XFS_BLF_DATAMAP_SIZE) { + xfs_buf_item_free_format(bip); kmem_cache_free(xfs_buf_item_cache, bip); xfs_err(mp, "buffer item dirty bitmap (%u uints) too small to reflect %u bytes!", From 8dc15b7a6e5918bad2b0583cf63d170f94a212df Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 15 Dec 2025 07:05:46 +0100 Subject: [PATCH 5/7] xfs: fix XFS_ERRTAG_FORCE_ZERO_RANGE for zoned file system The new XFS_ERRTAG_FORCE_ZERO_RANGE error tag added by commit ea9989668081 ("xfs: error tag to force zeroing on debug kernels") fails to account for the zoned space reservation rules and this reliably fails xfs/131 because the zeroing operation returns -EIO. Fix this by reserving enough space to zero the entire range, which requires a bit of (fairly ugly) reshuffling to do the error injection early enough to affect the space reservation. Fixes: ea9989668081 ("xfs: error tag to force zeroing on debug kernels") Signed-off-by: Christoph Hellwig Reviewed-by: Brian Foster Reviewed-by: Carlos Maiolino Signed-off-by: Carlos Maiolino --- fs/xfs/xfs_file.c | 58 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 6108612182e2..7874cf745af3 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -1240,6 +1240,38 @@ xfs_falloc_insert_range( return xfs_insert_file_space(XFS_I(inode), offset, len); } +/* + * For various operations we need to zero up to one block at each end of + * the affected range. For zoned file systems this will require a space + * allocation, for which we need a reservation ahead of time. + */ +#define XFS_ZONED_ZERO_EDGE_SPACE_RES 2 + +/* + * Zero range implements a full zeroing mechanism but is only used in limited + * situations. It is more efficient to allocate unwritten extents than to + * perform zeroing here, so use an errortag to randomly force zeroing on DEBUG + * kernels for added test coverage. + * + * On zoned file systems, the error is already injected by + * xfs_file_zoned_fallocate, which then reserves the additional space needed. + * We only check for this extra space reservation here. + */ +static inline bool +xfs_falloc_force_zero( + struct xfs_inode *ip, + struct xfs_zone_alloc_ctx *ac) +{ + if (xfs_is_zoned_inode(ip)) { + if (ac->reserved_blocks > XFS_ZONED_ZERO_EDGE_SPACE_RES) { + ASSERT(IS_ENABLED(CONFIG_XFS_DEBUG)); + return true; + } + return false; + } + return XFS_TEST_ERROR(ip->i_mount, XFS_ERRTAG_FORCE_ZERO_RANGE); +} + /* * Punch a hole and prealloc the range. We use a hole punch rather than * unwritten extent conversion for two reasons: @@ -1268,14 +1300,7 @@ xfs_falloc_zero_range( if (error) return error; - /* - * Zero range implements a full zeroing mechanism but is only used in - * limited situations. It is more efficient to allocate unwritten - * extents than to perform zeroing here, so use an errortag to randomly - * force zeroing on DEBUG kernels for added test coverage. - */ - if (XFS_TEST_ERROR(ip->i_mount, - XFS_ERRTAG_FORCE_ZERO_RANGE)) { + if (xfs_falloc_force_zero(ip, ac)) { error = xfs_zero_range(ip, offset, len, ac, NULL); } else { error = xfs_free_file_space(ip, offset, len, ac); @@ -1423,13 +1448,26 @@ xfs_file_zoned_fallocate( { struct xfs_zone_alloc_ctx ac = { }; struct xfs_inode *ip = XFS_I(file_inode(file)); + struct xfs_mount *mp = ip->i_mount; + xfs_filblks_t count_fsb; int error; - error = xfs_zoned_space_reserve(ip->i_mount, 2, XFS_ZR_RESERVED, &ac); + /* + * If full zeroing is forced by the error injection knob, we need a + * space reservation that covers the entire range. See the comment in + * xfs_zoned_write_space_reserve for the rationale for the calculation. + * Otherwise just reserve space for the two boundary blocks. + */ + count_fsb = XFS_ZONED_ZERO_EDGE_SPACE_RES; + if ((mode & FALLOC_FL_MODE_MASK) == FALLOC_FL_ZERO_RANGE && + XFS_TEST_ERROR(mp, XFS_ERRTAG_FORCE_ZERO_RANGE)) + count_fsb += XFS_B_TO_FSB(mp, len) + 1; + + error = xfs_zoned_space_reserve(mp, count_fsb, XFS_ZR_RESERVED, &ac); if (error) return error; error = __xfs_file_fallocate(file, mode, offset, len, &ac); - xfs_zoned_space_unreserve(ip->i_mount, &ac); + xfs_zoned_space_unreserve(mp, &ac); return error; } From 982d2616a2906113e433fdc0cfcc122f8d1bb60a Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 16 Dec 2025 18:30:08 +0100 Subject: [PATCH 6/7] xfs: validate that zoned RT devices are zone aligned Garbage collection assumes all zones contain the full amount of blocks. Mkfs already ensures this happens, but make the kernel check it as well to avoid getting into trouble due to fuzzers or mkfs bugs. Fixes: 2167eaabe2fa ("xfs: define the zoned on-disk format") Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Cc: stable@vger.kernel.org # v6.15 Signed-off-by: Carlos Maiolino --- fs/xfs/libxfs/xfs_sb.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index cdd16dd805d7..94c272a2ae26 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -301,6 +301,21 @@ xfs_validate_rt_geometry( sbp->sb_rbmblocks != xfs_expected_rbmblocks(sbp)) return false; + if (xfs_sb_is_v5(sbp) && + (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_ZONED)) { + uint32_t mod; + + /* + * Zoned RT devices must be aligned to the RT group size, + * because garbage collection assumes that all zones have the + * same size to avoid insane complexity if that weren't the + * case. + */ + div_u64_rem(sbp->sb_rextents, sbp->sb_rgextents, &mod); + if (mod) + return false; + } + return true; } From dc68c0f601691010dd5ae53442f8523f41a53131 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 16 Dec 2025 18:30:09 +0100 Subject: [PATCH 7/7] xfs: fix the zoned RT growfs check for zone alignment The grofs code for zoned RT subvolums already tries to check for zone alignment, but gets it wrong by using the old instead of the new mount structure. Fixes: 01b71e64bb87 ("xfs: support growfs on zoned file systems") Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Cc: stable@vger.kernel.org # v6.15 Signed-off-by: Carlos Maiolino --- fs/xfs/xfs_rtalloc.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 6907e871fa15..e063f4f2f2e6 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -1255,12 +1255,10 @@ xfs_growfs_check_rtgeom( min_logfsbs = min_t(xfs_extlen_t, xfs_log_calc_minimum_size(nmp), nmp->m_rsumblocks * 2); - kfree(nmp); - trace_xfs_growfs_check_rtgeom(mp, min_logfsbs); if (min_logfsbs > mp->m_sb.sb_logblocks) - return -EINVAL; + goto out_inval; if (xfs_has_zoned(mp)) { uint32_t gblocks = mp->m_groups[XG_TYPE_RTG].blocks; @@ -1268,16 +1266,20 @@ xfs_growfs_check_rtgeom( if (rextsize != 1) return -EINVAL; - div_u64_rem(mp->m_sb.sb_rblocks, gblocks, &rem); + div_u64_rem(nmp->m_sb.sb_rblocks, gblocks, &rem); if (rem) { xfs_warn(mp, "new RT volume size (%lld) not aligned to RT group size (%d)", - mp->m_sb.sb_rblocks, gblocks); - return -EINVAL; + nmp->m_sb.sb_rblocks, gblocks); + goto out_inval; } } + kfree(nmp); return 0; +out_inval: + kfree(nmp); + return -EINVAL; } /*