From: Anand Jain <anand.j...@oracle.com> btrfs inspect dump-tree picks the disk with the largest generation to read the root tree by scanning for the required devices by default.
But in 2 or more disks RAID1/5/6 you may need to know what's in the disks individually, so this option --noscan indicates to use only the given disk to dump. For example: mkfs.btrfs -fq -draid1 -mraid1 /dev/sd[b-d] btrfs in dump-tree --noscan /dev/sdb /dev/sdc However as usual without noscan option it works as it scans for the devices by its own. And if minimum required number of devices are not provided then when --noscan option is used, it errors out as shown below. btrfs in dump-tree --noscan /dev/sdb check arg type : /dev/sdbbtrfs-progs v4.14.1 warning, device 3 is missing warning, device 2 is missing bytenr mismatch, want=22036480, have=0 ERROR: cannot read chunk root ERROR: unable to open /dev/sdb Signed-off-by: Anand Jain <anand.j...@oracle.com> --- v2->v3: make it scalable for more than two disks in noscan mode v1->v2: rename --degraded to --noscan cmds-inspect-dump-tree.c | 60 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 7 deletions(-) diff --git a/cmds-inspect-dump-tree.c b/cmds-inspect-dump-tree.c index 0802b31e9596..8625cd608ad0 100644 --- a/cmds-inspect-dump-tree.c +++ b/cmds-inspect-dump-tree.c @@ -21,6 +21,7 @@ #include <unistd.h> #include <uuid/uuid.h> #include <getopt.h> +#include <fcntl.h> #include "kerncompat.h" #include "radix-tree.h" @@ -183,6 +184,46 @@ static u64 treeid_from_string(const char *str, const char **end) return id; } +static int scan_args(char **argv, int argc, int tmpind, int noscan) +{ + int fd; + int ret; + u64 num_devices; + struct btrfs_fs_devices *tmp_devices; + + while (tmpind < argc) { + ret = check_arg_type(argv[tmpind]); + if (ret != BTRFS_ARG_BLKDEV && ret != BTRFS_ARG_REG) { + error("not a block device or regular file: %s", + argv[tmpind]); + return -EINVAL; + } + + if (!noscan) { + tmpind++; + continue; + } + + fd = open(argv[tmpind], O_RDONLY); + if (fd < 0) { + error("cannot open %s: %m", argv[tmpind]); + return -EINVAL; + } + ret = btrfs_scan_one_device(fd, argv[tmpind], + &tmp_devices, &num_devices, + BTRFS_SUPER_INFO_OFFSET, + SBREAD_DEFAULT); + close(fd); + if (ret) { + error("cannot scan %s: %s", + argv[tmpind], strerror(-ret)); + return ret; + } + tmpind++; + } + return 0; +} + const char * const cmd_inspect_dump_tree_usage[] = { "btrfs inspect-internal dump-tree [options] device", "Dump tree structures from a given device", @@ -199,6 +240,7 @@ const char * const cmd_inspect_dump_tree_usage[] = { "-b|--block <block_num> print info from the specified block only", "-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 only uses the devices provided as the argument", NULL }; @@ -213,7 +255,7 @@ int cmd_inspect_dump_tree(int argc, char **argv) struct btrfs_disk_key disk_key; struct btrfs_key found_key; char uuidbuf[BTRFS_UUID_UNPARSED_SIZE]; - int ret; + int ret = 0; int slot; int extent_only = 0; int device_only = 0; @@ -225,10 +267,12 @@ int cmd_inspect_dump_tree(int argc, char **argv) struct btrfs_root *tree_root_scan; u64 tree_id = 0; bool follow = false; + bool noscan = false; while (1) { int c; - enum { GETOPT_VAL_FOLLOW = 256 }; + enum { GETOPT_VAL_FOLLOW = 256, + GETOPT_VAL_NOSCAN = 257}; static const struct option long_options[] = { { "extents", no_argument, NULL, 'e'}, { "device", no_argument, NULL, 'd'}, @@ -238,6 +282,7 @@ int cmd_inspect_dump_tree(int argc, char **argv) { "block", required_argument, NULL, 'b'}, { "tree", required_argument, NULL, 't'}, { "follow", no_argument, NULL, GETOPT_VAL_FOLLOW }, + { "noscan", no_argument, NULL, GETOPT_VAL_NOSCAN }, { NULL, 0, NULL, 0 } }; @@ -293,19 +338,20 @@ int cmd_inspect_dump_tree(int argc, char **argv) case GETOPT_VAL_FOLLOW: follow = true; break; + case GETOPT_VAL_NOSCAN: + open_ctree_flags |= OPEN_CTREE_NO_DEVICES; + noscan = true; + break; default: usage(cmd_inspect_dump_tree_usage); } } - if (check_argc_exact(argc - optind, 1)) + if (check_argc_min(argc - optind, 1)) usage(cmd_inspect_dump_tree_usage); - ret = check_arg_type(argv[optind]); - if (ret != BTRFS_ARG_BLKDEV && ret != BTRFS_ARG_REG) { - error("not a block device or regular file: %s", argv[optind]); + if (scan_args(argv, argc, optind, noscan)) goto out; - } printf("%s\n", PACKAGE_STRING); -- 2.15.0 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html