@@ -61,7 +61,7 @@ specify which mirror to print, valid values are 0, 1 and 2 and the superblock
must be present on the device with a valid signature, can be used together with
'--force'
-*dump-tree* [options] <device>::
+*dump-tree* [options] <device> [device...]::
(replaces the standalone tool *btrfs-debug-tree*)
+
Dump tree structures from a given device in textual form, expand keys to human
@@ -95,6 +95,9 @@ intermixed in the output
--bfs::::
use breadth-first search to print trees. the nodes are printed before all
leaves
+--device::::
+do not scan the system for other partner device(s), only use the device(s)
+provided in the argument
-t <tree_id>::::
print only the tree with the specified ID, where the ID can be numerical or
common name in a flexible human readable form
@@ -21,6 +21,7 @@
#include <unistd.h>
#include <uuid/uuid.h>
#include <getopt.h>
+#include <fcntl.h>
#include "kerncompat.h"
#include "radix-tree.h"
@@ -185,7 +186,7 @@ static u64 treeid_from_string(const char *str, const char **end)
}
const char * const cmd_inspect_dump_tree_usage[] = {
- "btrfs inspect-internal dump-tree [options] device",
+ "btrfs inspect-internal dump-tree [options] <device> [<device> ..]",
"Dump tree structures from a given device",
"Dump tree structures from a given device in textual form, expand keys to human",
"readable equivalents where possible.",
@@ -201,6 +202,7 @@ const char * const cmd_inspect_dump_tree_usage[] = {
" can be specified multiple times",
"-t|--tree <tree_id> print only tree with the given id (string or number)",
"--follow use with -b, to show all children tree blocks of <block_num>",
+ "--noscan do not scan for the partner device(s)",
NULL
};
@@ -296,7 +298,7 @@ int cmd_inspect_dump_tree(int argc, char **argv)
struct btrfs_key found_key;
struct cache_tree block_root; /* for multiple --block parameters */
char uuidbuf[BTRFS_UUID_UNPARSED_SIZE];
- int ret;
+ int ret = 0;
int slot;
int extent_only = 0;
int device_only = 0;
@@ -304,6 +306,7 @@ int cmd_inspect_dump_tree(int argc, char **argv)
int roots_only = 0;
int root_backups = 0;
int traverse = BTRFS_PRINT_TREE_DEFAULT;
+ int dev_optind;
unsigned open_ctree_flags;
u64 block_bytenr;
struct btrfs_root *tree_root_scan;
@@ -322,8 +325,8 @@ int cmd_inspect_dump_tree(int argc, char **argv)
optind = 0;
while (1) {
int c;
- enum { GETOPT_VAL_FOLLOW = 256, GETOPT_VAL_DFS,
- GETOPT_VAL_BFS };
+ enum { GETOPT_VAL_FOLLOW = 256, GETOPT_VAL_DFS, GETOPT_VAL_BFS,
+ GETOPT_VAL_NOSCAN};
static const struct option long_options[] = {
{ "extents", no_argument, NULL, 'e'},
{ "device", no_argument, NULL, 'd'},
@@ -335,6 +338,7 @@ int cmd_inspect_dump_tree(int argc, char **argv)
{ "follow", no_argument, NULL, GETOPT_VAL_FOLLOW },
{ "bfs", no_argument, NULL, GETOPT_VAL_BFS },
{ "dfs", no_argument, NULL, GETOPT_VAL_DFS },
+ { "noscan", no_argument, NULL, GETOPT_VAL_NOSCAN },
{ NULL, 0, NULL, 0 }
};
@@ -399,24 +403,49 @@ int cmd_inspect_dump_tree(int argc, char **argv)
case GETOPT_VAL_BFS:
traverse = BTRFS_PRINT_TREE_BFS;
break;
+ case GETOPT_VAL_NOSCAN:
+ open_ctree_flags |= OPEN_CTREE_NO_DEVICES;
+ break;
default:
usage_unknown_option(cmd_inspect_dump_tree_usage, argv);
}
}
- if (check_argc_exact(argc - optind, 1))
+ if (check_argc_min(argc - optind, 1))
return 1;
- ret = check_arg_type(argv[optind]);
- if (ret != BTRFS_ARG_BLKDEV && ret != BTRFS_ARG_REG) {
+ dev_optind = optind;
+ while (dev_optind < argc) {
+ int fd;
+ struct btrfs_fs_devices *fs_devices;
+ u64 num_devices;
+
+ ret = check_arg_type(argv[optind]);
+ if (ret != BTRFS_ARG_BLKDEV && ret != BTRFS_ARG_REG) {
+ if (ret < 0) {
+ errno = -ret;
+ error("invalid argument %s: %m", argv[dev_optind]);
+ } else {
+ error("not a block device or regular file: %s",
+ argv[dev_optind]);
+ }
+ }
+ fd = open(argv[dev_optind], O_RDONLY);
+ if (fd < 0) {
+ error("cannot open %s: %m", argv[dev_optind]);
+ return -EINVAL;
+ }
+ ret = btrfs_scan_one_device(fd, argv[dev_optind], &fs_devices,
+ &num_devices,
+ BTRFS_SUPER_INFO_OFFSET,
+ SBREAD_DEFAULT);
+ close(fd);
if (ret < 0) {
errno = -ret;
- error("invalid argument %s: %m", argv[optind]);
- } else {
- error("not a block device or regular file: %s",
- argv[optind]);
+ error("device scan %s: %m", argv[dev_optind]);
+ return ret;
}
- goto out;
+ dev_optind++;
}
printf("%s\n", PACKAGE_STRING);