]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
mkfs: create the realtime rmap inode
authorDarrick J. Wong <djwong@kernel.org>
Thu, 15 Aug 2024 18:57:41 +0000 (11:57 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Fri, 16 Aug 2024 21:57:42 +0000 (14:57 -0700)
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
libxfs/libxfs_api_defs.h
mkfs/proto.c
mkfs/xfs_mkfs.c

index 4d72b194408c3ba457f3dff9466acbe4617c8af8..5f00941176d0e54564f7e5a460f4948fae6a484d 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 9a0a1b11fc314d0af58b1959bcf9ed23a0011dec..0f7c1ba6f80acd4f10dc939469820143fb644b2a 100644 (file)
 #define xfs_rtrmapbt_droot_maxrecs     libxfs_rtrmapbt_droot_maxrecs
 #define xfs_rtrmapbt_maxlevels_ondisk  libxfs_rtrmapbt_maxlevels_ondisk
 #define xfs_rtrmapbt_init_cursor       libxfs_rtrmapbt_init_cursor
+#define xfs_rtrmapbt_init_rtsb         libxfs_rtrmapbt_init_rtsb
 #define xfs_rtrmapbt_maxrecs           libxfs_rtrmapbt_maxrecs
 #define xfs_rtrmapbt_mem_init          libxfs_rtrmapbt_mem_init
 #define xfs_rtrmapbt_mem_cursor                libxfs_rtrmapbt_mem_cursor
index 138087daba38bc76c59b20663e5fb9fd4bed24ed..703dfd366e733e9ca0da6eca55e2bb5b8209652c 100644 (file)
@@ -966,6 +966,28 @@ rtfreesp_init(
        }
 }
 
+static int
+init_rtrmap_for_rtsb(
+       struct xfs_rtgroup      *rtg)
+{
+       struct xfs_mount        *mp = rtg->rtg_mount;
+       struct xfs_trans        *tp;
+       int                     error;
+
+       error = -libxfs_trans_alloc_inode(rtg->rtg_inodes[XFS_RTGI_RMAP],
+                       &M_RES(mp)->tr_itruncate, 0, 0, false, &tp);
+       if (error)
+               return error;
+
+       error = -libxfs_rtrmapbt_init_rtsb(mp, rtg, tp);
+       if (error) {
+               libxfs_trans_cancel(tp);
+               return error;
+       }
+
+       return -libxfs_trans_commit(tp);
+}
+
 /*
  * Allocate the realtime bitmap and summary inodes, and fill in data if any.
  */
@@ -991,13 +1013,20 @@ rtinit(
                        create_sb_metadata_file(rtg, XFS_RTGI_SUMMARY,
                                        rtsummary_create);
                } else {
-
                        for (i = 0; i < XFS_RTGI_MAX; i++) {
                                error = -libxfs_rtginode_create(rtg, i, true);
                                if (error)
                                        fail(_("rt group inode creation failed"),
                                                        error);
                        }
+
+                       if (xfs_has_rtsb(mp) && xfs_has_rtrmapbt(mp) &&
+                           rtg->rtg_rgno == 0) {
+                               error = init_rtrmap_for_rtsb(rtg);
+                               if (error)
+                                       fail(_("rtrmap rtsb init failed"),
+                                                       error);
+                       }
                }
 
                rtfreesp_init(rtg);
index 241168d9ef89799ff1e1ea2f22ea1ce774107368..64dad7070e8d6fed1a0ab6d92efd1b15f0049c7d 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_RTGI_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_RTGI_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
         */