]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_mdrestore: restore rt group superblocks to realtime device
authorDarrick J. Wong <djwong@kernel.org>
Thu, 21 Nov 2024 00:24:38 +0000 (16:24 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 24 Dec 2024 02:01:34 +0000 (18:01 -0800)
Support restoring realtime device metadata to the realtime device, if
the dumped filesystem had one.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Andrey Albershteyn <aalbersh@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
man/man8/xfs_mdrestore.8
mdrestore/xfs_mdrestore.c

index f60e7b56ebf0d1128edcaa10368ec7d31d85b0d2..6f6e14e96c6a5c192bc0a4fcbdac14f48ab08543 100644 (file)
@@ -8,6 +8,9 @@ xfs_mdrestore \- restores an XFS metadump image to a filesystem image
 ] [
 .B \-l
 .I logdev
+] [
+.B \-r
+.I rtdev
 ]
 .I source
 .I target
@@ -17,6 +20,9 @@ xfs_mdrestore \- restores an XFS metadump image to a filesystem image
 [
 .B \-l
 .I logdev
+] [
+.B \-r
+.I rtdev
 ]
 .I source
 .br
@@ -61,6 +67,10 @@ Metadump in v2 format can contain metadata dumped from an external log.
 In such a scenario, the user has to provide a device to which the log device
 contents from the metadump file are copied.
 .TP
+.BI \-r " rtdev"
+Restore realtime device metadata to this device.
+This is only required for a metadump in v2 format.
+.TP
 .B \-V
 Prints the version number and exits.
 .SH DIAGNOSTICS
index c5584fec68813ee8a40af30011eedd1b1a9d800b..d5014981b15a68c2ecbbd05fe37ba68e072a3787 100644 (file)
@@ -28,7 +28,8 @@ struct mdrestore_ops {
        void (*show_info)(union mdrestore_headers *header, const char *md_file);
        void (*restore)(union mdrestore_headers *header, FILE *md_fp,
                        const struct mdrestore_dev *ddev,
-                       const struct mdrestore_dev *logdev);
+                       const struct mdrestore_dev *logdev,
+                       const struct mdrestore_dev *rtdev);
 };
 
 static struct mdrestore {
@@ -37,6 +38,7 @@ static struct mdrestore {
        bool                    show_info;
        bool                    progress_since_warning;
        bool                    external_log;
+       bool                    realtime_data;
 } mdrestore;
 
 static void
@@ -212,7 +214,8 @@ restore_v1(
        union mdrestore_headers         *h,
        FILE                            *md_fp,
        const struct mdrestore_dev      *ddev,
-       const struct mdrestore_dev      *logdev)
+       const struct mdrestore_dev      *logdev,
+       const struct mdrestore_dev      *rtdev)
 {
        struct xfs_metablock    *metablock;     /* header + index + blocks */
        __be64                  *block_index;
@@ -336,8 +339,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");
+       if ((h->v2.xmh_incompat_flags & cpu_to_be32(XFS_MD2_INCOMPAT_RTDEVICE)) &&
+           !mdrestore.realtime_data)
+               fatal("Realtime device is required\n");
 }
 
 static void
@@ -346,14 +350,17 @@ show_info_v2(
        const char              *md_file)
 {
        uint32_t                compat_flags;
+       uint32_t                incompat_flags;
 
        compat_flags = be32_to_cpu(h->v2.xmh_compat_flags);
+       incompat_flags = be32_to_cpu(h->v2.xmh_incompat_flags);
 
-       printf("%s: %sobfuscated, %s log, external log contents are %sdumped, %s metadata blocks,\n",
+       printf("%s: %sobfuscated, %s log, external log contents are %sdumped, rt device contents are %sdumped, %s metadata blocks,\n",
                md_file,
                compat_flags & XFS_MD2_COMPAT_OBFUSCATED ? "":"not ",
                compat_flags & XFS_MD2_COMPAT_DIRTYLOG ? "dirty":"clean",
                compat_flags & XFS_MD2_COMPAT_EXTERNALLOG ? "":"not ",
+               incompat_flags & XFS_MD2_INCOMPAT_RTDEVICE ? "":"not ",
                compat_flags & XFS_MD2_COMPAT_FULLBLOCKS ? "full":"zeroed");
 }
 
@@ -390,7 +397,8 @@ restore_v2(
        union mdrestore_headers         *h,
        FILE                            *md_fp,
        const struct mdrestore_dev      *ddev,
-       const struct mdrestore_dev      *logdev)
+       const struct mdrestore_dev      *logdev,
+       const struct mdrestore_dev      *rtdev)
 {
        struct xfs_sb           sb;
        struct xfs_meta_extent  xme;
@@ -431,6 +439,11 @@ restore_v2(
                verify_device_size(logdev, sb.sb_logblocks, sb.sb_blocksize);
        }
 
+       if (sb.sb_rblocks > 0) {
+               ASSERT(mdrestore.realtime_data == true);
+               verify_device_size(rtdev, sb.sb_rblocks, sb.sb_blocksize);
+       }
+
        if (pwrite(ddev->fd, block_buffer, len, 0) < 0)
                fatal("error writing primary superblock: %s\n",
                        strerror(errno));
@@ -459,6 +472,10 @@ restore_v2(
                        device = "log";
                        fd = logdev->fd;
                        break;
+               case XME_ADDR_RT_DEVICE:
+                       device = "rt";
+                       fd = rtdev->fd;
+                       break;
                default:
                        fatal("Invalid device found in metadump\n");
                        break;
@@ -488,7 +505,7 @@ static struct mdrestore_ops mdrestore_ops_v2 = {
 static void
 usage(void)
 {
-       fprintf(stderr, "Usage: %s [-V] [-g] [-i] [-l logdev] source target\n",
+       fprintf(stderr, "Usage: %s [-V] [-g] [-i] [-l logdev] [-r rtdev] source target\n",
                progname);
        exit(1);
 }
@@ -501,18 +518,21 @@ main(
        union mdrestore_headers headers;
        DEFINE_MDRESTORE_DEV(ddev);
        DEFINE_MDRESTORE_DEV(logdev);
+       DEFINE_MDRESTORE_DEV(rtdev);
        FILE                    *src_f;
        char                    *logdev_path = NULL;
+       char                    *rtdev_path = NULL;
        int                     c;
 
        mdrestore.show_progress = false;
        mdrestore.show_info = false;
        mdrestore.progress_since_warning = false;
        mdrestore.external_log = false;
+       mdrestore.realtime_data = false;
 
        progname = basename(argv[0]);
 
-       while ((c = getopt(argc, argv, "gil:V")) != EOF) {
+       while ((c = getopt(argc, argv, "gil:r:V")) != EOF) {
                switch (c) {
                        case 'g':
                                mdrestore.show_progress = true;
@@ -524,6 +544,10 @@ main(
                                logdev_path = optarg;
                                mdrestore.external_log = true;
                                break;
+                       case 'r':
+                               rtdev_path = optarg;
+                               mdrestore.realtime_data = true;
+                               break;
                        case 'V':
                                printf("%s version %s\n", progname, VERSION);
                                exit(0);
@@ -592,10 +616,15 @@ main(
        if (mdrestore.external_log)
                open_device(&logdev, logdev_path);
 
-       mdrestore.mdrops->restore(&headers, src_f, &ddev, &logdev);
+       /* check and open realtime device */
+       if (mdrestore.realtime_data)
+               open_device(&rtdev, rtdev_path);
+
+       mdrestore.mdrops->restore(&headers, src_f, &ddev, &logdev, &rtdev);
 
        close_device(&ddev);
        close_device(&logdev);
+       close_device(&rtdev);
 
        if (src_f != stdin)
                fclose(src_f);