]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
mkfs: enable reflink on the realtime device
authorDarrick J. Wong <djwong@kernel.org>
Fri, 15 Jul 2022 21:34:50 +0000 (14:34 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Wed, 22 Nov 2023 23:03:42 +0000 (15:03 -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>
libxfs/init.c
mkfs/proto.c
mkfs/xfs_mkfs.c

index 00d606f39bc25ab92bbd59aac395d65bd0fed981..88674dba7499fe354e33db3cdf8faa7feb3fcce0 100644 (file)
@@ -455,9 +455,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 436f9ac82b2e09281d10300c6c4570e9beb79084..5b9f36424864b2ff285218b07cde195c5f585d7b 100644 (file)
@@ -884,6 +884,40 @@ rtrmapbt_create(
        libxfs_imeta_free_path(path);
 }
 
+/* Create the realtime refcount btree inode. */
+static void
+rtrefcountbt_create(
+       struct xfs_rtgroup      *rtg)
+{
+       struct xfs_imeta_update upd;
+       struct xfs_mount        *mp = rtg->rtg_mount;
+       struct xfs_imeta_path   *path;
+       int                     error;
+
+       error = -libxfs_rtrefcountbt_create_path(mp, rtg->rtg_rgno, &path);
+       if (error)
+               fail( _("rtrefcount inode path creation failed"), error);
+
+       error = -libxfs_imeta_ensure_dirpath(mp, path);
+       if (error)
+               fail(_("rtgroup allocation failed"),
+                               error);
+
+       error = -libxfs_imeta_start_create(mp, path, &upd);
+       if (error)
+               res_failed(error);
+
+       error = -libxfs_rtrefcountbt_create(&upd, &rtg->rtg_refcountip);
+       if (error)
+               fail(_("rtrefcount inode creation failed"), error);
+
+       error = -libxfs_imeta_commit_update(&upd);
+       if (error)
+               fail(_("rtrefcountbt commit failed"), error);
+
+       libxfs_imeta_free_path(path);
+}
+
 /* Initialize block headers of rt free space files. */
 static int
 init_rtblock_headers(
@@ -1066,6 +1100,8 @@ rtinit(
        for_each_rtgroup(mp, rgno, rtg) {
                if (xfs_has_rtrmapbt(mp))
                        rtrmapbt_create(rtg);
+               if (xfs_has_rtreflink(mp))
+                       rtrefcountbt_create(rtg);
        }
 
        if (mp->m_sb.sb_rbmblocks == 0)
index 09cb275e97a760900b181c8d751fedff058d87b0..0edf2b781180f54b2b5bd5d346a45a2bfb893bcb 100644 (file)
@@ -2479,12 +2479,36 @@ _("parent pointers not supported on v4 filesystems\n"));
        }
 
        if (cli->xi->rtname) {
-               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 (cli->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.rtgroups && cli->sb_feat.reflink) {
+                       if (cli_opt_set(&mopts, M_REFLINK) &&
+                           cli_opt_set(&ropts, R_RTGROUPS)) {
+                               fprintf(stderr,
+_("reflink not supported on realtime devices without rtgroups feature\n"));
+                               usage();
+                       } else if (cli_opt_set(&mopts, M_REFLINK)) {
+                               cli->sb_feat.rtgroups = true;
+                       } else {
+                               cli->sb_feat.reflink = false;
+                       }
                }
-               cli->sb_feat.reflink = false;
 
                if (!cli->sb_feat.rtgroups && cli->sb_feat.rmapbt) {
                        if (cli_opt_set(&mopts, M_RMAPBT) &&
@@ -2652,6 +2676,19 @@ validate_rtextsize(
                        usage();
                }
                cfg->rtextblocks = (xfs_extlen_t)(rtextbytes >> cfg->blocklog);
+       } else if (cli->sb_feat.reflink && cli->xi->rtname) {
+               /*
+                * 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,
@@ -2683,6 +2720,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. */
@@ -4680,10 +4723,16 @@ check_rt_meta_prealloc(
                error = -libxfs_imeta_resv_init_inode(rtg->rtg_rmapip, ask);
                if (error)
                        prealloc_fail(mp, error, ask, _("realtime rmap btree"));
+
+               ask = libxfs_rtrefcountbt_calc_reserves(mp);
+               error = -libxfs_imeta_resv_init_inode(rtg->rtg_refcountip, ask);
+               if (error)
+                       prealloc_fail(mp, error, ask, _("realtime refcount btree"));
        }
 
        /* Unreserve the realtime metadata reservations. */
        for_each_rtgroup(mp, rgno, rtg) {
+               libxfs_imeta_resv_free_inode(rtg->rtg_refcountip);
                libxfs_imeta_resv_free_inode(rtg->rtg_rmapip);
        }