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
,
168 total_size
= pretty_sizes(stat
.total_bytes
);
169 inline_size
= pretty_sizes(stat
.total_inline
);
171 printf("\t%s total size, %s inline data, %Lu nodes, "
172 "%Lu leaves, %d levels\n",
173 total_size
, inline_size
, stat
.total_nodes
,
174 stat
.total_leaves
, level
+ 1);
179 btrfs_free_path(path
);
185 fprintf(stderr
, "Usage: calc-size [-v] [-b] <device>\n");
188 int main(int argc
, char **argv
)
190 struct btrfs_key key
;
191 struct fs_root
*roots
;
192 struct btrfs_root
*root
;
193 size_t fs_roots_size
= sizeof(struct fs_root
);
197 while ((opt
= getopt(argc
, argv
, "vb")) != -1) {
211 if (optind
>= argc
) {
217 if ((ret = check_mounted(argv[optind])) < 0) {
218 fprintf(stderr, "Could not check mount status: %d\n", ret);
220 fprintf(stderr, "Maybe you need to run as root?\n");
223 fprintf(stderr, "%s is currently mounted. Aborting.\n",
229 root
= open_ctree(argv
[optind
], 0, 0);
231 fprintf(stderr
, "Couldn't open ctree\n");
235 roots
= malloc(fs_roots_size
);
237 fprintf(stderr
, "No memory\n");
241 printf("Calculating size of root tree\n");
242 key
.objectid
= BTRFS_ROOT_TREE_OBJECTID
;
243 ret
= calc_root_size(root
, &key
, 0);
247 printf("Calculating size of extent tree\n");
248 key
.objectid
= BTRFS_EXTENT_TREE_OBJECTID
;
249 ret
= calc_root_size(root
, &key
, 0);
253 printf("Calculating size of csum tree\n");
254 key
.objectid
= BTRFS_CSUM_TREE_OBJECTID
;
255 ret
= calc_root_size(root
, &key
, 0);
259 roots
[0].key
.objectid
= BTRFS_FS_TREE_OBJECTID
;
260 roots
[0].key
.offset
= (u64
)-1;
261 printf("Calculatin' size of fs tree\n");
262 ret
= calc_root_size(root
, &roots
[0].key
, 1);