Btrfs-progs: make print-tree.c aware of free space cache
[platform/upstream/btrfs-progs.git] / print-tree.c
1 /*
2  * Copyright (C) 2007 Oracle.  All rights reserved.
3  *
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.
7  *
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.
12  *
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.
17  */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <uuid/uuid.h>
22 #include "kerncompat.h"
23 #include "radix-tree.h"
24 #include "ctree.h"
25 #include "disk-io.h"
26 #include "print-tree.h"
27
28 static int print_dir_item(struct extent_buffer *eb, struct btrfs_item *item,
29                           struct btrfs_dir_item *di)
30 {
31         u32 total;
32         u32 cur = 0;
33         u32 len;
34         u32 name_len;
35         u32 data_len;
36         char namebuf[BTRFS_NAME_LEN];
37         struct btrfs_disk_key location;
38
39         total = btrfs_item_size(eb, item);
40         while(cur < total) {
41                 btrfs_dir_item_key(eb, di, &location);
42                 printf("\t\tlocation ");
43                 btrfs_print_key(&location);
44                 printf(" type %u\n", btrfs_dir_type(eb, di));
45                 name_len = btrfs_dir_name_len(eb, di);
46                 data_len = btrfs_dir_data_len(eb, di);
47                 len = (name_len <= sizeof(namebuf))? name_len: sizeof(namebuf);
48                 read_extent_buffer(eb, namebuf, (unsigned long)(di + 1), len);
49                 printf("\t\tnamelen %u datalen %u name: %.*s\n",
50                        name_len, data_len, len, namebuf);
51                 len = sizeof(*di) + name_len + data_len;
52                 di = (struct btrfs_dir_item *)((char *)di + len);
53                 cur += len;
54         }
55         return 0;
56 }
57
58 static int print_inode_ref_item(struct extent_buffer *eb, struct btrfs_item *item,
59                                 struct btrfs_inode_ref *ref)
60 {
61         u32 total;
62         u32 cur = 0;
63         u32 len;
64         u32 name_len;
65         u64 index;
66         char namebuf[BTRFS_NAME_LEN];
67         total = btrfs_item_size(eb, item);
68         while(cur < total) {
69                 name_len = btrfs_inode_ref_name_len(eb, ref);
70                 index = btrfs_inode_ref_index(eb, ref);
71                 len = (name_len <= sizeof(namebuf))? name_len: sizeof(namebuf);
72                 read_extent_buffer(eb, namebuf, (unsigned long)(ref + 1), len);
73                 printf("\t\tinode ref index %llu namelen %u name: %.*s\n",
74                        (unsigned long long)index, name_len, len, namebuf);
75                 len = sizeof(*ref) + name_len;
76                 ref = (struct btrfs_inode_ref *)((char *)ref + len);
77                 cur += len;
78         }
79         return 0;
80 }
81
82 static void print_chunk(struct extent_buffer *eb, struct btrfs_chunk *chunk)
83 {
84         int num_stripes = btrfs_chunk_num_stripes(eb, chunk);
85         int i;
86         printf("\t\tchunk length %llu owner %llu type %llu num_stripes %d\n",
87                (unsigned long long)btrfs_chunk_length(eb, chunk),
88                (unsigned long long)btrfs_chunk_owner(eb, chunk),
89                (unsigned long long)btrfs_chunk_type(eb, chunk),
90                num_stripes);
91         for (i = 0 ; i < num_stripes ; i++) {
92                 printf("\t\t\tstripe %d devid %llu offset %llu\n", i,
93                       (unsigned long long)btrfs_stripe_devid_nr(eb, chunk, i),
94                       (unsigned long long)btrfs_stripe_offset_nr(eb, chunk, i));
95         }
96 }
97
98 static void print_dev_item(struct extent_buffer *eb,
99                            struct btrfs_dev_item *dev_item)
100 {
101         printf("\t\tdev item devid %llu "
102                "total_bytes %llu bytes used %Lu\n",
103                (unsigned long long)btrfs_device_id(eb, dev_item),
104                (unsigned long long)btrfs_device_total_bytes(eb, dev_item),
105                (unsigned long long)btrfs_device_bytes_used(eb, dev_item));
106 }
107
108 static void print_uuids(struct extent_buffer *eb)
109 {
110         char fs_uuid[37];
111         char chunk_uuid[37];
112         u8 disk_uuid[BTRFS_UUID_SIZE];
113
114         read_extent_buffer(eb, disk_uuid, (unsigned long)btrfs_header_fsid(eb),
115                            BTRFS_FSID_SIZE);
116
117         fs_uuid[36] = '\0';
118         uuid_unparse(disk_uuid, fs_uuid);
119
120         read_extent_buffer(eb, disk_uuid,
121                            (unsigned long)btrfs_header_chunk_tree_uuid(eb),
122                            BTRFS_UUID_SIZE);
123
124         chunk_uuid[36] = '\0';
125         uuid_unparse(disk_uuid, chunk_uuid);
126         printf("fs uuid %s\nchunk uuid %s\n", fs_uuid, chunk_uuid);
127 }
128
129 static void print_file_extent_item(struct extent_buffer *eb,
130                                    struct btrfs_item *item,
131                                    struct btrfs_file_extent_item *fi)
132 {
133         int extent_type = btrfs_file_extent_type(eb, fi);
134
135         if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
136                 printf("\t\tinline extent data size %u "
137                        "ram %u compress %d\n",
138                   btrfs_file_extent_inline_item_len(eb, item),
139                   btrfs_file_extent_inline_len(eb, fi),
140                   btrfs_file_extent_compression(eb, fi));
141                 return;
142         }
143         if (extent_type == BTRFS_FILE_EXTENT_PREALLOC) {
144                 printf("\t\tprealloc data disk byte %llu nr %llu\n",
145                   (unsigned long long)btrfs_file_extent_disk_bytenr(eb, fi),
146                   (unsigned long long)btrfs_file_extent_disk_num_bytes(eb, fi));
147                 printf("\t\tprealloc data offset %llu nr %llu\n",
148                   (unsigned long long)btrfs_file_extent_offset(eb, fi),
149                   (unsigned long long)btrfs_file_extent_num_bytes(eb, fi));
150                 return;
151         }
152         printf("\t\textent data disk byte %llu nr %llu\n",
153                 (unsigned long long)btrfs_file_extent_disk_bytenr(eb, fi),
154                 (unsigned long long)btrfs_file_extent_disk_num_bytes(eb, fi));
155         printf("\t\textent data offset %llu nr %llu ram %llu\n",
156                 (unsigned long long)btrfs_file_extent_offset(eb, fi),
157                 (unsigned long long)btrfs_file_extent_num_bytes(eb, fi),
158                 (unsigned long long)btrfs_file_extent_ram_bytes(eb, fi));
159         printf("\t\textent compression %d\n",
160                btrfs_file_extent_compression(eb, fi));
161 }
162
163 static void print_extent_item(struct extent_buffer *eb, int slot)
164 {
165         struct btrfs_extent_item *ei;
166         struct btrfs_extent_inline_ref *iref;
167         struct btrfs_extent_data_ref *dref;
168         struct btrfs_shared_data_ref *sref;
169         struct btrfs_disk_key key;
170         unsigned long end;
171         unsigned long ptr;
172         int type;
173         u32 item_size = btrfs_item_size_nr(eb, slot);
174         u64 flags;
175         u64 offset;
176
177         if (item_size < sizeof(*ei)) {
178 #ifdef BTRFS_COMPAT_EXTENT_TREE_V0
179                 struct btrfs_extent_item_v0 *ei0;
180                 BUG_ON(item_size != sizeof(*ei0));
181                 ei0 = btrfs_item_ptr(eb, slot, struct btrfs_extent_item_v0);
182                 printf("\t\textent refs %u\n",
183                        btrfs_extent_refs_v0(eb, ei0));
184                 return;
185 #else
186                 BUG();
187 #endif
188         }
189
190         ei = btrfs_item_ptr(eb, slot, struct btrfs_extent_item);
191         flags = btrfs_extent_flags(eb, ei);
192
193         printf("\t\textent refs %llu gen %llu flags %llu\n",
194                (unsigned long long)btrfs_extent_refs(eb, ei),
195                (unsigned long long)btrfs_extent_generation(eb, ei),
196                (unsigned long long)flags);
197
198         if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) {
199                 struct btrfs_tree_block_info *info;
200                 info = (struct btrfs_tree_block_info *)(ei + 1);
201                 btrfs_tree_block_key(eb, info, &key);
202                 printf("\t\ttree block key (%llu %x %llu) level %d\n",
203                        (unsigned long long)btrfs_disk_key_objectid(&key),
204                        key.type,
205                        (unsigned long long)btrfs_disk_key_offset(&key),
206                        btrfs_tree_block_level(eb, info));
207                 iref = (struct btrfs_extent_inline_ref *)(info + 1);
208         } else {
209                 iref = (struct btrfs_extent_inline_ref *)(ei + 1);
210         }
211
212         ptr = (unsigned long)iref;
213         end = (unsigned long)ei + item_size;
214         while (ptr < end) {
215                 iref = (struct btrfs_extent_inline_ref *)ptr;
216                 type = btrfs_extent_inline_ref_type(eb, iref);
217                 offset = btrfs_extent_inline_ref_offset(eb, iref);
218                 switch (type) {
219                 case BTRFS_TREE_BLOCK_REF_KEY:
220                         printf("\t\ttree block backref root %llu\n",
221                                (unsigned long long)offset);
222                         break;
223                 case BTRFS_SHARED_BLOCK_REF_KEY:
224                         printf("\t\tshared block backref parent %llu\n",
225                                (unsigned long long)offset);
226                         break;
227                 case BTRFS_EXTENT_DATA_REF_KEY:
228                         dref = (struct btrfs_extent_data_ref *)(&iref->offset);
229                         printf("\t\textent data backref root %llu "
230                                "objectid %llu offset %llu count %u\n",
231                                (unsigned long long)btrfs_extent_data_ref_root(eb, dref),
232                                (unsigned long long)btrfs_extent_data_ref_objectid(eb, dref),
233                                (unsigned long long)btrfs_extent_data_ref_offset(eb, dref),
234                                btrfs_extent_data_ref_count(eb, dref));
235                         break;
236                 case BTRFS_SHARED_DATA_REF_KEY:
237                         sref = (struct btrfs_shared_data_ref *)(iref + 1);
238                         printf("\t\tshared data backref parent %llu count %u\n",
239                                (unsigned long long)offset,
240                                btrfs_shared_data_ref_count(eb, sref));
241                         break;
242                 default:
243                         return;
244                 }
245                 ptr += btrfs_extent_inline_ref_size(type);
246         }
247         WARN_ON(ptr > end);
248 }
249
250 #ifdef BTRFS_COMPAT_EXTENT_TREE_V0
251 static void print_extent_ref_v0(struct extent_buffer *eb, int slot)
252 {
253         struct btrfs_extent_ref_v0 *ref0;
254
255         ref0 = btrfs_item_ptr(eb, slot, struct btrfs_extent_ref_v0);
256         printf("\t\textent back ref root %llu gen %llu "
257                 "owner %llu num_refs %lu\n",
258                 (unsigned long long)btrfs_ref_root_v0(eb, ref0),
259                 (unsigned long long)btrfs_ref_generation_v0(eb, ref0),
260                 (unsigned long long)btrfs_ref_objectid_v0(eb, ref0),
261                 (unsigned long)btrfs_ref_count_v0(eb, ref0));
262 }
263 #endif
264
265 static void print_root_ref(struct extent_buffer *leaf, int slot, char *tag)
266 {
267         struct btrfs_root_ref *ref;
268         char namebuf[BTRFS_NAME_LEN];
269         int namelen;
270
271         ref = btrfs_item_ptr(leaf, slot, struct btrfs_root_ref);
272         namelen = btrfs_root_ref_name_len(leaf, ref);
273         read_extent_buffer(leaf, namebuf, (unsigned long)(ref + 1), namelen);
274         printf("\t\troot %s key dirid %llu sequence %llu name %.*s\n", tag,
275                (unsigned long long)btrfs_root_ref_dirid(leaf, ref),
276                (unsigned long long)btrfs_root_ref_sequence(leaf, ref),
277                namelen, namebuf);
278 }
279
280 static void print_free_space_header(struct extent_buffer *leaf, int slot)
281 {
282         struct btrfs_free_space_header *header;
283         struct btrfs_disk_key location;
284
285         header = btrfs_item_ptr(leaf, slot, struct btrfs_free_space_header);
286         btrfs_free_space_key(leaf, header, &location);
287         printf("\t\tlocation ");
288         btrfs_print_key(&location);
289         printf("\n");
290         printf("\t\tcache generation %llu entries %llu bitmaps %llu\n",
291                (unsigned long long)btrfs_free_space_generation(leaf, header),
292                (unsigned long long)btrfs_free_space_entries(leaf, header),
293                (unsigned long long)btrfs_free_space_bitmaps(leaf, header));
294 }
295
296 static void print_key_type(u64 objectid, u8 type)
297 {
298         if (type == 0 && objectid == BTRFS_FREE_SPACE_OBJECTID) {
299                 printf("UNTYPED");
300                 return;
301         }
302
303         switch (type) {
304         case BTRFS_INODE_ITEM_KEY:
305                 printf("INODE_ITEM");
306                 break;
307         case BTRFS_INODE_REF_KEY:
308                 printf("INODE_REF");
309                 break;
310         case BTRFS_DIR_ITEM_KEY:
311                 printf("DIR_ITEM");
312                 break;
313         case BTRFS_DIR_INDEX_KEY:
314                 printf("DIR_INDEX");
315                 break;
316         case BTRFS_DIR_LOG_ITEM_KEY:
317                 printf("DIR_LOG_ITEM");
318                 break;
319         case BTRFS_DIR_LOG_INDEX_KEY:
320                 printf("DIR_LOG_INDEX");
321                 break;
322         case BTRFS_XATTR_ITEM_KEY:
323                 printf("XATTR_ITEM");
324                 break;
325         case BTRFS_ORPHAN_ITEM_KEY:
326                 printf("ORPHAN_ITEM");
327                 break;
328         case BTRFS_ROOT_ITEM_KEY:
329                 printf("ROOT_ITEM");
330                 break;
331         case BTRFS_ROOT_REF_KEY:
332                 printf("ROOT_REF");
333                 break;
334         case BTRFS_ROOT_BACKREF_KEY:
335                 printf("ROOT_BACKREF");
336                 break;
337         case BTRFS_EXTENT_ITEM_KEY:
338                 printf("EXTENT_ITEM");
339                 break;
340         case BTRFS_TREE_BLOCK_REF_KEY:
341                 printf("TREE_BLOCK_REF");
342                 break;
343         case BTRFS_SHARED_BLOCK_REF_KEY:
344                 printf("SHARED_BLOCK_REF");
345                 break;
346         case BTRFS_EXTENT_DATA_REF_KEY:
347                 printf("EXTENT_DATA_REF");
348                 break;
349         case BTRFS_SHARED_DATA_REF_KEY:
350                 printf("SHARED_DATA_REF");
351                 break;
352         case BTRFS_EXTENT_REF_V0_KEY:
353                 printf("EXTENT_REF_V0");
354                 break;
355         case BTRFS_CSUM_ITEM_KEY:
356                 printf("CSUM_ITEM");
357                 break;
358         case BTRFS_EXTENT_CSUM_KEY:
359                 printf("EXTENT_CSUM");
360                 break;
361         case BTRFS_EXTENT_DATA_KEY:
362                 printf("EXTENT_DATA");
363                 break;
364         case BTRFS_BLOCK_GROUP_ITEM_KEY:
365                 printf("BLOCK_GROUP_ITEM");
366                 break;
367         case BTRFS_CHUNK_ITEM_KEY:
368                 printf("CHUNK_ITEM");
369                 break;
370         case BTRFS_DEV_ITEM_KEY:
371                 printf("DEV_ITEM");
372                 break;
373         case BTRFS_DEV_EXTENT_KEY:
374                 printf("DEV_EXTENT");
375                 break;
376         case BTRFS_BALANCE_ITEM_KEY:
377                 printf("BALANCE_ITEM");
378                 break;
379         case BTRFS_STRING_ITEM_KEY:
380                 printf("STRING_ITEM");
381                 break;
382         default:
383                 printf("UNKNOWN");
384         };
385 }
386
387 static void print_objectid(u64 objectid, u8 type)
388 {
389         if (type == BTRFS_DEV_EXTENT_KEY) {
390                 printf("%llu", (unsigned long long)objectid); /* device id */
391                 return;
392         }
393
394         switch (objectid) {
395         case BTRFS_ROOT_TREE_OBJECTID:
396                 if (type == BTRFS_DEV_ITEM_KEY)
397                         printf("DEV_ITEMS");
398                 else
399                         printf("ROOT_TREE");
400                 break;
401         case BTRFS_EXTENT_TREE_OBJECTID:
402                 printf("EXTENT_TREE");
403                 break;
404         case BTRFS_CHUNK_TREE_OBJECTID:
405                 printf("CHUNK_TREE");
406                 break;
407         case BTRFS_DEV_TREE_OBJECTID:
408                 printf("DEV_TREE");
409                 break;
410         case BTRFS_FS_TREE_OBJECTID:
411                 printf("FS_TREE");
412                 break;
413         case BTRFS_ROOT_TREE_DIR_OBJECTID:
414                 printf("ROOT_TREE_DIR");
415                 break;
416         case BTRFS_CSUM_TREE_OBJECTID:
417                 printf("CSUM_TREE");
418                 break;
419         case BTRFS_BALANCE_OBJECTID:
420                 printf("BALANCE");
421                 break;
422         case BTRFS_ORPHAN_OBJECTID:
423                 printf("ORPHAN");
424                 break;
425         case BTRFS_TREE_LOG_OBJECTID:
426                 printf("TREE_LOG");
427                 break;
428         case BTRFS_TREE_LOG_FIXUP_OBJECTID:
429                 printf("LOG_FIXUP");
430                 break;
431         case BTRFS_TREE_RELOC_OBJECTID:
432                 printf("TREE_RELOC");
433                 break;
434         case BTRFS_DATA_RELOC_TREE_OBJECTID:
435                 printf("DATA_RELOC_TREE");
436                 break;
437         case BTRFS_EXTENT_CSUM_OBJECTID:
438                 printf("EXTENT_CSUM");
439                 break;
440         case BTRFS_FREE_SPACE_OBJECTID:
441                 printf("FREE_SPACE");
442                 break;
443         case BTRFS_FREE_INO_OBJECTID:
444                 printf("FREE_INO");
445                 break;
446         case BTRFS_MULTIPLE_OBJECTIDS:
447                 printf("MULTIPLE");
448                 break;
449         case BTRFS_FIRST_CHUNK_TREE_OBJECTID:
450                 if (type == BTRFS_CHUNK_ITEM_KEY) {
451                         printf("FIRST_CHUNK_TREE");
452                         break;
453                 }
454                 /* fall-thru */
455         default:
456                 printf("%llu", (unsigned long long)objectid);
457         }
458 }
459
460 void btrfs_print_key(struct btrfs_disk_key *disk_key)
461 {
462         u64 objectid = btrfs_disk_key_objectid(disk_key);
463         u8 type = btrfs_disk_key_type(disk_key);
464
465         printf("key (");
466         print_objectid(objectid, type);
467         printf(" ");
468         print_key_type(objectid, type);
469         printf(" %llu)", (unsigned long long)btrfs_disk_key_offset(disk_key));
470 }
471
472 void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
473 {
474         int i;
475         char *str;
476         struct btrfs_item *item;
477         struct btrfs_root_item *ri;
478         struct btrfs_dir_item *di;
479         struct btrfs_inode_item *ii;
480         struct btrfs_file_extent_item *fi;
481         struct btrfs_block_group_item *bi;
482         struct btrfs_extent_data_ref *dref;
483         struct btrfs_shared_data_ref *sref;
484         struct btrfs_inode_ref *iref;
485         struct btrfs_dev_extent *dev_extent;
486         struct btrfs_disk_key disk_key;
487         struct btrfs_root_item root_item;
488         struct btrfs_block_group_item bg_item;
489         struct btrfs_dir_log_item *dlog;
490         u32 nr = btrfs_header_nritems(l);
491         u64 objectid;
492         u32 type;
493
494         printf("leaf %llu items %d free space %d generation %llu owner %llu\n",
495                 (unsigned long long)btrfs_header_bytenr(l), nr,
496                 btrfs_leaf_free_space(root, l),
497                 (unsigned long long)btrfs_header_generation(l),
498                 (unsigned long long)btrfs_header_owner(l));
499         print_uuids(l);
500         fflush(stdout);
501         for (i = 0 ; i < nr ; i++) {
502                 item = btrfs_item_nr(l, i);
503                 btrfs_item_key(l, &disk_key, i);
504                 objectid = btrfs_disk_key_objectid(&disk_key);
505                 type = btrfs_disk_key_type(&disk_key);
506                 printf("\titem %d ", i);
507                 btrfs_print_key(&disk_key);
508                 printf(" itemoff %d itemsize %d\n",
509                         btrfs_item_offset(l, item),
510                         btrfs_item_size(l, item));
511
512                 if (type == 0 && objectid == BTRFS_FREE_SPACE_OBJECTID)
513                         print_free_space_header(l, i);
514
515                 switch (type) {
516                 case BTRFS_INODE_ITEM_KEY:
517                         ii = btrfs_item_ptr(l, i, struct btrfs_inode_item);
518                         printf("\t\tinode generation %llu size %llu block group %llu mode %o links %u\n",
519                                (unsigned long long)btrfs_inode_generation(l, ii),
520                                (unsigned long long)btrfs_inode_size(l, ii),
521                                (unsigned long long)btrfs_inode_block_group(l,ii),
522                                btrfs_inode_mode(l, ii),
523                                btrfs_inode_nlink(l, ii));
524                         break;
525                 case BTRFS_INODE_REF_KEY:
526                         iref = btrfs_item_ptr(l, i, struct btrfs_inode_ref);
527                         print_inode_ref_item(l, item, iref);
528                         break;
529                 case BTRFS_DIR_ITEM_KEY:
530                 case BTRFS_DIR_INDEX_KEY:
531                 case BTRFS_XATTR_ITEM_KEY:
532                         di = btrfs_item_ptr(l, i, struct btrfs_dir_item);
533                         print_dir_item(l, item, di);
534                         break;
535                 case BTRFS_DIR_LOG_INDEX_KEY:
536                 case BTRFS_DIR_LOG_ITEM_KEY:
537                         dlog = btrfs_item_ptr(l, i, struct btrfs_dir_log_item);
538                         printf("\t\tdir log end %Lu\n",
539                                (unsigned long long)btrfs_dir_log_end(l, dlog));
540                        break;
541                 case BTRFS_ORPHAN_ITEM_KEY:
542                         printf("\t\torphan item\n");
543                         break;
544                 case BTRFS_ROOT_ITEM_KEY:
545                         ri = btrfs_item_ptr(l, i, struct btrfs_root_item);
546                         read_extent_buffer(l, &root_item, (unsigned long)ri, sizeof(root_item));
547                         printf("\t\troot data bytenr %llu level %d dirid %llu refs %u gen %llu\n",
548                                 (unsigned long long)btrfs_root_bytenr(&root_item),
549                                 btrfs_root_level(&root_item),
550                                 (unsigned long long)btrfs_root_dirid(&root_item),
551                                 btrfs_root_refs(&root_item),
552                                 (unsigned long long)btrfs_root_generation(&root_item));
553                         if (btrfs_root_refs(&root_item) == 0) {
554                                 struct btrfs_key drop_key;
555                                 btrfs_disk_key_to_cpu(&drop_key,
556                                                       &root_item.drop_progress);
557                                 printf("\t\tdrop ");
558                                 btrfs_print_key(&root_item.drop_progress);
559                                 printf(" level %d\n", root_item.drop_level);
560                         }
561                         break;
562                 case BTRFS_ROOT_REF_KEY:
563                         print_root_ref(l, i, "ref");
564                         break;
565                 case BTRFS_ROOT_BACKREF_KEY:
566                         print_root_ref(l, i, "backref");
567                         break;
568                 case BTRFS_EXTENT_ITEM_KEY:
569                         print_extent_item(l, i);
570                         break;
571                 case BTRFS_TREE_BLOCK_REF_KEY:
572                         printf("\t\ttree block backref\n");
573                         break;
574                 case BTRFS_SHARED_BLOCK_REF_KEY:
575                         printf("\t\tshared block backref\n");
576                         break;
577                 case BTRFS_EXTENT_DATA_REF_KEY:
578                         dref = btrfs_item_ptr(l, i, struct btrfs_extent_data_ref);
579                         printf("\t\textent data backref root %llu "
580                                "objectid %llu offset %llu count %u\n",
581                                (unsigned long long)btrfs_extent_data_ref_root(l, dref),
582                                (unsigned long long)btrfs_extent_data_ref_objectid(l, dref),
583                                (unsigned long long)btrfs_extent_data_ref_offset(l, dref),
584                                btrfs_extent_data_ref_count(l, dref));
585                         break;
586                 case BTRFS_SHARED_DATA_REF_KEY:
587                         sref = btrfs_item_ptr(l, i, struct btrfs_shared_data_ref);
588                         printf("\t\tshared data backref count %u\n",
589                                btrfs_shared_data_ref_count(l, sref));
590                         break;
591                 case BTRFS_EXTENT_REF_V0_KEY:
592 #ifdef BTRFS_COMPAT_EXTENT_TREE_V0
593                         print_extent_ref_v0(l, i);
594 #else
595                         BUG();
596 #endif
597                         break;
598                 case BTRFS_CSUM_ITEM_KEY:
599                         printf("\t\tcsum item\n");
600                         break;
601                 case BTRFS_EXTENT_CSUM_KEY:
602                         printf("\t\textent csum item\n");
603                         break;
604                 case BTRFS_EXTENT_DATA_KEY:
605                         fi = btrfs_item_ptr(l, i,
606                                             struct btrfs_file_extent_item);
607                         print_file_extent_item(l, item, fi);
608                         break;
609                 case BTRFS_BLOCK_GROUP_ITEM_KEY:
610                         bi = btrfs_item_ptr(l, i,
611                                             struct btrfs_block_group_item);
612                         read_extent_buffer(l, &bg_item, (unsigned long)bi,
613                                            sizeof(bg_item));
614                         printf("\t\tblock group used %llu chunk_objectid %llu flags %llu\n",
615                                (unsigned long long)btrfs_block_group_used(&bg_item),
616                                (unsigned long long)btrfs_block_group_chunk_objectid(&bg_item),
617                                (unsigned long long)btrfs_block_group_flags(&bg_item));
618                         break;
619                 case BTRFS_CHUNK_ITEM_KEY:
620                         print_chunk(l, btrfs_item_ptr(l, i, struct btrfs_chunk));
621                         break;
622                 case BTRFS_DEV_ITEM_KEY:
623                         print_dev_item(l, btrfs_item_ptr(l, i,
624                                         struct btrfs_dev_item));
625                         break;
626                 case BTRFS_DEV_EXTENT_KEY:
627                         dev_extent = btrfs_item_ptr(l, i,
628                                                     struct btrfs_dev_extent);
629                         printf("\t\tdev extent chunk_tree %llu\n"
630                                "\t\tchunk objectid %llu chunk offset %llu "
631                                "length %llu\n",
632                                (unsigned long long)
633                                btrfs_dev_extent_chunk_tree(l, dev_extent),
634                                (unsigned long long)
635                                btrfs_dev_extent_chunk_objectid(l, dev_extent),
636                                (unsigned long long)
637                                btrfs_dev_extent_chunk_offset(l, dev_extent),
638                                (unsigned long long)
639                                btrfs_dev_extent_length(l, dev_extent));
640                         break;
641                 case BTRFS_STRING_ITEM_KEY:
642                         /* dirty, but it's simple */
643                         str = l->data + btrfs_item_ptr_offset(l, i);
644                         printf("\t\titem data %.*s\n", btrfs_item_size(l, item), str);
645                         break;
646                 };
647                 fflush(stdout);
648         }
649 }
650
651 void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *eb, int follow)
652 {
653         int i;
654         u32 nr;
655         u32 size;
656         struct btrfs_disk_key disk_key;
657         struct btrfs_key key;
658
659         if (!eb)
660                 return;
661         nr = btrfs_header_nritems(eb);
662         if (btrfs_is_leaf(eb)) {
663                 btrfs_print_leaf(root, eb);
664                 return;
665         }
666         printf("node %llu level %d items %d free %u generation %llu owner %llu\n",
667                (unsigned long long)eb->start,
668                 btrfs_header_level(eb), nr,
669                 (u32)BTRFS_NODEPTRS_PER_BLOCK(root) - nr,
670                 (unsigned long long)btrfs_header_generation(eb),
671                 (unsigned long long)btrfs_header_owner(eb));
672         print_uuids(eb);
673         fflush(stdout);
674         size = btrfs_level_size(root, btrfs_header_level(eb) - 1);
675         for (i = 0; i < nr; i++) {
676                 u64 blocknr = btrfs_node_blockptr(eb, i);
677                 btrfs_node_key(eb, &disk_key, i);
678                 btrfs_disk_key_to_cpu(&key, &disk_key);
679                 printf("\t");
680                 btrfs_print_key(&disk_key);
681                 printf(" block %llu (%llu) gen %llu\n",
682                        (unsigned long long)blocknr,
683                        (unsigned long long)blocknr / size,
684                        (unsigned long long)btrfs_node_ptr_generation(eb, i));
685                 fflush(stdout);
686         }
687         if (!follow)
688                 return;
689
690         for (i = 0; i < nr; i++) {
691                 struct extent_buffer *next = read_tree_block(root,
692                                              btrfs_node_blockptr(eb, i),
693                                              size,
694                                              btrfs_node_ptr_generation(eb, i));
695                 if (!next) {
696                         fprintf(stderr, "failed to read %llu in tree %llu\n",
697                                 (unsigned long long)btrfs_node_blockptr(eb, i),
698                                 (unsigned long long)btrfs_header_owner(eb));
699                         continue;
700                 }
701                 if (btrfs_is_leaf(next) &&
702                     btrfs_header_level(eb) != 1)
703                         BUG();
704                 if (btrfs_header_level(next) !=
705                         btrfs_header_level(eb) - 1)
706                         BUG();
707                 btrfs_print_tree(root, next, 1);
708                 free_extent_buffer(next);
709         }
710 }