]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
mkfs: enable reflink on the realtime device
authorDarrick J. Wong <djwong@kernel.org>
Mon, 24 Feb 2025 18:22:07 +0000 (10:22 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 25 Feb 2025 17:16:02 +0000 (09:16 -0800)
Allow the creation of filesystems with both reflink and realtime volumes
enabled.  For now we don't support a realtime extent size > 1.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
libxfs/init.c
libxfs/libxfs_api_defs.h
mkfs/xfs_mkfs.c

index 00bd46a6013e2841bf51da325791419bb7b77e5d..5b45ed3472762ca20319b0f5735ecc0eb1611eae 100644 (file)
@@ -305,9 +305,9 @@ rtmount_init(
        if (mp->m_sb.sb_rblocks == 0)
                return 0;
 
-       if (xfs_has_reflink(mp)) {
+       if (xfs_has_reflink(mp) && mp->m_sb.sb_rextsize > 1) {
                fprintf(stderr,
-       _("%s: Reflink not compatible with realtime device. Please try a newer xfsprogs.\n"),
+       _("%s: Reflink not compatible with realtime extent size > 1. Please try a newer xfsprogs.\n"),
                                progname);
                return -1;
        }
index 66cbb34f05a48f7a5cecaf32e552229cda0ab1ce..530feef2a47db8e3f32c0df1eed6c91a811f9be5 100644 (file)
 #define xfs_rtrefcountbt_absolute_maxlevels    libxfs_rtrefcountbt_absolute_maxlevels
 #define xfs_rtrefcountbt_calc_reserves libxfs_rtrefcountbt_calc_reserves
 #define xfs_rtrefcountbt_calc_size             libxfs_rtrefcountbt_calc_size
+#define xfs_rtrefcountbt_calc_reserves libxfs_rtrefcountbt_calc_reserves
 #define xfs_rtrefcountbt_commit_staged_btree   libxfs_rtrefcountbt_commit_staged_btree
 #define xfs_rtrefcountbt_create                libxfs_rtrefcountbt_create
 #define xfs_rtrefcountbt_droot_maxrecs libxfs_rtrefcountbt_droot_maxrecs
index 9dc71fb8c4c82af4fe844a75ecbadd09e3d4144e..3f4455d4638315d233d50ff1bcda19b85dc23d15 100644 (file)
@@ -2671,12 +2671,36 @@ _("inode btree counters not supported without finobt support\n"));
        }
 
        if (cli->xi->rt.name) {
-               if (cli->sb_feat.reflink && cli_opt_set(&mopts, M_REFLINK)) {
-                       fprintf(stderr,
-_("reflink not supported with realtime devices\n"));
-                       usage();
+               if (cli->rtextsize && cli->sb_feat.reflink) {
+                       if (cli_opt_set(&mopts, M_REFLINK)) {
+                               fprintf(stderr,
+_("reflink not supported on realtime devices with rt extent size specified\n"));
+                               usage();
+                       }
+                       cli->sb_feat.reflink = false;
+               }
+               if (cfg->blocksize < XFS_MIN_RTEXTSIZE && cli->sb_feat.reflink) {
+                       if (cli_opt_set(&mopts, M_REFLINK)) {
+                               fprintf(stderr,
+_("reflink not supported on realtime devices with blocksize %d < %d\n"),
+                                               cli->blocksize,
+                                               XFS_MIN_RTEXTSIZE);
+                               usage();
+                       }
+                       cli->sb_feat.reflink = false;
+               }
+               if (!cli->sb_feat.metadir && cli->sb_feat.reflink) {
+                       if (cli_opt_set(&mopts, M_REFLINK) &&
+                           cli_opt_set(&mopts, M_METADIR)) {
+                               fprintf(stderr,
+_("reflink not supported on realtime devices without metadir feature\n"));
+                               usage();
+                       } else if (cli_opt_set(&mopts, M_REFLINK)) {
+                               cli->sb_feat.metadir = true;
+                       } else {
+                               cli->sb_feat.reflink = false;
+                       }
                }
-               cli->sb_feat.reflink = false;
 
                if (!cli->sb_feat.metadir && cli->sb_feat.rmapbt) {
                        if (cli_opt_set(&mopts, M_RMAPBT) &&
@@ -2874,6 +2898,19 @@ validate_rtextsize(
                        usage();
                }
                cfg->rtextblocks = (xfs_extlen_t)(rtextbytes >> cfg->blocklog);
+       } else if (cli->sb_feat.reflink && cli->xi->rt.name) {
+               /*
+                * reflink doesn't support rt extent size > 1FSB yet, so set
+                * an extent size of 1FSB.  Make sure we still satisfy the
+                * minimum rt extent size.
+                */
+               if (cfg->blocksize < XFS_MIN_RTEXTSIZE) {
+                       fprintf(stderr,
+               _("reflink not supported on rt volume with blocksize %d\n"),
+                               cfg->blocksize);
+                       usage();
+               }
+               cfg->rtextblocks = 1;
        } else {
                /*
                 * If realtime extsize has not been specified by the user,
@@ -2905,6 +2942,12 @@ validate_rtextsize(
                }
        }
        ASSERT(cfg->rtextblocks);
+
+       if (cli->sb_feat.reflink && cfg->rtblocks > 0 && cfg->rtextblocks > 1) {
+               fprintf(stderr,
+_("reflink not supported on realtime with extent sizes > 1\n"));
+               usage();
+       }
 }
 
 /* Validate the incoming extsize hint. */
@@ -5086,11 +5129,19 @@ check_rt_meta_prealloc(
                error = -libxfs_metafile_resv_init(rtg_rmap(rtg), ask);
                if (error)
                        prealloc_fail(mp, error, ask, _("realtime rmap btree"));
+
+               ask = libxfs_rtrefcountbt_calc_reserves(mp);
+               error = -libxfs_metafile_resv_init(rtg_refcount(rtg), ask);
+               if (error)
+                       prealloc_fail(mp, error, ask,
+                                       _("realtime refcount btree"));
        }
 
        /* Unreserve the realtime metadata reservations. */
-       while ((rtg = xfs_rtgroup_next(mp, rtg)))
+       while ((rtg = xfs_rtgroup_next(mp, rtg))) {
                libxfs_metafile_resv_free(rtg_rmap(rtg));
+               libxfs_metafile_resv_free(rtg_refcount(rtg));
+       }
 
        /* Unreserve the per-AG reservations. */
        while ((pag = xfs_perag_next(mp, pag)))