1 #define _XOPEN_SOURCE 500
6 #include "kerncompat.h"
7 #include "radix-tree.h"
10 #include "print-tree.h"
11 #include "transaction.h"
12 #include "bit-radix.h"
14 static u64 blocks_used
= 0;
15 static u64 total_csum_bytes
= 0;
16 static u64 total_btree_blocks
= 0;
17 static u64 btree_space_waste
= 0;
19 struct extent_record
{
20 struct btrfs_disk_key parent_key
;
21 struct btrfs_disk_key node_key
;
29 static int check_node(struct btrfs_root
*root
,
30 struct btrfs_disk_key
*parent_key
,
31 struct btrfs_node
*node
)
34 u32 nritems
= btrfs_header_nritems(&node
->header
);
36 if (nritems
== 0 || nritems
> BTRFS_NODEPTRS_PER_BLOCK(root
))
38 if (parent_key
->flags
) {
39 if (memcmp(parent_key
, &node
->ptrs
[0].key
,
40 sizeof(struct btrfs_disk_key
)))
43 for (i
= 0; nritems
> 1 && i
< nritems
- 2; i
++) {
44 struct btrfs_key cpukey
;
45 btrfs_disk_key_to_cpu(&cpukey
, &node
->ptrs
[i
+ 1].key
);
46 if (btrfs_comp_keys(&node
->ptrs
[i
].key
, &cpukey
) >= 0)
52 static int check_leaf(struct btrfs_root
*root
,
53 struct btrfs_disk_key
*parent_key
,
54 struct btrfs_leaf
*leaf
)
57 u32 nritems
= btrfs_header_nritems(&leaf
->header
);
59 if (btrfs_header_level(&leaf
->header
) != 0) {
60 fprintf(stderr
, "leaf is not a leaf %Lu\n",
61 btrfs_header_blocknr(&leaf
->header
));
64 if (btrfs_leaf_free_space(root
, leaf
) < 0) {
65 fprintf(stderr
, "leaf free space incorrect %Lu %d\n",
66 btrfs_header_blocknr(&leaf
->header
),
67 btrfs_leaf_free_space(root
, leaf
));
74 if (parent_key
->flags
) {
75 if (memcmp(parent_key
, &leaf
->items
[0].key
,
76 sizeof(struct btrfs_disk_key
))) {
77 fprintf(stderr
, "leaf parent key incorrect %Lu\n",
78 btrfs_header_blocknr(&leaf
->header
));
82 for (i
= 0; nritems
> 1 && i
< nritems
- 2; i
++) {
83 struct btrfs_key cpukey
;
84 btrfs_disk_key_to_cpu(&cpukey
, &leaf
->items
[i
+ 1].key
);
85 if (btrfs_comp_keys(&leaf
->items
[i
].key
,
88 if (btrfs_item_offset(leaf
->items
+ i
) !=
89 btrfs_item_end(leaf
->items
+ i
+ 1))
92 if (btrfs_item_offset(leaf
->items
+ i
) +
93 btrfs_item_size(leaf
->items
+ i
) !=
94 BTRFS_LEAF_DATA_SIZE(root
))
101 static int check_block(struct btrfs_root
*root
,
102 struct radix_tree_root
*extent_radix
,
103 struct btrfs_buffer
*buf
)
105 struct extent_record
*rec
;
107 rec
= radix_tree_lookup(extent_radix
, buf
->blocknr
);
110 if (btrfs_is_leaf(&buf
->node
)) {
111 return check_leaf(root
, &rec
->parent_key
, &buf
->leaf
);
113 return check_node(root
, &rec
->parent_key
, &buf
->node
);
118 static int add_extent_rec(struct radix_tree_root
*extent_radix
,
119 struct btrfs_disk_key
*parent_key
,
120 u64 ref
, u64 start
, u64 nr
, u64 owner
,
121 u32 extent_item_refs
, int inc_ref
)
123 struct extent_record
*rec
;
125 rec
= radix_tree_lookup(extent_radix
, start
);
129 if (start
!= rec
->start
) {
130 fprintf(stderr
, "warning, start mismatch %Lu %Lu\n",
134 if (extent_item_refs
)
135 rec
->extent_item_refs
= extent_item_refs
;
138 rec
= malloc(sizeof(*rec
));
140 extent_item_refs
= 0;
150 if (extent_item_refs
)
151 rec
->extent_item_refs
= extent_item_refs
;
153 rec
->extent_item_refs
= 0;
156 memcpy(&rec
->parent_key
, parent_key
, sizeof(*parent_key
));
158 memset(&rec
->parent_key
, 0, sizeof(*parent_key
));
160 ret
= radix_tree_insert(extent_radix
, start
, rec
);
166 static int add_pending(struct radix_tree_root
*pending
,
167 struct radix_tree_root
*seen
, u64 blocknr
)
169 if (test_radix_bit(seen
, blocknr
))
171 set_radix_bit(pending
, blocknr
);
172 set_radix_bit(seen
, blocknr
);
175 static int pick_next_pending(struct radix_tree_root
*pending
,
176 struct radix_tree_root
*reada
,
177 struct radix_tree_root
*nodes
,
178 u64 last
, unsigned long *bits
, int bits_nr
)
180 unsigned long node_start
= last
;
182 ret
= find_first_radix_bit(reada
, bits
, 0, 1);
187 ret
= find_first_radix_bit(nodes
, bits
, node_start
, bits_nr
);
189 ret
= find_first_radix_bit(nodes
, bits
, 0, bits_nr
);
192 return find_first_radix_bit(pending
, bits
, 0, bits_nr
);
194 static struct btrfs_buffer reada_buf
;
196 static int run_next_block(struct btrfs_root
*root
,
200 struct radix_tree_root
*pending
,
201 struct radix_tree_root
*seen
,
202 struct radix_tree_root
*reada
,
203 struct radix_tree_root
*nodes
,
204 struct radix_tree_root
*extent_radix
)
206 struct btrfs_buffer
*buf
;
211 struct btrfs_leaf
*leaf
;
212 struct btrfs_node
*node
;
214 ret
= pick_next_pending(pending
, reada
, nodes
, *last
, bits
, bits_nr
);
218 for(i
= 0; i
< ret
; i
++) {
220 if (test_radix_bit(reada
, bits
[i
]))
222 set_radix_bit(reada
, bits
[i
]);
223 btrfs_map_bh_to_logical(root
, &reada_buf
, bits
[i
]);
224 offset
= reada_buf
.dev_blocknr
* root
->blocksize
;
225 last_block
= bits
[i
];
226 readahead(reada_buf
.fd
, offset
, root
->blocksize
);
230 clear_radix_bit(pending
, blocknr
);
231 clear_radix_bit(reada
, blocknr
);
232 clear_radix_bit(nodes
, blocknr
);
233 buf
= read_tree_block(root
, blocknr
);
234 nritems
= btrfs_header_nritems(&buf
->node
.header
);
235 ret
= check_block(root
, extent_radix
, buf
);
237 fprintf(stderr
, "bad block %Lu\n", blocknr
);
239 if (btrfs_is_leaf(&buf
->node
)) {
241 btree_space_waste
+= btrfs_leaf_free_space(root
, leaf
);
242 for (i
= 0; i
< nritems
; i
++) {
243 struct btrfs_file_extent_item
*fi
;
244 if (btrfs_disk_key_type(&leaf
->items
[i
].key
) ==
245 BTRFS_EXTENT_ITEM_KEY
) {
246 struct btrfs_key found
;
247 struct btrfs_extent_item
*ei
;
248 btrfs_disk_key_to_cpu(&found
,
249 &leaf
->items
[i
].key
);
250 ei
= btrfs_item_ptr(leaf
, i
,
251 struct btrfs_extent_item
);
252 add_extent_rec(extent_radix
, NULL
, 0,
255 btrfs_extent_owner(ei
),
256 btrfs_extent_refs(ei
), 0);
259 if (btrfs_disk_key_type(&leaf
->items
[i
].key
) ==
260 BTRFS_CSUM_ITEM_KEY
) {
262 btrfs_item_size(leaf
->items
+ i
);
265 if (btrfs_disk_key_type(&leaf
->items
[i
].key
) !=
266 BTRFS_EXTENT_DATA_KEY
)
268 fi
= btrfs_item_ptr(leaf
, i
,
269 struct btrfs_file_extent_item
);
270 if (btrfs_file_extent_type(fi
) !=
271 BTRFS_FILE_EXTENT_REG
)
273 ret
= add_extent_rec(extent_radix
, NULL
, blocknr
,
274 btrfs_file_extent_disk_blocknr(fi
),
275 btrfs_file_extent_disk_num_blocks(fi
),
276 btrfs_disk_key_objectid(&leaf
->items
[i
].key
),
283 level
= btrfs_header_level(&node
->header
);
284 for (i
= 0; i
< nritems
; i
++) {
285 u64 ptr
= btrfs_node_blockptr(node
, i
);
286 ret
= add_extent_rec(extent_radix
,
289 btrfs_header_owner(&node
->header
),
293 add_pending(nodes
, seen
, ptr
);
295 add_pending(pending
, seen
, ptr
);
298 btree_space_waste
+= (BTRFS_NODEPTRS_PER_BLOCK(root
) -
299 nritems
) * sizeof(struct btrfs_key_ptr
);
301 btrfs_block_release(root
, buf
);
302 total_btree_blocks
++;
306 static int add_root_to_pending(struct btrfs_buffer
*buf
,
309 struct radix_tree_root
*extent_radix
,
310 struct radix_tree_root
*pending
,
311 struct radix_tree_root
*seen
,
312 struct radix_tree_root
*reada
,
313 struct radix_tree_root
*nodes
)
315 if (btrfs_header_level(&buf
->node
.header
) > 0)
316 add_pending(nodes
, seen
, buf
->blocknr
);
318 add_pending(pending
, seen
, buf
->blocknr
);
319 add_extent_rec(extent_radix
, NULL
, 0, buf
->blocknr
, 1,
320 btrfs_header_owner(&buf
->node
.header
), 0, 1);
324 int check_extent_refs(struct btrfs_root
*root
,
325 struct radix_tree_root
*extent_radix
)
327 struct extent_record
*rec
[64];
333 ret
= radix_tree_gang_lookup(extent_radix
, (void **)rec
, 0,
337 for (i
= 0; i
< ret
; i
++) {
338 if (rec
[i
]->refs
!= rec
[i
]->extent_item_refs
) {
339 fprintf(stderr
, "ref mismatch on [%Lu %Lu] ",
340 rec
[i
]->start
, rec
[i
]->nr
);
341 fprintf(stderr
, "extent item %u, found %u\n",
342 rec
[i
]->extent_item_refs
,
346 radix_tree_delete(extent_radix
, rec
[i
]->start
);
353 int main(int ac
, char **av
) {
354 struct btrfs_super_block super
;
355 struct btrfs_root
*root
;
356 struct radix_tree_root extent_radix
;
357 struct radix_tree_root seen
;
358 struct radix_tree_root pending
;
359 struct radix_tree_root reada
;
360 struct radix_tree_root nodes
;
361 struct btrfs_path path
;
362 struct btrfs_key key
;
363 struct btrfs_key found_key
;
368 struct btrfs_leaf
*leaf
;
370 struct btrfs_root_item
*ri
;
375 INIT_RADIX_TREE(&extent_radix
, GFP_NOFS
);
376 init_bit_radix(&seen
);
377 init_bit_radix(&pending
);
378 init_bit_radix(&reada
);
379 init_bit_radix(&nodes
);
381 root
= open_ctree(av
[1], &super
);
383 bits_nr
= 1024 * 1024 / root
->blocksize
;
384 bits
= malloc(bits_nr
* sizeof(unsigned long));
390 add_root_to_pending(root
->fs_info
->tree_root
->node
, bits
, bits_nr
,
391 &extent_radix
, &pending
, &seen
, &reada
, &nodes
);
392 add_root_to_pending(root
->fs_info
->dev_root
->node
, bits
, bits_nr
,
393 &extent_radix
, &pending
, &seen
, &reada
, &nodes
);
395 btrfs_init_path(&path
);
399 btrfs_set_key_type(&key
, BTRFS_ROOT_ITEM_KEY
);
400 ret
= btrfs_search_slot(NULL
, root
->fs_info
->tree_root
,
404 leaf
= &path
.nodes
[0]->leaf
;
405 slot
= path
.slots
[0];
406 if (slot
>= btrfs_header_nritems(&leaf
->header
)) {
407 ret
= btrfs_next_leaf(root
, &path
);
410 leaf
= &path
.nodes
[0]->leaf
;
411 slot
= path
.slots
[0];
413 btrfs_disk_key_to_cpu(&found_key
,
414 &leaf
->items
[path
.slots
[0]].key
);
415 if (btrfs_key_type(&found_key
) == BTRFS_ROOT_ITEM_KEY
) {
416 struct btrfs_buffer
*buf
;
417 ri
= btrfs_item_ptr(leaf
, path
.slots
[0],
418 struct btrfs_root_item
);
419 buf
= read_tree_block(root
->fs_info
->tree_root
,
420 btrfs_root_blocknr(ri
));
421 add_root_to_pending(buf
, bits
, bits_nr
, &extent_radix
,
422 &pending
, &seen
, &reada
, &nodes
);
423 btrfs_block_release(root
->fs_info
->tree_root
, buf
);
427 btrfs_release_path(root
, &path
);
429 ret
= run_next_block(root
, bits
, bits_nr
, &last
, &pending
,
430 &seen
, &reada
, &nodes
, &extent_radix
);
434 ret
= check_extent_refs(root
, &extent_radix
);
435 close_ctree(root
, &super
);
436 printf("found %Lu blocks used err is %d\n", blocks_used
, ret
);
437 printf("total csum bytes: %Lu\n", total_csum_bytes
);
438 printf("total tree blocks: %Lu\n", total_btree_blocks
);
439 printf("btree space waste bytes: %Lu\n", btree_space_waste
);