int __add_to_free_space_tree(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info, struct btrfs_block_group_cache *block_group, struct btrfs_path *path, u64 start, u64 size) { struct btrfs_free_space_info *info; u32 flags; int ret; if (block_group->needs_free_space) { ret = __add_block_group_free_space(trans, fs_info, block_group, path); if (ret) return ret; } info = search_free_space_info(NULL, fs_info, block_group, path, 0); if (IS_ERR(info)) return PTR_ERR(info); flags = btrfs_free_space_flags(path->nodes[0], info); btrfs_release_path(path); if (flags & BTRFS_FREE_SPACE_USING_BITMAPS) { return modify_free_space_bitmap(trans, fs_info, block_group, path, start, size, 0); } else { return add_free_space_extent(trans, fs_info, block_group, path, start, size); } }
int load_free_space_tree(struct btrfs_caching_control *caching_ctl) { struct btrfs_block_group_cache *block_group; struct btrfs_fs_info *fs_info; struct btrfs_free_space_info *info; struct btrfs_path *path; u32 extent_count, flags; int ret; block_group = caching_ctl->block_group; fs_info = block_group->fs_info; path = btrfs_alloc_path(); if (!path) return -ENOMEM; /* * Just like caching_thread() doesn't want to deadlock on the extent * tree, we don't want to deadlock on the free space tree. */ path->skip_locking = 1; path->search_commit_root = 1; path->reada = 1; info = search_free_space_info(NULL, fs_info, block_group, path, 0); if (IS_ERR(info)) { ret = PTR_ERR(info); goto out; } extent_count = btrfs_free_space_extent_count(path->nodes[0], info); flags = btrfs_free_space_flags(path->nodes[0], info); /* * We left path pointing to the free space info item, so now * load_free_space_foo can just iterate through the free space tree from * there. */ if (flags & BTRFS_FREE_SPACE_USING_BITMAPS) ret = load_free_space_bitmaps(caching_ctl, path, extent_count); else ret = load_free_space_extents(caching_ctl, path, extent_count); out: btrfs_free_path(path); return ret; }
static int check_free_space_extents(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info, struct btrfs_block_group_cache *cache, struct btrfs_path *path, struct free_space_extent *extents, unsigned int num_extents) { struct btrfs_free_space_info *info; u32 flags; int ret; info = search_free_space_info(trans, fs_info, cache, path, 0); if (IS_ERR(info)) { test_msg("Could not find free space info\n"); btrfs_release_path(path); return PTR_ERR(info); } flags = btrfs_free_space_flags(path->nodes[0], info); btrfs_release_path(path); ret = __check_free_space_extents(trans, fs_info, cache, path, extents, num_extents); if (ret) return ret; /* Flip it to the other format and check that for good measure. */ if (flags & BTRFS_FREE_SPACE_USING_BITMAPS) { ret = convert_free_space_to_extents(trans, fs_info, cache, path); if (ret) { test_msg("Could not convert to extents\n"); return ret; } } else { ret = convert_free_space_to_bitmaps(trans, fs_info, cache, path); if (ret) { test_msg("Could not convert to bitmaps\n"); return ret; } } return __check_free_space_extents(trans, fs_info, cache, path, extents, num_extents); }
static int update_free_space_extent_count(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info, struct btrfs_block_group_cache *block_group, struct btrfs_path *path, int new_extents) { struct btrfs_free_space_info *info; u32 flags; u32 extent_count; int ret = 0; if (new_extents == 0) return 0; info = search_free_space_info(trans, fs_info, block_group, path, 1); if (IS_ERR(info)) { ret = PTR_ERR(info); goto out; } flags = btrfs_free_space_flags(path->nodes[0], info); extent_count = btrfs_free_space_extent_count(path->nodes[0], info); extent_count += new_extents; btrfs_set_free_space_extent_count(path->nodes[0], info, extent_count); btrfs_mark_buffer_dirty(path->nodes[0]); btrfs_release_path(path); if (!(flags & BTRFS_FREE_SPACE_USING_BITMAPS) && extent_count > block_group->bitmap_high_thresh) { ret = convert_free_space_to_bitmaps(trans, fs_info, block_group, path); } else if ((flags & BTRFS_FREE_SPACE_USING_BITMAPS) && extent_count < block_group->bitmap_low_thresh) { ret = convert_free_space_to_extents(trans, fs_info, block_group, path); } out: return ret; }
int convert_free_space_to_extents(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info, struct btrfs_block_group_cache *block_group, struct btrfs_path *path) { struct btrfs_root *root = fs_info->free_space_root; struct btrfs_free_space_info *info; struct btrfs_key key, found_key; struct extent_buffer *leaf; unsigned long *bitmap; u64 start, end; /* Initialize to silence GCC. */ u64 extent_start = 0; u64 offset; u32 bitmap_size, flags, expected_extent_count; int prev_bit = 0, bit, bitnr; u32 extent_count = 0; int done = 0, nr; int ret; bitmap_size = free_space_bitmap_size(block_group->key.offset, block_group->sectorsize); bitmap = alloc_bitmap(bitmap_size); if (!bitmap) { ret = -ENOMEM; goto out; } start = block_group->key.objectid; end = block_group->key.objectid + block_group->key.offset; key.objectid = end - 1; key.type = (u8)-1; key.offset = (u64)-1; while (!done) { ret = btrfs_search_prev_slot(trans, root, &key, path, -1, 1); if (ret) goto out; leaf = path->nodes[0]; nr = 0; path->slots[0]++; while (path->slots[0] > 0) { btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0] - 1); if (found_key.type == BTRFS_FREE_SPACE_INFO_KEY) { ASSERT(found_key.objectid == block_group->key.objectid); ASSERT(found_key.offset == block_group->key.offset); done = 1; break; } else if (found_key.type == BTRFS_FREE_SPACE_BITMAP_KEY) { unsigned long ptr; char *bitmap_cursor; u32 bitmap_pos, data_size; ASSERT(found_key.objectid >= start); ASSERT(found_key.objectid < end); ASSERT(found_key.objectid + found_key.offset <= end); bitmap_pos = div_u64(found_key.objectid - start, block_group->sectorsize * BITS_PER_BYTE); bitmap_cursor = ((char *)bitmap) + bitmap_pos; data_size = free_space_bitmap_size(found_key.offset, block_group->sectorsize); ptr = btrfs_item_ptr_offset(leaf, path->slots[0] - 1); read_extent_buffer(leaf, bitmap_cursor, ptr, data_size); nr++; path->slots[0]--; } else { ASSERT(0); } } ret = btrfs_del_items(trans, root, path, path->slots[0], nr); if (ret) goto out; btrfs_release_path(path); } info = search_free_space_info(trans, fs_info, block_group, path, 1); if (IS_ERR(info)) { ret = PTR_ERR(info); goto out; } leaf = path->nodes[0]; flags = btrfs_free_space_flags(leaf, info); flags &= ~BTRFS_FREE_SPACE_USING_BITMAPS; btrfs_set_free_space_flags(leaf, info, flags); expected_extent_count = btrfs_free_space_extent_count(leaf, info); btrfs_mark_buffer_dirty(leaf); btrfs_release_path(path); offset = start; bitnr = 0; while (offset < end) { bit = !!test_bit(bitnr, bitmap); if (prev_bit == 0 && bit == 1) { extent_start = offset; } else if (prev_bit == 1 && bit == 0) { key.objectid = extent_start; key.type = BTRFS_FREE_SPACE_EXTENT_KEY; key.offset = offset - extent_start; ret = btrfs_insert_empty_item(trans, root, path, &key, 0); if (ret) goto out; btrfs_release_path(path); extent_count++; } prev_bit = bit; offset += block_group->sectorsize; bitnr++; } if (prev_bit == 1) { key.objectid = extent_start; key.type = BTRFS_FREE_SPACE_EXTENT_KEY; key.offset = end - extent_start; ret = btrfs_insert_empty_item(trans, root, path, &key, 0); if (ret) goto out; btrfs_release_path(path); extent_count++; } if (extent_count != expected_extent_count) { btrfs_err(fs_info, "incorrect extent count for %llu; counted %u, expected %u", block_group->key.objectid, extent_count, expected_extent_count); ASSERT(0); ret = -EIO; goto out; } ret = 0; out: kvfree(bitmap); if (ret) btrfs_abort_transaction(trans, ret); return ret; }
int convert_free_space_to_bitmaps(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info, struct btrfs_block_group_cache *block_group, struct btrfs_path *path) { struct btrfs_root *root = fs_info->free_space_root; struct btrfs_free_space_info *info; struct btrfs_key key, found_key; struct extent_buffer *leaf; unsigned long *bitmap; char *bitmap_cursor; u64 start, end; u64 bitmap_range, i; u32 bitmap_size, flags, expected_extent_count; u32 extent_count = 0; int done = 0, nr; int ret; bitmap_size = free_space_bitmap_size(block_group->key.offset, block_group->sectorsize); bitmap = alloc_bitmap(bitmap_size); if (!bitmap) { ret = -ENOMEM; goto out; } start = block_group->key.objectid; end = block_group->key.objectid + block_group->key.offset; key.objectid = end - 1; key.type = (u8)-1; key.offset = (u64)-1; while (!done) { ret = btrfs_search_prev_slot(trans, root, &key, path, -1, 1); if (ret) goto out; leaf = path->nodes[0]; nr = 0; path->slots[0]++; while (path->slots[0] > 0) { btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0] - 1); if (found_key.type == BTRFS_FREE_SPACE_INFO_KEY) { ASSERT(found_key.objectid == block_group->key.objectid); ASSERT(found_key.offset == block_group->key.offset); done = 1; break; } else if (found_key.type == BTRFS_FREE_SPACE_EXTENT_KEY) { u64 first, last; ASSERT(found_key.objectid >= start); ASSERT(found_key.objectid < end); ASSERT(found_key.objectid + found_key.offset <= end); first = div_u64(found_key.objectid - start, block_group->sectorsize); last = div_u64(found_key.objectid + found_key.offset - start, block_group->sectorsize); bitmap_set(bitmap, first, last - first); extent_count++; nr++; path->slots[0]--; } else { ASSERT(0); } } ret = btrfs_del_items(trans, root, path, path->slots[0], nr); if (ret) goto out; btrfs_release_path(path); } info = search_free_space_info(trans, fs_info, block_group, path, 1); if (IS_ERR(info)) { ret = PTR_ERR(info); goto out; } leaf = path->nodes[0]; flags = btrfs_free_space_flags(leaf, info); flags |= BTRFS_FREE_SPACE_USING_BITMAPS; btrfs_set_free_space_flags(leaf, info, flags); expected_extent_count = btrfs_free_space_extent_count(leaf, info); btrfs_mark_buffer_dirty(leaf); btrfs_release_path(path); if (extent_count != expected_extent_count) { btrfs_err(fs_info, "incorrect extent count for %llu; counted %u, expected %u", block_group->key.objectid, extent_count, expected_extent_count); ASSERT(0); ret = -EIO; goto out; } bitmap_cursor = (char *)bitmap; bitmap_range = block_group->sectorsize * BTRFS_FREE_SPACE_BITMAP_BITS; i = start; while (i < end) { unsigned long ptr; u64 extent_size; u32 data_size; extent_size = min(end - i, bitmap_range); data_size = free_space_bitmap_size(extent_size, block_group->sectorsize); key.objectid = i; key.type = BTRFS_FREE_SPACE_BITMAP_KEY; key.offset = extent_size; ret = btrfs_insert_empty_item(trans, root, path, &key, data_size); if (ret) goto out; leaf = path->nodes[0]; ptr = btrfs_item_ptr_offset(leaf, path->slots[0]); write_extent_buffer(leaf, bitmap_cursor, ptr, data_size); btrfs_mark_buffer_dirty(leaf); btrfs_release_path(path); i += extent_size; bitmap_cursor += data_size; } ret = 0; out: kvfree(bitmap); if (ret) btrfs_abort_transaction(trans, ret); return ret; }
static int __check_free_space_extents(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info, struct btrfs_block_group_cache *cache, struct btrfs_path *path, struct free_space_extent *extents, unsigned int num_extents) { struct btrfs_free_space_info *info; struct btrfs_key key; int prev_bit = 0, bit; u64 extent_start = 0, offset, end; u32 flags, extent_count; unsigned int i; int ret; info = search_free_space_info(trans, fs_info, cache, path, 0); if (IS_ERR(info)) { test_msg("Could not find free space info\n"); ret = PTR_ERR(info); goto out; } flags = btrfs_free_space_flags(path->nodes[0], info); extent_count = btrfs_free_space_extent_count(path->nodes[0], info); if (extent_count != num_extents) { test_msg("Extent count is wrong\n"); ret = -EINVAL; goto out; } if (flags & BTRFS_FREE_SPACE_USING_BITMAPS) { if (path->slots[0] != 0) goto invalid; end = cache->key.objectid + cache->key.offset; i = 0; while (++path->slots[0] < btrfs_header_nritems(path->nodes[0])) { btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]); if (key.type != BTRFS_FREE_SPACE_BITMAP_KEY) goto invalid; offset = key.objectid; while (offset < key.objectid + key.offset) { bit = free_space_test_bit(cache, path, offset); if (prev_bit == 0 && bit == 1) { extent_start = offset; } else if (prev_bit == 1 && bit == 0) { if (i >= num_extents) goto invalid; if (i >= num_extents || extent_start != extents[i].start || offset - extent_start != extents[i].length) goto invalid; i++; } prev_bit = bit; offset += cache->sectorsize; } } if (prev_bit == 1) { if (i >= num_extents || extent_start != extents[i].start || end - extent_start != extents[i].length) goto invalid; i++; } if (i != num_extents) goto invalid; } else { if (btrfs_header_nritems(path->nodes[0]) != num_extents + 1 || path->slots[0] != 0) goto invalid; for (i = 0; i < num_extents; i++) { path->slots[0]++; btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]); if (key.type != BTRFS_FREE_SPACE_EXTENT_KEY || key.objectid != extents[i].start || key.offset != extents[i].length) goto invalid; } } ret = 0; out: btrfs_release_path(path); return ret; invalid: test_msg("Free space tree is invalid\n"); ret = -EINVAL; goto out; }
void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *eb) { struct btrfs_item *item; struct btrfs_disk_key disk_key; u32 i; u32 nr; nr = btrfs_header_nritems(eb); printf("leaf %llu items %d free space %d generation %llu owner %llu\n", (unsigned long long)btrfs_header_bytenr(eb), nr, btrfs_leaf_free_space(root, eb), (unsigned long long)btrfs_header_generation(eb), (unsigned long long)btrfs_header_owner(eb)); print_uuids(eb); fflush(stdout); for (i = 0; i < nr; i++) { u32 item_size; void *ptr; u64 objectid; u32 type; u64 offset; char flags_str[256]; char uuid_str[BTRFS_UUID_UNPARSED_SIZE]; u8 uuid[BTRFS_UUID_SIZE]; item = btrfs_item_nr(i); item_size = btrfs_item_size(eb, item); /* Untyped extraction of slot from btrfs_item_ptr */ ptr = btrfs_item_ptr(eb, i, void*); btrfs_item_key(eb, &disk_key, i); objectid = btrfs_disk_key_objectid(&disk_key); type = btrfs_disk_key_type(&disk_key); offset = btrfs_disk_key_offset(&disk_key); printf("\titem %d ", i); btrfs_print_key(&disk_key); printf(" itemoff %d itemsize %d\n", btrfs_item_offset(eb, item), btrfs_item_size(eb, item)); if (type == 0 && objectid == BTRFS_FREE_SPACE_OBJECTID) print_free_space_header(eb, i); switch (type) { case BTRFS_INODE_ITEM_KEY: print_inode_item(eb, ptr); break; case BTRFS_INODE_REF_KEY: print_inode_ref_item(eb, item_size, ptr); break; case BTRFS_INODE_EXTREF_KEY: print_inode_extref_item(eb, item_size, ptr); break; case BTRFS_DIR_ITEM_KEY: case BTRFS_DIR_INDEX_KEY: case BTRFS_XATTR_ITEM_KEY: print_dir_item(eb, item_size, ptr); break; case BTRFS_DIR_LOG_INDEX_KEY: case BTRFS_DIR_LOG_ITEM_KEY: { struct btrfs_dir_log_item *dlog; dlog = btrfs_item_ptr(eb, i, struct btrfs_dir_log_item); printf("\t\tdir log end %Lu\n", (unsigned long long)btrfs_dir_log_end(eb, dlog)); break; } case BTRFS_ORPHAN_ITEM_KEY: printf("\t\torphan item\n"); break; case BTRFS_ROOT_ITEM_KEY: print_root(eb, i); break; case BTRFS_ROOT_REF_KEY: print_root_ref(eb, i, "ref"); break; case BTRFS_ROOT_BACKREF_KEY: print_root_ref(eb, i, "backref"); break; case BTRFS_EXTENT_ITEM_KEY: print_extent_item(eb, i, 0); break; case BTRFS_METADATA_ITEM_KEY: print_extent_item(eb, i, 1); break; case BTRFS_TREE_BLOCK_REF_KEY: printf("\t\ttree block backref\n"); break; case BTRFS_SHARED_BLOCK_REF_KEY: printf("\t\tshared block backref\n"); break; case BTRFS_EXTENT_DATA_REF_KEY: { struct btrfs_extent_data_ref *dref; dref = btrfs_item_ptr(eb, i, struct btrfs_extent_data_ref); printf("\t\textent data backref root %llu " "objectid %llu offset %llu count %u\n", (unsigned long long)btrfs_extent_data_ref_root(eb, dref), (unsigned long long)btrfs_extent_data_ref_objectid(eb, dref), (unsigned long long)btrfs_extent_data_ref_offset(eb, dref), btrfs_extent_data_ref_count(eb, dref)); break; } case BTRFS_SHARED_DATA_REF_KEY: { struct btrfs_shared_data_ref *sref; sref = btrfs_item_ptr(eb, i, struct btrfs_shared_data_ref); printf("\t\tshared data backref count %u\n", btrfs_shared_data_ref_count(eb, sref)); break; } case BTRFS_EXTENT_REF_V0_KEY: #ifdef BTRFS_COMPAT_EXTENT_TREE_V0 print_extent_ref_v0(eb, i); #else BUG(); #endif break; case BTRFS_CSUM_ITEM_KEY: printf("\t\tcsum item\n"); break; case BTRFS_EXTENT_CSUM_KEY: printf("\t\textent csum item\n"); break; case BTRFS_EXTENT_DATA_KEY: print_file_extent_item(eb, item, i, ptr); break; case BTRFS_BLOCK_GROUP_ITEM_KEY: { struct btrfs_block_group_item bg_item; read_extent_buffer(eb, &bg_item, (unsigned long)ptr, sizeof(bg_item)); memset(flags_str, 0, sizeof(flags_str)); bg_flags_to_str(btrfs_block_group_flags(&bg_item), flags_str); printf("\t\tblock group used %llu chunk_objectid %llu flags %s\n", (unsigned long long)btrfs_block_group_used(&bg_item), (unsigned long long)btrfs_block_group_chunk_objectid(&bg_item), flags_str); break; } case BTRFS_FREE_SPACE_INFO_KEY: { struct btrfs_free_space_info *free_info; free_info = btrfs_item_ptr(eb, i, struct btrfs_free_space_info); printf("\t\tfree space info extent count %u flags %u\n", (unsigned)btrfs_free_space_extent_count(eb, free_info), (unsigned)btrfs_free_space_flags(eb, free_info)); break; } case BTRFS_FREE_SPACE_EXTENT_KEY: printf("\t\tfree space extent\n"); break; case BTRFS_FREE_SPACE_BITMAP_KEY: printf("\t\tfree space bitmap\n"); break; case BTRFS_CHUNK_ITEM_KEY: print_chunk(eb, ptr); break; case BTRFS_DEV_ITEM_KEY: print_dev_item(eb, ptr); break; case BTRFS_DEV_EXTENT_KEY: { struct btrfs_dev_extent *dev_extent; dev_extent = btrfs_item_ptr(eb, i, struct btrfs_dev_extent); read_extent_buffer(eb, uuid, (unsigned long)btrfs_dev_extent_chunk_tree_uuid(dev_extent), BTRFS_UUID_SIZE); uuid_unparse(uuid, uuid_str); printf("\t\tdev extent chunk_tree %llu\n" "\t\tchunk_objectid %llu chunk_offset %llu " "length %llu\n" "\t\tchunk_tree_uuid %s\n", (unsigned long long) btrfs_dev_extent_chunk_tree(eb, dev_extent), (unsigned long long) btrfs_dev_extent_chunk_objectid(eb, dev_extent), (unsigned long long) btrfs_dev_extent_chunk_offset(eb, dev_extent), (unsigned long long) btrfs_dev_extent_length(eb, dev_extent), uuid_str); break; } case BTRFS_QGROUP_STATUS_KEY: { struct btrfs_qgroup_status_item *qg_status; qg_status = btrfs_item_ptr(eb, i, struct btrfs_qgroup_status_item); memset(flags_str, 0, sizeof(flags_str)); qgroup_flags_to_str(btrfs_qgroup_status_flags(eb, qg_status), flags_str); printf("\t\tversion %llu generation %llu flags %s " "scan %lld\n", (unsigned long long) btrfs_qgroup_status_version(eb, qg_status), (unsigned long long) btrfs_qgroup_status_generation(eb, qg_status), flags_str, (unsigned long long) btrfs_qgroup_status_rescan(eb, qg_status)); break; } case BTRFS_QGROUP_RELATION_KEY: break; case BTRFS_QGROUP_INFO_KEY: { struct btrfs_qgroup_info_item *qg_info; qg_info = btrfs_item_ptr(eb, i, struct btrfs_qgroup_info_item); printf("\t\tgeneration %llu\n" "\t\treferenced %llu referenced_compressed %llu\n" "\t\texclusive %llu exclusive_compressed %llu\n", (unsigned long long) btrfs_qgroup_info_generation(eb, qg_info), (unsigned long long) btrfs_qgroup_info_referenced(eb, qg_info), (unsigned long long) btrfs_qgroup_info_referenced_compressed(eb, qg_info), (unsigned long long) btrfs_qgroup_info_exclusive(eb, qg_info), (unsigned long long) btrfs_qgroup_info_exclusive_compressed(eb, qg_info)); break; } case BTRFS_QGROUP_LIMIT_KEY: { struct btrfs_qgroup_limit_item *qg_limit; qg_limit = btrfs_item_ptr(eb, i, struct btrfs_qgroup_limit_item); printf("\t\tflags %llx\n" "\t\tmax_referenced %lld max_exclusive %lld\n" "\t\trsv_referenced %lld rsv_exclusive %lld\n", (unsigned long long) btrfs_qgroup_limit_flags(eb, qg_limit), (long long) btrfs_qgroup_limit_max_referenced(eb, qg_limit), (long long) btrfs_qgroup_limit_max_exclusive(eb, qg_limit), (long long) btrfs_qgroup_limit_rsv_referenced(eb, qg_limit), (long long) btrfs_qgroup_limit_rsv_exclusive(eb, qg_limit)); break; } case BTRFS_UUID_KEY_SUBVOL: case BTRFS_UUID_KEY_RECEIVED_SUBVOL: print_uuid_item(eb, btrfs_item_ptr_offset(eb, i), btrfs_item_size_nr(eb, i)); break; case BTRFS_STRING_ITEM_KEY: { const char *str = eb->data + btrfs_item_ptr_offset(eb, i); printf("\t\titem data %.*s\n", item_size, str); break; } case BTRFS_PERSISTENT_ITEM_KEY: printf("\t\tpersistent item objectid "); print_objectid(stdout, objectid, BTRFS_PERSISTENT_ITEM_KEY); printf(" offset %llu\n", (unsigned long long)offset); switch (objectid) { case BTRFS_DEV_STATS_OBJECTID: print_dev_stats(eb, ptr, item_size); break; default: printf("\t\tunknown persistent item objectid %llu\n", objectid); } break; case BTRFS_TEMPORARY_ITEM_KEY: printf("\t\ttemporary item objectid "); print_objectid(stdout, objectid, BTRFS_TEMPORARY_ITEM_KEY); printf(" offset %llu\n", (unsigned long long)offset); switch (objectid) { case BTRFS_BALANCE_OBJECTID: print_balance_item(eb, ptr); break; default: printf("\t\tunknown temporary item objectid %llu\n", objectid); } break; }; fflush(stdout); } }