Add new option '-B' to show tree block without calling open_ctree.
It's very useful to debug non-standard super or heavily damaged case.

As it needs nodesize, also adds a new option '-n' to specify nodesize.

Normal user should avoid calling it on random bytes, as it won't check
the validation of the tree block.

Signed-off-by: Qu Wenruo <[email protected]>
---
 Documentation/btrfs-debug-tree.asciidoc | 12 ++++-
 btrfs-debug-tree.c                      | 81 +++++++++++++++++++++++++++++----
 2 files changed, 82 insertions(+), 11 deletions(-)

diff --git a/Documentation/btrfs-debug-tree.asciidoc 
b/Documentation/btrfs-debug-tree.asciidoc
index 23fc115..a5528cb 100644
--- a/Documentation/btrfs-debug-tree.asciidoc
+++ b/Documentation/btrfs-debug-tree.asciidoc
@@ -25,8 +25,16 @@ Print detailed extents info.
 Print info of btrfs device and root tree dirs only.
 -r::
 Print info of roots only.
--b <block_num>::
-Print info of the specified block only.
+-b <bytenr>::
+Print info of the specified block at logical bytenr.
+-B <bytenr>::
+Print info of the specified block at on-disk bytenr.
+Need to use with '-n <nodesize>' option.
++
+Use with caution, as it won't do normal tree block check.
+
+-n <nodesize>::
+Specify the nodesize for '-B <bytenr>' option.
 
 EXIT STATUS
 -----------
diff --git a/btrfs-debug-tree.c b/btrfs-debug-tree.c
index 8adc39f..52e3de3 100644
--- a/btrfs-debug-tree.c
+++ b/btrfs-debug-tree.c
@@ -21,6 +21,8 @@
 #include <unistd.h>
 #include <uuid/uuid.h>
 #include <getopt.h>
+#include <fcntl.h>
+#include <sys/stat.h>
 
 #include "kerncompat.h"
 #include "radix-tree.h"
@@ -41,8 +43,11 @@ static int print_usage(int ret)
        fprintf(stderr, "\t-r : print info of roots only\n");
        fprintf(stderr, "\t-R : print info of roots and root backups\n");
        fprintf(stderr, "\t-u : print info of uuid tree only\n");
-       fprintf(stderr, "\t-b block_num : print info of the specified block"
-                    " only\n");
+       fprintf(stderr, "\t-b bytenr: print info of the specified block"
+                    " at logical bytenr only\n");
+       fprintf(stderr, "\t-B bytenr: print info of the specified block"
+                    " at disk bytenr only, need -n option(use with 
caution)\n");
+       fprintf(stderr, "\t-n nodesize: specify the nodesize to use with -B\n");
        fprintf(stderr,
                "\t-t tree_id : print only the tree with the given id\n");
        fprintf(stderr, "%s\n", PACKAGE_STRING);
@@ -122,6 +127,41 @@ static void print_old_roots(struct btrfs_super_block 
*super)
        }
 }
 
+static int print_ondisk_leaf(const char *device, u64 ondisk_bytenr,
+                            u32 nodesize)
+{
+       struct extent_buffer *buf = NULL;
+       int fd;
+       int ret;
+
+       buf = malloc(sizeof(*buf) + nodesize);
+       if (!buf) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       memset(buf, 0, sizeof(buf) + nodesize);
+       buf->start = ondisk_bytenr;
+       buf->len = nodesize;
+       buf->refs = 1;
+       fd = open(device, O_RDONLY);
+       if (fd < 0) {
+               ret = -errno;
+               goto out;
+       }
+
+       ret = pread(fd, buf->data, nodesize, ondisk_bytenr);
+       if (ret < nodesize) {
+               ret = (ret < 0 ? ret : -EIO);
+               goto out;
+       }
+
+       /* We don't check anything, user should be responsible for it */
+       btrfs_print_leaf(NULL, buf);
+out:
+       free(buf);
+       return ret;
+}
+
 int main(int ac, char **av)
 {
        struct btrfs_root *root;
@@ -140,7 +180,9 @@ int main(int ac, char **av)
        int uuid_tree_only = 0;
        int roots_only = 0;
        int root_backups = 0;
-       u64 block_only = 0;
+       u64 logical_only = 0;
+       u64 ondisk_only = 0;
+       u32 nodesize = 0;
        struct btrfs_root *tree_root_scan;
        u64 tree_id = 0;
 
@@ -153,7 +195,7 @@ int main(int ac, char **av)
                        { NULL, 0, NULL, 0 }
                };
 
-               c = getopt_long(ac, av, "deb:rRut:", long_options, NULL);
+               c = getopt_long(ac, av, "deb:B:rRut:n:", long_options, NULL);
                if (c < 0)
                        break;
                switch(c) {
@@ -174,7 +216,13 @@ int main(int ac, char **av)
                                root_backups = 1;
                                break;
                        case 'b':
-                               block_only = arg_strtou64(optarg);
+                               logical_only = arg_strtou64(optarg);
+                               break;
+                       case 'B':
+                               ondisk_only = arg_strtou64(optarg);
+                               break;
+                       case 'n':
+                               nodesize = arg_strtou64(optarg);
                                break;
                        case 't':
                                tree_id = arg_strtou64(optarg);
@@ -196,6 +244,21 @@ int main(int ac, char **av)
                exit(1);
        }
 
+       /* Ondisk_only means we won't need to go through open_ctree */
+       if (ondisk_only) {
+               if (!nodesize) {
+                       fprintf(stderr, "-n <nodesize> must be specified\n");
+                       exit(1);
+               }
+               ret = print_ondisk_leaf(av[optind], ondisk_only, nodesize);
+               if (ret < 0) {
+                       fprintf(stderr,
+                               "failed to print leaf at ondisk bytenr: %llu, 
%s\n",
+                               ondisk_only, strerror(-ret));
+                       ret = 1;
+               }
+               exit(ret);
+       }
        info = open_ctree_fs_info(av[optind], 0, 0, OPEN_CTREE_PARTIAL);
        if (!info) {
                fprintf(stderr, "unable to open %s\n", av[optind]);
@@ -208,9 +271,9 @@ int main(int ac, char **av)
                exit(1);
        }
 
-       if (block_only) {
+       if (logical_only) {
                leaf = read_tree_block(root,
-                                     block_only,
+                                     logical_only,
                                      root->leafsize, 0);
 
                if (extent_buffer_uptodate(leaf) &&
@@ -221,12 +284,12 @@ int main(int ac, char **av)
 
                if (!leaf) {
                        leaf = read_tree_block(root,
-                                             block_only,
+                                             logical_only,
                                              root->nodesize, 0);
                }
                if (!extent_buffer_uptodate(leaf)) {
                        fprintf(stderr, "failed to read %llu\n",
-                               (unsigned long long)block_only);
+                               (unsigned long long)logical_only);
                        goto close_root;
                }
                btrfs_print_tree(root, leaf, 0);
-- 
2.6.2

--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to