示例#1
0
static int find_root(struct btrfs_root *root)
{
	struct btrfs_multi_bio *multi = NULL;
	struct btrfs_device *device;
	u64 metadata_offset = 0, metadata_size = 0;
	off_t offset = 0;
	off_t bytenr;
	int fd;
	int err;
	int ret = 1;

	printf("Super think's the tree root is at %Lu, chunk root %Lu\n",
	       btrfs_super_root(root->fs_info->super_copy),
	       btrfs_super_chunk_root(root->fs_info->super_copy));

	err = btrfs_next_metadata(&root->fs_info->mapping_tree,
				  &metadata_offset, &metadata_size);
	if (err)
		return ret;

	offset = metadata_offset;
	while (1) {
		u64 map_length = 4096;
		u64 type;

		if (offset >
		    btrfs_super_total_bytes(root->fs_info->super_copy)) {
			printf("Went past the fs size, exiting");
			break;
		}
		if (offset >= (metadata_offset + metadata_size)) {
			err = btrfs_next_metadata(&root->fs_info->mapping_tree,
						  &metadata_offset,
						  &metadata_size);
			if (err) {
				printf("No more metdata to scan, exiting\n");
				break;
			}
			offset = metadata_offset;
		}
		err = __btrfs_map_block(&root->fs_info->mapping_tree, READ,
				      offset, &map_length, &type,
				      &multi, 0, NULL);
		if (err) {
			offset += map_length;
			continue;
		}

		if (!(type & BTRFS_BLOCK_GROUP_METADATA)) {
			offset += map_length;
			kfree(multi);
			continue;
		}

		device = multi->stripes[0].dev;
		fd = device->fd;
		bytenr = multi->stripes[0].physical;
		kfree(multi);

		err = read_physical(root, fd, offset, bytenr, map_length);
		if (!err) {
			ret = 0;
			break;
		} else if (err < 0) {
			ret = err;
			break;
		}
		offset += map_length;
	}
	return ret;
}
示例#2
0
static void dump_superblock(struct btrfs_super_block *sb, int full)
{
	int i;
	char *s, buf[BTRFS_UUID_UNPARSED_SIZE];
	u8 *p;

	printf("csum\t\t\t0x");
	for (i = 0, p = sb->csum; i < btrfs_super_csum_size(sb); i++)
		printf("%02x", p[i]);
	if (check_csum_sblock(sb, btrfs_super_csum_size(sb)))
		printf(" [match]");
	else
		printf(" [DON'T MATCH]");
	putchar('\n');

	printf("bytenr\t\t\t%llu\n",
		(unsigned long long)btrfs_super_bytenr(sb));
	printf("flags\t\t\t0x%llx\n",
		(unsigned long long)btrfs_super_flags(sb));
	print_readable_super_flag(btrfs_super_flags(sb));

	printf("magic\t\t\t");
	s = (char *) &sb->magic;
	for (i = 0; i < 8; i++)
		putchar(isprint(s[i]) ? s[i] : '.');
	if (btrfs_super_magic(sb) == BTRFS_MAGIC)
		printf(" [match]\n");
	else
		printf(" [DON'T MATCH]\n");

	uuid_unparse(sb->fsid, buf);
	printf("fsid\t\t\t%s\n", buf);

	printf("label\t\t\t");
	s = sb->label;
	for (i = 0; i < BTRFS_LABEL_SIZE && s[i]; i++)
		putchar(isprint(s[i]) ? s[i] : '.');
	putchar('\n');

	printf("generation\t\t%llu\n",
	       (unsigned long long)btrfs_super_generation(sb));
	printf("root\t\t\t%llu\n", (unsigned long long)btrfs_super_root(sb));
	printf("sys_array_size\t\t%llu\n",
	       (unsigned long long)btrfs_super_sys_array_size(sb));
	printf("chunk_root_generation\t%llu\n",
	       (unsigned long long)btrfs_super_chunk_root_generation(sb));
	printf("root_level\t\t%llu\n",
	       (unsigned long long)btrfs_super_root_level(sb));
	printf("chunk_root\t\t%llu\n",
	       (unsigned long long)btrfs_super_chunk_root(sb));
	printf("chunk_root_level\t%llu\n",
	       (unsigned long long)btrfs_super_chunk_root_level(sb));
	printf("log_root\t\t%llu\n",
	       (unsigned long long)btrfs_super_log_root(sb));
	printf("log_root_transid\t%llu\n",
	       (unsigned long long)btrfs_super_log_root_transid(sb));
	printf("log_root_level\t\t%llu\n",
	       (unsigned long long)btrfs_super_log_root_level(sb));
	printf("total_bytes\t\t%llu\n",
	       (unsigned long long)btrfs_super_total_bytes(sb));
	printf("bytes_used\t\t%llu\n",
	       (unsigned long long)btrfs_super_bytes_used(sb));
	printf("sectorsize\t\t%llu\n",
	       (unsigned long long)btrfs_super_sectorsize(sb));
	printf("nodesize\t\t%llu\n",
	       (unsigned long long)btrfs_super_nodesize(sb));
	printf("leafsize\t\t%llu\n",
	       (unsigned long long)btrfs_super_leafsize(sb));
	printf("stripesize\t\t%llu\n",
	       (unsigned long long)btrfs_super_stripesize(sb));
	printf("root_dir\t\t%llu\n",
	       (unsigned long long)btrfs_super_root_dir(sb));
	printf("num_devices\t\t%llu\n",
	       (unsigned long long)btrfs_super_num_devices(sb));
	printf("compat_flags\t\t0x%llx\n",
	       (unsigned long long)btrfs_super_compat_flags(sb));
	printf("compat_ro_flags\t\t0x%llx\n",
	       (unsigned long long)btrfs_super_compat_ro_flags(sb));
	printf("incompat_flags\t\t0x%llx\n",
	       (unsigned long long)btrfs_super_incompat_flags(sb));
	print_readable_incompat_flag(btrfs_super_incompat_flags(sb));
	printf("csum_type\t\t%llu\n",
	       (unsigned long long)btrfs_super_csum_type(sb));
	printf("csum_size\t\t%llu\n",
	       (unsigned long long)btrfs_super_csum_size(sb));
	printf("cache_generation\t%llu\n",
	       (unsigned long long)btrfs_super_cache_generation(sb));
	printf("uuid_tree_generation\t%llu\n",
	       (unsigned long long)btrfs_super_uuid_tree_generation(sb));

	uuid_unparse(sb->dev_item.uuid, buf);
	printf("dev_item.uuid\t\t%s\n", buf);

	uuid_unparse(sb->dev_item.fsid, buf);
	printf("dev_item.fsid\t\t%s %s\n", buf,
		!memcmp(sb->dev_item.fsid, sb->fsid, BTRFS_FSID_SIZE) ?
			"[match]" : "[DON'T MATCH]");

	printf("dev_item.type\t\t%llu\n", (unsigned long long)
	       btrfs_stack_device_type(&sb->dev_item));
	printf("dev_item.total_bytes\t%llu\n", (unsigned long long)
	       btrfs_stack_device_total_bytes(&sb->dev_item));
	printf("dev_item.bytes_used\t%llu\n", (unsigned long long)
	       btrfs_stack_device_bytes_used(&sb->dev_item));
	printf("dev_item.io_align\t%u\n", (unsigned int)
	       btrfs_stack_device_io_align(&sb->dev_item));
	printf("dev_item.io_width\t%u\n", (unsigned int)
	       btrfs_stack_device_io_width(&sb->dev_item));
	printf("dev_item.sector_size\t%u\n", (unsigned int)
	       btrfs_stack_device_sector_size(&sb->dev_item));
	printf("dev_item.devid\t\t%llu\n",
	       btrfs_stack_device_id(&sb->dev_item));
	printf("dev_item.dev_group\t%u\n", (unsigned int)
	       btrfs_stack_device_group(&sb->dev_item));
	printf("dev_item.seek_speed\t%u\n", (unsigned int)
	       btrfs_stack_device_seek_speed(&sb->dev_item));
	printf("dev_item.bandwidth\t%u\n", (unsigned int)
	       btrfs_stack_device_bandwidth(&sb->dev_item));
	printf("dev_item.generation\t%llu\n", (unsigned long long)
	       btrfs_stack_device_generation(&sb->dev_item));
	if (full) {
		printf("sys_chunk_array[%d]:\n", BTRFS_SYSTEM_CHUNK_ARRAY_SIZE);
		print_sys_chunk_array(sb);
		printf("backup_roots[%d]:\n", BTRFS_NUM_BACKUP_ROOTS);
		print_backup_roots(sb);
	}
}
示例#3
0
文件: sysfs.c 项目: macbury/linux-2.6
static ssize_t super_total_blocks_show(struct btrfs_fs_info *fs, char *buf)
{
	return snprintf(buf, PAGE_SIZE, "%llu\n",
		(unsigned long long)btrfs_super_total_bytes(&fs->super_copy));
}
示例#4
0
int btrfs_add_to_fsid(struct btrfs_trans_handle *trans,
		      struct btrfs_root *root, int fd, char *path,
		      u64 block_count, u32 io_width, u32 io_align,
		      u32 sectorsize)
{
	struct btrfs_super_block *disk_super;
	struct btrfs_super_block *super = root->fs_info->super_copy;
	struct btrfs_device *device;
	struct btrfs_dev_item *dev_item;
	char *buf;
	u64 total_bytes;
	u64 num_devs;
	int ret;

	device = kzalloc(sizeof(*device), GFP_NOFS);
	if (!device)
		return -ENOMEM;
	buf = kmalloc(sectorsize, GFP_NOFS);
	if (!buf) {
		kfree(device);
		return -ENOMEM;
	}
	BUG_ON(sizeof(*disk_super) > sectorsize);
	memset(buf, 0, sectorsize);

	disk_super = (struct btrfs_super_block *)buf;
	dev_item = &disk_super->dev_item;

	uuid_generate(device->uuid);
	device->devid = 0;
	device->type = 0;
	device->io_width = io_width;
	device->io_align = io_align;
	device->sector_size = sectorsize;
	device->fd = fd;
	device->writeable = 1;
	device->total_bytes = block_count;
	device->bytes_used = 0;
	device->total_ios = 0;
	device->dev_root = root->fs_info->dev_root;

	ret = btrfs_add_device(trans, root, device);
	BUG_ON(ret);

	total_bytes = btrfs_super_total_bytes(super) + block_count;
	btrfs_set_super_total_bytes(super, total_bytes);

	num_devs = btrfs_super_num_devices(super) + 1;
	btrfs_set_super_num_devices(super, num_devs);

	memcpy(disk_super, super, sizeof(*disk_super));

	printf("adding device %s id %llu\n", path,
	       (unsigned long long)device->devid);

	btrfs_set_super_bytenr(disk_super, BTRFS_SUPER_INFO_OFFSET);
	btrfs_set_stack_device_id(dev_item, device->devid);
	btrfs_set_stack_device_type(dev_item, device->type);
	btrfs_set_stack_device_io_align(dev_item, device->io_align);
	btrfs_set_stack_device_io_width(dev_item, device->io_width);
	btrfs_set_stack_device_sector_size(dev_item, device->sector_size);
	btrfs_set_stack_device_total_bytes(dev_item, device->total_bytes);
	btrfs_set_stack_device_bytes_used(dev_item, device->bytes_used);
	memcpy(&dev_item->uuid, device->uuid, BTRFS_UUID_SIZE);

	ret = pwrite(fd, buf, sectorsize, BTRFS_SUPER_INFO_OFFSET);
	BUG_ON(ret != sectorsize);

	kfree(buf);
	list_add(&device->dev_list, &root->fs_info->fs_devices->devices);
	device->fs_devices = root->fs_info->fs_devices;
	return 0;
}
示例#5
0
int main(int ac, char **av)
{
	char *file;
	struct btrfs_root *root;
	struct btrfs_trans_handle *trans;
	char *label = NULL;
	char *first_file;
	u64 block_count = 0;
	u64 dev_block_count = 0;
	u64 blocks[7];
	u64 alloc_start = 0;
	u64 metadata_profile = 0;
	u64 data_profile = 0;
	u32 leafsize = sysconf(_SC_PAGESIZE);
	u32 sectorsize = 4096;
	u32 nodesize = leafsize;
	u32 stripesize = 4096;
	int zero_end = 1;
	int option_index = 0;
	int fd;
	int ret;
	int i;
	int mixed = 0;
	int data_profile_opt = 0;
	int metadata_profile_opt = 0;
	int discard = 1;
	int ssd = 0;
	int force_overwrite = 0;

	char *source_dir = NULL;
	int source_dir_set = 0;
	u64 num_of_meta_chunks = 0;
	u64 size_of_data = 0;
	u64 source_dir_size = 0;
	int dev_cnt = 0;
	int saved_optind;
	char estr[100];
	u64 features = 0;

	while(1) {
		int c;
		c = getopt_long(ac, av, "A:b:fl:n:s:m:d:L:O:r:VMK",
				long_options, &option_index);
		if (c < 0)
			break;
		switch(c) {
			case 'A':
				alloc_start = parse_size(optarg);
				break;
			case 'f':
				force_overwrite = 1;
				break;
			case 'd':
				data_profile = parse_profile(optarg);
				data_profile_opt = 1;
				break;
			case 'l':
			case 'n':
				nodesize = parse_size(optarg);
				leafsize = parse_size(optarg);
				break;
			case 'L':
				label = parse_label(optarg);
				break;
			case 'm':
				metadata_profile = parse_profile(optarg);
				metadata_profile_opt = 1;
				break;
			case 'M':
				mixed = 1;
				break;
			case 'O': {
				char *orig = strdup(optarg);
				char *tmp = orig;

				tmp = parse_fs_features(tmp, &features);
				if (tmp) {
					fprintf(stderr,
						"Unrecognized filesystem feature '%s'\n",
							tmp);
					free(orig);
					exit(1);
				}
				free(orig);
				if (features & BTRFS_FEATURE_LIST_ALL) {
					list_all_fs_features();
					exit(0);
				}
				break;
				}
			case 's':
				sectorsize = parse_size(optarg);
				break;
			case 'b':
				block_count = parse_size(optarg);
				if (block_count <= 1024*1024*1024) {
					printf("SMALL VOLUME: forcing mixed "
					       "metadata/data groups\n");
					mixed = 1;
				}
				zero_end = 0;
				break;
			case 'V':
				print_version();
				break;
			case 'r':
				source_dir = optarg;
				source_dir_set = 1;
				break;
			case 'K':
				discard = 0;
				break;
			default:
				print_usage();
		}
	}
	sectorsize = max(sectorsize, (u32)sysconf(_SC_PAGESIZE));
	if (check_leaf_or_node_size(leafsize, sectorsize))
		exit(1);
	if (check_leaf_or_node_size(nodesize, sectorsize))
		exit(1);
	saved_optind = optind;
	dev_cnt = ac - optind;
	if (dev_cnt == 0)
		print_usage();

	if (source_dir_set && dev_cnt > 1) {
		fprintf(stderr,
			"The -r option is limited to a single device\n");
		exit(1);
	}
	while (dev_cnt-- > 0) {
		file = av[optind++];
		if (is_block_device(file))
			if (test_dev_for_mkfs(file, force_overwrite, estr)) {
				fprintf(stderr, "Error: %s", estr);
				exit(1);
			}
	}

	optind = saved_optind;
	dev_cnt = ac - optind;

	file = av[optind++];
	ssd = is_ssd(file);

	if (is_vol_small(file)) {
		printf("SMALL VOLUME: forcing mixed metadata/data groups\n");
		mixed = 1;
		if (metadata_profile != data_profile) {
			if (metadata_profile_opt || data_profile_opt) {
				fprintf(stderr,
	"With mixed block groups data and metadata profiles must be the same\n");
				exit(1);
			}
		}
	}
	/*
	* Set default profiles according to number of added devices.
	* For mixed groups defaults are single/single.
	*/
	if (!mixed) {
		if (!metadata_profile_opt) {
			if (dev_cnt == 1 && ssd)
				printf("Detected a SSD, turning off metadata "
				"duplication.  Mkfs with -m dup if you want to "
				"force metadata duplication.\n");

			metadata_profile = (dev_cnt > 1) ?
					BTRFS_BLOCK_GROUP_RAID1 : (ssd) ?
					0: BTRFS_BLOCK_GROUP_DUP;
		}
		if (!data_profile_opt) {
			data_profile = (dev_cnt > 1) ?
				BTRFS_BLOCK_GROUP_RAID0 : 0; /* raid0 or single */
		}
	} else {
		metadata_profile = 0;
		data_profile = 0;
	}

	ret = test_num_disk_vs_raid(metadata_profile, data_profile,
			dev_cnt, mixed, estr);
	if (ret) {
		fprintf(stderr, "Error: %s\n", estr);
		exit(1);
	}

	/* if we are here that means all devs are good to btrfsify */
	printf("\nWARNING! - %s IS EXPERIMENTAL\n", BTRFS_BUILD_VERSION);
	printf("WARNING! - see http://btrfs.wiki.kernel.org before using\n\n");

	dev_cnt--;

	if (!source_dir_set) {
		/*
		 * open without O_EXCL so that the problem should not
		 * occur by the following processing.
		 * (btrfs_register_one_device() fails if O_EXCL is on)
		 */
		fd = open(file, O_RDWR);
		if (fd < 0) {
			fprintf(stderr, "unable to open %s: %s\n", file,
				strerror(errno));
			exit(1);
		}
		first_file = file;
		ret = btrfs_prepare_device(fd, file, zero_end, &dev_block_count,
					   block_count, &mixed, discard);
		if (block_count && block_count > dev_block_count) {
			fprintf(stderr, "%s is smaller than requested size\n", file);
			exit(1);
		}
	} else {
		fd = open_target(file);
		if (fd < 0) {
			fprintf(stderr, "unable to open the %s\n", file);
			exit(1);
		}

		first_file = file;
		source_dir_size = size_sourcedir(source_dir, sectorsize,
					     &num_of_meta_chunks, &size_of_data);
		if(block_count < source_dir_size)
			block_count = source_dir_size;
		ret = zero_output_file(fd, block_count, sectorsize);
		if (ret) {
			fprintf(stderr, "unable to zero the output file\n");
			exit(1);
		}
		/* our "device" is the new image file */
		dev_block_count = block_count;
	}

	/* To create the first block group and chunk 0 in make_btrfs */
	if (dev_block_count < BTRFS_MKFS_SYSTEM_GROUP_SIZE) {
		fprintf(stderr, "device is too small to make filesystem\n");
		exit(1);
	}

	blocks[0] = BTRFS_SUPER_INFO_OFFSET;
	for (i = 1; i < 7; i++) {
		blocks[i] = BTRFS_SUPER_INFO_OFFSET + 1024 * 1024 +
			leafsize * i;
	}

	/*
	 * FS features that can be set by other means than -O
	 * just set the bit here
	 */
	if (mixed)
		features |= BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS;

	if ((data_profile | metadata_profile) &
	    (BTRFS_BLOCK_GROUP_RAID5 | BTRFS_BLOCK_GROUP_RAID6)) {
		features |= BTRFS_FEATURE_INCOMPAT_RAID56;
	}

	process_fs_features(features);

	ret = make_btrfs(fd, file, label, blocks, dev_block_count,
			 nodesize, leafsize,
			 sectorsize, stripesize, features);
	if (ret) {
		fprintf(stderr, "error during mkfs: %s\n", strerror(-ret));
		exit(1);
	}

	root = open_ctree(file, 0, OPEN_CTREE_WRITES);
	if (!root) {
		fprintf(stderr, "Open ctree failed\n");
		close(fd);
		exit(1);
	}
	root->fs_info->alloc_start = alloc_start;

	ret = make_root_dir(root, mixed);
	if (ret) {
		fprintf(stderr, "failed to setup the root directory\n");
		exit(1);
	}

	trans = btrfs_start_transaction(root, 1);

	if (dev_cnt == 0)
		goto raid_groups;

	btrfs_register_one_device(file);

	zero_end = 1;
	while (dev_cnt-- > 0) {
		int old_mixed = mixed;

		file = av[optind++];

		/*
		 * open without O_EXCL so that the problem should not
		 * occur by the following processing.
		 * (btrfs_register_one_device() fails if O_EXCL is on)
		 */
		fd = open(file, O_RDWR);
		if (fd < 0) {
			fprintf(stderr, "unable to open %s: %s\n", file,
				strerror(errno));
			exit(1);
		}
		ret = btrfs_device_already_in_root(root, fd,
						   BTRFS_SUPER_INFO_OFFSET);
		if (ret) {
			fprintf(stderr, "skipping duplicate device %s in FS\n",
				file);
			close(fd);
			continue;
		}
		ret = btrfs_prepare_device(fd, file, zero_end, &dev_block_count,
					   block_count, &mixed, discard);
		mixed = old_mixed;
		BUG_ON(ret);

		ret = btrfs_add_to_fsid(trans, root, fd, file, dev_block_count,
					sectorsize, sectorsize, sectorsize);
		BUG_ON(ret);
		btrfs_register_one_device(file);
	}

raid_groups:
	if (!source_dir_set) {
		ret = create_raid_groups(trans, root, data_profile,
				 data_profile_opt, metadata_profile,
				 metadata_profile_opt, mixed, ssd);
		BUG_ON(ret);
	}

	ret = create_data_reloc_tree(trans, root);
	BUG_ON(ret);

	printf("fs created label %s on %s\n\tnodesize %u leafsize %u "
	    "sectorsize %u size %s\n",
	    label, first_file, nodesize, leafsize, sectorsize,
	    pretty_size(btrfs_super_total_bytes(root->fs_info->super_copy)));

	printf("%s\n", BTRFS_BUILD_VERSION);
	btrfs_commit_transaction(trans, root);

	if (source_dir_set) {
		trans = btrfs_start_transaction(root, 1);
		ret = create_chunks(trans, root,
				    num_of_meta_chunks, size_of_data);
		BUG_ON(ret);
		btrfs_commit_transaction(trans, root);

		ret = make_image(source_dir, root, fd);
		BUG_ON(ret);
	}

	ret = close_ctree(root);
	BUG_ON(ret);
	free(label);
	return 0;
}
示例#6
0
int main(int ac, char **av)
{
    struct btrfs_root *root;
    struct btrfs_fs_info *info;
    struct btrfs_path path;
    struct btrfs_key key;
    struct btrfs_root_item ri;
    struct extent_buffer *leaf;
    struct btrfs_disk_key disk_key;
    struct btrfs_key found_key;
    char uuidbuf[BTRFS_UUID_UNPARSED_SIZE];
    int ret;
    int slot;
    int extent_only = 0;
    int device_only = 0;
    int uuid_tree_only = 0;
    int roots_only = 0;
    int root_backups = 0;
    u64 block_only = 0;
    struct btrfs_root *tree_root_scan;
    u64 tree_id = 0;

    radix_tree_init();

    while(1) {
        int c;
        static const struct option long_options[] = {
            { "help", no_argument, NULL, GETOPT_VAL_HELP},
            { NULL, 0, NULL, 0 }
        };

        c = getopt_long(ac, av, "deb:rRut:", long_options, NULL);
        if (c < 0)
            break;
        switch(c) {
        case 'e':
            extent_only = 1;
            break;
        case 'd':
            device_only = 1;
            break;
        case 'r':
            roots_only = 1;
            break;
        case 'u':
            uuid_tree_only = 1;
            break;
        case 'R':
            roots_only = 1;
            root_backups = 1;
            break;
        case 'b':
            block_only = arg_strtou64(optarg);
            break;
        case 't':
            tree_id = arg_strtou64(optarg);
            break;
        case GETOPT_VAL_HELP:
        default:
            print_usage(c != GETOPT_VAL_HELP);
        }
    }
    set_argv0(av);
    ac = ac - optind;
    if (check_argc_exact(ac, 1))
        print_usage(1);

    ret = check_arg_type(av[optind]);
    if (ret != BTRFS_ARG_BLKDEV && ret != BTRFS_ARG_REG) {
        fprintf(stderr, "'%s' is not a block device or regular file\n",
                av[optind]);
        exit(1);
    }

    info = open_ctree_fs_info(av[optind], 0, 0, OPEN_CTREE_PARTIAL);
    if (!info) {
        fprintf(stderr, "unable to open %s\n", av[optind]);
        exit(1);
    }

    root = info->fs_root;
    if (!root) {
        fprintf(stderr, "unable to open %s\n", av[optind]);
        exit(1);
    }

    if (block_only) {
        leaf = read_tree_block(root,
                               block_only,
                               root->leafsize, 0);

        if (extent_buffer_uptodate(leaf) &&
                btrfs_header_level(leaf) != 0) {
            free_extent_buffer(leaf);
            leaf = NULL;
        }

        if (!leaf) {
            leaf = read_tree_block(root,
                                   block_only,
                                   root->nodesize, 0);
        }
        if (!extent_buffer_uptodate(leaf)) {
            fprintf(stderr, "failed to read %llu\n",
                    (unsigned long long)block_only);
            goto close_root;
        }
        btrfs_print_tree(root, leaf, 0);
        free_extent_buffer(leaf);
        goto close_root;
    }

    if (!(extent_only || uuid_tree_only || tree_id)) {
        if (roots_only) {
            printf("root tree: %llu level %d\n",
                   (unsigned long long)info->tree_root->node->start,
                   btrfs_header_level(info->tree_root->node));
            printf("chunk tree: %llu level %d\n",
                   (unsigned long long)info->chunk_root->node->start,
                   btrfs_header_level(info->chunk_root->node));
        } else {
            if (info->tree_root->node) {
                printf("root tree\n");
                btrfs_print_tree(info->tree_root,
                                 info->tree_root->node, 1);
            }

            if (info->chunk_root->node) {
                printf("chunk tree\n");
                btrfs_print_tree(info->chunk_root,
                                 info->chunk_root->node, 1);
            }
        }
    }
    tree_root_scan = info->tree_root;

    btrfs_init_path(&path);
again:
    if (!extent_buffer_uptodate(tree_root_scan->node))
        goto no_node;

    /*
     * Tree's that are not pointed by the tree of tree roots
     */
    if (tree_id && tree_id == BTRFS_ROOT_TREE_OBJECTID) {
        if (!info->tree_root->node) {
            error("cannot print root tree, invalid pointer");
            goto no_node;
        }
        printf("root tree\n");
        btrfs_print_tree(info->tree_root, info->tree_root->node, 1);
        goto no_node;
    }

    if (tree_id && tree_id == BTRFS_CHUNK_TREE_OBJECTID) {
        if (!info->chunk_root->node) {
            error("cannot print chunk tree, invalid pointer");
            goto no_node;
        }
        printf("chunk tree\n");
        btrfs_print_tree(info->chunk_root, info->chunk_root->node, 1);
        goto no_node;
    }

    key.offset = 0;
    key.objectid = 0;
    btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY);
    ret = btrfs_search_slot(NULL, tree_root_scan, &key, &path, 0, 0);
    BUG_ON(ret < 0);
    while(1) {
        leaf = path.nodes[0];
        slot = path.slots[0];
        if (slot >= btrfs_header_nritems(leaf)) {
            ret = btrfs_next_leaf(tree_root_scan, &path);
            if (ret != 0)
                break;
            leaf = path.nodes[0];
            slot = path.slots[0];
        }
        btrfs_item_key(leaf, &disk_key, path.slots[0]);
        btrfs_disk_key_to_cpu(&found_key, &disk_key);
        if (btrfs_key_type(&found_key) == BTRFS_ROOT_ITEM_KEY) {
            unsigned long offset;
            struct extent_buffer *buf;
            int skip = extent_only | device_only | uuid_tree_only;

            offset = btrfs_item_ptr_offset(leaf, slot);
            read_extent_buffer(leaf, &ri, offset, sizeof(ri));
            buf = read_tree_block(tree_root_scan,
                                  btrfs_root_bytenr(&ri),
                                  btrfs_level_size(tree_root_scan,
                                                   btrfs_root_level(&ri)),
                                  0);
            if (!extent_buffer_uptodate(buf))
                goto next;
            if (tree_id && found_key.objectid != tree_id) {
                free_extent_buffer(buf);
                goto next;
            }

            switch(found_key.objectid) {
            case BTRFS_ROOT_TREE_OBJECTID:
                if (!skip)
                    printf("root");
                break;
            case BTRFS_EXTENT_TREE_OBJECTID:
                if (!device_only && !uuid_tree_only)
                    skip = 0;
                if (!skip)
                    printf("extent");
                break;
            case BTRFS_CHUNK_TREE_OBJECTID:
                if (!skip) {
                    printf("chunk");
                }
                break;
            case BTRFS_DEV_TREE_OBJECTID:
                if (!uuid_tree_only)
                    skip = 0;
                if (!skip)
                    printf("device");
                break;
            case BTRFS_FS_TREE_OBJECTID:
                if (!skip) {
                    printf("fs");
                }
                break;
            case BTRFS_ROOT_TREE_DIR_OBJECTID:
                skip = 0;
                printf("directory");
                break;
            case BTRFS_CSUM_TREE_OBJECTID:
                if (!skip) {
                    printf("checksum");
                }
                break;
            case BTRFS_ORPHAN_OBJECTID:
                if (!skip) {
                    printf("orphan");
                }
                break;
            case BTRFS_TREE_LOG_OBJECTID:
                if (!skip) {
                    printf("log");
                }
                break;
            case BTRFS_TREE_LOG_FIXUP_OBJECTID:
                if (!skip) {
                    printf("log fixup");
                }
                break;
            case BTRFS_TREE_RELOC_OBJECTID:
                if (!skip) {
                    printf("reloc");
                }
                break;
            case BTRFS_DATA_RELOC_TREE_OBJECTID:
                if (!skip) {
                    printf("data reloc");
                }
                break;
            case BTRFS_EXTENT_CSUM_OBJECTID:
                if (!skip) {
                    printf("extent checksum");
                }
                break;
            case BTRFS_QUOTA_TREE_OBJECTID:
                if (!skip) {
                    printf("quota");
                }
                break;
            case BTRFS_UUID_TREE_OBJECTID:
                if (!extent_only && !device_only)
                    skip = 0;
                if (!skip)
                    printf("uuid");
                break;
            case BTRFS_FREE_SPACE_TREE_OBJECTID:
                if (!skip)
                    printf("free space");
                break;
            case BTRFS_MULTIPLE_OBJECTIDS:
                if (!skip) {
                    printf("multiple");
                }
                break;
            default:
                if (!skip) {
                    printf("file");
                }
            }
            if (extent_only && !skip) {
                print_extents(tree_root_scan, buf);
            } else if (!skip) {
                printf(" tree ");
                btrfs_print_key(&disk_key);
                if (roots_only) {
                    printf(" %llu level %d\n",
                           (unsigned long long)buf->start,
                           btrfs_header_level(buf));
                } else {
                    printf(" \n");
                    btrfs_print_tree(tree_root_scan, buf, 1);
                }
            }
            free_extent_buffer(buf);
        }
next:
        path.slots[0]++;
    }
no_node:
    btrfs_release_path(&path);

    if (tree_root_scan == info->tree_root &&
            info->log_root_tree) {
        tree_root_scan = info->log_root_tree;
        goto again;
    }

    if (extent_only || device_only || uuid_tree_only)
        goto close_root;

    if (root_backups)
        print_old_roots(info->super_copy);

    printf("total bytes %llu\n",
           (unsigned long long)btrfs_super_total_bytes(info->super_copy));
    printf("bytes used %llu\n",
           (unsigned long long)btrfs_super_bytes_used(info->super_copy));
    uuidbuf[BTRFS_UUID_UNPARSED_SIZE - 1] = '\0';
    uuid_unparse(info->super_copy->fsid, uuidbuf);
    printf("uuid %s\n", uuidbuf);
    printf("%s\n", PACKAGE_STRING);
close_root:
    ret = close_ctree(root);
    btrfs_close_all_devices();
    return ret;
}
示例#7
0
int main(int ac, char **av)
{
	struct btrfs_root *root;
	struct btrfs_fs_info *info;
	struct btrfs_path path;
	struct btrfs_key key;
	struct btrfs_root_item ri;
	struct extent_buffer *leaf;
	struct btrfs_disk_key disk_key;
	struct btrfs_key found_key;
	char uuidbuf[37];
	int ret;
	int slot;
	int extent_only = 0;
	int device_only = 0;
	int roots_only = 0;
	int root_backups = 0;
	u64 block_only = 0;
	struct btrfs_root *tree_root_scan;

	radix_tree_init();

	while(1) {
		int c;
		c = getopt(ac, av, "deb:rR");
		if (c < 0)
			break;
		switch(c) {
			case 'e':
				extent_only = 1;
				break;
			case 'd':
				device_only = 1;
				break;
			case 'r':
				roots_only = 1;
				break;
			case 'R':
				roots_only = 1;
				root_backups = 1;
				break;
			case 'b':
				block_only = atoll(optarg);
				break;
			default:
				print_usage();
		}
	}
	ac = ac - optind;
	if (ac != 1)
		print_usage();

	info = open_ctree_fs_info(av[optind], 0, 0, 1);
	if (!info) {
		fprintf(stderr, "unable to open %s\n", av[optind]);
		exit(1);
	}
	root = info->fs_root;

	if (block_only) {
		if (!root) {
			fprintf(stderr, "unable to open %s\n", av[optind]);
			exit(1);
		}
		leaf = read_tree_block(root,
				      block_only,
				      root->leafsize, 0);

		if (leaf && btrfs_header_level(leaf) != 0) {
			free_extent_buffer(leaf);
			leaf = NULL;
		}

		if (!leaf) {
			leaf = read_tree_block(root,
					      block_only,
					      root->nodesize, 0);
		}
		if (!leaf) {
			fprintf(stderr, "failed to read %llu\n",
				(unsigned long long)block_only);
			return 0;
		}
		btrfs_print_tree(root, leaf, 0);
		return 0;
	}

	if (!extent_only) {
		if (roots_only) {
			printf("root tree: %llu level %d\n",
			     (unsigned long long)info->tree_root->node->start,
			     btrfs_header_level(info->tree_root->node));
			printf("chunk tree: %llu level %d\n",
			     (unsigned long long)info->chunk_root->node->start,
			     btrfs_header_level(info->chunk_root->node));
		} else {
			if (info->tree_root->node) {
				printf("root tree\n");
				btrfs_print_tree(info->tree_root,
						 info->tree_root->node, 1);
			}

			if (info->chunk_root->node) {
				printf("chunk tree\n");
				btrfs_print_tree(info->chunk_root,
						 info->chunk_root->node, 1);
			}
		}
	}
	tree_root_scan = info->tree_root;

	btrfs_init_path(&path);
again:
	if (!extent_buffer_uptodate(tree_root_scan->node))
		goto no_node;

	key.offset = 0;
	key.objectid = 0;
	btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY);
	ret = btrfs_search_slot(NULL, tree_root_scan, &key, &path, 0, 0);
	BUG_ON(ret < 0);
	while(1) {
		leaf = path.nodes[0];
		slot = path.slots[0];
		if (slot >= btrfs_header_nritems(leaf)) {
			ret = btrfs_next_leaf(tree_root_scan, &path);
			if (ret != 0)
				break;
			leaf = path.nodes[0];
			slot = path.slots[0];
		}
		btrfs_item_key(leaf, &disk_key, path.slots[0]);
		btrfs_disk_key_to_cpu(&found_key, &disk_key);
		if (btrfs_key_type(&found_key) == BTRFS_ROOT_ITEM_KEY) {
			unsigned long offset;
			struct extent_buffer *buf;
			int skip = extent_only | device_only;

			offset = btrfs_item_ptr_offset(leaf, slot);
			read_extent_buffer(leaf, &ri, offset, sizeof(ri));
			buf = read_tree_block(tree_root_scan,
					      btrfs_root_bytenr(&ri),
					      btrfs_level_size(tree_root_scan,
							btrfs_root_level(&ri)),
					      0);
			if (!extent_buffer_uptodate(buf))
				goto next;

			switch(found_key.objectid) {
			case BTRFS_ROOT_TREE_OBJECTID:
				if (!skip)
					printf("root");
				break;
			case BTRFS_EXTENT_TREE_OBJECTID:
				if (!device_only)
					skip = 0;
				if (!extent_only && !device_only)
					printf("extent");
				break;
			case BTRFS_CHUNK_TREE_OBJECTID:
				if (!skip) {
					printf("chunk");
				}
				break;
			case BTRFS_DEV_TREE_OBJECTID:
				skip = 0;
				printf("device");
				break;
			case BTRFS_FS_TREE_OBJECTID:
				if (!skip) {
					printf("fs");
				}
				break;
			case BTRFS_ROOT_TREE_DIR_OBJECTID:
				skip = 0;
				printf("directory");
				break;
			case BTRFS_CSUM_TREE_OBJECTID:
				if (!skip) {
					printf("checksum");
				}
				break;
			case BTRFS_ORPHAN_OBJECTID:
				if (!skip) {
					printf("orphan");
				}
				break;
			case BTRFS_TREE_LOG_OBJECTID:
				if (!skip) {
					printf("log");
				}
				break;
			case BTRFS_TREE_LOG_FIXUP_OBJECTID:
				if (!skip) {
					printf("log fixup");
				}
				break;
			case BTRFS_TREE_RELOC_OBJECTID:
				if (!skip) {
					printf("reloc");
				}
				break;
			case BTRFS_DATA_RELOC_TREE_OBJECTID:
				if (!skip) {
					printf("data reloc");
				}
				break;
			case BTRFS_EXTENT_CSUM_OBJECTID:
				if (!skip) {
					printf("extent checksum");
				}
				break;
			case BTRFS_QUOTA_TREE_OBJECTID:
				if (!skip) {
					printf("quota");
				}
				break;
			case BTRFS_MULTIPLE_OBJECTIDS:
				if (!skip) {
					printf("multiple");
				}
				break;
			default:
				if (!skip) {
					printf("file");
				}
			}
			if (extent_only && !skip) {
				print_extents(tree_root_scan, buf);
			} else if (!skip) {
				printf(" tree ");
				btrfs_print_key(&disk_key);
				if (roots_only) {
					printf(" %llu level %d\n",
					       (unsigned long long)buf->start,
					       btrfs_header_level(buf));
				} else {
					printf(" \n");
					btrfs_print_tree(tree_root_scan, buf, 1);
				}
			}
		}
next:
		path.slots[0]++;
	}
no_node:
	btrfs_release_path(root, &path);

	if (tree_root_scan == info->tree_root &&
	    info->log_root_tree) {
		tree_root_scan = info->log_root_tree;
		goto again;
	}

	if (extent_only || device_only)
		return 0;

	if (root_backups)
		print_old_roots(&info->super_copy);

	printf("total bytes %llu\n",
	       (unsigned long long)btrfs_super_total_bytes(&info->super_copy));
	printf("bytes used %llu\n",
	       (unsigned long long)btrfs_super_bytes_used(&info->super_copy));
	uuidbuf[36] = '\0';
	uuid_unparse(info->super_copy.fsid, uuidbuf);
	printf("uuid %s\n", uuidbuf);
	printf("%s\n", BTRFS_BUILD_VERSION);
	return 0;
}
示例#8
0
static int create_raid_groups(struct btrfs_trans_handle *trans,
			      struct btrfs_root *root, u64 data_profile,
			      int data_profile_opt, u64 metadata_profile,
			      int metadata_profile_opt, int mixed, int ssd,
			      int enospc_log)
{
	u64 num_devices = btrfs_super_num_devices(root->fs_info->super_copy);
	u64 allowed = 0;
	u64 devices_for_raid = num_devices;
	int ret;

	root = root->fs_info->extent_root;
	/*
	 * Set default profiles according to number of added devices.
	 * For mixed groups defaults are single/single.
	 */
	if (!metadata_profile_opt && !mixed) {
		if (num_devices == 1 && ssd)
			printf("Detected a SSD, turning off metadata "
			       "duplication.  Mkfs with -m dup if you want to "
			       "force metadata duplication.\n");
		metadata_profile = (num_devices > 1) ?
			BTRFS_BLOCK_GROUP_RAID1 : (ssd) ? 0: BTRFS_BLOCK_GROUP_DUP;
	}
	if (!data_profile_opt && !mixed) {
		data_profile = (num_devices > 1) ?
			BTRFS_BLOCK_GROUP_RAID0 : 0; /* raid0 or single */
	}

	if (devices_for_raid > 4)
		devices_for_raid = 4;

	switch (devices_for_raid) {
	default:
	case 4:
		allowed |= BTRFS_BLOCK_GROUP_RAID10;
	case 3:
		allowed |= BTRFS_BLOCK_GROUP_RAID6;
	case 2:
		allowed |= BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 |
			BTRFS_BLOCK_GROUP_RAID5;
		break;
	case 1:
		allowed |= BTRFS_BLOCK_GROUP_DUP;
	}

	if (metadata_profile & ~allowed) {
		fprintf(stderr,	"unable to create FS with metadata "
			"profile %llu (have %llu devices)\n", metadata_profile,
			num_devices);
		exit(1);
	}
	if (data_profile & ~allowed) {
		fprintf(stderr, "unable to create FS with data "
			"profile %llu (have %llu devices)\n", data_profile,
			num_devices);
		exit(1);
	}

	/* allow dup'ed data chunks only in mixed mode */
	if (!mixed && (data_profile & BTRFS_BLOCK_GROUP_DUP)) {
		fprintf(stderr, "dup for data is allowed only in mixed mode\n");
		exit(1);
	}

	if (allowed & metadata_profile) {
		u64 meta_flags = BTRFS_BLOCK_GROUP_METADATA;

		ret = create_one_raid_group(trans, root,
					    BTRFS_BLOCK_GROUP_SYSTEM |
					    (allowed & metadata_profile));
		BUG_ON(ret);

		if (mixed)
			meta_flags |= BTRFS_BLOCK_GROUP_DATA;

		ret = create_one_raid_group(trans, root, meta_flags |
					    (allowed & metadata_profile));
		BUG_ON(ret);

		ret = recow_roots(trans, root);
		BUG_ON(ret);
	}

	if (!mixed && enospc_log) {
		u64 total_bytes =
			btrfs_super_total_bytes(root->fs_info->super_copy);
		u64 alloced_bytes = 0;
		u64 alloc_flags = BTRFS_BLOCK_GROUP_ENOSPC |
			(allowed & metadata_profile);

		if (alloc_flags & (BTRFS_BLOCK_GROUP_RAID1 |
				   BTRFS_BLOCK_GROUP_DUP)) {
			total_bytes >>= 1;
		} else if (alloc_flags & (BTRFS_BLOCK_GROUP_RAID10)) {
static void dump_superblock(struct btrfs_super_block *sb, int full)
{
	int i;
	char *s, buf[BTRFS_UUID_UNPARSED_SIZE];
	u8 *p;
	u32 csum_size;
	u16 csum_type;
	bool metadata_uuid_present = (btrfs_super_incompat_flags(sb) &
		BTRFS_FEATURE_INCOMPAT_METADATA_UUID);
	int cmp_res = 0;


	csum_type = btrfs_super_csum_type(sb);
	csum_size = BTRFS_CSUM_SIZE;
	printf("csum_type\t\t%hu (", csum_type);
	if (csum_type >= ARRAY_SIZE(btrfs_csum_sizes)) {
		printf("INVALID");
	} else {
		if (csum_type == BTRFS_CSUM_TYPE_CRC32) {
			printf("crc32c");
			csum_size = btrfs_csum_sizes[csum_type];
		} else {
			printf("unknown");
		}
	}
	printf(")\n");
	printf("csum_size\t\t%llu\n", (unsigned long long)csum_size);

	printf("csum\t\t\t0x");
	for (i = 0, p = sb->csum; i < csum_size; i++)
		printf("%02x", p[i]);
	if (csum_type != BTRFS_CSUM_TYPE_CRC32 ||
	    csum_size != btrfs_csum_sizes[BTRFS_CSUM_TYPE_CRC32])
		printf(" [UNKNOWN CSUM TYPE OR SIZE]");
	else if (check_csum_sblock(sb, csum_size))
		printf(" [match]");
	else
		printf(" [DON'T MATCH]");
	putchar('\n');

	printf("bytenr\t\t\t%llu\n",
		(unsigned long long)btrfs_super_bytenr(sb));
	printf("flags\t\t\t0x%llx\n",
		(unsigned long long)btrfs_super_flags(sb));
	print_readable_super_flag(btrfs_super_flags(sb));

	printf("magic\t\t\t");
	s = (char *) &sb->magic;
	for (i = 0; i < 8; i++)
		putchar(isprint(s[i]) ? s[i] : '.');
	if (btrfs_super_magic(sb) == BTRFS_MAGIC)
		printf(" [match]\n");
	else
		printf(" [DON'T MATCH]\n");

	uuid_unparse(sb->fsid, buf);
	printf("fsid\t\t\t%s\n", buf);
	if (metadata_uuid_present) {
		uuid_unparse(sb->metadata_uuid, buf);
		printf("metadata_uuid\t\t%s\n", buf);
	} else {
		printf("metadata_uuid\t\t%s\n", buf);
	}

	printf("label\t\t\t");
	s = sb->label;
	for (i = 0; i < BTRFS_LABEL_SIZE && s[i]; i++)
		putchar(isprint(s[i]) ? s[i] : '.');
	putchar('\n');

	printf("generation\t\t%llu\n",
	       (unsigned long long)btrfs_super_generation(sb));
	printf("root\t\t\t%llu\n", (unsigned long long)btrfs_super_root(sb));
	printf("sys_array_size\t\t%llu\n",
	       (unsigned long long)btrfs_super_sys_array_size(sb));
	printf("chunk_root_generation\t%llu\n",
	       (unsigned long long)btrfs_super_chunk_root_generation(sb));
	printf("root_level\t\t%llu\n",
	       (unsigned long long)btrfs_super_root_level(sb));
	printf("chunk_root\t\t%llu\n",
	       (unsigned long long)btrfs_super_chunk_root(sb));
	printf("chunk_root_level\t%llu\n",
	       (unsigned long long)btrfs_super_chunk_root_level(sb));
	printf("log_root\t\t%llu\n",
	       (unsigned long long)btrfs_super_log_root(sb));
	printf("log_root_transid\t%llu\n",
	       (unsigned long long)btrfs_super_log_root_transid(sb));
	printf("log_root_level\t\t%llu\n",
	       (unsigned long long)btrfs_super_log_root_level(sb));
	printf("total_bytes\t\t%llu\n",
	       (unsigned long long)btrfs_super_total_bytes(sb));
	printf("bytes_used\t\t%llu\n",
	       (unsigned long long)btrfs_super_bytes_used(sb));
	printf("sectorsize\t\t%llu\n",
	       (unsigned long long)btrfs_super_sectorsize(sb));
	printf("nodesize\t\t%llu\n",
	       (unsigned long long)btrfs_super_nodesize(sb));
	printf("leafsize (deprecated)\t%u\n",
	       le32_to_cpu(sb->__unused_leafsize));
	printf("stripesize\t\t%llu\n",
	       (unsigned long long)btrfs_super_stripesize(sb));
	printf("root_dir\t\t%llu\n",
	       (unsigned long long)btrfs_super_root_dir(sb));
	printf("num_devices\t\t%llu\n",
	       (unsigned long long)btrfs_super_num_devices(sb));
	printf("compat_flags\t\t0x%llx\n",
	       (unsigned long long)btrfs_super_compat_flags(sb));
	printf("compat_ro_flags\t\t0x%llx\n",
	       (unsigned long long)btrfs_super_compat_ro_flags(sb));
	print_readable_compat_ro_flag(btrfs_super_compat_ro_flags(sb));
	printf("incompat_flags\t\t0x%llx\n",
	       (unsigned long long)btrfs_super_incompat_flags(sb));
	print_readable_incompat_flag(btrfs_super_incompat_flags(sb));
	printf("cache_generation\t%llu\n",
	       (unsigned long long)btrfs_super_cache_generation(sb));
	printf("uuid_tree_generation\t%llu\n",
	       (unsigned long long)btrfs_super_uuid_tree_generation(sb));

	uuid_unparse(sb->dev_item.uuid, buf);
	printf("dev_item.uuid\t\t%s\n", buf);

	uuid_unparse(sb->dev_item.fsid, buf);
	if (metadata_uuid_present) {
		cmp_res = !memcmp(sb->dev_item.fsid, sb->metadata_uuid,
				 BTRFS_FSID_SIZE);
	} else {
		cmp_res = !memcmp(sb->dev_item.fsid, sb->fsid, BTRFS_FSID_SIZE);
	}
	printf("dev_item.fsid\t\t%s %s\n", buf,
	       cmp_res ? "[match]" : "[DON'T MATCH]");

	printf("dev_item.type\t\t%llu\n", (unsigned long long)
	       btrfs_stack_device_type(&sb->dev_item));
	printf("dev_item.total_bytes\t%llu\n", (unsigned long long)
	       btrfs_stack_device_total_bytes(&sb->dev_item));
	printf("dev_item.bytes_used\t%llu\n", (unsigned long long)
	       btrfs_stack_device_bytes_used(&sb->dev_item));
	printf("dev_item.io_align\t%u\n", (unsigned int)
	       btrfs_stack_device_io_align(&sb->dev_item));
	printf("dev_item.io_width\t%u\n", (unsigned int)
	       btrfs_stack_device_io_width(&sb->dev_item));
	printf("dev_item.sector_size\t%u\n", (unsigned int)
	       btrfs_stack_device_sector_size(&sb->dev_item));
	printf("dev_item.devid\t\t%llu\n",
	       btrfs_stack_device_id(&sb->dev_item));
	printf("dev_item.dev_group\t%u\n", (unsigned int)
	       btrfs_stack_device_group(&sb->dev_item));
	printf("dev_item.seek_speed\t%u\n", (unsigned int)
	       btrfs_stack_device_seek_speed(&sb->dev_item));
	printf("dev_item.bandwidth\t%u\n", (unsigned int)
	       btrfs_stack_device_bandwidth(&sb->dev_item));
	printf("dev_item.generation\t%llu\n", (unsigned long long)
	       btrfs_stack_device_generation(&sb->dev_item));
	if (full) {
		printf("sys_chunk_array[%d]:\n", BTRFS_SYSTEM_CHUNK_ARRAY_SIZE);
		print_sys_chunk_array(sb);
		printf("backup_roots[%d]:\n", BTRFS_NUM_BACKUP_ROOTS);
		print_backup_roots(sb);
	}
}