2 * Copyright (C) 2011 Red Hat. All rights reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License v2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public
14 * License along with this program; if not, write to the
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 021110-1307, USA.
19 #define _XOPEN_SOURCE 500
28 #include "kerncompat.h"
31 #include "print-tree.h"
32 #include "transaction.h"
38 static int verbose = 0;
39 static int no_pretty = 0;
51 struct btrfs_key *snaps;
54 static int walk_leaf(struct btrfs_root *root, struct btrfs_path *path,
55 struct root_stats *stat, int find_inline)
57 struct extent_buffer *b = path->nodes[0];
58 struct btrfs_file_extent_item *fi;
59 struct btrfs_key found_key;
62 stat->total_bytes += root->leafsize;
68 for (i = 0; i < btrfs_header_nritems(b); i++) {
69 btrfs_item_key_to_cpu(b, &found_key, i);
70 if (found_key.type != BTRFS_EXTENT_DATA_KEY)
73 fi = btrfs_item_ptr(b, i, struct btrfs_file_extent_item);
74 if (btrfs_file_extent_type(b, fi) == BTRFS_FILE_EXTENT_INLINE)
76 btrfs_file_extent_inline_item_len(b,
83 static int walk_nodes(struct btrfs_root *root, struct btrfs_path *path,
84 struct root_stats *stat, int level, int find_inline)
86 struct extent_buffer *b = path->nodes[level];
90 stat->total_bytes += root->nodesize;
93 for (i = 0; i < btrfs_header_nritems(b); i++) {
94 struct extent_buffer *tmp = NULL;
96 path->slots[level] = i;
97 if ((level - 1) > 0 || find_inline) {
98 tmp = read_tree_block(root, btrfs_node_blockptr(b, i),
99 btrfs_level_size(root, level - 1),
100 btrfs_node_ptr_generation(b, i));
102 fprintf(stderr, "Failed to read blocknr %Lu\n",
103 btrfs_node_blockptr(b, i));
106 path->nodes[level - 1] = tmp;
109 ret = walk_nodes(root, path, stat, level - 1,
112 ret = walk_leaf(root, path, stat, find_inline);
113 free_extent_buffer(tmp);
115 fprintf(stderr, "Error walking down path\n");
123 static int calc_root_size(struct btrfs_root *tree_root, struct btrfs_key *key,
126 struct btrfs_root *root;
127 struct btrfs_path *path;
128 struct root_stats stat;
133 root = btrfs_read_fs_root(tree_root->fs_info, key);
135 fprintf(stderr, "Failed to read root %Lu\n", key->objectid);
139 path = btrfs_alloc_path();
141 fprintf(stderr, "Could not allocate path\n");
145 memset(&stat, 0, sizeof(stat));
146 level = btrfs_header_level(root->node);
147 path->nodes[level] = root->node;
149 ret = walk_leaf(root, path, &stat, find_inline);
155 ret = walk_nodes(root, path, &stat, level, find_inline);
159 if (no_pretty || size_fail) {
160 printf("\t%Lu total bytes, %Lu inline data bytes, %Lu nodes, "
161 "%Lu leaves, %d levels\n", stat.total_bytes,
162 stat.total_inline, stat.total_nodes, stat.total_leaves,
165 printf("\t%s total size, %s inline data, %Lu nodes, "
166 "%Lu leaves, %d levels\n",
167 pretty_size(stat.total_bytes),
168 pretty_size(stat.total_inline),
169 stat.total_nodes, stat.total_leaves, level + 1);
172 btrfs_free_path(path);
178 fprintf(stderr, "Usage: calc-size [-v] [-b] <device>\n");
181 int main(int argc, char **argv)
183 struct btrfs_key key;
184 struct fs_root *roots;
185 struct btrfs_root *root;
186 size_t fs_roots_size = sizeof(struct fs_root);
190 while ((opt = getopt(argc, argv, "vb")) != -1) {
204 if (optind >= argc) {
210 if ((ret = check_mounted(argv[optind])) < 0) {
211 fprintf(stderr, "Could not check mount status: %d\n", ret);
213 fprintf(stderr, "Maybe you need to run as root?\n");
216 fprintf(stderr, "%s is currently mounted. Aborting.\n",
222 root = open_ctree(argv[optind], 0, 0);
224 fprintf(stderr, "Couldn't open ctree\n");
228 roots = malloc(fs_roots_size);
230 fprintf(stderr, "No memory\n");
234 printf("Calculating size of root tree\n");
235 key.objectid = BTRFS_ROOT_TREE_OBJECTID;
236 ret = calc_root_size(root, &key, 0);
240 printf("Calculating size of extent tree\n");
241 key.objectid = BTRFS_EXTENT_TREE_OBJECTID;
242 ret = calc_root_size(root, &key, 0);
246 printf("Calculating size of csum tree\n");
247 key.objectid = BTRFS_CSUM_TREE_OBJECTID;
248 ret = calc_root_size(root, &key, 0);
252 roots[0].key.objectid = BTRFS_FS_TREE_OBJECTID;
253 roots[0].key.offset = (u64)-1;
254 printf("Calculatin' size of fs tree\n");
255 ret = calc_root_size(root, &roots[0].key, 1);