print-tree.c 11.0 KB
Newer Older
C
Chris Mason 已提交
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.
 */

C
Chris Mason 已提交
19 20
#include "ctree.h"
#include "disk-io.h"
C
Chris Mason 已提交
21
#include "print-tree.h"
C
Chris Mason 已提交
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;
C
Chris Mason 已提交
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++) {
C
Chris Mason 已提交
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)
{
C
Chris Mason 已提交
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
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);
98
		printk(KERN_INFO "\t\ttree block key (%llu %u %llu) "
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
		       "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)
C
Chris Mason 已提交
159 160
{
	int i;
D
Daniel J Blueman 已提交
161
	u32 type, nr;
C
Chris Mason 已提交
162
	struct btrfs_item *item;
163
	struct btrfs_root_item *ri;
164
	struct btrfs_dir_item *di;
165
	struct btrfs_inode_item *ii;
C
Chris Mason 已提交
166
	struct btrfs_block_group_item *bi;
167
	struct btrfs_file_extent_item *fi;
168 169 170
	struct btrfs_extent_data_ref *dref;
	struct btrfs_shared_data_ref *sref;
	struct btrfs_dev_extent *dev_extent;
171 172
	struct btrfs_key key;
	struct btrfs_key found_key;
173

D
Daniel J Blueman 已提交
174 175 176 177 178
	if (!l)
		return;

	nr = btrfs_header_nritems(l);

179
	btrfs_info(root->fs_info, "leaf %llu total ptrs %d free space %d",
180
		(unsigned long long)btrfs_header_bytenr(l), nr,
C
Chris Mason 已提交
181
		btrfs_leaf_free_space(root, l));
C
Chris Mason 已提交
182
	for (i = 0 ; i < nr ; i++) {
183 184 185
		item = btrfs_item_nr(l, i);
		btrfs_item_key_to_cpu(l, &key, i);
		type = btrfs_key_type(&key);
186
		printk(KERN_INFO "\titem %d key (%llu %u %llu) itemoff %d "
C
Chris Mason 已提交
187
		       "itemsize %d\n",
C
Chris Mason 已提交
188
			i,
189 190 191
			(unsigned long long)key.objectid, type,
			(unsigned long long)key.offset,
			btrfs_item_offset(l, item), btrfs_item_size(l, item));
192 193
		switch (type) {
		case BTRFS_INODE_ITEM_KEY:
194
			ii = btrfs_item_ptr(l, i, struct btrfs_inode_item);
C
Chris Mason 已提交
195 196 197 198
			printk(KERN_INFO "\t\tinode generation %llu size %llu "
			       "mode %o\n",
			       (unsigned long long)
			       btrfs_inode_generation(l, ii),
199 200
			      (unsigned long long)btrfs_inode_size(l, ii),
			       btrfs_inode_mode(l, ii));
201 202
			break;
		case BTRFS_DIR_ITEM_KEY:
203
			di = btrfs_item_ptr(l, i, struct btrfs_dir_item);
204
			btrfs_dir_item_key_to_cpu(l, di, &found_key);
C
Chris Mason 已提交
205
			printk(KERN_INFO "\t\tdir oid %llu type %u\n",
206 207
				(unsigned long long)found_key.objectid,
				btrfs_dir_type(l, di));
208 209 210
			break;
		case BTRFS_ROOT_ITEM_KEY:
			ri = btrfs_item_ptr(l, i, struct btrfs_root_item);
C
Chris Mason 已提交
211 212 213
			printk(KERN_INFO "\t\troot data bytenr %llu refs %u\n",
				(unsigned long long)
				btrfs_disk_root_bytenr(l, ri),
214
				btrfs_disk_root_refs(l, ri));
215 216
			break;
		case BTRFS_EXTENT_ITEM_KEY:
217
			print_extent_item(l, i);
218
			break;
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
		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));
235
			break;
236 237 238
		case BTRFS_EXTENT_DATA_KEY:
			fi = btrfs_item_ptr(l, i,
					    struct btrfs_file_extent_item);
239
			if (btrfs_file_extent_type(l, fi) ==
240
			    BTRFS_FILE_EXTENT_INLINE) {
C
Chris Mason 已提交
241 242 243
				printk(KERN_INFO "\t\tinline extent data "
				       "size %u\n",
				       btrfs_file_extent_inline_len(l, fi));
244 245
				break;
			}
C
Chris Mason 已提交
246 247 248 249 250 251 252 253 254 255 256 257 258 259
			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));
260
			break;
261 262 263 264 265 266
		case BTRFS_EXTENT_REF_V0_KEY:
#ifdef BTRFS_COMPAT_EXTENT_TREE_V0
			print_extent_ref_v0(l, i);
#else
			BUG();
#endif
267
			break;
C
Chris Mason 已提交
268 269 270
		case BTRFS_BLOCK_GROUP_ITEM_KEY:
			bi = btrfs_item_ptr(l, i,
					    struct btrfs_block_group_item);
C
Chris Mason 已提交
271 272 273
			printk(KERN_INFO "\t\tblock group used %llu\n",
			       (unsigned long long)
			       btrfs_disk_block_group_used(l, bi));
274
			break;
275
		case BTRFS_CHUNK_ITEM_KEY:
C
Chris Mason 已提交
276 277
			print_chunk(l, btrfs_item_ptr(l, i,
						      struct btrfs_chunk));
278 279 280 281 282 283 284 285
			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);
C
Chris Mason 已提交
286
			printk(KERN_INFO "\t\tdev extent chunk_tree %llu\n"
287 288 289 290 291 292 293 294 295 296
			       "\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));
297
			break;
298 299 300
		case BTRFS_DEV_STATS_KEY:
			printk(KERN_INFO "\t\tdevice stats\n");
			break;
301 302 303
		case BTRFS_DEV_REPLACE_KEY:
			printk(KERN_INFO "\t\tdev replace\n");
			break;
304
		};
C
Chris Mason 已提交
305 306
	}
}
C
Chris Mason 已提交
307

308
void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *c)
C
Chris Mason 已提交
309
{
310
	int i; u32 nr;
311
	struct btrfs_key key;
312
	int level;
C
Chris Mason 已提交
313

314
	if (!c)
C
Chris Mason 已提交
315
		return;
316
	nr = btrfs_header_nritems(c);
317 318
	level = btrfs_header_level(c);
	if (level == 0) {
319
		btrfs_print_leaf(root, c);
C
Chris Mason 已提交
320 321
		return;
	}
322 323 324
	btrfs_info(root->fs_info, "node %llu level %d total ptrs %d free spc %u",
		(unsigned long long)btrfs_header_bytenr(c),
		level, nr, (u32)BTRFS_NODEPTRS_PER_BLOCK(root) - nr);
C
Chris Mason 已提交
325
	for (i = 0; i < nr; i++) {
326
		btrfs_node_key_to_cpu(c, &key, i);
C
Chris Mason 已提交
327
		printk(KERN_INFO "\tkey %d (%llu %u %llu) block %llu\n",
C
Chris Mason 已提交
328
		       i,
329 330 331
		       (unsigned long long)key.objectid,
		       key.type,
		       (unsigned long long)key.offset,
C
Chris Mason 已提交
332
		       (unsigned long long)btrfs_node_blockptr(c, i));
C
Chris Mason 已提交
333 334
	}
	for (i = 0; i < nr; i++) {
335
		struct extent_buffer *next = read_tree_block(root,
336
					btrfs_node_blockptr(c, i),
337 338
					btrfs_level_size(root, level - 1),
					btrfs_node_ptr_generation(c, i));
339
		if (btrfs_is_leaf(next) &&
340
		   level != 1)
C
Chris Mason 已提交
341
			BUG();
342
		if (btrfs_header_level(next) !=
343
		       level - 1)
C
Chris Mason 已提交
344
			BUG();
345 346
		btrfs_print_tree(root, next);
		free_extent_buffer(next);
C
Chris Mason 已提交
347 348
	}
}