]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
mkfs: create the realtime rmap inode xfs-realtime-rmap-rebase
authorDarrick J. Wong <djwong@kernel.org>
Fri, 9 Aug 2024 12:34:30 +0000 (14:34 +0200)
committerChristoph Hellwig <hch@lst.de>
Sun, 11 Aug 2024 06:35:55 +0000 (08:35 +0200)
Create a realtime rmapbt inode if we format the fs with realtime
and rmap.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
libxfs/init.c
mkfs/xfs_mkfs.c

index 61b9e2463320321e577d4382539eff412ff0aef1..3e2a74ee743fd9250d587a9b8f56c4f5d4398bd8 100644 (file)
@@ -307,13 +307,6 @@ rtmount_init(
                return -1;
        }
 
-       if (xfs_has_rmapbt(mp)) {
-               fprintf(stderr,
-       _("%s: Reverse mapping btree not compatible with realtime device. Please try a newer xfsprogs.\n"),
-                               progname);
-               return -1;
-       }
-
        if (mp->m_rtdev_targp->bt_bdev == 0 && !xfs_is_debugger(mp)) {
                fprintf(stderr, _("%s: filesystem has a realtime subvolume\n"),
                        progname);
index 5aae3b84a64c2de1b9f823d0a4f4f4d6a909819e..a945aeebd850bb0e991ad486173c05dbfc441ede 100644 (file)
@@ -2560,12 +2560,18 @@ _("reflink not supported with realtime devices\n"));
                }
                cli->sb_feat.reflink = false;
 
-               if (cli->sb_feat.rmapbt && cli_opt_set(&mopts, M_RMAPBT)) {
-                       fprintf(stderr,
-_("rmapbt not supported with realtime devices\n"));
-                       usage();
+               if (!cli->sb_feat.rtgroups && cli->sb_feat.rmapbt) {
+                       if (cli_opt_set(&mopts, M_RMAPBT) &&
+                           cli_opt_set(&ropts, R_RTGROUPS)) {
+                               fprintf(stderr,
+_("rmapbt not supported on realtime devices without rtgroups feature\n"));
+                               usage();
+                       } else if (cli_opt_set(&mopts, M_RMAPBT)) {
+                               cli->sb_feat.rtgroups = true;
+                       } else {
+                               cli->sb_feat.rmapbt = false;
+                       }
                }
-               cli->sb_feat.rmapbt = false;
        }
 
        if ((cli->fsx.fsx_xflags & FS_XFLAG_COWEXTSIZE) &&
@@ -4803,6 +4809,78 @@ write_rtsb(
        libxfs_buf_relse(sb_bp);
 }
 
+static inline void
+prealloc_fail(
+       struct xfs_mount        *mp,
+       int                     error,
+       xfs_filblks_t           ask,
+       const char              *tag)
+{
+       if (error == ENOSPC)
+               fprintf(stderr,
+       _("%s: cannot handle expansion of %s; need %llu free blocks, have %llu\n"),
+                               progname, tag, (unsigned long long)ask,
+                               (unsigned long long)mp->m_sb.sb_fdblocks);
+       else
+               fprintf(stderr,
+       _("%s: error %d while checking free space for %s\n"),
+                               progname, error, tag);
+       exit(1);
+}
+
+/*
+ * Make sure there's enough space on the data device to handle realtime
+ * metadata btree expansions.
+ */
+static void
+check_rt_meta_prealloc(
+       struct xfs_mount        *mp)
+{
+       struct xfs_perag        *pag;
+       struct xfs_rtgroup      *rtg;
+       xfs_agnumber_t          agno;
+       xfs_rgnumber_t          rgno;
+       xfs_filblks_t           ask;
+       int                     error;
+
+       /*
+        * First create all the per-AG reservations, since they take from the
+        * free block count.  Each AG should start with enough free space for
+        * the per-AG reservation.
+        */
+       mp->m_finobt_nores = false;
+
+       for_each_perag(mp, agno, pag) {
+               error = -libxfs_ag_resv_init(pag, NULL);
+               if (error && error != ENOSPC) {
+                       fprintf(stderr,
+       _("%s: error %d while checking AG free space for realtime metadata\n"),
+                                       progname, error);
+                       exit(1);
+               }
+       }
+
+       /* Realtime metadata btree inode */
+       for_each_rtgroup(mp, rgno, rtg) {
+               ask = libxfs_rtrmapbt_calc_reserves(mp);
+               error = -libxfs_metafile_resv_init(
+                               rtg->rtg_inodes[XFS_RTG_RMAP], ask);
+               if (error)
+                       prealloc_fail(mp, error, ask, _("realtime rmap btree"));
+       }
+
+       /* Unreserve the realtime metadata reservations. */
+       for_each_rtgroup(mp, rgno, rtg) {
+               libxfs_metafile_resv_free(rtg->rtg_inodes[XFS_RTG_RMAP]);
+       }
+
+       /* Unreserve the per-AG reservations. */
+       for_each_perag(mp, agno, pag)
+               libxfs_ag_resv_free(pag);
+
+       mp->m_finobt_nores = false;
+}
+
 int
 main(
        int                     argc,
@@ -5139,6 +5217,9 @@ main(
         */
        check_root_ino(mp);
 
+       /* Make sure we can handle space preallocations of rt metadata btrees */
+       check_rt_meta_prealloc(mp);
+
        /*
         * Re-write multiple secondary superblocks with rootinode field set
         */