@@ -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
-----------
@@ -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);
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 <quwenruo@cn.fujitsu.com> --- Documentation/btrfs-debug-tree.asciidoc | 12 ++++- btrfs-debug-tree.c | 81 +++++++++++++++++++++++++++++---- 2 files changed, 82 insertions(+), 11 deletions(-)