static void print_file_extent_item(struct extent_buffer *eb, struct btrfs_item *item, struct btrfs_file_extent_item *fi) { int extent_type = btrfs_file_extent_type(eb, fi); if (extent_type == BTRFS_FILE_EXTENT_INLINE) { printf("\t\tinline extent data size %u " "ram %u compress %d\n", btrfs_file_extent_inline_item_len(eb, item), btrfs_file_extent_inline_len(eb, fi), btrfs_file_extent_compression(eb, fi)); return; } if (extent_type == BTRFS_FILE_EXTENT_PREALLOC) { printf("\t\tprealloc data disk byte %llu nr %llu\n", (unsigned long long)btrfs_file_extent_disk_bytenr(eb, fi), (unsigned long long)btrfs_file_extent_disk_num_bytes(eb, fi)); printf("\t\tprealloc data offset %llu nr %llu\n", (unsigned long long)btrfs_file_extent_offset(eb, fi), (unsigned long long)btrfs_file_extent_num_bytes(eb, fi)); return; } printf("\t\textent data disk byte %llu nr %llu\n", (unsigned long long)btrfs_file_extent_disk_bytenr(eb, fi), (unsigned long long)btrfs_file_extent_disk_num_bytes(eb, fi)); printf("\t\textent data offset %llu nr %llu ram %llu\n", (unsigned long long)btrfs_file_extent_offset(eb, fi), (unsigned long long)btrfs_file_extent_num_bytes(eb, fi), (unsigned long long)btrfs_file_extent_ram_bytes(eb, fi)); printf("\t\textent compression %d\n", btrfs_file_extent_compression(eb, fi)); }
static int copy_one_inline(struct btrfs_root *root, int fd, struct btrfs_path *path, u64 pos) { struct extent_buffer *leaf = path->nodes[0]; struct btrfs_file_extent_item *fi; char buf[4096]; char *outbuf; u64 ram_size; ssize_t done; unsigned long ptr; int ret; int len; int inline_item_len; int compress; fi = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_file_extent_item); ptr = btrfs_file_extent_inline_start(fi); len = btrfs_file_extent_inline_len(leaf, path->slots[0], fi); inline_item_len = btrfs_file_extent_inline_item_len(leaf, btrfs_item_nr(path->slots[0])); read_extent_buffer(leaf, buf, ptr, inline_item_len); compress = btrfs_file_extent_compression(leaf, fi); if (compress == BTRFS_COMPRESS_NONE) { done = pwrite(fd, buf, len, pos); if (done < len) { fprintf(stderr, "Short inline write, wanted %d, did " "%zd: %d\n", len, done, errno); return -1; } return 0; } ram_size = btrfs_file_extent_ram_bytes(leaf, fi); outbuf = calloc(1, ram_size); if (!outbuf) { error("not enough memory"); return -ENOMEM; } ret = decompress(root, buf, outbuf, len, &ram_size, compress); if (ret) { free(outbuf); return ret; } done = pwrite(fd, outbuf, ram_size, pos); free(outbuf); if (done < ram_size) { fprintf(stderr, "Short compressed inline write, wanted %Lu, " "did %zd: %d\n", ram_size, done, errno); return -1; } return 0; }
static void print_file_extent_item(struct extent_buffer *eb, struct btrfs_item *item, int slot, struct btrfs_file_extent_item *fi) { int extent_type = btrfs_file_extent_type(eb, fi); char compress_str[16]; compress_type_to_str(btrfs_file_extent_compression(eb, fi), compress_str); printf("\t\tgeneration %llu type %hhu (%s)\n", btrfs_file_extent_generation(eb, fi), extent_type, file_extent_type_to_str(extent_type)); if (extent_type == BTRFS_FILE_EXTENT_INLINE) { printf("\t\tinline extent data size %u ram_bytes %u compression %hhu (%s)\n", btrfs_file_extent_inline_item_len(eb, item), btrfs_file_extent_inline_len(eb, slot, fi), btrfs_file_extent_compression(eb, fi), compress_str); return; } if (extent_type == BTRFS_FILE_EXTENT_PREALLOC) { printf("\t\tprealloc data disk byte %llu nr %llu\n", (unsigned long long)btrfs_file_extent_disk_bytenr(eb, fi), (unsigned long long)btrfs_file_extent_disk_num_bytes(eb, fi)); printf("\t\tprealloc data offset %llu nr %llu\n", (unsigned long long)btrfs_file_extent_offset(eb, fi), (unsigned long long)btrfs_file_extent_num_bytes(eb, fi)); return; } printf("\t\textent data disk byte %llu nr %llu\n", (unsigned long long)btrfs_file_extent_disk_bytenr(eb, fi), (unsigned long long)btrfs_file_extent_disk_num_bytes(eb, fi)); printf("\t\textent data offset %llu nr %llu ram %llu\n", (unsigned long long)btrfs_file_extent_offset(eb, fi), (unsigned long long)btrfs_file_extent_num_bytes(eb, fi), (unsigned long long)btrfs_file_extent_ram_bytes(eb, fi)); printf("\t\textent compression %hhu (%s)\n", btrfs_file_extent_compression(eb, fi), compress_str); }
void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) { int i; u32 type; u32 nr = btrfs_header_nritems(l); struct btrfs_item *item; struct btrfs_root_item *ri; struct btrfs_dir_item *di; struct btrfs_inode_item *ii; struct btrfs_block_group_item *bi; struct btrfs_file_extent_item *fi; struct btrfs_extent_data_ref *dref; struct btrfs_shared_data_ref *sref; struct btrfs_dev_extent *dev_extent; struct btrfs_key key; struct btrfs_key found_key; printk(KERN_INFO "leaf %llu total ptrs %d free space %d\n", (unsigned long long)btrfs_header_bytenr(l), nr, btrfs_leaf_free_space(root, l)); for (i = 0 ; i < nr ; i++) { item = btrfs_item_nr(l, i); btrfs_item_key_to_cpu(l, &key, i); type = btrfs_key_type(&key); printk(KERN_INFO "\titem %d key (%llu %x %llu) itemoff %d " "itemsize %d\n", i, (unsigned long long)key.objectid, type, (unsigned long long)key.offset, btrfs_item_offset(l, item), btrfs_item_size(l, item)); switch (type) { case BTRFS_INODE_ITEM_KEY: ii = btrfs_item_ptr(l, i, struct btrfs_inode_item); printk(KERN_INFO "\t\tinode generation %llu size %llu " "mode %o\n", (unsigned long long) btrfs_inode_generation(l, ii), (unsigned long long)btrfs_inode_size(l, ii), btrfs_inode_mode(l, ii)); break; case BTRFS_DIR_ITEM_KEY: di = btrfs_item_ptr(l, i, struct btrfs_dir_item); btrfs_dir_item_key_to_cpu(l, di, &found_key); printk(KERN_INFO "\t\tdir oid %llu type %u\n", (unsigned long long)found_key.objectid, btrfs_dir_type(l, di)); break; case BTRFS_ROOT_ITEM_KEY: ri = btrfs_item_ptr(l, i, struct btrfs_root_item); printk(KERN_INFO "\t\troot data bytenr %llu refs %u\n", (unsigned long long) btrfs_disk_root_bytenr(l, ri), btrfs_disk_root_refs(l, ri)); break; case BTRFS_EXTENT_ITEM_KEY: print_extent_item(l, i); break; 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)); break; case BTRFS_EXTENT_DATA_KEY: fi = btrfs_item_ptr(l, i, struct btrfs_file_extent_item); if (btrfs_file_extent_type(l, fi) == BTRFS_FILE_EXTENT_INLINE) { printk(KERN_INFO "\t\tinline extent data " "size %u\n", btrfs_file_extent_inline_len(l, fi)); break; } 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)); break; case BTRFS_EXTENT_REF_V0_KEY: #ifdef BTRFS_COMPAT_EXTENT_TREE_V0 print_extent_ref_v0(l, i); #else BUG(); #endif break; case BTRFS_BLOCK_GROUP_ITEM_KEY: bi = btrfs_item_ptr(l, i, struct btrfs_block_group_item); printk(KERN_INFO "\t\tblock group used %llu\n", (unsigned long long) btrfs_disk_block_group_used(l, bi)); break; case BTRFS_CHUNK_ITEM_KEY: print_chunk(l, btrfs_item_ptr(l, i, struct btrfs_chunk)); 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); printk(KERN_INFO "\t\tdev extent chunk_tree %llu\n" "\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)); }; } }
/* * this is very complex, but the basic idea is to drop all extents * in the range start - end. hint_block is filled in with a block number * that would be a good hint to the block allocator for this file. * * If an extent intersects the range but is not entirely inside the range * it is either truncated or split. Anything entirely inside the range * is deleted from the tree. */ int btrfs_drop_extents(struct btrfs_trans_handle *trans, struct inode *inode, u64 start, u64 end, u64 *hint_byte, int drop_cache) { struct btrfs_root *root = BTRFS_I(inode)->root; struct extent_buffer *leaf; struct btrfs_file_extent_item *fi; struct btrfs_path *path; struct btrfs_key key; struct btrfs_key new_key; u64 search_start = start; u64 disk_bytenr = 0; u64 num_bytes = 0; u64 extent_offset = 0; u64 extent_end = 0; int del_nr = 0; int del_slot = 0; int extent_type; int recow; int ret; if (drop_cache) btrfs_drop_extent_cache(inode, start, end - 1, 0); path = btrfs_alloc_path(); if (!path) return -ENOMEM; while (1) { recow = 0; ret = btrfs_lookup_file_extent(trans, root, path, inode->i_ino, search_start, -1); if (ret < 0) break; if (ret > 0 && path->slots[0] > 0 && search_start == start) { leaf = path->nodes[0]; btrfs_item_key_to_cpu(leaf, &key, path->slots[0] - 1); if (key.objectid == inode->i_ino && key.type == BTRFS_EXTENT_DATA_KEY) path->slots[0]--; } ret = 0; next_slot: leaf = path->nodes[0]; if (path->slots[0] >= btrfs_header_nritems(leaf)) { BUG_ON(del_nr > 0); ret = btrfs_next_leaf(root, path); if (ret < 0) break; if (ret > 0) { ret = 0; break; } leaf = path->nodes[0]; recow = 1; } btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); if (key.objectid > inode->i_ino || key.type > BTRFS_EXTENT_DATA_KEY || key.offset >= end) break; fi = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_file_extent_item); extent_type = btrfs_file_extent_type(leaf, fi); if (extent_type == BTRFS_FILE_EXTENT_REG || extent_type == BTRFS_FILE_EXTENT_PREALLOC) { disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); num_bytes = btrfs_file_extent_disk_num_bytes(leaf, fi); extent_offset = btrfs_file_extent_offset(leaf, fi); extent_end = key.offset + btrfs_file_extent_num_bytes(leaf, fi); } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) { extent_end = key.offset + btrfs_file_extent_inline_len(leaf, fi); } else { WARN_ON(1); extent_end = search_start; } if (extent_end <= search_start) { path->slots[0]++; goto next_slot; } search_start = max(key.offset, start); if (recow) { btrfs_release_path(root, path); continue; } /* * | - range to drop - | * | -------- extent -------- | */ if (start > key.offset && end < extent_end) { BUG_ON(del_nr > 0); BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE); memcpy(&new_key, &key, sizeof(new_key)); new_key.offset = start; ret = btrfs_duplicate_item(trans, root, path, &new_key); if (ret == -EAGAIN) { btrfs_release_path(root, path); continue; } if (ret < 0) break; leaf = path->nodes[0]; fi = btrfs_item_ptr(leaf, path->slots[0] - 1, struct btrfs_file_extent_item); btrfs_set_file_extent_num_bytes(leaf, fi, start - key.offset); fi = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_file_extent_item); extent_offset += start - key.offset; btrfs_set_file_extent_offset(leaf, fi, extent_offset); btrfs_set_file_extent_num_bytes(leaf, fi, extent_end - start); btrfs_mark_buffer_dirty(leaf); if (disk_bytenr > 0) { ret = btrfs_inc_extent_ref(trans, root, disk_bytenr, num_bytes, 0, root->root_key.objectid, new_key.objectid, start - extent_offset); BUG_ON(ret); *hint_byte = disk_bytenr; } key.offset = start; } /* * | ---- range to drop ----- | * | -------- extent -------- | */ if (start <= key.offset && end < extent_end) { BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE); memcpy(&new_key, &key, sizeof(new_key)); new_key.offset = end; btrfs_set_item_key_safe(trans, root, path, &new_key); extent_offset += end - key.offset; btrfs_set_file_extent_offset(leaf, fi, extent_offset); btrfs_set_file_extent_num_bytes(leaf, fi, extent_end - end); btrfs_mark_buffer_dirty(leaf); if (disk_bytenr > 0) { inode_sub_bytes(inode, end - key.offset); *hint_byte = disk_bytenr; } break; } search_start = extent_end; /* * | ---- range to drop ----- | * | -------- extent -------- | */ if (start > key.offset && end >= extent_end) { BUG_ON(del_nr > 0); BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE); btrfs_set_file_extent_num_bytes(leaf, fi, start - key.offset); btrfs_mark_buffer_dirty(leaf); if (disk_bytenr > 0) { inode_sub_bytes(inode, extent_end - start); *hint_byte = disk_bytenr; } if (end == extent_end) break; path->slots[0]++; goto next_slot; } /* * | ---- range to drop ----- | * | ------ extent ------ | */ if (start <= key.offset && end >= extent_end) { if (del_nr == 0) { del_slot = path->slots[0]; del_nr = 1; } else { BUG_ON(del_slot + del_nr != path->slots[0]); del_nr++; } if (extent_type == BTRFS_FILE_EXTENT_INLINE) { inode_sub_bytes(inode, extent_end - key.offset); extent_end = ALIGN(extent_end, root->sectorsize); } else if (disk_bytenr > 0) { ret = btrfs_free_extent(trans, root, disk_bytenr, num_bytes, 0, root->root_key.objectid, key.objectid, key.offset - extent_offset); BUG_ON(ret); inode_sub_bytes(inode, extent_end - key.offset); *hint_byte = disk_bytenr; } if (end == extent_end) break; if (path->slots[0] + 1 < btrfs_header_nritems(leaf)) { path->slots[0]++; goto next_slot; } ret = btrfs_del_items(trans, root, path, del_slot, del_nr); BUG_ON(ret); del_nr = 0; del_slot = 0; btrfs_release_path(root, path); continue; } BUG_ON(1); }
void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l) { unsigned int i; u32 nr = btrfs_header_nritems(&l->header); struct btrfs_item *item; struct btrfs_extent_item *ei; struct btrfs_root_item *ri; struct btrfs_dir_item *di; struct btrfs_inode_item *ii; struct btrfs_file_extent_item *fi; struct btrfs_csum_item *ci; struct btrfs_block_group_item *bi; u32 type; printf("leaf %llu ptrs %d free space %d generation %llu owner %llu\n", (u64)btrfs_header_blocknr(&l->header), nr, btrfs_leaf_free_space(root, l), (u64)btrfs_header_generation(&l->header), (u64)btrfs_header_owner(&l->header)); fflush(stdout); for (i = 0 ; i < nr ; i++) { item = l->items + i; type = btrfs_disk_key_type(&item->key); printf("\titem %d key (%llu %x %llu) itemoff %d itemsize %d\n", i, (u64)btrfs_disk_key_objectid(&item->key), btrfs_disk_key_flags(&item->key), (u64)btrfs_disk_key_offset(&item->key), btrfs_item_offset(item), btrfs_item_size(item)); switch (type) { case BTRFS_INODE_ITEM_KEY: ii = btrfs_item_ptr(l, i, struct btrfs_inode_item); printf("\t\tinode generation %llu size %llu block group %llu mode %o\n", (u64)btrfs_inode_generation(ii), (u64)btrfs_inode_size(ii), (u64)btrfs_inode_block_group(ii), btrfs_inode_mode(ii)); break; case BTRFS_DIR_ITEM_KEY: di = btrfs_item_ptr(l, i, struct btrfs_dir_item); print_dir_item(l->items + i, di); break; case BTRFS_DIR_INDEX_KEY: di = btrfs_item_ptr(l, i, struct btrfs_dir_item); print_dir_item(l->items + i, di); break; case BTRFS_ROOT_ITEM_KEY: ri = btrfs_item_ptr(l, i, struct btrfs_root_item); printf("\t\troot data blocknr %llu dirid %llu refs %u\n", (u64)btrfs_root_blocknr(ri), (u64)btrfs_root_dirid(ri), btrfs_root_refs(ri)); break; case BTRFS_EXTENT_ITEM_KEY: ei = btrfs_item_ptr(l, i, struct btrfs_extent_item); printf("\t\textent data refs %u owner %llu\n", btrfs_extent_refs(ei), (u64)btrfs_extent_owner(ei)); break; case BTRFS_CSUM_ITEM_KEY: ci = btrfs_item_ptr(l, i, struct btrfs_csum_item); printf("\t\tcsum item\n"); break; case BTRFS_EXTENT_DATA_KEY: fi = btrfs_item_ptr(l, i, struct btrfs_file_extent_item); if (btrfs_file_extent_type(fi) == BTRFS_FILE_EXTENT_INLINE) { printf("\t\tinline extent data size %u\n", btrfs_file_extent_inline_len(l->items + i)); break; } printf("\t\textent data disk block %llu nr %llu\n", (u64)btrfs_file_extent_disk_blocknr(fi), (u64)btrfs_file_extent_disk_num_blocks(fi)); printf("\t\textent data offset %llu nr %llu\n", (u64)btrfs_file_extent_offset(fi), (u64)btrfs_file_extent_num_blocks(fi)); break; case BTRFS_BLOCK_GROUP_ITEM_KEY: bi = btrfs_item_ptr(l, i, struct btrfs_block_group_item); printf("\t\tblock group used %llu flags %x\n", (u64)btrfs_block_group_used(bi), bi->flags); break; case BTRFS_STRING_ITEM_KEY: printf("\t\titem data %.*s\n", btrfs_item_size(item), btrfs_leaf_data(l) + btrfs_item_offset(item)); break; }; fflush(stdout); } }
/* * this is very complex, but the basic idea is to drop all extents * in the range start - end. hint_block is filled in with a block number * that would be a good hint to the block allocator for this file. * * If an extent intersects the range but is not entirely inside the range * it is either truncated or split. Anything entirely inside the range * is deleted from the tree. * * inline_limit is used to tell this code which offsets in the file to keep * if they contain inline extents. */ noinline int btrfs_drop_extents(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct inode *inode, u64 start, u64 end, u64 inline_limit, u64 *hint_byte) { u64 extent_end = 0; u64 locked_end = end; u64 search_start = start; u64 leaf_start; u64 ram_bytes = 0; u64 orig_parent = 0; u64 disk_bytenr = 0; u8 compression; u8 encryption; u16 other_encoding = 0; u64 root_gen; u64 root_owner; struct extent_buffer *leaf; struct btrfs_file_extent_item *extent; struct btrfs_path *path; struct btrfs_key key; struct btrfs_file_extent_item old; int keep; int slot; int bookend; int found_type = 0; int found_extent; int found_inline; int recow; int ret; inline_limit = 0; btrfs_drop_extent_cache(inode, start, end - 1, 0); path = btrfs_alloc_path(); if (!path) return -ENOMEM; while (1) { recow = 0; btrfs_release_path(root, path); ret = btrfs_lookup_file_extent(trans, root, path, inode->i_ino, search_start, -1); if (ret < 0) goto out; if (ret > 0) { if (path->slots[0] == 0) { ret = 0; goto out; } path->slots[0]--; } next_slot: keep = 0; bookend = 0; found_extent = 0; found_inline = 0; leaf_start = 0; root_gen = 0; root_owner = 0; compression = 0; encryption = 0; extent = NULL; leaf = path->nodes[0]; slot = path->slots[0]; ret = 0; btrfs_item_key_to_cpu(leaf, &key, slot); if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY && key.offset >= end) { goto out; } if (btrfs_key_type(&key) > BTRFS_EXTENT_DATA_KEY || key.objectid != inode->i_ino) { goto out; } if (recow) { search_start = max(key.offset, start); continue; } if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY) { extent = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); found_type = btrfs_file_extent_type(leaf, extent); compression = btrfs_file_extent_compression(leaf, extent); encryption = btrfs_file_extent_encryption(leaf, extent); other_encoding = btrfs_file_extent_other_encoding(leaf, extent); if (found_type == BTRFS_FILE_EXTENT_REG || found_type == BTRFS_FILE_EXTENT_PREALLOC) { extent_end = btrfs_file_extent_disk_bytenr(leaf, extent); if (extent_end) *hint_byte = extent_end; extent_end = key.offset + btrfs_file_extent_num_bytes(leaf, extent); ram_bytes = btrfs_file_extent_ram_bytes(leaf, extent); found_extent = 1; } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { found_inline = 1; extent_end = key.offset + btrfs_file_extent_inline_len(leaf, extent); } } else {
int btrfs_check_file(struct btrfs_root *root, struct inode *inode) { return 0; #if 0 struct btrfs_path *path; struct btrfs_key found_key; struct extent_buffer *leaf; struct btrfs_file_extent_item *extent; u64 last_offset = 0; int nritems; int slot; int found_type; int ret; int err = 0; u64 extent_end = 0; path = btrfs_alloc_path(); ret = btrfs_lookup_file_extent(NULL, root, path, inode->i_ino, last_offset, 0); while (1) { nritems = btrfs_header_nritems(path->nodes[0]); if (path->slots[0] >= nritems) { ret = btrfs_next_leaf(root, path); if (ret) goto out; nritems = btrfs_header_nritems(path->nodes[0]); } slot = path->slots[0]; leaf = path->nodes[0]; btrfs_item_key_to_cpu(leaf, &found_key, slot); if (found_key.objectid != inode->i_ino) break; if (found_key.type != BTRFS_EXTENT_DATA_KEY) goto out; if (found_key.offset < last_offset) { WARN_ON(1); btrfs_print_leaf(root, leaf); printk(KERN_ERR "inode %lu found offset %llu " "expected %llu\n", inode->i_ino, (unsigned long long)found_key.offset, (unsigned long long)last_offset); err = 1; goto out; } extent = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); found_type = btrfs_file_extent_type(leaf, extent); if (found_type == BTRFS_FILE_EXTENT_REG) { extent_end = found_key.offset + btrfs_file_extent_num_bytes(leaf, extent); } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { struct btrfs_item *item; item = btrfs_item_nr(leaf, slot); extent_end = found_key.offset + btrfs_file_extent_inline_len(leaf, extent); extent_end = (extent_end + root->sectorsize - 1) & ~((u64)root->sectorsize - 1); } last_offset = extent_end; path->slots[0]++; } if (0 && last_offset < inode->i_size) { WARN_ON(1); btrfs_print_leaf(root, leaf); printk(KERN_ERR "inode %lu found offset %llu size %llu\n", inode->i_ino, (unsigned long long)last_offset, (unsigned long long)inode->i_size); err = 1; } out: btrfs_free_path(path); return err; #endif }
void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) { int i; u32 type, nr; struct btrfs_item *item; struct btrfs_root_item *ri; struct btrfs_dir_item *di; struct btrfs_inode_item *ii; struct btrfs_block_group_item *bi; struct btrfs_file_extent_item *fi; struct btrfs_extent_data_ref *dref; struct btrfs_shared_data_ref *sref; struct btrfs_dev_extent *dev_extent; struct btrfs_key key; struct btrfs_key found_key; if (!l) return; nr = btrfs_header_nritems(l); btrfs_info(root->fs_info, "leaf %llu total ptrs %d free space %d", btrfs_header_bytenr(l), nr, btrfs_leaf_free_space(root, l)); for (i = 0 ; i < nr ; i++) { item = btrfs_item_nr(i); btrfs_item_key_to_cpu(l, &key, i); type = key.type; printk(KERN_INFO "\titem %d key (%llu %u %llu) itemoff %d " "itemsize %d\n", i, key.objectid, type, key.offset, btrfs_item_offset(l, item), btrfs_item_size(l, item)); switch (type) { case BTRFS_INODE_ITEM_KEY: ii = btrfs_item_ptr(l, i, struct btrfs_inode_item); printk(KERN_INFO "\t\tinode generation %llu size %llu " "mode %o\n", btrfs_inode_generation(l, ii), btrfs_inode_size(l, ii), btrfs_inode_mode(l, ii)); break; case BTRFS_DIR_ITEM_KEY: di = btrfs_item_ptr(l, i, struct btrfs_dir_item); btrfs_dir_item_key_to_cpu(l, di, &found_key); printk(KERN_INFO "\t\tdir oid %llu type %u\n", found_key.objectid, btrfs_dir_type(l, di)); break; case BTRFS_ROOT_ITEM_KEY: ri = btrfs_item_ptr(l, i, struct btrfs_root_item); printk(KERN_INFO "\t\troot data bytenr %llu refs %u\n", btrfs_disk_root_bytenr(l, ri), btrfs_disk_root_refs(l, ri)); break; case BTRFS_EXTENT_ITEM_KEY: case BTRFS_METADATA_ITEM_KEY: print_extent_item(l, i, type); break; 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)); break; case BTRFS_EXTENT_DATA_KEY: fi = btrfs_item_ptr(l, i, struct btrfs_file_extent_item); if (btrfs_file_extent_type(l, fi) == BTRFS_FILE_EXTENT_INLINE) { printk(KERN_INFO "\t\tinline extent data " "size %u\n", btrfs_file_extent_inline_len(l, i, fi)); break; } printk(KERN_INFO "\t\textent data disk bytenr %llu " "nr %llu\n", btrfs_file_extent_disk_bytenr(l, fi), btrfs_file_extent_disk_num_bytes(l, fi)); printk(KERN_INFO "\t\textent data offset %llu " "nr %llu ram %llu\n", btrfs_file_extent_offset(l, fi), btrfs_file_extent_num_bytes(l, fi), btrfs_file_extent_ram_bytes(l, fi)); break; case BTRFS_EXTENT_REF_V0_KEY: #ifdef BTRFS_COMPAT_EXTENT_TREE_V0 print_extent_ref_v0(l, i); #else BUG(); #endif break; case BTRFS_BLOCK_GROUP_ITEM_KEY: bi = btrfs_item_ptr(l, i, struct btrfs_block_group_item); printk(KERN_INFO "\t\tblock group used %llu\n", btrfs_disk_block_group_used(l, bi)); break; case BTRFS_CHUNK_ITEM_KEY: print_chunk(l, btrfs_item_ptr(l, i, struct btrfs_chunk)); 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); printk(KERN_INFO "\t\tdev extent chunk_tree %llu\n" "\t\tchunk objectid %llu chunk offset %llu " "length %llu\n", btrfs_dev_extent_chunk_tree(l, dev_extent), btrfs_dev_extent_chunk_objectid(l, dev_extent), btrfs_dev_extent_chunk_offset(l, dev_extent), btrfs_dev_extent_length(l, dev_extent)); break; case BTRFS_PERSISTENT_ITEM_KEY: printk(KERN_INFO "\t\tpersistent item objectid %llu offset %llu\n", key.objectid, key.offset); switch (key.objectid) { case BTRFS_DEV_STATS_OBJECTID: printk(KERN_INFO "\t\tdevice stats\n"); break; default: printk(KERN_INFO "\t\tunknown persistent item\n"); } break; case BTRFS_TEMPORARY_ITEM_KEY: printk(KERN_INFO "\t\ttemporary item objectid %llu offset %llu\n", key.objectid, key.offset); switch (key.objectid) { case BTRFS_BALANCE_OBJECTID: printk(KERN_INFO "\t\tbalance status\n"); break; default: printk(KERN_INFO "\t\tunknown temporary item\n"); } break; case BTRFS_DEV_REPLACE_KEY: printk(KERN_INFO "\t\tdev replace\n"); break; case BTRFS_UUID_KEY_SUBVOL: case BTRFS_UUID_KEY_RECEIVED_SUBVOL: print_uuid_item(l, btrfs_item_ptr_offset(l, i), btrfs_item_size_nr(l, i)); break; }; } }