]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
xfs_db: metadump realtime devices
authorDarrick J. Wong <djwong@kernel.org>
Wed, 3 Jul 2024 21:22:08 +0000 (14:22 -0700)
committerChristoph Hellwig <hch@lst.de>
Tue, 6 Aug 2024 12:53:50 +0000 (05:53 -0700)
Teach the metadump device to dump the filesystem metadata of a realtime
device to the metadump file.  Currently, this is limited to the realtime
superblock.

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 04b437e617df0e8ed5a3612a1a636d2f6a19bc7e..93d12b20a6cce07cdcd16fb14c29cfb307462430 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;
@@ -3027,6 +3028,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);
@@ -3039,8 +3041,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");
@@ -3050,6 +3055,30 @@ init_metadump_v2(void)
        return 0;
 }
 
+static int
+copy_rtsb(void)
+{
+       int             error;
+
+       if (metadump.show_progress)
+               print_progress("Copying realtime superblock");
+
+       push_cur();
+       error = set_rt_cur(&typtab[TYP_RTSB], XFS_RTSB_DADDR,
+                       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 realtime superblock");
+               return !metadump.stop_on_read_error;
+       }
+       error = write_buf(iocur_top);
+       pop_cur();
+
+       return error ? 0 : 1;
+}
+
 static int
 write_metadump_v2(
        enum typnm              type,
@@ -3064,6 +3093,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;
 
@@ -3112,6 +3143,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",
@@ -3190,6 +3222,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.
         *
@@ -3289,6 +3335,12 @@ metadump_f(
        if (!exitcode && !(metadump.version == 1 && metadump.external_log))
                exitcode = !copy_log();
 
+       /* copy rt superblock */
+       if (!exitcode && metadump.realtime_data && xfs_has_rtsb(mp)) {
+               if (!copy_rtsb())
+                       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 269edb8f89969d5401b418f80115116c0d82dc25..c6c00270234442ea14d84c4e554113253b037d89 100644 (file)
@@ -314,7 +314,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)
@@ -324,6 +324,9 @@ read_header_v2(
 
        if (!mdrestore.external_log && (compat & XFS_MD2_COMPAT_EXTERNALLOG))
                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