print-tree.c 10.8 KB
Newer Older
Chris Mason's avatar
Chris Mason committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*
 * Copyright (C) 2007 Oracle.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License v2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 021110-1307, USA.
 */

Chris Mason's avatar
Chris Mason committed
19
20
#include "ctree.h"
#include "disk-io.h"
21
#include "print-tree.h"
Chris Mason's avatar
Chris Mason committed
22

23
24
25
26
static void print_chunk(struct extent_buffer *eb, struct btrfs_chunk *chunk)
{
	int num_stripes = btrfs_chunk_num_stripes(eb, chunk);
	int i;
27
28
	printk(KERN_INFO "\t\tchunk length %llu owner %llu type %llu "
	       "num_stripes %d\n",
29
	       (unsigned long long)btrfs_chunk_length(eb, chunk),
30
31
32
33
	       (unsigned long long)btrfs_chunk_owner(eb, chunk),
	       (unsigned long long)btrfs_chunk_type(eb, chunk),
	       num_stripes);
	for (i = 0 ; i < num_stripes ; i++) {
34
		printk(KERN_INFO "\t\t\tstripe %d devid %llu offset %llu\n", i,
35
36
37
38
39
40
41
		      (unsigned long long)btrfs_stripe_devid_nr(eb, chunk, i),
		      (unsigned long long)btrfs_stripe_offset_nr(eb, chunk, i));
	}
}
static void print_dev_item(struct extent_buffer *eb,
			   struct btrfs_dev_item *dev_item)
{
42
43
	printk(KERN_INFO "\t\tdev item devid %llu "
	       "total_bytes %llu bytes used %llu\n",
44
45
46
47
	       (unsigned long long)btrfs_device_id(eb, dev_item),
	       (unsigned long long)btrfs_device_total_bytes(eb, dev_item),
	       (unsigned long long)btrfs_device_bytes_used(eb, dev_item));
}
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
static void print_extent_data_ref(struct extent_buffer *eb,
				  struct btrfs_extent_data_ref *ref)
{
	printk(KERN_INFO "\t\textent data backref root %llu "
	       "objectid %llu offset %llu count %u\n",
	       (unsigned long long)btrfs_extent_data_ref_root(eb, ref),
	       (unsigned long long)btrfs_extent_data_ref_objectid(eb, ref),
	       (unsigned long long)btrfs_extent_data_ref_offset(eb, ref),
	       btrfs_extent_data_ref_count(eb, ref));
}

static void print_extent_item(struct extent_buffer *eb, int slot)
{
	struct btrfs_extent_item *ei;
	struct btrfs_extent_inline_ref *iref;
	struct btrfs_extent_data_ref *dref;
	struct btrfs_shared_data_ref *sref;
	struct btrfs_disk_key key;
	unsigned long end;
	unsigned long ptr;
	int type;
	u32 item_size = btrfs_item_size_nr(eb, slot);
	u64 flags;
	u64 offset;

	if (item_size < sizeof(*ei)) {
#ifdef BTRFS_COMPAT_EXTENT_TREE_V0
		struct btrfs_extent_item_v0 *ei0;
		BUG_ON(item_size != sizeof(*ei0));
		ei0 = btrfs_item_ptr(eb, slot, struct btrfs_extent_item_v0);
		printk(KERN_INFO "\t\textent refs %u\n",
		       btrfs_extent_refs_v0(eb, ei0));
		return;
#else
		BUG();
#endif
	}

	ei = btrfs_item_ptr(eb, slot, struct btrfs_extent_item);
	flags = btrfs_extent_flags(eb, ei);

	printk(KERN_INFO "\t\textent refs %llu gen %llu flags %llu\n",
	       (unsigned long long)btrfs_extent_refs(eb, ei),
	       (unsigned long long)btrfs_extent_generation(eb, ei),
	       (unsigned long long)flags);

	if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) {
		struct btrfs_tree_block_info *info;
		info = (struct btrfs_tree_block_info *)(ei + 1);
		btrfs_tree_block_key(eb, info, &key);
		printk(KERN_INFO "\t\ttree block key (%llu %x %llu) "
		       "level %d\n",
		       (unsigned long long)btrfs_disk_key_objectid(&key),
		       key.type,
		       (unsigned long long)btrfs_disk_key_offset(&key),
		       btrfs_tree_block_level(eb, info));
		iref = (struct btrfs_extent_inline_ref *)(info + 1);
	} else {
		iref = (struct btrfs_extent_inline_ref *)(ei + 1);
	}

	ptr = (unsigned long)iref;
	end = (unsigned long)ei + item_size;
	while (ptr < end) {
		iref = (struct btrfs_extent_inline_ref *)ptr;
		type = btrfs_extent_inline_ref_type(eb, iref);
		offset = btrfs_extent_inline_ref_offset(eb, iref);
		switch (type) {
		case BTRFS_TREE_BLOCK_REF_KEY:
			printk(KERN_INFO "\t\ttree block backref "
				"root %llu\n", (unsigned long long)offset);
			break;
		case BTRFS_SHARED_BLOCK_REF_KEY:
			printk(KERN_INFO "\t\tshared block backref "
				"parent %llu\n", (unsigned long long)offset);
			break;
		case BTRFS_EXTENT_DATA_REF_KEY:
			dref = (struct btrfs_extent_data_ref *)(&iref->offset);
			print_extent_data_ref(eb, dref);
			break;
		case BTRFS_SHARED_DATA_REF_KEY:
			sref = (struct btrfs_shared_data_ref *)(iref + 1);
			printk(KERN_INFO "\t\tshared data backref "
			       "parent %llu count %u\n",
			       (unsigned long long)offset,
			       btrfs_shared_data_ref_count(eb, sref));
			break;
		default:
			BUG();
		}
		ptr += btrfs_extent_inline_ref_size(type);
	}
	WARN_ON(ptr > end);
}

#ifdef BTRFS_COMPAT_EXTENT_TREE_V0
static void print_extent_ref_v0(struct extent_buffer *eb, int slot)
{
	struct btrfs_extent_ref_v0 *ref0;

	ref0 = btrfs_item_ptr(eb, slot, struct btrfs_extent_ref_v0);
	printk("\t\textent back ref root %llu gen %llu "
		"owner %llu num_refs %lu\n",
		(unsigned long long)btrfs_ref_root_v0(eb, ref0),
		(unsigned long long)btrfs_ref_generation_v0(eb, ref0),
		(unsigned long long)btrfs_ref_objectid_v0(eb, ref0),
		(unsigned long)btrfs_ref_count_v0(eb, ref0));
}
#endif

158
void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
Chris Mason's avatar
Chris Mason committed
159
160
{
	int i;
161
	u32 type;
162
	u32 nr = btrfs_header_nritems(l);
Chris Mason's avatar
Chris Mason committed
163
	struct btrfs_item *item;
164
	struct btrfs_root_item *ri;
165
	struct btrfs_dir_item *di;
166
	struct btrfs_inode_item *ii;
Chris Mason's avatar
Chris Mason committed
167
	struct btrfs_block_group_item *bi;
168
	struct btrfs_file_extent_item *fi;
169
170
171
	struct btrfs_extent_data_ref *dref;
	struct btrfs_shared_data_ref *sref;
	struct btrfs_dev_extent *dev_extent;
172
173
	struct btrfs_key key;
	struct btrfs_key found_key;
174

175
	printk(KERN_INFO "leaf %llu total ptrs %d free space %d\n",
176
		(unsigned long long)btrfs_header_bytenr(l), nr,
177
		btrfs_leaf_free_space(root, l));
Chris Mason's avatar
Chris Mason committed
178
	for (i = 0 ; i < nr ; i++) {
179
180
181
		item = btrfs_item_nr(l, i);
		btrfs_item_key_to_cpu(l, &key, i);
		type = btrfs_key_type(&key);
182
183
		printk(KERN_INFO "\titem %d key (%llu %x %llu) itemoff %d "
		       "itemsize %d\n",
Chris Mason's avatar
Chris Mason committed
184
			i,
185
186
187
			(unsigned long long)key.objectid, type,
			(unsigned long long)key.offset,
			btrfs_item_offset(l, item), btrfs_item_size(l, item));
188
189
		switch (type) {
		case BTRFS_INODE_ITEM_KEY:
190
			ii = btrfs_item_ptr(l, i, struct btrfs_inode_item);
191
192
193
194
			printk(KERN_INFO "\t\tinode generation %llu size %llu "
			       "mode %o\n",
			       (unsigned long long)
			       btrfs_inode_generation(l, ii),
195
196
			      (unsigned long long)btrfs_inode_size(l, ii),
			       btrfs_inode_mode(l, ii));
197
198
			break;
		case BTRFS_DIR_ITEM_KEY:
199
			di = btrfs_item_ptr(l, i, struct btrfs_dir_item);
200
			btrfs_dir_item_key_to_cpu(l, di, &found_key);
201
			printk(KERN_INFO "\t\tdir oid %llu type %u\n",
202
203
				(unsigned long long)found_key.objectid,
				btrfs_dir_type(l, di));
204
205
206
			break;
		case BTRFS_ROOT_ITEM_KEY:
			ri = btrfs_item_ptr(l, i, struct btrfs_root_item);
207
208
209
			printk(KERN_INFO "\t\troot data bytenr %llu refs %u\n",
				(unsigned long long)
				btrfs_disk_root_bytenr(l, ri),
210
				btrfs_disk_root_refs(l, ri));
211
212
			break;
		case BTRFS_EXTENT_ITEM_KEY:
213
			print_extent_item(l, i);
214
			break;
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
		case BTRFS_TREE_BLOCK_REF_KEY:
			printk(KERN_INFO "\t\ttree block backref\n");
			break;
		case BTRFS_SHARED_BLOCK_REF_KEY:
			printk(KERN_INFO "\t\tshared block backref\n");
			break;
		case BTRFS_EXTENT_DATA_REF_KEY:
			dref = btrfs_item_ptr(l, i,
					      struct btrfs_extent_data_ref);
			print_extent_data_ref(l, dref);
			break;
		case BTRFS_SHARED_DATA_REF_KEY:
			sref = btrfs_item_ptr(l, i,
					      struct btrfs_shared_data_ref);
			printk(KERN_INFO "\t\tshared data backref count %u\n",
			       btrfs_shared_data_ref_count(l, sref));
231
			break;
232
233
234
		case BTRFS_EXTENT_DATA_KEY:
			fi = btrfs_item_ptr(l, i,
					    struct btrfs_file_extent_item);
235
			if (btrfs_file_extent_type(l, fi) ==
236
			    BTRFS_FILE_EXTENT_INLINE) {
237
238
239
				printk(KERN_INFO "\t\tinline extent data "
				       "size %u\n",
				       btrfs_file_extent_inline_len(l, fi));
240
241
				break;
			}
242
243
244
245
246
247
248
249
250
251
252
253
254
255
			printk(KERN_INFO "\t\textent data disk bytenr %llu "
			       "nr %llu\n",
			       (unsigned long long)
			       btrfs_file_extent_disk_bytenr(l, fi),
			       (unsigned long long)
			       btrfs_file_extent_disk_num_bytes(l, fi));
			printk(KERN_INFO "\t\textent data offset %llu "
			       "nr %llu ram %llu\n",
			       (unsigned long long)
			       btrfs_file_extent_offset(l, fi),
			       (unsigned long long)
			       btrfs_file_extent_num_bytes(l, fi),
			       (unsigned long long)
			       btrfs_file_extent_ram_bytes(l, fi));
256
			break;
257
258
259
260
261
262
		case BTRFS_EXTENT_REF_V0_KEY:
#ifdef BTRFS_COMPAT_EXTENT_TREE_V0
			print_extent_ref_v0(l, i);
#else
			BUG();
#endif
Chris Mason's avatar
Chris Mason committed
263
264
265
		case BTRFS_BLOCK_GROUP_ITEM_KEY:
			bi = btrfs_item_ptr(l, i,
					    struct btrfs_block_group_item);
266
267
268
			printk(KERN_INFO "\t\tblock group used %llu\n",
			       (unsigned long long)
			       btrfs_disk_block_group_used(l, bi));
269
			break;
270
		case BTRFS_CHUNK_ITEM_KEY:
271
272
			print_chunk(l, btrfs_item_ptr(l, i,
						      struct btrfs_chunk));
273
274
275
276
277
278
279
280
			break;
		case BTRFS_DEV_ITEM_KEY:
			print_dev_item(l, btrfs_item_ptr(l, i,
					struct btrfs_dev_item));
			break;
		case BTRFS_DEV_EXTENT_KEY:
			dev_extent = btrfs_item_ptr(l, i,
						    struct btrfs_dev_extent);
281
			printk(KERN_INFO "\t\tdev extent chunk_tree %llu\n"
282
283
284
285
286
287
288
289
290
291
			       "\t\tchunk objectid %llu chunk offset %llu "
			       "length %llu\n",
			       (unsigned long long)
			       btrfs_dev_extent_chunk_tree(l, dev_extent),
			       (unsigned long long)
			       btrfs_dev_extent_chunk_objectid(l, dev_extent),
			       (unsigned long long)
			       btrfs_dev_extent_chunk_offset(l, dev_extent),
			       (unsigned long long)
			       btrfs_dev_extent_length(l, dev_extent));
292
		};
Chris Mason's avatar
Chris Mason committed
293
294
	}
}
Chris Mason's avatar
Chris Mason committed
295

296
void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *c)
Chris Mason's avatar
Chris Mason committed
297
{
298
	int i; u32 nr;
299
	struct btrfs_key key;
300
	int level;
Chris Mason's avatar
Chris Mason committed
301

302
	if (!c)
Chris Mason's avatar
Chris Mason committed
303
		return;
304
	nr = btrfs_header_nritems(c);
305
306
	level = btrfs_header_level(c);
	if (level == 0) {
307
		btrfs_print_leaf(root, c);
Chris Mason's avatar
Chris Mason committed
308
309
		return;
	}
310
	printk(KERN_INFO "node %llu level %d total ptrs %d free spc %u\n",
311
	       (unsigned long long)btrfs_header_bytenr(c),
312
	      level, nr,
Chris Mason's avatar
Chris Mason committed
313
	       (u32)BTRFS_NODEPTRS_PER_BLOCK(root) - nr);
Chris Mason's avatar
Chris Mason committed
314
	for (i = 0; i < nr; i++) {
315
		btrfs_node_key_to_cpu(c, &key, i);
316
		printk(KERN_INFO "\tkey %d (%llu %u %llu) block %llu\n",
Chris Mason's avatar
Chris Mason committed
317
		       i,
318
319
320
		       (unsigned long long)key.objectid,
		       key.type,
		       (unsigned long long)key.offset,
Chris Mason's avatar
Chris Mason committed
321
		       (unsigned long long)btrfs_node_blockptr(c, i));
Chris Mason's avatar
Chris Mason committed
322
323
	}
	for (i = 0; i < nr; i++) {
324
		struct extent_buffer *next = read_tree_block(root,
325
					btrfs_node_blockptr(c, i),
326
327
					btrfs_level_size(root, level - 1),
					btrfs_node_ptr_generation(c, i));
328
		if (btrfs_is_leaf(next) &&
329
		   level != 1)
Chris Mason's avatar
Chris Mason committed
330
			BUG();
331
		if (btrfs_header_level(next) !=
332
		       level - 1)
Chris Mason's avatar
Chris Mason committed
333
			BUG();
334
335
		btrfs_print_tree(root, next);
		free_extent_buffer(next);
Chris Mason's avatar
Chris Mason committed
336
337
	}
}