X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=btrfs-calc-size.c;h=d2d68ab259eb5691bb903dddd2a0bc2241c08572;hb=23df5de0d07028f31f017a0f80091ba158980742;hp=137208455857c24d636df78198e0f396b72fe205;hpb=ccdd0a067f36b689a0928074d53e5020f3ff5f5d;p=platform%2Fupstream%2Fbtrfs-progs.git diff --git a/btrfs-calc-size.c b/btrfs-calc-size.c index 1372084..d2d68ab 100644 --- a/btrfs-calc-size.c +++ b/btrfs-calc-size.c @@ -16,497 +16,24 @@ * Boston, MA 021110-1307, USA. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "kerncompat.h" -#include "ctree.h" -#include "disk-io.h" -#include "print-tree.h" -#include "transaction.h" -#include "list.h" #include "volumes.h" #include "utils.h" - -static int verbose = 0; -static int no_pretty = 0; - -struct seek { - u64 distance; - u64 count; - struct rb_node n; -}; - -struct root_stats { - u64 total_nodes; - u64 total_leaves; - u64 total_bytes; - u64 total_inline; - u64 total_seeks; - u64 forward_seeks; - u64 backward_seeks; - u64 total_seek_len; - u64 max_seek_len; - u64 total_clusters; - u64 total_cluster_size; - u64 min_cluster_size; - u64 max_cluster_size; - u64 lowest_bytenr; - u64 highest_bytenr; - struct rb_root seek_root; - int total_levels; -}; - -struct fs_root { - struct btrfs_key key; - struct btrfs_key *snaps; -}; - -static int add_seek(struct rb_root *root, u64 dist) -{ - struct rb_node **p = &root->rb_node; - struct rb_node *parent = NULL; - struct seek *seek = NULL; - - while (*p) { - parent = *p; - seek = rb_entry(parent, struct seek, n); - - if (dist < seek->distance) { - p = &(*p)->rb_left; - } else if (dist > seek->distance) { - p = &(*p)->rb_right; - } else { - seek->count++; - return 0; - } - } - - seek = malloc(sizeof(struct seek)); - if (!seek) - return -ENOMEM; - seek->distance = dist; - seek->count = 1; - rb_link_node(&seek->n, parent, p); - rb_insert_color(&seek->n, root); - return 0; -} - -static int walk_leaf(struct btrfs_root *root, struct btrfs_path *path, - struct root_stats *stat, int find_inline) -{ - struct extent_buffer *b = path->nodes[0]; - struct btrfs_file_extent_item *fi; - struct btrfs_key found_key; - int i; - - stat->total_bytes += root->leafsize; - stat->total_leaves++; - - if (!find_inline) - return 0; - - for (i = 0; i < btrfs_header_nritems(b); i++) { - btrfs_item_key_to_cpu(b, &found_key, i); - if (found_key.type != BTRFS_EXTENT_DATA_KEY) - continue; - - fi = btrfs_item_ptr(b, i, struct btrfs_file_extent_item); - if (btrfs_file_extent_type(b, fi) == BTRFS_FILE_EXTENT_INLINE) - stat->total_inline += - btrfs_file_extent_inline_item_len(b, - btrfs_item_nr(i)); - } - - return 0; -} - -static u64 calc_distance(u64 block1, u64 block2) -{ - if (block1 < block2) - return block2 - block1; - return block1 - block2; -} - -static int walk_nodes(struct btrfs_root *root, struct btrfs_path *path, - struct root_stats *stat, int level, int find_inline) -{ - struct extent_buffer *b = path->nodes[level]; - u64 last_block; - u64 cluster_size = root->leafsize; - int i; - int ret = 0; - - stat->total_bytes += root->nodesize; - stat->total_nodes++; - - last_block = btrfs_header_bytenr(b); - for (i = 0; i < btrfs_header_nritems(b); i++) { - struct extent_buffer *tmp = NULL; - u64 cur_blocknr = btrfs_node_blockptr(b, i); - - path->slots[level] = i; - if ((level - 1) > 0 || find_inline) { - tmp = read_tree_block(root, cur_blocknr, - btrfs_level_size(root, level - 1), - btrfs_node_ptr_generation(b, i)); - if (!extent_buffer_uptodate(tmp)) { - fprintf(stderr, "Failed to read blocknr %Lu\n", - btrfs_node_blockptr(b, i)); - continue; - } - path->nodes[level - 1] = tmp; - } - if (level - 1) - ret = walk_nodes(root, path, stat, level - 1, - find_inline); - else - ret = walk_leaf(root, path, stat, find_inline); - if (last_block + root->leafsize != cur_blocknr) { - u64 distance = calc_distance(last_block + - root->leafsize, - cur_blocknr); - stat->total_seeks++; - stat->total_seek_len += distance; - if (stat->max_seek_len < distance) - stat->max_seek_len = distance; - if (add_seek(&stat->seek_root, distance)) { - fprintf(stderr, "Error adding new seek\n"); - ret = -ENOMEM; - break; - } - - if (last_block < cur_blocknr) - stat->forward_seeks++; - else - stat->backward_seeks++; - if (cluster_size != root->leafsize) { - stat->total_cluster_size += cluster_size; - stat->total_clusters++; - if (cluster_size < stat->min_cluster_size) - stat->min_cluster_size = cluster_size; - if (cluster_size > stat->max_cluster_size) - stat->max_cluster_size = cluster_size; - } - cluster_size = root->leafsize; - } else { - cluster_size += root->leafsize; - } - last_block = cur_blocknr; - if (cur_blocknr < stat->lowest_bytenr) - stat->lowest_bytenr = cur_blocknr; - if (cur_blocknr > stat->highest_bytenr) - stat->highest_bytenr = cur_blocknr; - free_extent_buffer(tmp); - if (ret) { - fprintf(stderr, "Error walking down path\n"); - break; - } - } - - return ret; -} - -static void print_seek_histogram(struct root_stats *stat) -{ - struct rb_node *n = rb_first(&stat->seek_root); - struct seek *seek; - u64 tick_interval; - u64 group_start; - u64 group_count = 0; - u64 group_end; - u64 i; - u64 max_seek = stat->max_seek_len; - int digits = 1; - - if (stat->total_seeks < 20) - return; - - while ((max_seek /= 10)) - digits++; - - /* Make a tick count as 5% of the total seeks */ - tick_interval = stat->total_seeks / 20; - printf("\tSeek histogram\n"); - for (; n; n = rb_next(n)) { - u64 ticks, gticks = 0; - - seek = rb_entry(n, struct seek, n); - ticks = seek->count / tick_interval; - if (group_count) - gticks = group_count / tick_interval; - - if (ticks <= 2 && gticks <= 2) { - if (group_count == 0) - group_start = seek->distance; - group_end = seek->distance; - group_count += seek->count; - continue; - } - - if (group_count) { - - gticks = group_count / tick_interval; - printf("\t\t%*Lu - %*Lu: %*Lu ", digits, group_start, - digits, group_end, digits, group_count); - if (gticks) { - for (i = 0; i < gticks; i++) - printf("#"); - printf("\n"); - } else { - printf("|\n"); - } - group_count = 0; - } - - if (ticks <= 2) - continue; - - printf("\t\t%*Lu - %*Lu: %*Lu ", digits, seek->distance, - digits, seek->distance, digits, seek->count); - for (i = 0; i < ticks; i++) - printf("#"); - printf("\n"); - } - if (group_count) { - u64 gticks; - - gticks = group_count / tick_interval; - printf("\t\t%*Lu - %*Lu: %*Lu ", digits, group_start, - digits, group_end, digits, group_count); - if (gticks) { - for (i = 0; i < gticks; i++) - printf("#"); - printf("\n"); - } else { - printf("|\n"); - } - group_count = 0; - } -} - -static void timeval_subtract(struct timeval *result,struct timeval *x, - struct timeval *y) -{ - if (x->tv_usec < y->tv_usec) { - int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; - y->tv_usec -= 1000000 * nsec; - y->tv_sec += nsec; - } - - if (x->tv_usec - y->tv_usec > 1000000) { - int nsec = (x->tv_usec - y->tv_usec) / 1000000; - y->tv_usec += 1000000 * nsec; - y->tv_sec -= nsec; - } - - result->tv_sec = x->tv_sec - y->tv_sec; - result->tv_usec = x->tv_usec - y->tv_usec; -} - -static int calc_root_size(struct btrfs_root *tree_root, struct btrfs_key *key, - int find_inline) -{ - struct btrfs_root *root; - struct btrfs_path *path; - struct rb_node *n; - struct timeval start, end, diff = {0}; - struct root_stats stat; - int level; - int ret = 0; - int size_fail = 0; - - root = btrfs_read_fs_root(tree_root->fs_info, key); - if (IS_ERR(root)) { - fprintf(stderr, "Failed to read root %Lu\n", key->objectid); - return 1; - } - - path = btrfs_alloc_path(); - if (!path) { - fprintf(stderr, "Could not allocate path\n"); - return 1; - } - - memset(&stat, 0, sizeof(stat)); - level = btrfs_header_level(root->node); - stat.lowest_bytenr = btrfs_header_bytenr(root->node); - stat.highest_bytenr = stat.lowest_bytenr; - stat.min_cluster_size = (u64)-1; - stat.max_cluster_size = root->leafsize; - path->nodes[level] = root->node; - if (gettimeofday(&start, NULL)) { - fprintf(stderr, "Error getting time: %d\n", errno); - goto out; - } - if (!level) { - ret = walk_leaf(root, path, &stat, find_inline); - if (ret) - goto out; - goto out_print; - } - - ret = walk_nodes(root, path, &stat, level, find_inline); - if (ret) - goto out; - if (gettimeofday(&end, NULL)) { - fprintf(stderr, "Error getting time: %d\n", errno); - goto out; - } - timeval_subtract(&diff, &end, &start); -out_print: - if (stat.min_cluster_size == (u64)-1) { - stat.min_cluster_size = 0; - stat.total_clusters = 1; - } - - if (no_pretty || size_fail) { - printf("\tTotal size: %Lu\n", stat.total_bytes); - printf("\t\tInline data: %Lu\n", stat.total_inline); - printf("\tTotal seeks: %Lu\n", stat.total_seeks); - printf("\t\tForward seeks: %Lu\n", stat.forward_seeks); - printf("\t\tBackward seeks: %Lu\n", stat.backward_seeks); - printf("\t\tAvg seek len: %Lu\n", stat.total_seek_len / - stat.total_seeks); - print_seek_histogram(&stat); - printf("\tTotal clusters: %Lu\n", stat.total_clusters); - printf("\t\tAvg cluster size: %Lu\n", stat.total_cluster_size / - stat.total_clusters); - printf("\t\tMin cluster size: %Lu\n", stat.min_cluster_size); - printf("\t\tMax cluster size: %Lu\n", stat.max_cluster_size); - printf("\tTotal disk spread: %Lu\n", stat.highest_bytenr - - stat.lowest_bytenr); - printf("\tTotal read time: %d s %d us\n", (int)diff.tv_sec, - (int)diff.tv_usec); - printf("\tLevels: %d\n", level + 1); - } else { - printf("\tTotal size: %s\n", pretty_size(stat.total_bytes)); - printf("\t\tInline data: %s\n", pretty_size(stat.total_inline)); - printf("\tTotal seeks: %Lu\n", stat.total_seeks); - printf("\t\tForward seeks: %Lu\n", stat.forward_seeks); - printf("\t\tBackward seeks: %Lu\n", stat.backward_seeks); - printf("\t\tAvg seek len: %s\n", stat.total_seeks ? - pretty_size(stat.total_seek_len / stat.total_seeks) : - pretty_size(0)); - print_seek_histogram(&stat); - printf("\tTotal clusters: %Lu\n", stat.total_clusters); - printf("\t\tAvg cluster size: %s\n", - pretty_size((stat.total_cluster_size / - stat.total_clusters))); - printf("\t\tMin cluster size: %s\n", - pretty_size(stat.min_cluster_size)); - printf("\t\tMax cluster size: %s\n", - pretty_size(stat.max_cluster_size)); - printf("\tTotal disk spread: %s\n", - pretty_size(stat.highest_bytenr - - stat.lowest_bytenr)); - printf("\tTotal read time: %d s %d us\n", (int)diff.tv_sec, - (int)diff.tv_usec); - printf("\tLevels: %d\n", level + 1); - } -out: - while ((n = rb_first(&stat.seek_root)) != NULL) { - struct seek *seek = rb_entry(n, struct seek, n); - rb_erase(n, &stat.seek_root); - free(seek); - } - - btrfs_free_path(path); - return ret; -} - -static void usage() -{ - fprintf(stderr, "Usage: calc-size [-v] [-b] \n"); -} +#include "commands.h" +#include "help.h" int main(int argc, char **argv) { - struct btrfs_key key; - struct fs_root *roots; - struct btrfs_root *root; - size_t fs_roots_size = sizeof(struct fs_root); - int opt; - int ret = 0; - - while ((opt = getopt(argc, argv, "vb")) != -1) { - switch (opt) { - case 'v': - verbose++; - break; - case 'b': - no_pretty = 1; - break; - default: - usage(); - exit(1); - } - } - - set_argv0(argv); - argc = argc - optind; - if (check_argc_min(argc, 1)) { - usage(); - exit(1); - } - - /* - if ((ret = check_mounted(argv[optind])) < 0) { - fprintf(stderr, "Could not check mount status: %d\n", ret); - if (ret == -EACCES) - fprintf(stderr, "Maybe you need to run as root?\n"); - return ret; - } else if (ret) { - fprintf(stderr, "%s is currently mounted. Aborting.\n", - argv[optind]); - return -EBUSY; - } - */ - - root = open_ctree(argv[optind], 0, 0); - if (!root) { - fprintf(stderr, "Couldn't open ctree\n"); - exit(1); - } + int ret; - roots = malloc(fs_roots_size); - if (!roots) { - fprintf(stderr, "No memory\n"); - goto out; - } + warning( +"\nthe tool has been deprecated, please use 'btrfs inspect-internal tree-stats' instead\n"); - printf("Calculating size of root tree\n"); - key.objectid = BTRFS_ROOT_TREE_OBJECTID; - ret = calc_root_size(root, &key, 0); - if (ret) - goto out; + if (argc > 1 && !strcmp(argv[1], "--help")) + usage(cmd_inspect_tree_stats_usage); - printf("Calculating size of extent tree\n"); - key.objectid = BTRFS_EXTENT_TREE_OBJECTID; - ret = calc_root_size(root, &key, 0); - if (ret) - goto out; + ret = cmd_inspect_tree_stats(argc, argv); - printf("Calculating size of csum tree\n"); - key.objectid = BTRFS_CSUM_TREE_OBJECTID; - ret = calc_root_size(root, &key, 0); - if (ret) - goto out; + btrfs_close_all_devices(); - roots[0].key.objectid = BTRFS_FS_TREE_OBJECTID; - roots[0].key.offset = (u64)-1; - printf("Calculatin' size of fs tree\n"); - ret = calc_root_size(root, &roots[0].key, 1); - if (ret) - goto out; -out: - close_ctree(root); - free(roots); return ret; }