]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
xfs_db: metadump realtime devices
authorDarrick J. Wong <djwong@kernel.org>
Thu, 25 Aug 2022 21:43:51 +0000 (14:43 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Wed, 22 Nov 2023 23:03:34 +0000 (15:03 -0800)
Teach the metadump device to dump the filesystem metadata of a realtime
device to the metadump file.  Currently, this is limited to the rt group
superblocks.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
db/metadump.c
db/xfs_metadump.sh
include/xfs_metadump.h
man/man8/xfs_metadump.8
mdrestore/xfs_mdrestore.c

index 3e3fa9a0f9ec9360120f5e879a39dacebec4b959..01411cc2508d472dc25481c4548f4f517aadba09 100644 (file)
@@ -85,6 +85,7 @@ static struct metadump {
        bool                    dirty_log;
        bool                    external_log;
        bool                    stdout_metadump;
+       bool                    realtime_data;
        xfs_ino_t               cur_ino;
        /* Metadump file */
        FILE                    *outf;
@@ -3099,6 +3100,7 @@ init_metadump_v2(void)
 {
        struct xfs_metadump_header      xmh = {0};
        uint32_t                        compat_flags = 0;
+       uint32_t                        incompat_flags = 0;
 
        xmh.xmh_magic = cpu_to_be32(XFS_MD_MAGIC_V2);
        xmh.xmh_version = cpu_to_be32(2);
@@ -3111,8 +3113,11 @@ init_metadump_v2(void)
                compat_flags |= XFS_MD2_COMPAT_DIRTYLOG;
        if (metadump.external_log)
                compat_flags |= XFS_MD2_COMPAT_EXTERNALLOG;
+       if (metadump.realtime_data)
+               incompat_flags |= XFS_MD2_INCOMPAT_RTDEVICE;
 
        xmh.xmh_compat_flags = cpu_to_be32(compat_flags);
+       xmh.xmh_incompat_flags = cpu_to_be32(incompat_flags);
 
        if (fwrite(&xmh, sizeof(xmh), 1, metadump.outf) != 1) {
                print_warning("error writing to target file");
@@ -3122,6 +3127,39 @@ init_metadump_v2(void)
        return 0;
 }
 
+static int
+copy_rtsupers(void)
+{
+       int             error;
+       xfs_rtblock_t   rtbno;
+       xfs_rgnumber_t  rgno = 0;
+
+       if (metadump.show_progress)
+               print_progress("Copying realtime superblocks");
+
+       for (rgno = 0; rgno < mp->m_sb.sb_rgcount; rgno++) {
+               rtbno = xfs_rgbno_to_rtb(mp, rgno, 0);
+
+               push_cur();
+               error = set_rt_cur(&typtab[TYP_RTSB],
+                               xfs_rtb_to_daddr(mp, rtbno),
+                               XFS_FSB_TO_BB(mp, 1), DB_RING_ADD, NULL);
+               if (error)
+                       return 0;
+               if (iocur_top->data == NULL) {
+                       pop_cur();
+                       print_warning("cannot read rt super %u", rgno);
+                       return !metadump.stop_on_read_error;
+               }
+               error = write_buf(iocur_top);
+               pop_cur();
+               if (error)
+                       return 0;
+       }
+
+       return 1;
+}
+
 static int
 write_metadump_v2(
        enum typnm              type,
@@ -3136,6 +3174,8 @@ write_metadump_v2(
        if (type == TYP_LOG &&
            mp->m_logdev_targp->bt_bdev != mp->m_ddev_targp->bt_bdev)
                addr |= XME_ADDR_LOG_DEVICE;
+       else if (type == TYP_RTSB)
+               addr |= XME_ADDR_RT_DEVICE;
        else
                addr |= XME_ADDR_DATA_DEVICE;
 
@@ -3184,6 +3224,7 @@ metadump_f(
        metadump.zero_stale_data = true;
        metadump.dirty_log = false;
        metadump.external_log = false;
+       metadump.realtime_data = false;
 
        if (mp->m_sb.sb_magicnum != XFS_SB_MAGIC) {
                print_warning("bad superblock magic number %x, giving up",
@@ -3262,6 +3303,20 @@ metadump_f(
                return 1;
        }
 
+       /* The realtime device only contains metadata if rtgroups is enabled. */
+       if (mp->m_rtdev_targp->bt_bdev && xfs_has_rtgroups(mp))
+               metadump.realtime_data = true;
+
+       if (metadump.realtime_data && !version_opt_set)
+               metadump.version = 2;
+
+       if (metadump.version == 2 && xfs_has_realtime(mp) &&
+           xfs_has_rtgroups(mp) &&
+           !metadump.realtime_data) {
+               print_warning("realtime device not loaded, use -R");
+               return 1;
+       }
+
        /*
         * If we'll copy the log, see if the log is dirty.
         *
@@ -3365,6 +3420,12 @@ metadump_f(
        if (!exitcode && !(metadump.version == 1 && metadump.external_log))
                exitcode = !copy_log();
 
+       /* copy rt sueprblocks */
+       if (!exitcode && metadump.realtime_data) {
+               if (!copy_rtsupers())
+                       exitcode = 1;
+       }
+
        /* write the remaining index */
        if (!exitcode && metadump.mdops->finish_dump)
                exitcode = metadump.mdops->finish_dump() < 0;
index 9e8f86e53eb45da0c2a12da65f23700474a893a0..b5c6959f2007f8ec193c918e93c731376084041e 100755 (executable)
@@ -6,9 +6,9 @@
 
 OPTS=" "
 DBOPTS=" "
-USAGE="Usage: xfs_metadump [-aefFogwV] [-m max_extents] [-l logdev] source target"
+USAGE="Usage: xfs_metadump [-aefFogwV] [-m max_extents] [-l logdev] [-r rtdev] [-v version] source target"
 
-while getopts "aefgl:m:owFv:V" c
+while getopts "aefFgl:m:or:wv:V" c
 do
        case $c in
        a)      OPTS=$OPTS"-a ";;
@@ -25,6 +25,7 @@ do
                status=$?
                exit $status
                ;;
+       r)      DBOPTS=$DBOPTS"-R "$OPTARG" ";;
        \?)     echo $USAGE 1>&2
                exit 2
                ;;
index e9c3dcb8f711b91e20191a574d42c8907a21af99..e35f791573efc261c52101d893c7c68fb26f762b 100644 (file)
@@ -68,12 +68,18 @@ struct xfs_metadump_header {
 /* Dump contains external log contents. */
 #define XFS_MD2_COMPAT_EXTERNALLOG     (1 << 3)
 
+/* Dump contains realtime device contents. */
+#define XFS_MD2_INCOMPAT_RTDEVICE      (1U << 0)
+
+#define XFS_MD2_INCOMPAT_ALL           (XFS_MD2_INCOMPAT_RTDEVICE)
+
 struct xfs_meta_extent {
        /*
         * Lowest 54 bits are used to store 512 byte addresses.
         * Next 2 bits is used for indicating the device.
         * 00 - Data device
         * 01 - External log
+        * 10 - Realtime device
         */
        __be64 xme_addr;
        /* In units of 512 byte blocks */
@@ -88,6 +94,8 @@ struct xfs_meta_extent {
 #define XME_ADDR_DATA_DEVICE   (0ULL << XME_ADDR_DEVICE_SHIFT)
 /* Extent was copied from the log device */
 #define XME_ADDR_LOG_DEVICE    (1ULL << XME_ADDR_DEVICE_SHIFT)
+/* Extent was copied from the rt device */
+#define XME_ADDR_RT_DEVICE     (2ULL << XME_ADDR_DEVICE_SHIFT)
 
 #define XME_ADDR_DEVICE_MASK   (3ULL << XME_ADDR_DEVICE_SHIFT)
 
index 496b5926603f4859954bc3f1fc6130f40e944f83..8618ea99b9a57eab3fe558335a4ba408e6ff293f 100644 (file)
@@ -12,6 +12,9 @@ xfs_metadump \- copy XFS filesystem metadata to a file
 .B \-l
 .I logdev
 ] [
+.B \-r
+.I rtdev
+] [
 .B \-v
 .I version
 ]
@@ -146,6 +149,14 @@ this value.  The default size is 2097151 blocks.
 .B \-o
 Disables obfuscation of file names and extended attributes.
 .TP
+.BI \-r  " rtdev"
+For filesystems that have a realtime section, this specifies the device where
+the realtime section resides.
+If the v2 metadump format is selected, the realtime group superblocks will be
+copied to the metadump.
+The v2 metadump format will be selected automatically if the filesystem
+contains realtime groups.
+.TP
 .B \-v
 The format of the metadump file to be produced.
 Valid values are 1 and 2.
index 807df15b40db2e406d9692cd1049d65e8ec36144..ad50842ce19f428a795dc41cb1f0b86c722481a8 100644 (file)
@@ -280,7 +280,7 @@ read_header_v2(
                        sizeof(h->v2) - sizeof(h->v2.xmh_magic), 1, md_fp) != 1)
                fatal("error reading from metadump file\n");
 
-       if (h->v2.xmh_incompat_flags != 0)
+       if (h->v2.xmh_incompat_flags & cpu_to_be32(~XFS_MD2_INCOMPAT_ALL))
                fatal("Metadump header has unknown incompat flags set\n");
 
        if (h->v2.xmh_reserved != 0)
@@ -289,6 +289,9 @@ read_header_v2(
        if ((h->v2.xmh_compat_flags & cpu_to_be32(XFS_MD2_COMPAT_EXTERNALLOG)) &&
            !mdrestore.external_log)
                fatal("External Log device is required\n");
+
+       if (h->v2.xmh_incompat_flags & cpu_to_be32(XFS_MD2_INCOMPAT_RTDEVICE))
+               fatal("Realtime device not yet supported\n");
 }
 
 static void