Commit 7bb86316 authored by Chris Mason's avatar Chris Mason

Btrfs: Add back pointers from extents to the btree or file referencing them

Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 74493f7a
This diff is collapsed.
...@@ -544,11 +544,12 @@ BTRFS_SETGET_FUNCS(ref_generation, struct btrfs_extent_ref, generation, 64); ...@@ -544,11 +544,12 @@ BTRFS_SETGET_FUNCS(ref_generation, struct btrfs_extent_ref, generation, 64);
BTRFS_SETGET_FUNCS(ref_objectid, struct btrfs_extent_ref, objectid, 64); BTRFS_SETGET_FUNCS(ref_objectid, struct btrfs_extent_ref, objectid, 64);
BTRFS_SETGET_FUNCS(ref_offset, struct btrfs_extent_ref, offset, 64); BTRFS_SETGET_FUNCS(ref_offset, struct btrfs_extent_ref, offset, 64);
BTRFS_SETGET_STACK_FUNCS(ref_root, struct btrfs_extent_ref, root, 64); BTRFS_SETGET_STACK_FUNCS(stack_ref_root, struct btrfs_extent_ref, root, 64);
BTRFS_SETGET_STACK_FUNCS(ref_generation, struct btrfs_extent_ref, BTRFS_SETGET_STACK_FUNCS(stack_ref_generation, struct btrfs_extent_ref,
generation, 64); generation, 64);
BTRFS_SETGET_STACK_FUNCS(ref_objectid, struct btrfs_extent_ref, objectid, 64); BTRFS_SETGET_STACK_FUNCS(stack_ref_objectid, struct btrfs_extent_ref,
BTRFS_SETGET_STACK_FUNCS(ref_offset, struct btrfs_extent_ref, offset, 64); objectid, 64);
BTRFS_SETGET_STACK_FUNCS(stack_ref_offset, struct btrfs_extent_ref, offset, 64);
BTRFS_SETGET_STACK_FUNCS(stack_extent_refs, struct btrfs_extent_item, BTRFS_SETGET_STACK_FUNCS(stack_extent_refs, struct btrfs_extent_item,
refs, 32); refs, 32);
...@@ -914,24 +915,45 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, ...@@ -914,24 +915,45 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
*hint, u64 search_start, *hint, u64 search_start,
int data, int owner); int data, int owner);
int btrfs_inc_root_ref(struct btrfs_trans_handle *trans, int btrfs_inc_root_ref(struct btrfs_trans_handle *trans,
struct btrfs_root *root); struct btrfs_root *root, u64 owner_objectid);
struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
struct btrfs_root *root, u32 size, struct btrfs_root *root, u32 size,
u64 root_objectid,
u64 hint, u64 empty_size); u64 hint, u64 empty_size);
struct extent_buffer *__btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
u32 blocksize,
u64 root_objectid,
u64 ref_generation,
u64 first_objectid,
int level,
u64 hint,
u64 empty_size);
int btrfs_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);
int btrfs_alloc_extent(struct btrfs_trans_handle *trans, int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
struct btrfs_root *root, u64 owner, struct btrfs_root *root,
u64 num_bytes, u64 empty_size, u64 search_start, u64 num_bytes, u64 root_objectid, u64 ref_generation,
u64 owner, u64 owner_offset,
u64 empty_size, u64 hint_byte,
u64 search_end, struct btrfs_key *ins, int data); u64 search_end, struct btrfs_key *ins, int data);
int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
struct extent_buffer *buf); struct extent_buffer *buf);
int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root 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 ref_generation,
u64 owner_objectid, u64 owner_offset, int pin);
int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_root *root,
struct extent_map_tree *unpin); struct extent_map_tree *unpin);
int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_root *root,
u64 bytenr, u64 num_bytes); u64 bytenr, u64 num_bytes,
u64 root_objectid, u64 ref_generation,
u64 owner, u64 owner_offset);
int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
struct btrfs_root *root); struct btrfs_root *root);
int btrfs_free_block_groups(struct btrfs_fs_info *info); int btrfs_free_block_groups(struct btrfs_fs_info *info);
...@@ -966,6 +988,7 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -966,6 +988,7 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root
*root, struct btrfs_path *path, struct btrfs_key *root, struct btrfs_path *path, struct btrfs_key
*cpu_key, u32 data_size); *cpu_key, u32 data_size);
int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path); int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path);
int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path);
int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf); int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf);
int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root
*root); *root);
......
...@@ -210,7 +210,7 @@ static int btree_writepages(struct address_space *mapping, ...@@ -210,7 +210,7 @@ static int btree_writepages(struct address_space *mapping,
{ {
struct extent_map_tree *tree; struct extent_map_tree *tree;
tree = &BTRFS_I(mapping->host)->extent_tree; tree = &BTRFS_I(mapping->host)->extent_tree;
if (wbc->sync_mode == WB_SYNC_NONE) { if (0 && wbc->sync_mode == WB_SYNC_NONE) {
u64 num_dirty; u64 num_dirty;
u64 start = 0; u64 start = 0;
unsigned long thresh = 96 * 1024 * 1024; unsigned long thresh = 96 * 1024 * 1024;
......
This diff is collapsed.
...@@ -496,7 +496,10 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans, ...@@ -496,7 +496,10 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
sizeof(old)); sizeof(old));
if (disk_bytenr != 0) { if (disk_bytenr != 0) {
ret = btrfs_inc_extent_ref(trans, root, ret = btrfs_inc_extent_ref(trans, root,
disk_bytenr, disk_num_bytes); disk_bytenr, disk_num_bytes,
root->root_key.objectid,
trans->transid,
key.objectid, end);
BUG_ON(ret); BUG_ON(ret);
} }
} }
...@@ -541,6 +544,14 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans, ...@@ -541,6 +544,14 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
u64 disk_bytenr = 0; u64 disk_bytenr = 0;
u64 disk_num_bytes = 0; u64 disk_num_bytes = 0;
u64 extent_num_bytes = 0; u64 extent_num_bytes = 0;
u64 root_gen;
if (leaf != root->node) {
root_gen =
btrfs_header_generation(path->nodes[1]);
} else {
root_gen = btrfs_header_generation(leaf);
}
if (found_extent) { if (found_extent) {
disk_bytenr = disk_bytenr =
btrfs_file_extent_disk_bytenr(leaf, btrfs_file_extent_disk_bytenr(leaf,
...@@ -562,8 +573,11 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans, ...@@ -562,8 +573,11 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
if (found_extent && disk_bytenr != 0) { if (found_extent && disk_bytenr != 0) {
inode->i_blocks -= extent_num_bytes >> 9; inode->i_blocks -= extent_num_bytes >> 9;
ret = btrfs_free_extent(trans, root, ret = btrfs_free_extent(trans, root,
disk_bytenr, disk_bytenr,
disk_num_bytes, 0); disk_num_bytes,
root->root_key.objectid,
root_gen, inode->i_ino,
key.offset, 0);
} }
BUG_ON(ret); BUG_ON(ret);
......
...@@ -93,7 +93,9 @@ static int run_delalloc_range(struct inode *inode, u64 start, u64 end) ...@@ -93,7 +93,9 @@ static int run_delalloc_range(struct inode *inode, u64 start, u64 end)
if (alloc_hint == EXTENT_MAP_INLINE) if (alloc_hint == EXTENT_MAP_INLINE)
goto out; goto out;
ret = btrfs_alloc_extent(trans, root, inode->i_ino, num_bytes, 0, ret = btrfs_alloc_extent(trans, root, num_bytes,
root->root_key.objectid, trans->transid,
inode->i_ino, start, 0,
alloc_hint, (u64)-1, &ins, 1); alloc_hint, (u64)-1, &ins, 1);
if (ret) { if (ret) {
WARN_ON(1); WARN_ON(1);
...@@ -560,6 +562,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, ...@@ -560,6 +562,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
u64 extent_start = 0; u64 extent_start = 0;
u64 extent_num_bytes = 0; u64 extent_num_bytes = 0;
u64 item_end = 0; u64 item_end = 0;
u64 root_gen = 0;
int found_extent; int found_extent;
int del_item; int del_item;
int extent_type = -1; int extent_type = -1;
...@@ -670,6 +673,15 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, ...@@ -670,6 +673,15 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
found_extent = 1; found_extent = 1;
inode->i_blocks -= num_dec; inode->i_blocks -= num_dec;
} }
if (leaf == root->node) {
root_gen =
btrfs_header_generation(leaf);
} else {
struct extent_buffer *parent;
parent = path->nodes[1];
root_gen =
btrfs_header_generation(parent);
}
} }
} else if (extent_type == BTRFS_FILE_EXTENT_INLINE && } else if (extent_type == BTRFS_FILE_EXTENT_INLINE &&
!del_item) { !del_item) {
...@@ -690,7 +702,10 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, ...@@ -690,7 +702,10 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
btrfs_release_path(root, path); btrfs_release_path(root, path);
if (found_extent) { if (found_extent) {
ret = btrfs_free_extent(trans, root, extent_start, ret = btrfs_free_extent(trans, root, extent_start,
extent_num_bytes, 0); extent_num_bytes,
root->root_key.objectid,
root_gen, inode->i_ino,
found_key.offset, 0);
BUG_ON(ret); BUG_ON(ret);
} }
} }
...@@ -1900,7 +1915,14 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen) ...@@ -1900,7 +1915,14 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen)
trans = btrfs_start_transaction(root, 1); trans = btrfs_start_transaction(root, 1);
BUG_ON(!trans); BUG_ON(!trans);
leaf = btrfs_alloc_free_block(trans, root, root->leafsize, 0, 0); ret = btrfs_find_free_objectid(trans, root->fs_info->tree_root,
0, &objectid);
if (ret)
goto fail;
leaf = __btrfs_alloc_free_block(trans, root, root->leafsize,
objectid, trans->transid, 0, 0,
0, 0);
if (IS_ERR(leaf)) if (IS_ERR(leaf))
return PTR_ERR(leaf); return PTR_ERR(leaf);
...@@ -1908,7 +1930,8 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen) ...@@ -1908,7 +1930,8 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen)
btrfs_set_header_level(leaf, 0); btrfs_set_header_level(leaf, 0);
btrfs_set_header_bytenr(leaf, leaf->start); btrfs_set_header_bytenr(leaf, leaf->start);
btrfs_set_header_generation(leaf, trans->transid); btrfs_set_header_generation(leaf, trans->transid);
btrfs_set_header_owner(leaf, root->root_key.objectid); btrfs_set_header_owner(leaf, objectid);
write_extent_buffer(leaf, root->fs_info->fsid, write_extent_buffer(leaf, root->fs_info->fsid,
(unsigned long)btrfs_header_fsid(leaf), (unsigned long)btrfs_header_fsid(leaf),
BTRFS_FSID_SIZE); BTRFS_FSID_SIZE);
...@@ -1933,11 +1956,6 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen) ...@@ -1933,11 +1956,6 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen)
free_extent_buffer(leaf); free_extent_buffer(leaf);
leaf = NULL; leaf = NULL;
ret = btrfs_find_free_objectid(trans, root->fs_info->tree_root,
0, &objectid);
if (ret)
goto fail;
btrfs_set_root_dirid(&root_item, new_dirid); btrfs_set_root_dirid(&root_item, new_dirid);
key.objectid = objectid; key.objectid = objectid;
...@@ -2056,7 +2074,7 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen) ...@@ -2056,7 +2074,7 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen)
if (ret) if (ret)
goto fail; goto fail;
ret = btrfs_inc_root_ref(trans, root); ret = btrfs_inc_root_ref(trans, root, objectid);
if (ret) if (ret)
goto fail; goto fail;
fail: fail:
......
...@@ -33,6 +33,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) ...@@ -33,6 +33,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
struct btrfs_file_extent_item *fi; struct btrfs_file_extent_item *fi;
struct btrfs_key key; struct btrfs_key key;
struct btrfs_key found_key; struct btrfs_key found_key;
struct btrfs_extent_ref *ref;
u32 type; u32 type;
printk("leaf %llu total ptrs %d free space %d\n", printk("leaf %llu total ptrs %d free space %d\n",
...@@ -73,6 +74,15 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) ...@@ -73,6 +74,15 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
printk("\t\textent data refs %u\n", printk("\t\textent data refs %u\n",
btrfs_extent_refs(l, ei)); btrfs_extent_refs(l, ei));
break; break;
case BTRFS_EXTENT_REF_KEY:
ref = btrfs_item_ptr(l, i, struct btrfs_extent_ref);
printk("\t\textent back ref root %llu gen %llu "
"owner %llu offset %llu\n",
(unsigned long long)btrfs_ref_root(l, ref),
(unsigned long long)btrfs_ref_generation(l, ref),
(unsigned long long)btrfs_ref_objectid(l, ref),
(unsigned long long)btrfs_ref_offset(l, ref));
break;
case BTRFS_EXTENT_DATA_KEY: case BTRFS_EXTENT_DATA_KEY:
fi = btrfs_item_ptr(l, i, fi = btrfs_item_ptr(l, i,
......
...@@ -78,6 +78,8 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans, ...@@ -78,6 +78,8 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans,
break; break;
if (*level == 1) { if (*level == 1) {
WARN_ON(btrfs_header_generation(path->nodes[*level]) !=
trans->transid);
ret = btrfs_realloc_node(trans, root, ret = btrfs_realloc_node(trans, root,
path->nodes[*level], path->nodes[*level],
path->slots[*level], path->slots[*level],
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment