summaryrefslogtreecommitdiff
path: root/fs/xfs/xfs_zone_alloc.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2026-01-14 07:53:26 +0100
committerCarlos Maiolino <cem@kernel.org>2026-01-21 12:57:17 +0100
commit776b76f7547fb839954aae06f58ac7b6b35c0b25 (patch)
tree747042563f78fb45edc5aea8d37934646c82a037 /fs/xfs/xfs_zone_alloc.c
parentfc633b5c5b80c1d840b7a8bc2828be96582c6b55 (diff)
downloadlinux-next-776b76f7547fb839954aae06f58ac7b6b35c0b25.tar.gz
linux-next-776b76f7547fb839954aae06f58ac7b6b35c0b25.zip
xfs: pass the write pointer to xfs_init_zone
Move the two methods to query the write pointer out of xfs_init_zone into the callers, so that xfs_init_zone doesn't have to bother with the blk_zone structure and instead operates purely at the XFS realtime group level. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com> Reviewed-by: Damien Le Moal <dlemoal@kernel.org> Signed-off-by: Carlos Maiolino <cem@kernel.org>
Diffstat (limited to 'fs/xfs/xfs_zone_alloc.c')
-rw-r--r--fs/xfs/xfs_zone_alloc.c66
1 files changed, 37 insertions, 29 deletions
diff --git a/fs/xfs/xfs_zone_alloc.c b/fs/xfs/xfs_zone_alloc.c
index 4ca7769b5adb..335e683436d3 100644
--- a/fs/xfs/xfs_zone_alloc.c
+++ b/fs/xfs/xfs_zone_alloc.c
@@ -981,43 +981,43 @@ struct xfs_init_zones {
uint64_t reclaimable;
};
+/*
+ * For sequential write required zones, we restart writing at the hardware write
+ * pointer returned by xfs_zone_validate().
+ *
+ * For conventional zones or conventional devices we have to query the rmap to
+ * find the highest recorded block and set the write pointer to the block after
+ * that. In case of a power loss this misses blocks where the data I/O has
+ * completed but not recorded in the rmap yet, and it also rewrites blocks if
+ * the most recently written ones got deleted again before unmount, but this is
+ * the best we can do without hardware support.
+ */
+static xfs_rgblock_t
+xfs_rmap_estimate_write_pointer(
+ struct xfs_rtgroup *rtg)
+{
+ xfs_rgblock_t highest_rgbno;
+
+ xfs_rtgroup_lock(rtg, XFS_RTGLOCK_RMAP);
+ highest_rgbno = xfs_rtrmap_highest_rgbno(rtg);
+ xfs_rtgroup_unlock(rtg, XFS_RTGLOCK_RMAP);
+
+ if (highest_rgbno == NULLRGBLOCK)
+ return 0;
+ return highest_rgbno + 1;
+}
+
static int
xfs_init_zone(
struct xfs_init_zones *iz,
struct xfs_rtgroup *rtg,
- struct blk_zone *zone)
+ xfs_rgblock_t write_pointer)
{
struct xfs_mount *mp = rtg_mount(rtg);
struct xfs_zone_info *zi = mp->m_zone_info;
uint32_t used = rtg_rmap(rtg)->i_used_blocks;
- xfs_rgblock_t write_pointer, highest_rgbno;
int error;
- if (zone && !xfs_zone_validate(zone, rtg, &write_pointer))
- return -EFSCORRUPTED;
-
- /*
- * For sequential write required zones we retrieved the hardware write
- * pointer above.
- *
- * For conventional zones or conventional devices we don't have that
- * luxury. Instead query the rmap to find the highest recorded block
- * and set the write pointer to the block after that. In case of a
- * power loss this misses blocks where the data I/O has completed but
- * not recorded in the rmap yet, and it also rewrites blocks if the most
- * recently written ones got deleted again before unmount, but this is
- * the best we can do without hardware support.
- */
- if (!zone || zone->cond == BLK_ZONE_COND_NOT_WP) {
- xfs_rtgroup_lock(rtg, XFS_RTGLOCK_RMAP);
- highest_rgbno = xfs_rtrmap_highest_rgbno(rtg);
- if (highest_rgbno == NULLRGBLOCK)
- write_pointer = 0;
- else
- write_pointer = highest_rgbno + 1;
- xfs_rtgroup_unlock(rtg, XFS_RTGLOCK_RMAP);
- }
-
/*
* If there are no used blocks, but the zone is not in empty state yet
* we lost power before the zoned reset. In that case finish the work
@@ -1066,6 +1066,7 @@ xfs_get_zone_info_cb(
struct xfs_mount *mp = iz->mp;
xfs_fsblock_t zsbno = xfs_daddr_to_rtb(mp, zone->start);
xfs_rgnumber_t rgno;
+ xfs_rgblock_t write_pointer;
struct xfs_rtgroup *rtg;
int error;
@@ -1080,7 +1081,13 @@ xfs_get_zone_info_cb(
xfs_warn(mp, "realtime group not found for zone %u.", rgno);
return -EFSCORRUPTED;
}
- error = xfs_init_zone(iz, rtg, zone);
+ if (!xfs_zone_validate(zone, rtg, &write_pointer)) {
+ xfs_rtgroup_rele(rtg);
+ return -EFSCORRUPTED;
+ }
+ if (zone->cond == BLK_ZONE_COND_NOT_WP)
+ write_pointer = xfs_rmap_estimate_write_pointer(rtg);
+ error = xfs_init_zone(iz, rtg, write_pointer);
xfs_rtgroup_rele(rtg);
return error;
}
@@ -1290,7 +1297,8 @@ xfs_mount_zones(
struct xfs_rtgroup *rtg = NULL;
while ((rtg = xfs_rtgroup_next(mp, rtg))) {
- error = xfs_init_zone(&iz, rtg, NULL);
+ error = xfs_init_zone(&iz, rtg,
+ xfs_rmap_estimate_write_pointer(rtg));
if (error) {
xfs_rtgroup_rele(rtg);
goto out_free_zone_info;