diff --git a/image/main.c b/image/main.c
index 14eba0cac11b..4cb842be26fb 100644
--- a/image/main.c
+++ b/image/main.c
@@ -53,7 +53,15 @@ const struct dump_version dump_versions[NR_DUMP_VERSIONS] = {
{ .version = 0,
.max_pending_size = SZ_256K,
.magic_cpu = 0xbd5c25e27295668bULL,
- .extra_sb_flags = 1 }
+ .extra_sb_flags = 1 },
+ /*
+ * The newer format, with much larger item size to contain
+ * any data extent.
+ */
+ { .version = 1,
+ .max_pending_size = SZ_256M,
+ .magic_cpu = 0x31765f506d55445fULL, /* ascii _DUmP_v1, no null */
+ .extra_sb_flags = 0 },
};
const struct dump_version *current_version = &dump_versions[0];@@ -455,10 +463,14 @@ static void metadump_destroy(struct metadump_struct *md, int num_threads)
static int metadump_init(struct metadump_struct *md, struct btrfs_root *root,
FILE *out, int num_threads, int compress_level,
- enum sanitize_mode sanitize_names)
+ bool dump_data, enum sanitize_mode sanitize_names)
{
int i, ret = 0;
+ /* We need larger item/cluster limit for data extents */
+ if (dump_data)
+ current_version = &dump_versions[1];
+
memset(md, 0, sizeof(*md));
INIT_LIST_HEAD(&md->list);
INIT_LIST_HEAD(&md->ordered);@@ -886,7 +898,7 @@ static int copy_space_cache(struct btrfs_root *root,
}
static int copy_from_extent_tree(struct metadump_struct *metadump,
- struct btrfs_path *path)
+ struct btrfs_path *path, bool dump_data)
{
struct btrfs_root *extent_root;
struct extent_buffer *leaf;@@ -951,9 +963,15 @@ static int copy_from_extent_tree(struct metadump_struct *metadump,
ei = btrfs_item_ptr(leaf, path->slots[0],
struct btrfs_extent_item);
if (btrfs_extent_flags(leaf, ei) &
- BTRFS_EXTENT_FLAG_TREE_BLOCK) {
+ BTRFS_EXTENT_FLAG_TREE_BLOCK ||
+ (dump_data && (btrfs_extent_flags(leaf, ei) &
+ BTRFS_EXTENT_FLAG_DATA))) {
+ bool is_data;
+
+ is_data = btrfs_extent_flags(leaf, ei) &
+ BTRFS_EXTENT_FLAG_DATA;
ret = add_extent(bytenr, num_bytes, metadump,
- 0);
+ is_data);
if (ret) {
error("unable to add block %llu: %d",
(unsigned long long)bytenr, ret);@@ -976,7 +994,7 @@ static int copy_from_extent_tree(struct metadump_struct *metadump,
static int create_metadump(const char *input, FILE *out, int num_threads,
int compress_level, enum sanitize_mode sanitize,
- int walk_trees)
+ int walk_trees, bool dump_data)
{
struct btrfs_root *root;
struct btrfs_path path;@@ -991,7 +1009,7 @@ static int create_metadump(const char *input, FILE *out, int num_threads,
}
ret = metadump_init(&metadump, root, out, num_threads,
- compress_level, sanitize);
+ compress_level, dump_data, sanitize);
if (ret) {
error("failed to initialize metadump: %d", ret);
close_ctree(root);@@ -1023,7 +1041,7 @@ static int create_metadump(const char *input, FILE *out, int num_threads,
goto out;
}
} else {
- ret = copy_from_extent_tree(&metadump, &path);
+ ret = copy_from_extent_tree(&metadump, &path, dump_data);
if (ret) {
err = ret;
goto out;@@ -2929,6 +2947,7 @@ static void print_usage(int ret)
printf("\t-s \tsanitize file names, use once to just use garbage, use twice if you want crc collisions\n");
printf("\t-w \twalk all trees instead of using extent tree, do this if your extent tree is broken\n");
printf("\t-m \trestore for multiple devices\n");
+ printf("\t-d \talso dump data, conflicts with -w\n");
printf("\n");
printf("\tIn the dump mode, source is the btrfs device and target is the output file (use '-' for stdout).\n");
printf("\tIn the restore mode, source is the dumped image and target is the btrfs device/file.\n");@@ -2948,6 +2967,7 @@ int BOX_MAIN(image)(int argc, char *argv[])
int ret;
enum sanitize_mode sanitize = SANITIZE_NONE;
int dev_cnt = 0;
+ bool dump_data = false;
int usage_error = 0;
FILE *out;
@@ -2956,7 +2976,7 @@ int BOX_MAIN(image)(int argc, char *argv[])
{ "help", no_argument, NULL, GETOPT_VAL_HELP},
{ NULL, 0, NULL, 0 }
};
- int c = getopt_long(argc, argv, "rc:t:oswm", long_options, NULL);
+ int c = getopt_long(argc, argv, "rc:t:oswmd", long_options, NULL);
if (c < 0)
break;
switch (c) {@@ -2996,6 +3016,9 @@ int BOX_MAIN(image)(int argc, char *argv[])
create = 0;
multi_devices = 1;
break;
+ case 'd':
+ dump_data = true;
+ break;
case GETOPT_VAL_HELP:
default:
print_usage(c != GETOPT_VAL_HELP);
@@ -3014,10 +3037,15 @@ int BOX_MAIN(image)(int argc, char *argv[])
"create and restore cannot be used at the same time");
usage_error++;
}
+ if (dump_data && walk_trees) {
+ error("-d conflicts with -w option");
+ usage_error++;
+ }
} else {
- if (walk_trees || sanitize != SANITIZE_NONE || compress_level) {
+ if (walk_trees || sanitize != SANITIZE_NONE || compress_level ||
+ dump_data) {
error(
- "using -w, -s, -c options for restore makes no sense");
+ "using -w, -s, -c, -d options for restore makes no sense");
usage_error++;
}
if (multi_devices && dev_cnt < 2) {@@ -3070,7 +3098,8 @@ int BOX_MAIN(image)(int argc, char *argv[])
}
ret = create_metadump(source, out, num_threads,
- compress_level, sanitize, walk_trees);
+ compress_level, sanitize, walk_trees,
+ dump_data);
} else {
ret = restore_metadump(source, out, old_restore, num_threads,
0, target, multi_devices);diff --git a/image/metadump.h b/image/metadump.h
index 7bdddc7b853c..db56add42f1c 100644
--- a/image/metadump.h
+++ b/image/metadump.h
@@ -38,7 +38,7 @@ struct dump_version {
unsigned int extra_sb_flags:1;
};
-#define NR_DUMP_VERSIONS 1
+#define NR_DUMP_VERSIONS 2
extern const struct dump_version dump_versions[NR_DUMP_VERSIONS];
const extern struct dump_version *current_version;
--
2.32.0