From 03241303ebfb698803235d394b9438501498374c Mon Sep 17 00:00:00 2001 From: Anand Jain Date: Wed, 26 Jun 2019 01:30:17 -0700 Subject: [PATCH] btrfs-progs: dump-tree: add noscan option The comman 'btrfs inspect dump-tree ' will scan all the devices from the filesystem by defaul. So as of now you can not inspect each mirrored device independently. This patch adds option --noscan, which when used won't scan the system for the partner devices, instead it just uses the devices provided in the argument. For example: btrfs inspect dump-tree --noscan [..] This helps to debug degraded raid1 and raid10. Signed-off-by: Anand Jain Signed-off-by: David Sterba --- Documentation/btrfs-inspect-internal.asciidoc | 5 +- cmds/inspect-dump-tree.c | 53 ++++++++++++++----- 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/Documentation/btrfs-inspect-internal.asciidoc b/Documentation/btrfs-inspect-internal.asciidoc index 210f18c3..81193600 100644 --- a/Documentation/btrfs-inspect-internal.asciidoc +++ b/Documentation/btrfs-inspect-internal.asciidoc @@ -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] :: +*dump-tree* [options] [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 +--noscan:::: +do not automatically scan the system for other devices from the same +filesystem, only use the devices provided as the arguments -t :::: print only the tree with the specified ID, where the ID can be numerical or common name in a flexible human readable form diff --git a/cmds/inspect-dump-tree.c b/cmds/inspect-dump-tree.c index b02aacc8..e50130a4 100644 --- a/cmds/inspect-dump-tree.c +++ b/cmds/inspect-dump-tree.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "kerncompat.h" #include "kernel-lib/radix-tree.h" @@ -186,7 +187,7 @@ static u64 treeid_from_string(const char *str, const char **end) } static const char * const cmd_inspect_dump_tree_usage[] = { - "btrfs inspect-internal dump-tree [options] device", + "btrfs inspect-internal dump-tree [options] [ ..]", "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.", @@ -202,6 +203,7 @@ static const char * const cmd_inspect_dump_tree_usage[] = { " can be specified multiple times", "-t|--tree print only tree with the given id (string or number)", "--follow use with -b, to show all children tree blocks of ", + "--noscan do not scan the devices from the filesystem, use only the listed ones", NULL }; @@ -298,7 +300,7 @@ static int cmd_inspect_dump_tree(const struct cmd_struct *cmd, 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; @@ -306,6 +308,7 @@ static int cmd_inspect_dump_tree(const struct cmd_struct *cmd, 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; @@ -324,8 +327,8 @@ static int cmd_inspect_dump_tree(const struct cmd_struct *cmd, 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'}, @@ -337,6 +340,7 @@ static int cmd_inspect_dump_tree(const struct cmd_struct *cmd, { "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 } }; @@ -401,24 +405,49 @@ static int cmd_inspect_dump_tree(const struct cmd_struct *cmd, 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, 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);