]> git-server-git.apps.pok.os.sepia.ceph.com Git - xfsprogs-dev.git/commitdiff
mkfs: set rtstart from user-specified dblocks
authorDarrick J. Wong <djwong@kernel.org>
Tue, 20 Jan 2026 17:50:48 +0000 (09:50 -0800)
committerAndrey Albershteyn <aalbersh@kernel.org>
Tue, 27 Jan 2026 16:59:35 +0000 (17:59 +0100)
generic/211 fails to format the disk on a system with an internal zoned
device.  Poking through the shell scripts, it's apparently doing this:

# mkfs.xfs -d size=629145600 -r size=629145600 -b size=4096 -m metadir=1,autofsck=1,uquota,gquota,pquota, -r zoned=1 -d rtinherit=1 /dev/sdd
size 629145600 specified for data subvolume is too large, maximum is 131072 blocks

Strange -- we asked for 629M data and rt sections, the device is 20GB in
size, but it claims insufficient space in the data subvolume.

Further analysis shows that open_devices is setting rtstart to 1% of the
size of the data volume (or no less than 300M) and rounding that up to
the nearest power of two (512M).  Hence the 131072 number.

But wait, we said that we wanted a 629M data section.  Let's set rtstart
to the same value if the user didn't already provide one, instead of
using the default value.

Cc: linux-xfs@vger.kernel.org # v6.15.0
Fixes: 2e5a737a61d34e ("xfs_mkfs: support creating file system with zoned RT devices")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
mkfs/xfs_mkfs.c

index b34407725f76df1ae3b73feadc60801a77d93f14..a90160b26065b785a51709acc7332f94000e5dd0 100644 (file)
@@ -3696,6 +3696,36 @@ _("log stripe unit (%d bytes) is too large (maximum is 256KiB)\n"
 
 }
 
+static uint64_t
+calc_rtstart(
+       const struct mkfs_params        *cfg,
+       const struct libxfs_init        *xi)
+{
+       uint64_t                        rt_target_size;
+       uint64_t                        rtstart = 1;
+
+       if (cfg->dblocks) {
+               /*
+                * If the user specified the size of the data device but not
+                * the start of the internal rt device, set the internal rt
+                * volume to start at the end of the data device.
+                */
+               return cfg->dblocks << (cfg->blocklog - BBSHIFT);
+       }
+
+       /*
+        * By default reserve at 1% of the total capacity (rounded up to the
+        * next power of two) for metadata, but match the minimum we enforce
+        * elsewhere. This matches what SMR HDDs provide.
+        */
+       rt_target_size = max((xi->data.size + 99) / 100,
+                            BTOBB(300 * 1024 * 1024));
+
+       while (rtstart < rt_target_size)
+               rtstart <<= 1;
+       return rtstart;
+}
+
 static void
 open_devices(
        struct mkfs_params      *cfg,
@@ -3720,17 +3750,7 @@ open_devices(
                zt->rt.zone_capacity = zt->data.zone_capacity;
                zt->rt.nr_zones = zt->data.nr_zones - zt->data.nr_conv_zones;
        } else if (cfg->sb_feat.zoned && !cfg->rtstart && !xi->rt.dev) {
-               /*
-                * By default reserve at 1% of the total capacity (rounded up to
-                * the next power of two) for metadata, but match the minimum we
-                * enforce elsewhere. This matches what SMR HDDs provide.
-                */
-               uint64_t rt_target_size = max((xi->data.size + 99) / 100,
-                                             BTOBB(300 * 1024 * 1024));
-
-               cfg->rtstart = 1;
-               while (cfg->rtstart < rt_target_size)
-                       cfg->rtstart <<= 1;
+               cfg->rtstart = calc_rtstart(cfg, xi);
        }
 
        if (cfg->rtstart) {