]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
metadump: Define and use struct metadump
authorChandan Babu R <chandan.babu@oracle.com>
Mon, 6 Nov 2023 13:10:37 +0000 (18:40 +0530)
committerCarlos Maiolino <cem@kernel.org>
Tue, 21 Nov 2023 13:09:36 +0000 (14:09 +0100)
This commit collects all state tracking variables in a new "struct metadump"
structure. This is done to collect all the global variables in one place
rather than having them spread across the file. A new structure member of type
"struct metadump_ops *" will be added by a future commit to support the two
versions of metadump.

Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
db/metadump.c

index 14eda6880cbbf9d26073c87cf5b9f000b92ddd96..da91000c7ab9efebed07c1919f5f676ad64fe858 100644 (file)
@@ -41,25 +41,27 @@ static const cmdinfo_t      metadump_cmd =
                N_("[-a] [-e] [-g] [-m max_extent] [-w] [-o] filename"),
                N_("dump metadata to a file"), metadump_help };
 
-static FILE            *outf;          /* metadump file */
-
-static xfs_metablock_t         *metablock;     /* header + index + buffers */
-static __be64          *block_index;
-static char            *block_buffer;
-
-static int             num_indices;
-static int             cur_index;
-
-static xfs_ino_t       cur_ino;
-
-static bool            show_progress = false;
-static bool            stop_on_read_error = false;
-static int             max_extent_size = DEFAULT_MAX_EXT_SIZE;
-static bool            obfuscate = true;
-static bool            zero_stale_data = true;
-static bool            show_warnings = false;
-static bool            progress_since_warning = false;
-static bool            stdout_metadump;
+static struct metadump {
+       int                     version;
+       bool                    show_progress;
+       bool                    stop_on_read_error;
+       int                     max_extent_size;
+       bool                    show_warnings;
+       bool                    obfuscate;
+       bool                    zero_stale_data;
+       bool                    progress_since_warning;
+       bool                    dirty_log;
+       bool                    stdout_metadump;
+       xfs_ino_t               cur_ino;
+       /* Metadump file */
+       FILE                    *outf;
+       /* header + index + buffers */
+       struct xfs_metablock    *metablock;
+       __be64                  *block_index;
+       char                    *block_buffer;
+       int                     num_indices;
+       int                     cur_index;
+} metadump;
 
 void
 metadump_init(void)
@@ -99,9 +101,10 @@ print_warning(const char *fmt, ...)
        va_end(ap);
        buf[sizeof(buf)-1] = '\0';
 
-       fprintf(stderr, "%s%s: %s\n", progress_since_warning ? "\n" : "",
+       fprintf(stderr, "%s%s: %s\n",
+                       metadump.progress_since_warning ? "\n" : "",
                        progname, buf);
-       progress_since_warning = false;
+       metadump.progress_since_warning = false;
 }
 
 static void
@@ -119,10 +122,10 @@ print_progress(const char *fmt, ...)
        va_end(ap);
        buf[sizeof(buf)-1] = '\0';
 
-       f = stdout_metadump ? stderr : stdout;
+       f = metadump.stdout_metadump ? stderr : stdout;
        fprintf(f, "\r%-59s", buf);
        fflush(f);
-       progress_since_warning = true;
+       metadump.progress_since_warning = true;
 }
 
 /*
@@ -137,17 +140,19 @@ print_progress(const char *fmt, ...)
 static int
 write_index(void)
 {
+       struct xfs_metablock *metablock = metadump.metablock;
        /*
         * write index block and following data blocks (streaming)
         */
-       metablock->mb_count = cpu_to_be16(cur_index);
-       if (fwrite(metablock, (cur_index + 1) << BBSHIFT, 1, outf) != 1) {
+       metablock->mb_count = cpu_to_be16(metadump.cur_index);
+       if (fwrite(metablock, (metadump.cur_index + 1) << BBSHIFT, 1,
+                       metadump.outf) != 1) {
                print_warning("error writing to target file");
                return -1;
        }
 
-       memset(block_index, 0, num_indices * sizeof(__be64));
-       cur_index = 0;
+       memset(metadump.block_index, 0, metadump.num_indices * sizeof(__be64));
+       metadump.cur_index = 0;
        return 0;
 }
 
@@ -164,9 +169,10 @@ write_buf_segment(
        int             ret;
 
        for (i = 0; i < len; i++, off++, data += BBSIZE) {
-               block_index[cur_index] = cpu_to_be64(off);
-               memcpy(&block_buffer[cur_index << BBSHIFT], data, BBSIZE);
-               if (++cur_index == num_indices) {
+               metadump.block_index[metadump.cur_index] = cpu_to_be64(off);
+               memcpy(&metadump.block_buffer[metadump.cur_index << BBSHIFT],
+                               data, BBSIZE);
+               if (++metadump.cur_index == metadump.num_indices) {
                        ret = write_index();
                        if (ret)
                                return -EIO;
@@ -389,11 +395,11 @@ scan_btree(
        if (iocur_top->data == NULL) {
                print_warning("cannot read %s block %u/%u", typtab[btype].name,
                                agno, agbno);
-               rval = !stop_on_read_error;
+               rval = !metadump.stop_on_read_error;
                goto pop_out;
        }
 
-       if (zero_stale_data) {
+       if (metadump.zero_stale_data) {
                zero_btree_block(iocur_top->data, btype);
                iocur_top->need_crc = 1;
        }
@@ -447,7 +453,7 @@ scanfunc_freesp(
 
        numrecs = be16_to_cpu(block->bb_numrecs);
        if (numrecs > mp->m_alloc_mxr[1]) {
-               if (show_warnings)
+               if (metadump.show_warnings)
                        print_warning("invalid numrecs (%u) in %s block %u/%u",
                                numrecs, typtab[btype].name, agno, agbno);
                return 1;
@@ -456,7 +462,7 @@ scanfunc_freesp(
        pp = XFS_ALLOC_PTR_ADDR(mp, block, 1, mp->m_alloc_mxr[1]);
        for (i = 0; i < numrecs; i++) {
                if (!valid_bno(agno, be32_to_cpu(pp[i]))) {
-                       if (show_warnings)
+                       if (metadump.show_warnings)
                                print_warning("invalid block number (%u/%u) "
                                        "in %s block %u/%u",
                                        agno, be32_to_cpu(pp[i]),
@@ -483,13 +489,13 @@ copy_free_bno_btree(
 
        /* validate root and levels before processing the tree */
        if (root == 0 || root > mp->m_sb.sb_agblocks) {
-               if (show_warnings)
+               if (metadump.show_warnings)
                        print_warning("invalid block number (%u) in bnobt "
                                        "root in agf %u", root, agno);
                return 1;
        }
        if (levels > mp->m_alloc_maxlevels) {
-               if (show_warnings)
+               if (metadump.show_warnings)
                        print_warning("invalid level (%u) in bnobt root "
                                        "in agf %u", levels, agno);
                return 1;
@@ -511,13 +517,13 @@ copy_free_cnt_btree(
 
        /* validate root and levels before processing the tree */
        if (root == 0 || root > mp->m_sb.sb_agblocks) {
-               if (show_warnings)
+               if (metadump.show_warnings)
                        print_warning("invalid block number (%u) in cntbt "
                                        "root in agf %u", root, agno);
                return 1;
        }
        if (levels > mp->m_alloc_maxlevels) {
-               if (show_warnings)
+               if (metadump.show_warnings)
                        print_warning("invalid level (%u) in cntbt root "
                                        "in agf %u", levels, agno);
                return 1;
@@ -544,7 +550,7 @@ scanfunc_rmapbt(
 
        numrecs = be16_to_cpu(block->bb_numrecs);
        if (numrecs > mp->m_rmap_mxr[1]) {
-               if (show_warnings)
+               if (metadump.show_warnings)
                        print_warning("invalid numrecs (%u) in %s block %u/%u",
                                numrecs, typtab[btype].name, agno, agbno);
                return 1;
@@ -553,7 +559,7 @@ scanfunc_rmapbt(
        pp = XFS_RMAP_PTR_ADDR(block, 1, mp->m_rmap_mxr[1]);
        for (i = 0; i < numrecs; i++) {
                if (!valid_bno(agno, be32_to_cpu(pp[i]))) {
-                       if (show_warnings)
+                       if (metadump.show_warnings)
                                print_warning("invalid block number (%u/%u) "
                                        "in %s block %u/%u",
                                        agno, be32_to_cpu(pp[i]),
@@ -583,13 +589,13 @@ copy_rmap_btree(
 
        /* validate root and levels before processing the tree */
        if (root == 0 || root > mp->m_sb.sb_agblocks) {
-               if (show_warnings)
+               if (metadump.show_warnings)
                        print_warning("invalid block number (%u) in rmapbt "
                                        "root in agf %u", root, agno);
                return 1;
        }
        if (levels > mp->m_rmap_maxlevels) {
-               if (show_warnings)
+               if (metadump.show_warnings)
                        print_warning("invalid level (%u) in rmapbt root "
                                        "in agf %u", levels, agno);
                return 1;
@@ -616,7 +622,7 @@ scanfunc_refcntbt(
 
        numrecs = be16_to_cpu(block->bb_numrecs);
        if (numrecs > mp->m_refc_mxr[1]) {
-               if (show_warnings)
+               if (metadump.show_warnings)
                        print_warning("invalid numrecs (%u) in %s block %u/%u",
                                numrecs, typtab[btype].name, agno, agbno);
                return 1;
@@ -625,7 +631,7 @@ scanfunc_refcntbt(
        pp = XFS_REFCOUNT_PTR_ADDR(block, 1, mp->m_refc_mxr[1]);
        for (i = 0; i < numrecs; i++) {
                if (!valid_bno(agno, be32_to_cpu(pp[i]))) {
-                       if (show_warnings)
+                       if (metadump.show_warnings)
                                print_warning("invalid block number (%u/%u) "
                                        "in %s block %u/%u",
                                        agno, be32_to_cpu(pp[i]),
@@ -655,13 +661,13 @@ copy_refcount_btree(
 
        /* validate root and levels before processing the tree */
        if (root == 0 || root > mp->m_sb.sb_agblocks) {
-               if (show_warnings)
+               if (metadump.show_warnings)
                        print_warning("invalid block number (%u) in refcntbt "
                                        "root in agf %u", root, agno);
                return 1;
        }
        if (levels > mp->m_refc_maxlevels) {
-               if (show_warnings)
+               if (metadump.show_warnings)
                        print_warning("invalid level (%u) in refcntbt root "
                                        "in agf %u", levels, agno);
                return 1;
@@ -773,7 +779,8 @@ in_lost_found(
        /* Record the "lost+found" inode if we haven't done so already */
 
        ASSERT(ino != 0);
-       if (!orphanage_ino && is_orphanage_dir(mp, cur_ino, namelen, name))
+       if (!orphanage_ino && is_orphanage_dir(mp, metadump.cur_ino, namelen,
+                                               name))
                orphanage_ino = ino;
 
        /* We don't obfuscate the "lost+found" directory itself */
@@ -783,7 +790,7 @@ in_lost_found(
 
        /* Most files aren't in "lost+found" at all */
 
-       if (cur_ino != orphanage_ino)
+       if (metadump.cur_ino != orphanage_ino)
                return 0;
 
        /*
@@ -897,7 +904,7 @@ generate_obfuscated_name(
                print_warning("duplicate name for inode %llu "
                                "in dir inode %llu\n",
                        (unsigned long long) ino,
-                       (unsigned long long) cur_ino);
+                       (unsigned long long) metadump.cur_ino);
                return;
        }
 
@@ -907,7 +914,7 @@ generate_obfuscated_name(
                print_warning("unable to record name for inode %llu "
                                "in dir inode %llu\n",
                        (unsigned long long) ino,
-                       (unsigned long long) cur_ino);
+                       (unsigned long long) metadump.cur_ino);
 }
 
 static void
@@ -923,9 +930,9 @@ process_sf_dir(
        ino_dir_size = be64_to_cpu(dip->di_size);
        if (ino_dir_size > XFS_DFORK_DSIZE(dip, mp)) {
                ino_dir_size = XFS_DFORK_DSIZE(dip, mp);
-               if (show_warnings)
+               if (metadump.show_warnings)
                        print_warning("invalid size in dir inode %llu",
-                                       (long long)cur_ino);
+                                       (long long)metadump.cur_ino);
        }
 
        sfep = xfs_dir2_sf_firstentry(sfp);
@@ -939,9 +946,9 @@ process_sf_dir(
                int     namelen = sfep->namelen;
 
                if (namelen == 0) {
-                       if (show_warnings)
+                       if (metadump.show_warnings)
                                print_warning("zero length entry in dir inode "
-                                               "%llu", (long long)cur_ino);
+                                       "%llu", (long long)metadump.cur_ino);
                        if (i != sfp->count - 1)
                                break;
                        namelen = ino_dir_size - ((char *)&sfep->name[0] -
@@ -949,16 +956,17 @@ process_sf_dir(
                } else if ((char *)sfep - (char *)sfp +
                                libxfs_dir2_sf_entsize(mp, sfp, sfep->namelen) >
                                ino_dir_size) {
-                       if (show_warnings)
+                       if (metadump.show_warnings)
                                print_warning("entry length in dir inode %llu "
-                                       "overflows space", (long long)cur_ino);
+                                       "overflows space",
+                                       (long long)metadump.cur_ino);
                        if (i != sfp->count - 1)
                                break;
                        namelen = ino_dir_size - ((char *)&sfep->name[0] -
                                         (char *)sfp);
                }
 
-               if (obfuscate)
+               if (metadump.obfuscate)
                        generate_obfuscated_name(
                                         libxfs_dir2_sf_get_ino(mp, sfp, sfep),
                                         namelen, &sfep->name[0]);
@@ -968,7 +976,8 @@ process_sf_dir(
        }
 
        /* zero stale data in rest of space in data fork, if any */
-       if (zero_stale_data && (ino_dir_size < XFS_DFORK_DSIZE(dip, mp)))
+       if (metadump.zero_stale_data &&
+           (ino_dir_size < XFS_DFORK_DSIZE(dip, mp)))
                memset(sfep, 0, XFS_DFORK_DSIZE(dip, mp) - ino_dir_size);
 }
 
@@ -1026,18 +1035,18 @@ process_sf_symlink(
 
        len = be64_to_cpu(dip->di_size);
        if (len > XFS_DFORK_DSIZE(dip, mp)) {
-               if (show_warnings)
+               if (metadump.show_warnings)
                        print_warning("invalid size (%d) in symlink inode %llu",
-                                       len, (long long)cur_ino);
+                                       len, (long long)metadump.cur_ino);
                len = XFS_DFORK_DSIZE(dip, mp);
        }
 
        buf = (char *)XFS_DFORK_DPTR(dip);
-       if (obfuscate)
+       if (metadump.obfuscate)
                obfuscate_path_components(buf, len);
 
        /* zero stale data in rest of space in data fork, if any */
-       if (zero_stale_data && len < XFS_DFORK_DSIZE(dip, mp))
+       if (metadump.zero_stale_data && len < XFS_DFORK_DSIZE(dip, mp))
                memset(&buf[len], 0, XFS_DFORK_DSIZE(dip, mp) - len);
 }
 
@@ -1062,9 +1071,9 @@ process_sf_attr(
        ino_attr_size = be16_to_cpu(asfp->hdr.totsize);
        if (ino_attr_size > XFS_DFORK_ASIZE(dip, mp)) {
                ino_attr_size = XFS_DFORK_ASIZE(dip, mp);
-               if (show_warnings)
+               if (metadump.show_warnings)
                        print_warning("invalid attr size in inode %llu",
-                                       (long long)cur_ino);
+                                       (long long)metadump.cur_ino);
        }
 
        asfep = &asfp->list[0];
@@ -1074,19 +1083,20 @@ process_sf_attr(
                int     namelen = asfep->namelen;
 
                if (namelen == 0) {
-                       if (show_warnings)
+                       if (metadump.show_warnings)
                                print_warning("zero length attr entry in inode "
-                                               "%llu", (long long)cur_ino);
+                                       "%llu", (long long)metadump.cur_ino);
                        break;
                } else if ((char *)asfep - (char *)asfp +
                                xfs_attr_sf_entsize(asfep) > ino_attr_size) {
-                       if (show_warnings)
+                       if (metadump.show_warnings)
                                print_warning("attr entry length in inode %llu "
-                                       "overflows space", (long long)cur_ino);
+                                       "overflows space",
+                                       (long long)metadump.cur_ino);
                        break;
                }
 
-               if (obfuscate) {
+               if (metadump.obfuscate) {
                        generate_obfuscated_name(0, asfep->namelen,
                                                 &asfep->nameval[0]);
                        memset(&asfep->nameval[asfep->namelen], 'v',
@@ -1098,7 +1108,8 @@ process_sf_attr(
        }
 
        /* zero stale data in rest of space in attr fork, if any */
-       if (zero_stale_data && (ino_attr_size < XFS_DFORK_ASIZE(dip, mp)))
+       if (metadump.zero_stale_data &&
+           (ino_attr_size < XFS_DFORK_ASIZE(dip, mp)))
                memset(asfep, 0, XFS_DFORK_ASIZE(dip, mp) - ino_attr_size);
 }
 
@@ -1109,7 +1120,7 @@ process_dir_free_block(
        struct xfs_dir2_free            *free;
        struct xfs_dir3_icfree_hdr      freehdr;
 
-       if (!zero_stale_data)
+       if (!metadump.zero_stale_data)
                return;
 
        free = (struct xfs_dir2_free *)block;
@@ -1131,10 +1142,10 @@ process_dir_free_block(
                break;
        }
        default:
-               if (show_warnings)
+               if (metadump.show_warnings)
                        print_warning("invalid magic in dir inode %llu "
                                      "free block",
-                                     (unsigned long long)cur_ino);
+                                     (unsigned long long)metadump.cur_ino);
                break;
        }
 }
@@ -1146,7 +1157,7 @@ process_dir_leaf_block(
        struct xfs_dir2_leaf            *leaf;
        struct xfs_dir3_icleaf_hdr      leafhdr;
 
-       if (!zero_stale_data)
+       if (!metadump.zero_stale_data)
                return;
 
        /* Yes, this works for dir2 & dir3.  Difference is padding. */
@@ -1229,10 +1240,10 @@ process_dir_data_block(
        }
 
        if (be32_to_cpu(datahdr->magic) != wantmagic) {
-               if (show_warnings)
+               if (metadump.show_warnings)
                        print_warning(
                "invalid magic in dir inode %llu block %ld",
-                                       (unsigned long long)cur_ino, (long)offset);
+               (unsigned long long)metadump.cur_ino, (long)offset);
                return;
        }
 
@@ -1252,10 +1263,10 @@ process_dir_data_block(
                        if (dir_offset + free_length > end_of_data ||
                            !free_length ||
                            (free_length & (XFS_DIR2_DATA_ALIGN - 1))) {
-                               if (show_warnings)
+                               if (metadump.show_warnings)
                                        print_warning(
                        "invalid length for dir free space in inode %llu",
-                                               (long long)cur_ino);
+                                               (long long)metadump.cur_ino);
                                return;
                        }
                        if (be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) !=
@@ -1268,7 +1279,7 @@ process_dir_data_block(
                         * actually at a variable offset, so zeroing &dup->tag
                         * is zeroing the free space in between
                         */
-                       if (zero_stale_data) {
+                       if (metadump.zero_stale_data) {
                                int zlen = free_length -
                                                sizeof(xfs_dir2_data_unused_t);
 
@@ -1286,23 +1297,23 @@ process_dir_data_block(
 
                if (dir_offset + length > end_of_data ||
                    ptr + length > endptr) {
-                       if (show_warnings)
+                       if (metadump.show_warnings)
                                print_warning(
                        "invalid length for dir entry name in inode %llu",
-                                       (long long)cur_ino);
+                                       (long long)metadump.cur_ino);
                        return;
                }
                if (be16_to_cpu(*libxfs_dir2_data_entry_tag_p(mp, dep)) !=
                                dir_offset)
                        return;
 
-               if (obfuscate)
+               if (metadump.obfuscate)
                        generate_obfuscated_name(be64_to_cpu(dep->inumber),
                                         dep->namelen, &dep->name[0]);
                dir_offset += length;
                ptr += length;
                /* Zero the unused space after name, up to the tag */
-               if (zero_stale_data) {
+               if (metadump.zero_stale_data) {
                        /* 1 byte for ftype; don't bother with conditional */
                        int zlen =
                                (char *)libxfs_dir2_data_entry_tag_p(mp, dep) -
@@ -1338,7 +1349,7 @@ process_symlink_block(
 
                print_warning("cannot read %s block %u/%u (%llu)",
                                typtab[btype].name, agno, agbno, s);
-               rval = !stop_on_read_error;
+               rval = !metadump.stop_on_read_error;
                goto out_pop;
        }
        link = iocur_top->data;
@@ -1346,10 +1357,10 @@ process_symlink_block(
        if (xfs_has_crc((mp)))
                link += sizeof(struct xfs_dsymlink_hdr);
 
-       if (obfuscate)
+       if (metadump.obfuscate)
                obfuscate_path_components(link, XFS_SYMLINK_BUF_SPACE(mp,
                                                        mp->m_sb.sb_blocksize));
-       if (zero_stale_data) {
+       if (metadump.zero_stale_data) {
                size_t  linklen, zlen;
 
                linklen = strlen(link);
@@ -1416,7 +1427,8 @@ process_attr_block(
        if ((be16_to_cpu(leaf->hdr.info.magic) != XFS_ATTR_LEAF_MAGIC) &&
            (be16_to_cpu(leaf->hdr.info.magic) != XFS_ATTR3_LEAF_MAGIC)) {
                for (i = 0; i < attr_data.remote_val_count; i++) {
-                       if (obfuscate && attr_data.remote_vals[i] == offset)
+                       if (metadump.obfuscate &&
+                           attr_data.remote_vals[i] == offset)
                                /* Macros to handle both attr and attr3 */
                                memset(block +
                                        (bs - XFS_ATTR3_RMT_BUF_SPACE(mp, bs)),
@@ -1433,9 +1445,9 @@ process_attr_block(
            nentries * sizeof(xfs_attr_leaf_entry_t) +
                        xfs_attr3_leaf_hdr_size(leaf) >
                                XFS_ATTR3_RMT_BUF_SPACE(mp, bs)) {
-               if (show_warnings)
+               if (metadump.show_warnings)
                        print_warning("invalid attr count in inode %llu",
-                                       (long long)cur_ino);
+                                       (long long)metadump.cur_ino);
                return;
        }
 
@@ -1450,22 +1462,22 @@ process_attr_block(
                        first_name = xfs_attr3_leaf_name(leaf, i);
 
                if (be16_to_cpu(entry->nameidx) > mp->m_sb.sb_blocksize) {
-                       if (show_warnings)
+                       if (metadump.show_warnings)
                                print_warning(
                                "invalid attr nameidx in inode %llu",
-                                               (long long)cur_ino);
+                                               (long long)metadump.cur_ino);
                        break;
                }
                if (entry->flags & XFS_ATTR_LOCAL) {
                        local = xfs_attr3_leaf_name_local(leaf, i);
                        if (local->namelen == 0) {
-                               if (show_warnings)
+                               if (metadump.show_warnings)
                                        print_warning(
                                "zero length for attr name in inode %llu",
-                                               (long long)cur_ino);
+                                               (long long)metadump.cur_ino);
                                break;
                        }
-                       if (obfuscate) {
+                       if (metadump.obfuscate) {
                                generate_obfuscated_name(0, local->namelen,
                                        &local->nameval[0]);
                                memset(&local->nameval[local->namelen], 'v',
@@ -1477,18 +1489,18 @@ process_attr_block(
                        zlen = xfs_attr_leaf_entsize_local(nlen, vlen) -
                                (offsetof(struct xfs_attr_leaf_name_local, nameval) +
                                 nlen + vlen);
-                       if (zero_stale_data)
+                       if (metadump.zero_stale_data)
                                memset(&local->nameval[nlen + vlen], 0, zlen);
                } else {
                        remote = xfs_attr3_leaf_name_remote(leaf, i);
                        if (remote->namelen == 0 || remote->valueblk == 0) {
-                               if (show_warnings)
+                               if (metadump.show_warnings)
                                        print_warning(
                                "invalid attr entry in inode %llu",
-                                               (long long)cur_ino);
+                                               (long long)metadump.cur_ino);
                                break;
                        }
-                       if (obfuscate) {
+                       if (metadump.obfuscate) {
                                generate_obfuscated_name(0, remote->namelen,
                                                         &remote->name[0]);
                                add_remote_vals(be32_to_cpu(remote->valueblk),
@@ -1499,13 +1511,13 @@ process_attr_block(
                        zlen = xfs_attr_leaf_entsize_remote(nlen) -
                                (offsetof(struct xfs_attr_leaf_name_remote, name) +
                                 nlen);
-                       if (zero_stale_data)
+                       if (metadump.zero_stale_data)
                                memset(&remote->name[nlen], 0, zlen);
                }
        }
 
        /* Zero from end of entries array to the first name/val */
-       if (zero_stale_data) {
+       if (metadump.zero_stale_data) {
                struct xfs_attr_leaf_entry *entries;
 
                entries = xfs_attr3_leaf_entryp(leaf);
@@ -1538,16 +1550,16 @@ process_single_fsb_objects(
 
                        print_warning("cannot read %s block %u/%u (%llu)",
                                        typtab[btype].name, agno, agbno, s);
-                       rval = !stop_on_read_error;
+                       rval = !metadump.stop_on_read_error;
                        goto out_pop;
 
                }
 
-               if (!obfuscate && !zero_stale_data)
+               if (!metadump.obfuscate && !metadump.zero_stale_data)
                        goto write;
 
                /* Zero unused part of interior nodes */
-               if (zero_stale_data) {
+               if (metadump.zero_stale_data) {
                        xfs_da_intnode_t *node = iocur_top->data;
                        int magic = be16_to_cpu(node->hdr.info.magic);
 
@@ -1658,12 +1670,12 @@ process_multi_fsb_dir(
 
                                print_warning("cannot read %s block %u/%u (%llu)",
                                                typtab[btype].name, agno, agbno, s);
-                               rval = !stop_on_read_error;
+                               rval = !metadump.stop_on_read_error;
                                goto out_pop;
 
                        }
 
-                       if (!obfuscate && !zero_stale_data)
+                       if (!metadump.obfuscate && !metadump.zero_stale_data)
                                goto write;
 
                        dp = iocur_top->data;
@@ -1755,25 +1767,27 @@ process_bmbt_reclist(
                 * one is found, stop processing remaining extents
                 */
                if (i > 0 && op + cp > o) {
-                       if (show_warnings)
+                       if (metadump.show_warnings)
                                print_warning("bmap extent %d in %s ino %llu "
                                        "starts at %llu, previous extent "
                                        "ended at %llu", i,
-                                       typtab[btype].name, (long long)cur_ino,
+                                       typtab[btype].name,
+                                       (long long)metadump.cur_ino,
                                        o, op + cp - 1);
                        break;
                }
 
-               if (c > max_extent_size) {
+               if (c > metadump.max_extent_size) {
                        /*
                         * since we are only processing non-data extents,
                         * large numbers of blocks in a metadata extent is
                         * extremely rare and more than likely to be corrupt.
                         */
-                       if (show_warnings)
+                       if (metadump.show_warnings)
                                print_warning("suspicious count %u in bmap "
                                        "extent %d in %s ino %llu", c, i,
-                                       typtab[btype].name, (long long)cur_ino);
+                                       typtab[btype].name,
+                                       (long long)metadump.cur_ino);
                        break;
                }
 
@@ -1784,19 +1798,21 @@ process_bmbt_reclist(
                agbno = XFS_FSB_TO_AGBNO(mp, s);
 
                if (!valid_bno(agno, agbno)) {
-                       if (show_warnings)
+                       if (metadump.show_warnings)
                                print_warning("invalid block number %u/%u "
                                        "(%llu) in bmap extent %d in %s ino "
                                        "%llu", agno, agbno, s, i,
-                                       typtab[btype].name, (long long)cur_ino);
+                                       typtab[btype].name,
+                                       (long long)metadump.cur_ino);
                        break;
                }
 
                if (!valid_bno(agno, agbno + c - 1)) {
-                       if (show_warnings)
+                       if (metadump.show_warnings)
                                print_warning("bmap extent %i in %s inode %llu "
                                        "overflows AG (end is %u/%u)", i,
-                                       typtab[btype].name, (long long)cur_ino,
+                                       typtab[btype].name,
+                                       (long long)metadump.cur_ino,
                                        agno, agbno + c - 1);
                        break;
                }
@@ -1832,7 +1848,7 @@ scanfunc_bmap(
 
        if (level == 0) {
                if (nrecs > mp->m_bmap_dmxr[0]) {
-                       if (show_warnings)
+                       if (metadump.show_warnings)
                                print_warning("invalid numrecs (%u) in %s "
                                        "block %u/%u", nrecs,
                                        typtab[btype].name, agno, agbno);
@@ -1843,7 +1859,7 @@ scanfunc_bmap(
        }
 
        if (nrecs > mp->m_bmap_dmxr[1]) {
-               if (show_warnings)
+               if (metadump.show_warnings)
                        print_warning("invalid numrecs (%u) in %s block %u/%u",
                                        nrecs, typtab[btype].name, agno, agbno);
                return 1;
@@ -1858,7 +1874,7 @@ scanfunc_bmap(
 
                if (bno == 0 || bno > mp->m_sb.sb_agblocks ||
                                ag > mp->m_sb.sb_agcount) {
-                       if (show_warnings)
+                       if (metadump.show_warnings)
                                print_warning("invalid block number (%u/%u) "
                                        "in %s block %u/%u", ag, bno,
                                        typtab[btype].name, agno, agbno);
@@ -1893,10 +1909,10 @@ process_btinode(
        nrecs = be16_to_cpu(dib->bb_numrecs);
 
        if (level > XFS_BM_MAXLEVELS(mp, whichfork)) {
-               if (show_warnings)
+               if (metadump.show_warnings)
                        print_warning("invalid level (%u) in inode %lld %s "
-                                       "root", level, (long long)cur_ino,
-                                       typtab[btype].name);
+                               "root", level, (long long)metadump.cur_ino,
+                               typtab[btype].name);
                return 1;
        }
 
@@ -1907,16 +1923,16 @@ process_btinode(
 
        maxrecs = libxfs_bmdr_maxrecs(XFS_DFORK_SIZE(dip, mp, whichfork), 0);
        if (nrecs > maxrecs) {
-               if (show_warnings)
+               if (metadump.show_warnings)
                        print_warning("invalid numrecs (%u) in inode %lld %s "
-                                       "root", nrecs, (long long)cur_ino,
-                                       typtab[btype].name);
+                               "root", nrecs, (long long)metadump.cur_ino,
+                               typtab[btype].name);
                return 1;
        }
 
        pp = XFS_BMDR_PTR_ADDR(dib, 1, maxrecs);
 
-       if (zero_stale_data) {
+       if (metadump.zero_stale_data) {
                char    *top;
 
                /* Unused btree key space */
@@ -1937,11 +1953,11 @@ process_btinode(
 
                if (bno == 0 || bno > mp->m_sb.sb_agblocks ||
                                ag > mp->m_sb.sb_agcount) {
-                       if (show_warnings)
+                       if (metadump.show_warnings)
                                print_warning("invalid block number (%u/%u) "
-                                               "in inode %llu %s root", ag,
-                                               bno, (long long)cur_ino,
-                                               typtab[btype].name);
+                                       "in inode %llu %s root", ag, bno,
+                                       (long long)metadump.cur_ino,
+                                       typtab[btype].name);
                        continue;
                }
 
@@ -1968,14 +1984,16 @@ process_exinode(
                        whichfork);
        used = nex * sizeof(xfs_bmbt_rec_t);
        if (nex > max_nex || used > XFS_DFORK_SIZE(dip, mp, whichfork)) {
-               if (show_warnings)
+               if (metadump.show_warnings)
                        print_warning("bad number of extents %llu in inode %lld",
-                               (unsigned long long)nex, (long long)cur_ino);
+                               (unsigned long long)nex,
+                               (long long)metadump.cur_ino);
                return 1;
        }
 
        /* Zero unused data fork past used extents */
-       if (zero_stale_data && (used < XFS_DFORK_SIZE(dip, mp, whichfork)))
+       if (metadump.zero_stale_data &&
+           (used < XFS_DFORK_SIZE(dip, mp, whichfork)))
                memset(XFS_DFORK_PTR(dip, whichfork) + used, 0,
                       XFS_DFORK_SIZE(dip, mp, whichfork) - used);
 
@@ -1991,7 +2009,7 @@ process_inode_data(
 {
        switch (dip->di_format) {
                case XFS_DINODE_FMT_LOCAL:
-                       if (!(obfuscate || zero_stale_data))
+                       if (!(metadump.obfuscate || metadump.zero_stale_data))
                                break;
 
                        /*
@@ -2003,7 +2021,7 @@ process_inode_data(
                                print_warning(
 "Invalid data fork size (%d) in inode %llu, preserving contents!",
                                                XFS_DFORK_DSIZE(dip, mp),
-                                               (long long)cur_ino);
+                                               (long long)metadump.cur_ino);
                                break;
                        }
 
@@ -2035,9 +2053,9 @@ process_dev_inode(
        struct xfs_dinode               *dip)
 {
        if (xfs_dfork_data_extents(dip)) {
-               if (show_warnings)
+               if (metadump.show_warnings)
                        print_warning("inode %llu has unexpected extents",
-                                     (unsigned long long)cur_ino);
+                                     (unsigned long long)metadump.cur_ino);
                return;
        }
 
@@ -2049,11 +2067,11 @@ process_dev_inode(
        if (XFS_DFORK_DSIZE(dip, mp) > XFS_LITINO(mp)) {
                print_warning(
 "Invalid data fork size (%d) in inode %llu, preserving contents!",
-                               XFS_DFORK_DSIZE(dip, mp), (long long)cur_ino);
+                       XFS_DFORK_DSIZE(dip, mp), (long long)metadump.cur_ino);
                return;
        }
 
-       if (zero_stale_data) {
+       if (metadump.zero_stale_data) {
                unsigned int    size = sizeof(xfs_dev_t);
 
                memset(XFS_DFORK_DPTR(dip) + size, 0,
@@ -2079,17 +2097,17 @@ process_inode(
        bool                    crc_was_ok = false; /* no recalc by default */
        bool                    need_new_crc = false;
 
-       cur_ino = XFS_AGINO_TO_INO(mp, agno, agino);
+       metadump.cur_ino = XFS_AGINO_TO_INO(mp, agno, agino);
 
        /* we only care about crc recalculation if we will modify the inode. */
-       if (obfuscate || zero_stale_data) {
+       if (metadump.obfuscate || metadump.zero_stale_data) {
                crc_was_ok = libxfs_verify_cksum((char *)dip,
                                        mp->m_sb.sb_inodesize,
                                        offsetof(struct xfs_dinode, di_crc));
        }
 
        if (free_inode) {
-               if (zero_stale_data) {
+               if (metadump.zero_stale_data) {
                        /* Zero all of the inode literal area */
                        memset(XFS_DFORK_DPTR(dip), 0, XFS_LITINO(mp));
                }
@@ -2131,7 +2149,8 @@ process_inode(
                switch (dip->di_aformat) {
                        case XFS_DINODE_FMT_LOCAL:
                                need_new_crc = true;
-                               if (obfuscate || zero_stale_data)
+                               if (metadump.obfuscate ||
+                                   metadump.zero_stale_data)
                                        process_sf_attr(dip);
                                break;
 
@@ -2148,7 +2167,7 @@ process_inode(
 
 done:
        /* Heavy handed but low cost; just do it as a catch-all. */
-       if (zero_stale_data)
+       if (metadump.zero_stale_data)
                need_new_crc = true;
 
        if (crc_was_ok && need_new_crc)
@@ -2208,7 +2227,7 @@ copy_inode_chunk(
        if (agino == 0 || agino == NULLAGINO || !valid_bno(agno, agbno) ||
                        !valid_bno(agno, XFS_AGINO_TO_AGBNO(mp,
                                        agino + XFS_INODES_PER_CHUNK - 1))) {
-               if (show_warnings)
+               if (metadump.show_warnings)
                        print_warning("bad inode number %llu (%u/%u)",
                                XFS_AGINO_TO_INO(mp, agno, agino), agno, agino);
                return 1;
@@ -2224,7 +2243,7 @@ copy_inode_chunk(
                        (xfs_has_align(mp) &&
                                        mp->m_sb.sb_inoalignmt != 0 &&
                                        agbno % mp->m_sb.sb_inoalignmt != 0)) {
-               if (show_warnings)
+               if (metadump.show_warnings)
                        print_warning("badly aligned inode (start = %llu)",
                                        XFS_AGINO_TO_INO(mp, agno, agino));
                return 1;
@@ -2241,7 +2260,7 @@ copy_inode_chunk(
                if (iocur_top->data == NULL) {
                        print_warning("cannot read inode block %u/%u",
                                      agno, agbno);
-                       rval = !stop_on_read_error;
+                       rval = !metadump.stop_on_read_error;
                        goto pop_out;
                }
 
@@ -2267,7 +2286,7 @@ next_bp:
                ioff += inodes_per_buf;
        }
 
-       if (show_progress)
+       if (metadump.show_progress)
                print_progress("Copied %u of %u inodes (%u of %u AGs)",
                                inodes_copied, mp->m_sb.sb_icount, agno,
                                mp->m_sb.sb_agcount);
@@ -2297,7 +2316,7 @@ scanfunc_ino(
 
        if (level == 0) {
                if (numrecs > igeo->inobt_mxr[0]) {
-                       if (show_warnings)
+                       if (metadump.show_warnings)
                                print_warning("invalid numrecs %d in %s "
                                        "block %u/%u", numrecs,
                                        typtab[btype].name, agno, agbno);
@@ -2320,7 +2339,7 @@ scanfunc_ino(
        }
 
        if (numrecs > igeo->inobt_mxr[1]) {
-               if (show_warnings)
+               if (metadump.show_warnings)
                        print_warning("invalid numrecs %d in %s block %u/%u",
                                numrecs, typtab[btype].name, agno, agbno);
                numrecs = igeo->inobt_mxr[1];
@@ -2329,7 +2348,7 @@ scanfunc_ino(
        pp = XFS_INOBT_PTR_ADDR(mp, block, 1, igeo->inobt_mxr[1]);
        for (i = 0; i < numrecs; i++) {
                if (!valid_bno(agno, be32_to_cpu(pp[i]))) {
-                       if (show_warnings)
+                       if (metadump.show_warnings)
                                print_warning("invalid block number (%u/%u) "
                                        "in %s block %u/%u",
                                        agno, be32_to_cpu(pp[i]),
@@ -2357,13 +2376,13 @@ copy_inodes(
 
        /* validate root and levels before processing the tree */
        if (root == 0 || root > mp->m_sb.sb_agblocks) {
-               if (show_warnings)
+               if (metadump.show_warnings)
                        print_warning("invalid block number (%u) in inobt "
                                        "root in agi %u", root, agno);
                return 1;
        }
        if (levels > M_IGEO(mp)->inobt_maxlevels) {
-               if (show_warnings)
+               if (metadump.show_warnings)
                        print_warning("invalid level (%u) in inobt root "
                                        "in agi %u", levels, agno);
                return 1;
@@ -2377,7 +2396,7 @@ copy_inodes(
                levels = be32_to_cpu(agi->agi_free_level);
 
                if (root == 0 || root > mp->m_sb.sb_agblocks) {
-                       if (show_warnings)
+                       if (metadump.show_warnings)
                                print_warning("invalid block number (%u) in "
                                                "finobt root in agi %u", root,
                                                agno);
@@ -2385,7 +2404,7 @@ copy_inodes(
                }
 
                if (levels > M_IGEO(mp)->inobt_maxlevels) {
-                       if (show_warnings)
+                       if (metadump.show_warnings)
                                print_warning("invalid level (%u) in finobt "
                                                "root in agi %u", levels, agno);
                        return 1;
@@ -2416,11 +2435,11 @@ scan_ag(
                        XFS_FSS_TO_BB(mp, 1), DB_RING_IGN, NULL);
        if (!iocur_top->data) {
                print_warning("cannot read superblock for ag %u", agno);
-               if (stop_on_read_error)
+               if (metadump.stop_on_read_error)
                        goto pop_out;
        } else {
                /* Replace any filesystem label with "L's" */
-               if (obfuscate) {
+               if (metadump.obfuscate) {
                        struct xfs_sb *sb = iocur_top->data;
                        memset(sb->sb_fname, 'L',
                               min(strlen(sb->sb_fname), sizeof(sb->sb_fname)));
@@ -2438,7 +2457,7 @@ scan_ag(
        agf = iocur_top->data;
        if (iocur_top->data == NULL) {
                print_warning("cannot read agf block for ag %u", agno);
-               if (stop_on_read_error)
+               if (metadump.stop_on_read_error)
                        goto pop_out;
        } else {
                if (write_buf(iocur_top))
@@ -2453,7 +2472,7 @@ scan_ag(
        agi = iocur_top->data;
        if (iocur_top->data == NULL) {
                print_warning("cannot read agi block for ag %u", agno);
-               if (stop_on_read_error)
+               if (metadump.stop_on_read_error)
                        goto pop_out;
        } else {
                if (write_buf(iocur_top))
@@ -2467,10 +2486,10 @@ scan_ag(
                        XFS_FSS_TO_BB(mp, 1), DB_RING_IGN, NULL);
        if (iocur_top->data == NULL) {
                print_warning("cannot read agfl block for ag %u", agno);
-               if (stop_on_read_error)
+               if (metadump.stop_on_read_error)
                        goto pop_out;
        } else {
-               if (agf && zero_stale_data) {
+               if (agf && metadump.zero_stale_data) {
                        /* Zero out unused bits of agfl */
                        int i;
                         __be32  *agfl_bno;
@@ -2493,7 +2512,7 @@ scan_ag(
 
        /* copy AG free space btrees */
        if (agf) {
-               if (show_progress)
+               if (metadump.show_progress)
                        print_progress("Copying free space trees of AG %u",
                                        agno);
                if (!copy_free_bno_btree(agno, agf))
@@ -2539,7 +2558,7 @@ copy_ino(
 
        if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks ||
                        offset >= mp->m_sb.sb_inopblock) {
-               if (show_warnings)
+               if (metadump.show_warnings)
                        print_warning("invalid %s inode number (%lld)",
                                        typtab[itype].name, (long long)ino);
                return 1;
@@ -2551,12 +2570,12 @@ copy_ino(
        if (iocur_top->data == NULL) {
                print_warning("cannot read %s inode %lld",
                                typtab[itype].name, (long long)ino);
-               rval = !stop_on_read_error;
+               rval = !metadump.stop_on_read_error;
                goto pop_out;
        }
        off_cur(offset << mp->m_sb.sb_inodelog, mp->m_sb.sb_inodesize);
 
-       cur_ino = ino;
+       metadump.cur_ino = ino;
        rval = process_inode_data(iocur_top->data, itype);
 pop_out:
        pop_cur();
@@ -2592,7 +2611,7 @@ copy_log(void)
        int             logversion;
        int             cycle = XLOG_INIT_CYCLE;
 
-       if (show_progress)
+       if (metadump.show_progress)
                print_progress("Copying log");
 
        push_cur();
@@ -2601,11 +2620,11 @@ copy_log(void)
        if (iocur_top->data == NULL) {
                pop_cur();
                print_warning("cannot read log");
-               return !stop_on_read_error;
+               return !metadump.stop_on_read_error;
        }
 
        /* If not obfuscating or zeroing, just copy the log as it is */
-       if (!obfuscate && !zero_stale_data)
+       if (!metadump.obfuscate && !metadump.zero_stale_data)
                goto done;
 
        dirty = xlog_is_dirty(mp, &log, &x, 0);
@@ -2613,7 +2632,7 @@ copy_log(void)
        switch (dirty) {
        case 0:
                /* clear out a clean log */
-               if (show_progress)
+               if (metadump.show_progress)
                        print_progress("Zeroing clean log");
 
                logstart = XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart);
@@ -2628,7 +2647,7 @@ copy_log(void)
                break;
        case 1:
                /* keep the dirty log */
-               if (obfuscate)
+               if (metadump.obfuscate)
                        print_warning(
 _("Warning: log recovery of an obfuscated metadata image can leak "
 "unobfuscated metadata and/or cause image corruption.  If possible, "
@@ -2636,7 +2655,7 @@ _("Warning: log recovery of an obfuscated metadata image can leak "
                break;
        case -1:
                /* log detection error */
-               if (obfuscate)
+               if (metadump.obfuscate)
                        print_warning(
 _("Could not discern log; image will contain unobfuscated metadata in log."));
                break;
@@ -2659,9 +2678,15 @@ metadump_f(
        char            *p;
 
        exitcode = 1;
-       show_progress = false;
-       show_warnings = false;
-       stop_on_read_error = false;
+
+       metadump.version = 1;
+       metadump.show_progress = false;
+       metadump.stop_on_read_error = false;
+       metadump.max_extent_size = DEFAULT_MAX_EXT_SIZE;
+       metadump.show_warnings = false;
+       metadump.obfuscate = true;
+       metadump.zero_stale_data = true;
+       metadump.dirty_log = false;
 
        if (mp->m_sb.sb_magicnum != XFS_SB_MAGIC) {
                print_warning("bad superblock magic number %x, giving up",
@@ -2682,27 +2707,29 @@ metadump_f(
        while ((c = getopt(argc, argv, "aegm:ow")) != EOF) {
                switch (c) {
                        case 'a':
-                               zero_stale_data = false;
+                               metadump.zero_stale_data = false;
                                break;
                        case 'e':
-                               stop_on_read_error = true;
+                               metadump.stop_on_read_error = true;
                                break;
                        case 'g':
-                               show_progress = true;
+                               metadump.show_progress = true;
                                break;
                        case 'm':
-                               max_extent_size = (int)strtol(optarg, &p, 0);
-                               if (*p != '\0' || max_extent_size <= 0) {
+                               metadump.max_extent_size =
+                                       (int)strtol(optarg, &p, 0);
+                               if (*p != '\0' ||
+                                   metadump.max_extent_size <= 0) {
                                        print_warning("bad max extent size %s",
                                                        optarg);
                                        return 0;
                                }
                                break;
                        case 'o':
-                               obfuscate = false;
+                               metadump.obfuscate = false;
                                break;
                        case 'w':
-                               show_warnings = true;
+                               metadump.show_warnings = true;
                                break;
                        default:
                                print_warning("bad option for metadump command");
@@ -2715,21 +2742,6 @@ metadump_f(
                return 0;
        }
 
-       metablock = (xfs_metablock_t *)calloc(BBSIZE + 1, BBSIZE);
-       if (metablock == NULL) {
-               print_warning("memory allocation failure");
-               return 0;
-       }
-       metablock->mb_blocklog = BBSHIFT;
-       metablock->mb_magic = cpu_to_be32(XFS_MD_MAGIC);
-
-       /* Set flags about state of metadump */
-       metablock->mb_info = XFS_METADUMP_INFO_FLAGS;
-       if (obfuscate)
-               metablock->mb_info |= XFS_METADUMP_OBFUSCATED;
-       if (!zero_stale_data)
-               metablock->mb_info |= XFS_METADUMP_FULLBLOCKS;
-
        /* If we'll copy the log, see if the log is dirty */
        if (mp->m_sb.sb_logstart) {
                push_cur();
@@ -2740,34 +2752,52 @@ metadump_f(
                        struct xlog     log;
 
                        if (xlog_is_dirty(mp, &log, &x, 0))
-                               metablock->mb_info |= XFS_METADUMP_DIRTYLOG;
+                               metadump.dirty_log = true;
                }
                pop_cur();
        }
 
-       block_index = (__be64 *)((char *)metablock + sizeof(xfs_metablock_t));
-       block_buffer = (char *)metablock + BBSIZE;
-       num_indices = (BBSIZE - sizeof(xfs_metablock_t)) / sizeof(__be64);
+       metadump.metablock = (xfs_metablock_t *)calloc(BBSIZE + 1, BBSIZE);
+       if (metadump.metablock == NULL) {
+               print_warning("memory allocation failure");
+               return -1;
+       }
+       metadump.metablock->mb_blocklog = BBSHIFT;
+       metadump.metablock->mb_magic = cpu_to_be32(XFS_MD_MAGIC);
+
+       /* Set flags about state of metadump */
+       metadump.metablock->mb_info = XFS_METADUMP_INFO_FLAGS;
+       if (metadump.obfuscate)
+               metadump.metablock->mb_info |= XFS_METADUMP_OBFUSCATED;
+       if (!metadump.zero_stale_data)
+               metadump.metablock->mb_info |= XFS_METADUMP_FULLBLOCKS;
+       if (metadump.dirty_log)
+               metadump.metablock->mb_info |= XFS_METADUMP_DIRTYLOG;
+
+       metadump.block_index = (__be64 *)((char *)metadump.metablock +
+                                       sizeof(xfs_metablock_t));
+       metadump.block_buffer = (char *)metadump.metablock + BBSIZE;
+       metadump.num_indices = (BBSIZE - sizeof(xfs_metablock_t)) /
+               sizeof(__be64);
 
        /*
         * A metadump block can hold at most num_indices of BBSIZE sectors;
         * do not try to dump a filesystem with a sector size which does not
         * fit within num_indices (i.e. within a single metablock).
         */
-       if (mp->m_sb.sb_sectsize > num_indices * BBSIZE) {
+       if (mp->m_sb.sb_sectsize > metadump.num_indices * BBSIZE) {
                print_warning("Cannot dump filesystem with sector size %u",
                              mp->m_sb.sb_sectsize);
-               free(metablock);
+               free(metadump.metablock);
                return 0;
        }
 
-       cur_index = 0;
        start_iocur_sp = iocur_sp;
 
        if (strcmp(argv[optind], "-") == 0) {
                if (isatty(fileno(stdout))) {
                        print_warning("cannot write to a terminal");
-                       free(metablock);
+                       free(metadump.metablock);
                        return 0;
                }
                /*
@@ -2791,17 +2821,17 @@ metadump_f(
                        close(outfd);
                        goto out;
                }
-               outf = fdopen(outfd, "a");
-               if (outf == NULL) {
+               metadump.outf = fdopen(outfd, "a");
+               if (metadump.outf == NULL) {
                        fprintf(stderr, "cannot create dump stream\n");
                        dup2(outfd, STDOUT_FILENO);
                        close(outfd);
                        goto out;
                }
-               stdout_metadump = true;
+               metadump.stdout_metadump = true;
        } else {
-               outf = fopen(argv[optind], "wb");
-               if (outf == NULL) {
+               metadump.outf = fopen(argv[optind], "wb");
+               if (metadump.outf == NULL) {
                        print_warning("cannot create dump file");
                        goto out;
                }
@@ -2828,24 +2858,24 @@ metadump_f(
        if (!exitcode)
                exitcode = write_index() < 0;
 
-       if (progress_since_warning)
-               fputc('\n', stdout_metadump ? stderr : stdout);
+       if (metadump.progress_since_warning)
+               fputc('\n', metadump.stdout_metadump ? stderr : stdout);
 
-       if (stdout_metadump) {
-               fflush(outf);
+       if (metadump.stdout_metadump) {
+               fflush(metadump.outf);
                fflush(stdout);
                ret = dup2(outfd, STDOUT_FILENO);
                if (ret < 0)
                        perror("un-redirecting stdout");
-               stdout_metadump = false;
+               metadump.stdout_metadump = false;
        }
-       fclose(outf);
+       fclose(metadump.outf);
 
        /* cleanup iocur stack */
        while (iocur_sp > start_iocur_sp)
                pop_cur();
 out:
-       free(metablock);
+       free(metadump.metablock);
 
        return 0;
 }