#include <stdlib.h>
#include <unistd.h>
#include <uuid/uuid.h>
+#include <getopt.h>
+
#include "kerncompat.h"
#include "radix-tree.h"
#include "ctree.h"
#include "disk-io.h"
#include "print-tree.h"
#include "transaction.h"
-#include "version.h"
+#include "utils.h"
-static int print_usage(void)
+static int print_usage(int ret)
{
fprintf(stderr, "usage: btrfs-debug-tree [-e] [-d] [-r] [-R] [-u]\n");
fprintf(stderr, " [-b block_num ] device\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, "%s\n", BTRFS_BUILD_VERSION);
- exit(1);
+ fprintf(stderr,
+ "\t-t tree_id : print only the tree with the given id\n");
+ fprintf(stderr, "%s\n", PACKAGE_STRING);
+ exit(ret);
}
static void print_extents(struct btrfs_root *root, struct extent_buffer *eb)
btrfs_node_blockptr(eb, i),
size,
btrfs_node_ptr_generation(eb, i));
+ if (!extent_buffer_uptodate(next))
+ continue;
if (btrfs_is_leaf(next) &&
btrfs_header_level(eb) != 1)
BUG();
struct extent_buffer *leaf;
struct btrfs_disk_key disk_key;
struct btrfs_key found_key;
- char uuidbuf[37];
+ char uuidbuf[BTRFS_UUID_UNPARSED_SIZE];
int ret;
int slot;
int extent_only = 0;
int root_backups = 0;
u64 block_only = 0;
struct btrfs_root *tree_root_scan;
+ u64 tree_id = 0;
radix_tree_init();
while(1) {
int c;
- c = getopt(ac, av, "deb:rRu");
+ static const struct option long_options[] = {
+ { "help", no_argument, NULL, GETOPT_VAL_HELP},
+ { NULL, 0, NULL, 0 }
+ };
+
+ c = getopt_long(ac, av, "deb:rRut:", long_options, NULL);
if (c < 0)
break;
switch(c) {
root_backups = 1;
break;
case 'b':
- block_only = atoll(optarg);
+ block_only = arg_strtou64(optarg);
break;
+ case 't':
+ tree_id = arg_strtou64(optarg);
+ break;
+ case GETOPT_VAL_HELP:
default:
- print_usage();
+ print_usage(c != GETOPT_VAL_HELP);
}
}
+ set_argv0(av);
ac = ac - optind;
- if (ac != 1)
- print_usage();
+ if (check_argc_exact(ac, 1))
+ print_usage(1);
- info = open_ctree_fs_info(av[optind], 0, 0, 0, 1);
+ ret = check_arg_type(av[optind]);
+ if (ret != BTRFS_ARG_BLKDEV && ret != BTRFS_ARG_REG) {
+ fprintf(stderr, "'%s' is not a block device or regular file\n",
+ av[optind]);
+ exit(1);
+ }
+
+ info = open_ctree_fs_info(av[optind], 0, 0, OPEN_CTREE_PARTIAL);
if (!info) {
fprintf(stderr, "unable to open %s\n", av[optind]);
exit(1);
}
+
root = info->fs_root;
+ if (!root) {
+ fprintf(stderr, "unable to open %s\n", av[optind]);
+ exit(1);
+ }
if (block_only) {
- if (!root) {
- fprintf(stderr, "unable to open %s\n", av[optind]);
- exit(1);
- }
leaf = read_tree_block(root,
block_only,
root->leafsize, 0);
- if (leaf && btrfs_header_level(leaf) != 0) {
+ if (extent_buffer_uptodate(leaf) &&
+ btrfs_header_level(leaf) != 0) {
free_extent_buffer(leaf);
leaf = NULL;
}
block_only,
root->nodesize, 0);
}
- if (!leaf) {
+ if (!extent_buffer_uptodate(leaf)) {
fprintf(stderr, "failed to read %llu\n",
(unsigned long long)block_only);
goto close_root;
}
btrfs_print_tree(root, leaf, 0);
+ free_extent_buffer(leaf);
goto close_root;
}
- if (!(extent_only || uuid_tree_only)) {
+ if (!(extent_only || uuid_tree_only || tree_id)) {
if (roots_only) {
printf("root tree: %llu level %d\n",
(unsigned long long)info->tree_root->node->start,
0);
if (!extent_buffer_uptodate(buf))
goto next;
+ if (tree_id && found_key.objectid != tree_id) {
+ free_extent_buffer(buf);
+ goto next;
+ }
switch(found_key.objectid) {
case BTRFS_ROOT_TREE_OBJECTID:
path.slots[0]++;
}
no_node:
- btrfs_release_path(root, &path);
+ btrfs_release_path(&path);
if (tree_root_scan == info->tree_root &&
info->log_root_tree) {
(unsigned long long)btrfs_super_total_bytes(info->super_copy));
printf("bytes used %llu\n",
(unsigned long long)btrfs_super_bytes_used(info->super_copy));
- uuidbuf[36] = '\0';
+ uuidbuf[BTRFS_UUID_UNPARSED_SIZE - 1] = '\0';
uuid_unparse(info->super_copy->fsid, uuidbuf);
printf("uuid %s\n", uuidbuf);
- printf("%s\n", BTRFS_BUILD_VERSION);
+ printf("%s\n", PACKAGE_STRING);
close_root:
return close_ctree(root);
}