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

Reply via email to