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