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); } }
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; }
static struct btrfs_fs_info *__open_ctree_fd(int fp, const char *path, u64 sb_bytenr, u64 root_tree_bytenr, int writes, int partial) { u32 sectorsize; u32 nodesize; u32 leafsize; u32 blocksize; u32 stripesize; u64 generation; struct btrfs_key key; struct btrfs_root *tree_root = malloc(sizeof(struct btrfs_root)); struct btrfs_root *extent_root = malloc(sizeof(struct btrfs_root)); struct btrfs_root *chunk_root = malloc(sizeof(struct btrfs_root)); struct btrfs_root *dev_root = malloc(sizeof(struct btrfs_root)); struct btrfs_root *csum_root = malloc(sizeof(struct btrfs_root)); struct btrfs_fs_info *fs_info = malloc(sizeof(*fs_info)); int ret; struct btrfs_super_block *disk_super; struct btrfs_fs_devices *fs_devices = NULL; u64 total_devs; u64 features; if (sb_bytenr == 0) sb_bytenr = BTRFS_SUPER_INFO_OFFSET; /* try to drop all the caches */ if (posix_fadvise(fp, 0, 0, POSIX_FADV_DONTNEED)) fprintf(stderr, "Warning, could not drop caches\n"); ret = btrfs_scan_one_device(fp, path, &fs_devices, &total_devs, sb_bytenr); if (ret) { fprintf(stderr, "No valid Btrfs found on %s\n", path); goto out; } if (total_devs != 1) { ret = btrfs_scan_for_fsid(fs_devices, total_devs, 1); if (ret) goto out; } memset(fs_info, 0, sizeof(*fs_info)); fs_info->super_copy = calloc(1, BTRFS_SUPER_INFO_SIZE); fs_info->tree_root = tree_root; fs_info->extent_root = extent_root; fs_info->chunk_root = chunk_root; fs_info->dev_root = dev_root; fs_info->csum_root = csum_root; if (!writes) fs_info->readonly = 1; extent_io_tree_init(&fs_info->extent_cache); extent_io_tree_init(&fs_info->free_space_cache); extent_io_tree_init(&fs_info->block_group_cache); extent_io_tree_init(&fs_info->pinned_extents); extent_io_tree_init(&fs_info->pending_del); extent_io_tree_init(&fs_info->extent_ins); cache_tree_init(&fs_info->fs_root_cache); cache_tree_init(&fs_info->mapping_tree.cache_tree); mutex_init(&fs_info->fs_mutex); fs_info->fs_devices = fs_devices; INIT_LIST_HEAD(&fs_info->dirty_cowonly_roots); INIT_LIST_HEAD(&fs_info->space_info); __setup_root(4096, 4096, 4096, 4096, tree_root, fs_info, BTRFS_ROOT_TREE_OBJECTID); if (writes) ret = btrfs_open_devices(fs_devices, O_RDWR); else ret = btrfs_open_devices(fs_devices, O_RDONLY); if (ret) goto out_cleanup; fs_info->super_bytenr = sb_bytenr; disk_super = fs_info->super_copy; ret = btrfs_read_dev_super(fs_devices->latest_bdev, disk_super, sb_bytenr); if (ret) { printk("No valid btrfs found\n"); goto out_devices; } memcpy(fs_info->fsid, &disk_super->fsid, BTRFS_FSID_SIZE); features = btrfs_super_incompat_flags(disk_super) & ~BTRFS_FEATURE_INCOMPAT_SUPP; if (features) { printk("couldn't open because of unsupported " "option features (%Lx).\n", (unsigned long long)features); goto out_devices; } features = btrfs_super_incompat_flags(disk_super); if (!(features & BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF)) { features |= BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF; btrfs_set_super_incompat_flags(disk_super, features); } features = btrfs_super_compat_ro_flags(disk_super) & ~BTRFS_FEATURE_COMPAT_RO_SUPP; if (writes && features) { printk("couldn't open RDWR because of unsupported " "option features (%Lx).\n", (unsigned long long)features); goto out_devices; } nodesize = btrfs_super_nodesize(disk_super); leafsize = btrfs_super_leafsize(disk_super); sectorsize = btrfs_super_sectorsize(disk_super); stripesize = btrfs_super_stripesize(disk_super); tree_root->nodesize = nodesize; tree_root->leafsize = leafsize; tree_root->sectorsize = sectorsize; tree_root->stripesize = stripesize; ret = btrfs_read_sys_array(tree_root); if (ret) goto out_devices; blocksize = btrfs_level_size(tree_root, btrfs_super_chunk_root_level(disk_super)); generation = btrfs_super_chunk_root_generation(disk_super); __setup_root(nodesize, leafsize, sectorsize, stripesize, chunk_root, fs_info, BTRFS_CHUNK_TREE_OBJECTID); chunk_root->node = read_tree_block(chunk_root, btrfs_super_chunk_root(disk_super), blocksize, generation); if (!extent_buffer_uptodate(chunk_root->node)) { printk("Couldn't read chunk root\n"); goto out_devices; } read_extent_buffer(chunk_root->node, fs_info->chunk_tree_uuid, (unsigned long)btrfs_header_chunk_tree_uuid(chunk_root->node), BTRFS_UUID_SIZE); if (!(btrfs_super_flags(disk_super) & BTRFS_SUPER_FLAG_METADUMP)) { ret = btrfs_read_chunk_tree(chunk_root); if (ret) { printk("Couldn't read chunk tree\n"); goto out_chunk; } } blocksize = btrfs_level_size(tree_root, btrfs_super_root_level(disk_super)); generation = btrfs_super_generation(disk_super); if (!root_tree_bytenr) root_tree_bytenr = btrfs_super_root(disk_super); tree_root->node = read_tree_block(tree_root, root_tree_bytenr, blocksize, generation); if (!extent_buffer_uptodate(tree_root->node)) { printk("Couldn't read tree root\n"); goto out_failed; } ret = find_and_setup_root(tree_root, fs_info, BTRFS_EXTENT_TREE_OBJECTID, extent_root); if (ret) { printk("Couldn't setup extent tree\n"); goto out_failed; } extent_root->track_dirty = 1; ret = find_and_setup_root(tree_root, fs_info, BTRFS_DEV_TREE_OBJECTID, dev_root); if (ret) { printk("Couldn't setup device tree\n"); goto out_failed; } dev_root->track_dirty = 1; ret = find_and_setup_root(tree_root, fs_info, BTRFS_CSUM_TREE_OBJECTID, csum_root); if (ret) { printk("Couldn't setup csum tree\n"); if (!partial) goto out_failed; } csum_root->track_dirty = 1; find_and_setup_log_root(tree_root, fs_info, disk_super); fs_info->generation = generation; fs_info->last_trans_committed = generation; btrfs_read_block_groups(fs_info->tree_root); key.objectid = BTRFS_FS_TREE_OBJECTID; key.type = BTRFS_ROOT_ITEM_KEY; key.offset = (u64)-1; fs_info->fs_root = btrfs_read_fs_root(fs_info, &key); if (!fs_info->fs_root) goto out_failed; fs_info->data_alloc_profile = (u64)-1; fs_info->metadata_alloc_profile = (u64)-1; fs_info->system_alloc_profile = fs_info->metadata_alloc_profile; return fs_info; out_failed: if (partial) return fs_info; if (fs_info->csum_root) free_extent_buffer(fs_info->csum_root->node); if (fs_info->dev_root) free_extent_buffer(fs_info->dev_root->node); if (fs_info->extent_root) free_extent_buffer(fs_info->extent_root->node); if (fs_info->tree_root) free_extent_buffer(fs_info->tree_root->node); out_chunk: if (fs_info->chunk_root) free_extent_buffer(fs_info->chunk_root->node); out_devices: close_all_devices(fs_info); out_cleanup: extent_io_tree_cleanup(&fs_info->extent_cache); extent_io_tree_cleanup(&fs_info->free_space_cache); extent_io_tree_cleanup(&fs_info->block_group_cache); extent_io_tree_cleanup(&fs_info->pinned_extents); extent_io_tree_cleanup(&fs_info->pending_del); extent_io_tree_cleanup(&fs_info->extent_ins); out: free(tree_root); free(extent_root); free(chunk_root); free(dev_root); free(csum_root); free(fs_info); return NULL; }
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); } }