From 4122e65cb2132e28e0c18106a251875d2e68c35d Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Tue, 11 Dec 2007 09:21:42 -0500 Subject: Add back pointers from extents to the file or btree referencing them --- btrfsck.c | 2 +- ctree.c | 48 ++++++++--- ctree.h | 50 ++++++----- extent-tree.c | 262 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---- mkfs.c | 1 - print-tree.c | 15 +++- 6 files changed, 323 insertions(+), 55 deletions(-) diff --git a/btrfsck.c b/btrfsck.c index 02299bc1..d13658e7 100644 --- a/btrfsck.c +++ b/btrfsck.c @@ -382,7 +382,7 @@ static int run_next_block(struct btrfs_root *root, add_extent_rec(extent_cache, NULL, 0, found.objectid, found.offset, - btrfs_extent_owner(ei), + 0, btrfs_extent_refs(ei), 0, 0); continue; } diff --git a/ctree.c b/ctree.c index 71796067..e5b2356c 100644 --- a/ctree.c +++ b/ctree.c @@ -59,6 +59,7 @@ int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root **cow_ret) { struct btrfs_buffer *cow; + u64 root_gen; if (!list_empty(&buf->dirty)) { *cow_ret = buf; @@ -72,19 +73,23 @@ int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root *cow_ret = cow; btrfs_inc_ref(trans, root, buf); if (buf == root->node) { + root_gen = btrfs_header_generation(&buf->node.header); root->node = cow; cow->count++; if (buf != root->commit_root) btrfs_free_extent(trans, root, buf->bytenr, - buf->size, 1); + buf->size, root->root_key.objectid, + root_gen, 0, 0, 1); btrfs_block_release(root, buf); } else { + root_gen = btrfs_header_generation(&parent->node.header); btrfs_set_node_blockptr(&parent->node, parent_slot, cow->bytenr); btrfs_set_node_ptr_generation(&parent->node, parent_slot, trans->transid); BUG_ON(list_empty(&parent->dirty)); - btrfs_free_extent(trans, root, buf->bytenr, buf->size, 1); + btrfs_free_extent(trans, root, buf->bytenr, buf->size, + root->root_key.objectid, root_gen, 0, 0, 1); } btrfs_block_release(root, buf); return 0; @@ -362,8 +367,10 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root /* once for the root ptr */ btrfs_block_release(root, mid_buf); clean_tree_block(trans, root, mid_buf); - return btrfs_free_extent(trans, root, bytenr, - root->nodesize, 1); + return btrfs_free_extent(trans, root, bytenr, root->nodesize, + root->root_key.objectid, + btrfs_header_generation(&mid->header), + 0, 0, 1); } parent = &parent_buf->node; @@ -396,7 +403,10 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root if (wret < 0) ret = wret; if (btrfs_header_nritems(&right->header) == 0) { + u64 generation; u64 bytenr = right_buf->bytenr; + + generation = btrfs_header_generation(&parent->header); btrfs_block_release(root, right_buf); clean_tree_block(trans, root, right_buf); right_buf = NULL; @@ -406,7 +416,9 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root if (wret) ret = wret; wret = btrfs_free_extent(trans, root, bytenr, - root->nodesize, 1); + root->nodesize, + root->root_key.objectid, + generation, 0, 0, 1); if (wret) ret = wret; } else { @@ -435,6 +447,9 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root if (btrfs_header_nritems(&mid->header) == 0) { /* we've managed to empty the middle node, drop it */ u64 bytenr = mid_buf->bytenr; + u64 generation; + + generation = btrfs_header_generation(&parent->header); btrfs_block_release(root, mid_buf); clean_tree_block(trans, root, mid_buf); mid_buf = NULL; @@ -442,8 +457,9 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root wret = del_ptr(trans, root, path, level + 1, pslot); if (wret) ret = wret; - wret = btrfs_free_extent(trans, root, bytenr, - root->nodesize, 1); + wret = btrfs_free_extent(trans, root, bytenr, root->nodesize, + root->root_key.objectid, + generation, 0, 0, 1); if (wret) ret = wret; } else { @@ -1589,13 +1605,17 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, btrfs_set_header_level(&leaf->header, 0); BUG_ON(list_empty(&leaf_buf->dirty)); } else { + u64 generation = + btrfs_header_generation(&path->nodes[1]->node.header); + clean_tree_block(trans, root, leaf_buf); wret = del_ptr(trans, root, path, 1, path->slots[1]); if (wret) ret = wret; - wret = btrfs_free_extent(trans, root, - leaf_buf->bytenr, - leaf_buf->size, 1); + wret = btrfs_free_extent(trans, root, leaf_buf->bytenr, + leaf_buf->size, + root->root_key.objectid, + generation, 0, 0, 1); if (wret) ret = wret; } @@ -1628,12 +1648,18 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, } if (btrfs_header_nritems(&leaf->header) == 0) { u64 bytenr = leaf_buf->bytenr; + struct btrfs_buffer *parent = path->nodes[1]; + u64 generation = + btrfs_header_generation(&parent->node.header); + clean_tree_block(trans, root, leaf_buf); wret = del_ptr(trans, root, path, 1, slot); if (wret) ret = wret; wret = btrfs_free_extent(trans, root, bytenr, - leaf_buf->size, 1); + leaf_buf->size, + root->root_key.objectid, + generation, 0, 0, 1); btrfs_block_release(root, leaf_buf); if (wret) ret = wret; diff --git a/ctree.h b/ctree.h index d1df4f2a..174fb239 100644 --- a/ctree.h +++ b/ctree.h @@ -183,7 +183,13 @@ struct btrfs_path { */ struct btrfs_extent_item { __le32 refs; - __le64 owner; +} __attribute__ ((__packed__)); + +struct btrfs_extent_ref { + __le64 root; + __le64 generation; + __le64 objectid; + __le64 offset; } __attribute__ ((__packed__)); struct btrfs_inode_timespec { @@ -377,12 +383,13 @@ struct btrfs_root { * are used, and how many references there are to each block */ #define BTRFS_EXTENT_ITEM_KEY 33 +#define BTRFS_EXTENT_REF_KEY 34 /* * block groups give us hints into the extent allocation trees. Which * blocks are free etc etc */ -#define BTRFS_BLOCK_GROUP_ITEM_KEY 34 +#define BTRFS_BLOCK_GROUP_ITEM_KEY 50 /* * string items are for debugging. They just store a short string of @@ -390,6 +397,15 @@ struct btrfs_root { */ #define BTRFS_STRING_ITEM_KEY 253 +#define BTRFS_SETGET_STACK_FUNCS(name, type, member, bits) \ +static inline u##bits btrfs_##name(type *s) \ +{ \ + return le##bits##_to_cpu(s->member); \ +} \ +static inline void btrfs_set_##name(type *s, u##bits val) \ +{ \ + s->member = cpu_to_le##bits(val); \ +} static inline u64 btrfs_block_group_used(struct btrfs_block_group_item *bi) { @@ -538,25 +554,13 @@ static inline void btrfs_set_timespec_nsec(struct btrfs_inode_timespec *ts, ts->nsec = cpu_to_le32(val); } -static inline u32 btrfs_extent_refs(struct btrfs_extent_item *ei) -{ - return le32_to_cpu(ei->refs); -} - -static inline void btrfs_set_extent_refs(struct btrfs_extent_item *ei, u32 val) -{ - ei->refs = cpu_to_le32(val); -} +BTRFS_SETGET_STACK_FUNCS(extent_refs, struct btrfs_extent_item, refs, 32); -static inline u64 btrfs_extent_owner(struct btrfs_extent_item *ei) -{ - return le64_to_cpu(ei->owner); -} - -static inline void btrfs_set_extent_owner(struct btrfs_extent_item *ei, u64 val) -{ - ei->owner = cpu_to_le64(val); -} +BTRFS_SETGET_STACK_FUNCS(ref_root, struct btrfs_extent_ref, root, 64); +BTRFS_SETGET_STACK_FUNCS(ref_generation, struct btrfs_extent_ref, + generation, 64); +BTRFS_SETGET_STACK_FUNCS(ref_objectid, struct btrfs_extent_ref, objectid, 64); +BTRFS_SETGET_STACK_FUNCS(ref_offset, struct btrfs_extent_ref, offset, 64); static inline u64 btrfs_node_blockptr(struct btrfs_node *n, int nr) { @@ -1068,9 +1072,11 @@ struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_buffer *buf); int btrfs_inc_root_ref(struct btrfs_trans_handle *trans, - struct btrfs_root *root); + struct btrfs_root *root, u64 owner_objectid); int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root - *root, u64 bytenr, u64 num_bytes, int pin); + *root, u64 bytenr, u64 num_bytes, + u64 root_objectid, u64 root_generation, + u64 owner, u64 owner_offset, int pin); int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_buffer *buf, struct btrfs_buffer *parent, int parent_slot, diff --git a/extent-tree.c b/extent-tree.c index ac8ae752..c0695ec2 100644 --- a/extent-tree.c +++ b/extent-tree.c @@ -24,14 +24,156 @@ #include "disk-io.h" #include "print-tree.h" #include "transaction.h" +#include "crc32c.h" static int finish_current_insert(struct btrfs_trans_handle *trans, struct btrfs_root *extent_root); static int run_pending(struct btrfs_trans_handle *trans, struct btrfs_root *extent_root); +static u64 hash_extent_ref(u64 root_objectid, u64 ref_generation, + u64 owner, u64 owner_offset) +{ + u32 high_crc = ~(u32)0; + u32 low_crc = ~(u32)0; + __le64 lenum; + + lenum = cpu_to_le64(root_objectid); + high_crc = crc32c(high_crc, &lenum, sizeof(lenum)); + lenum = cpu_to_le64(ref_generation); + low_crc = crc32c(low_crc, &lenum, sizeof(lenum)); + +#if 0 + lenum = cpu_to_le64(owner); + low_crc = crc32c(low_crc, &lenum, sizeof(lenum)); + lenum = cpu_to_le64(owner_offset); + low_crc = crc32c(low_crc, &lenum, sizeof(lenum)); +#endif + return ((u64)high_crc << 32) | (u64)low_crc; +} + +static int match_extent_ref(struct btrfs_extent_ref *disk_ref, + struct btrfs_extent_ref *cpu_ref) +{ + int ret = memcmp(cpu_ref, disk_ref, sizeof(*cpu_ref)); + return ret == 0; +} + +static int lookup_extent_backref(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct btrfs_path *path, u64 bytenr, + u64 root_objectid, u64 ref_generation, + u64 owner, u64 owner_offset, int del) +{ + u64 hash; + struct btrfs_key key; + struct btrfs_key found_key; + struct btrfs_extent_ref ref; + struct btrfs_buffer *leaf; + struct btrfs_extent_ref *disk_ref; + int ret; + int ret2; + + btrfs_set_ref_root(&ref, root_objectid); + btrfs_set_ref_generation(&ref, ref_generation); + btrfs_set_ref_objectid(&ref, owner); + btrfs_set_ref_offset(&ref, owner_offset); + + hash = hash_extent_ref(root_objectid, ref_generation, owner, + owner_offset); + key.offset = hash; + key.objectid = bytenr; + key.type = BTRFS_EXTENT_REF_KEY; + + while (1) { + ret = btrfs_search_slot(trans, root, &key, path, + del ? -1 : 0, del); + if (ret < 0) + goto out; + leaf = path->nodes[0]; + if (ret != 0) { + u32 nritems = btrfs_header_nritems(&leaf->node.header); + if (path->slots[0] >= nritems) { + ret2 = btrfs_next_leaf(root, path); + if (ret2) + goto out; + leaf = path->nodes[0]; + } + btrfs_disk_key_to_cpu(&found_key, + &leaf->leaf.items[path->slots[0]].key); + if (found_key.objectid != bytenr || + found_key.type != BTRFS_EXTENT_REF_KEY) + goto out; + key.offset = found_key.offset; + if (del) { + btrfs_release_path(root, path); + continue; + } + } + disk_ref = btrfs_item_ptr(&path->nodes[0]->leaf, + path->slots[0], + struct btrfs_extent_ref); + if (match_extent_ref(disk_ref, &ref)) { + ret = 0; + goto out; + } + btrfs_disk_key_to_cpu(&found_key, + &leaf->leaf.items[path->slots[0]].key); + key.offset = found_key.offset + 1; + btrfs_release_path(root, path); + } +out: + return ret; +} + +static int insert_extent_backref(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct btrfs_path *path, u64 bytenr, + u64 root_objectid, u64 ref_generation, + u64 owner, u64 owner_offset) +{ + u64 hash; + struct btrfs_key key; + struct btrfs_extent_ref ref; + struct btrfs_extent_ref *disk_ref; + int ret; + + btrfs_set_ref_root(&ref, root_objectid); + btrfs_set_ref_generation(&ref, ref_generation); + btrfs_set_ref_objectid(&ref, owner); + btrfs_set_ref_offset(&ref, owner_offset); + + hash = hash_extent_ref(root_objectid, ref_generation, owner, + owner_offset); + key.offset = hash; + key.objectid = bytenr; + key.type = BTRFS_EXTENT_REF_KEY; + + ret = btrfs_insert_empty_item(trans, root, path, &key, sizeof(ref)); + while (ret == -EEXIST) { + disk_ref = btrfs_item_ptr(&path->nodes[0]->leaf, path->slots[0], + struct btrfs_extent_ref); + if (match_extent_ref(disk_ref, &ref)) + goto out; + key.offset++; + ret = btrfs_insert_empty_item(trans, root, path, &key, + sizeof(ref)); + } + if (ret) + goto out; + disk_ref = btrfs_item_ptr(&path->nodes[0]->leaf, path->slots[0], + struct btrfs_extent_ref); + memcpy(disk_ref, &ref, sizeof(ref)); + dirty_tree_block(trans, root, path->nodes[0]); +out: + btrfs_release_path(root, path); + return ret; +} + static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root - *root, u64 bytenr, u32 blocksize) + *root, u64 bytenr, u32 blocksize, + u64 root_objectid, u64 ref_generation, + u64 owner, u64 owner_offset) { struct btrfs_path path; int ret; @@ -56,6 +198,12 @@ static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root BUG_ON(list_empty(&path.nodes[0]->dirty)); btrfs_release_path(root->fs_info->extent_root, &path); + + ret = insert_extent_backref(trans, root->fs_info->extent_root, &path, + bytenr, root_objectid, ref_generation, + owner, owner_offset); + BUG_ON(ret); + finish_current_insert(trans, root->fs_info->extent_root); run_pending(trans, root->fs_info->extent_root); return 0; @@ -69,7 +217,9 @@ static int lookup_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root struct btrfs_key key; struct btrfs_leaf *l; struct btrfs_extent_item *item; + btrfs_init_path(&path); + key.objectid = bytenr; key.offset = blocksize; btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); @@ -103,17 +253,19 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, for (i = 0; i < btrfs_header_nritems(&buf->node.header); i++) { bytenr = btrfs_node_blockptr(&buf->node, i); - inc_block_ref(trans, root, bytenr, blocksize); + inc_block_ref(trans, root, bytenr, blocksize, + root->root_key.objectid, trans->transid, 0, 0); } return 0; } int btrfs_inc_root_ref(struct btrfs_trans_handle *trans, - struct btrfs_root *root) + struct btrfs_root *root, u64 owner_objectid) { return inc_block_ref(trans, root, root->node->bytenr, - root->node->size); + root->node->size, owner_objectid, + trans->transid, 0, 0); } static int write_one_cache_group(struct btrfs_trans_handle *trans, @@ -241,9 +393,10 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct struct cache_extent *pe; struct cache_extent *next; struct cache_tree *pending_tree = &info->pending_tree; + struct btrfs_path path; + btrfs_init_path(&path); btrfs_set_extent_refs(&extent_item, 1); - btrfs_set_extent_owner(&extent_item, extent_root->root_key.objectid); ins.offset = 1; btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY); pe = find_first_cache_extent(pending_tree, 0); @@ -265,6 +418,12 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct btrfs_print_tree(extent_root, extent_root->node); } BUG_ON(ret); + + ret = insert_extent_backref(trans, extent_root, &path, + ins.objectid, + extent_root->root_key.objectid, + 0, 0, 0); + BUG_ON(ret); } return 0; } @@ -273,7 +432,9 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct * remove an extent from the root, returns 0 on success */ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root - *root, u64 bytenr, u64 num_bytes, int pin) + *root, u64 bytenr, u64 num_bytes, + u64 root_objectid, u64 ref_generation, + u64 owner_objectid, u64 owner_offset, int pin) { struct btrfs_path path; struct btrfs_key key; @@ -288,6 +449,19 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root key.offset = num_bytes; btrfs_init_path(&path); + + ret = lookup_extent_backref(trans, extent_root, &path, + bytenr, root_objectid, + ref_generation, + owner_objectid, owner_offset, 1); + if (ret == 0) { + ret = btrfs_del_item(trans, extent_root, &path); + } else { + // FIXME deal with missing references here + } + + btrfs_release_path(extent_root, &path); + ret = btrfs_search_slot(trans, extent_root, &key, &path, -1, 1); if (ret) { btrfs_print_tree(extent_root, extent_root->node); @@ -345,7 +519,9 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct while(pe) { remove_cache_extent(del_pending, pe); ret = __free_extent(trans, extent_root, - pe->start, pe->size, 1); + pe->start, pe->size, + extent_root->root_key.objectid, + 0, 0, 0, 1); BUG_ON(ret); next = next_cache_extent(pe); if (!next) @@ -368,19 +544,26 @@ static int run_pending(struct btrfs_trans_handle *trans, struct btrfs_root * remove an extent from the root, returns 0 on success */ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root - *root, u64 bytenr, u64 num_bytes, int pin) + *root, u64 bytenr, u64 num_bytes, + u64 root_objectid, u64 root_generation, + u64 owner_objectid, u64 owner_offset, int pin) { struct btrfs_root *extent_root = root->fs_info->extent_root; int pending_ret; int ret; + if (!root->ref_cows) + root_generation = 0; + if (root == extent_root) { ret = insert_cache_extent(&root->fs_info->del_pending, bytenr, num_bytes); BUG_ON(ret); return 0; } - ret = __free_extent(trans, root, bytenr, num_bytes, pin); + ret = __free_extent(trans, root, bytenr, num_bytes, + root_objectid, root_generation, owner_objectid, + owner_offset, pin); pending_ret = run_pending(trans, root->fs_info->extent_root); return ret ? ret : pending_ret; } @@ -509,8 +692,9 @@ error: * returns 0 if everything worked, non-zero otherwise. */ static int alloc_extent(struct btrfs_trans_handle *trans, - struct btrfs_root *root, u64 owner, - u64 num_bytes, u64 search_start, + struct btrfs_root *root, u64 num_bytes, + u64 root_objectid, u64 ref_generation, u64 owner, + u64 owner_offset, u64 search_start, u64 search_end, struct btrfs_key *ins) { int ret; @@ -519,9 +703,11 @@ static int alloc_extent(struct btrfs_trans_handle *trans, struct btrfs_fs_info *info = root->fs_info; struct btrfs_root *extent_root = info->extent_root; struct btrfs_extent_item extent_item; + struct btrfs_path path; + + btrfs_init_path(&path); btrfs_set_extent_refs(&extent_item, 1); - btrfs_set_extent_owner(&extent_item, owner); ret = find_free_extent(trans, root, num_bytes, search_start, search_end, ins); @@ -543,6 +729,12 @@ static int alloc_extent(struct btrfs_trans_handle *trans, ret = btrfs_insert_item(trans, extent_root, ins, &extent_item, sizeof(extent_item)); + BUG_ON(ret); + ret = insert_extent_backref(trans, extent_root, &path, ins->objectid, + root_objectid, ref_generation, + owner, owner_offset); + BUG_ON(ret); + finish_current_insert(trans, extent_root); pending_ret = run_pending(trans, extent_root); if (ret) @@ -562,11 +754,19 @@ struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, u32 blocksize) { + u64 ref_generation; struct btrfs_key ins; int ret; struct btrfs_buffer *buf; - ret = alloc_extent(trans, root, root->root_key.objectid, - blocksize, 0, (u64)-1, &ins); + + if (root->ref_cows) + ref_generation = trans->transid; + else + ref_generation = 0; + + ret = alloc_extent(trans, root, blocksize, + root->root_key.objectid, ref_generation, + 0, 0, 0, (u64)-1, &ins); if (ret) { BUG(); return NULL; @@ -590,6 +790,9 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root { struct btrfs_buffer *next; struct btrfs_buffer *cur; + struct btrfs_buffer *parent; + u64 root_owner; + u64 root_gen; u64 bytenr; int ret; u32 refs; @@ -612,8 +815,13 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root bytenr = btrfs_node_blockptr(&cur->node, path->slots[*level]); ret = lookup_block_ref(trans, root, bytenr, size, &refs); if (refs != 1 || *level == 1) { + parent = path->nodes[*level]; + root_owner = btrfs_header_owner(&parent->node.header); + root_gen = + btrfs_header_generation(&parent->node.header); path->slots[*level]++; - ret = btrfs_free_extent(trans, root, bytenr, size, 1); + ret = btrfs_free_extent(trans, root, bytenr, size, + root_owner, root_gen, 0, 0, 1); BUG_ON(ret); continue; } @@ -626,8 +834,16 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root path->slots[*level] = 0; } out: + if (*level == BTRFS_MAX_LEVEL - 1 || !path->nodes[*level + 1]) + parent = path->nodes[*level]; + else + parent = path->nodes[*level + 1]; + + root_owner = btrfs_header_owner(&parent->node.header); + root_gen = btrfs_header_generation(&parent->node.header); ret = btrfs_free_extent(trans, root, path->nodes[*level]->bytenr, - btrfs_level_size(root, *level), 1); + btrfs_level_size(root, *level), + root_owner, root_gen, 0, 0, 1); btrfs_block_release(root, path->nodes[*level]); path->nodes[*level] = NULL; *level += 1; @@ -646,6 +862,9 @@ static int walk_up_tree(struct btrfs_trans_handle *trans, struct btrfs_root int i; int slot; int ret; + u64 root_owner; + u64 root_gen; + struct btrfs_buffer *parent; for(i = *level; i < BTRFS_MAX_LEVEL - 1 && path->nodes[i]; i++) { slot = path->slots[i]; if (slot < @@ -654,9 +873,18 @@ static int walk_up_tree(struct btrfs_trans_handle *trans, struct btrfs_root *level = i; return 0; } else { + if (path->nodes[*level] == root->node) + parent = path->nodes[*level]; + else + parent = path->nodes[*level + 1]; + + root_owner = btrfs_header_owner(&parent->node.header); + root_gen = + btrfs_header_generation(&parent->node.header); ret = btrfs_free_extent(trans, root, path->nodes[*level]->bytenr, - btrfs_level_size(root, *level), 1); + btrfs_level_size(root, *level), + root_owner, root_gen, 0, 0, 1); btrfs_block_release(root, path->nodes[*level]); path->nodes[*level] = NULL; *level = i + 1; diff --git a/mkfs.c b/mkfs.c index 2b1b5003..ffc6af18 100644 --- a/mkfs.c +++ b/mkfs.c @@ -278,7 +278,6 @@ printf("blocksize is %d\n", leafsize); btrfs_set_item_offset(&item, itemoff); btrfs_set_item_size(&item, sizeof(struct btrfs_extent_item)); btrfs_set_extent_refs(&extent_item, 1); - btrfs_set_extent_owner(&extent_item, BTRFS_ROOT_TREE_OBJECTID); memcpy(empty_leaf->items, &item, sizeof(item)); memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item), &extent_item, btrfs_item_size(&item)); diff --git a/print-tree.c b/print-tree.c index 8a30919f..9c85f638 100644 --- a/print-tree.c +++ b/print-tree.c @@ -57,6 +57,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l) struct btrfs_file_extent_item *fi; struct btrfs_csum_item *ci; struct btrfs_block_group_item *bi; + struct btrfs_extent_ref *ref; u32 type; printf("leaf %llu ptrs %d free space %d generation %llu owner %llu\n", @@ -114,9 +115,17 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l) 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), - (unsigned long long)btrfs_extent_owner(ei)); + printf("\t\textent data refs %u\n", + btrfs_extent_refs(ei)); + break; + case BTRFS_EXTENT_REF_KEY: + ref = btrfs_item_ptr(l, i, struct btrfs_extent_ref); + printf("\t\textent back ref root %llu gen %llu " + "owner %llu offset %llu\n", + (unsigned long long)btrfs_ref_root(ref), + (unsigned long long)btrfs_ref_generation(ref), + (unsigned long long)btrfs_ref_objectid(ref), + (unsigned long long)btrfs_ref_offset(ref)); break; case BTRFS_CSUM_ITEM_KEY: ci = btrfs_item_ptr(l, i, -- cgit v1.2.3