Commit 74493f7a authored by Chris Mason's avatar Chris Mason

Btrfs: Implement generation numbers in block pointers

Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 17636e03
...@@ -114,6 +114,9 @@ static int __btrfs_cow_block(struct btrfs_trans_handle *trans, ...@@ -114,6 +114,9 @@ static int __btrfs_cow_block(struct btrfs_trans_handle *trans,
} else { } else {
btrfs_set_node_blockptr(parent, parent_slot, btrfs_set_node_blockptr(parent, parent_slot,
cow->start); cow->start);
WARN_ON(trans->transid == 0);
btrfs_set_node_ptr_generation(parent, parent_slot,
trans->transid);
btrfs_mark_buffer_dirty(parent); btrfs_mark_buffer_dirty(parent);
WARN_ON(btrfs_header_generation(parent) != trans->transid); WARN_ON(btrfs_header_generation(parent) != trans->transid);
btrfs_free_extent(trans, root, buf->start, buf->len, 1); btrfs_free_extent(trans, root, buf->start, buf->len, 1);
...@@ -967,6 +970,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -967,6 +970,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
{ {
struct extent_buffer *b; struct extent_buffer *b;
u64 bytenr; u64 bytenr;
u64 ptr_gen;
int slot; int slot;
int ret; int ret;
int level; int level;
...@@ -1031,10 +1035,18 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1031,10 +1035,18 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
if (level == lowest_level) if (level == lowest_level)
break; break;
bytenr = btrfs_node_blockptr(b, slot); bytenr = btrfs_node_blockptr(b, slot);
ptr_gen = btrfs_node_ptr_generation(b, slot);
if (should_reada) if (should_reada)
reada_for_search(root, p, level, slot); reada_for_search(root, p, level, slot);
b = read_tree_block(root, bytenr, b = read_tree_block(root, bytenr,
btrfs_level_size(root, level - 1)); btrfs_level_size(root, level - 1));
if (ptr_gen != btrfs_header_generation(b)) {
printk("block %llu bad gen wanted %llu "
"found %llu\n",
(unsigned long long)b->start,
(unsigned long long)ptr_gen,
(unsigned long long)btrfs_header_generation(b));
}
} else { } else {
p->slots[level] = slot; p->slots[level] = slot;
if (ins_len > 0 && btrfs_leaf_free_space(root, b) < if (ins_len > 0 && btrfs_leaf_free_space(root, b) <
...@@ -1218,6 +1230,8 @@ static int insert_new_root(struct btrfs_trans_handle *trans, ...@@ -1218,6 +1230,8 @@ static int insert_new_root(struct btrfs_trans_handle *trans,
btrfs_node_key(lower, &lower_key, 0); btrfs_node_key(lower, &lower_key, 0);
btrfs_set_node_key(c, &lower_key, 0); btrfs_set_node_key(c, &lower_key, 0);
btrfs_set_node_blockptr(c, 0, lower->start); btrfs_set_node_blockptr(c, 0, lower->start);
WARN_ON(btrfs_header_generation(lower) == 0);
btrfs_set_node_ptr_generation(c, 0, btrfs_header_generation(lower));
btrfs_mark_buffer_dirty(c); btrfs_mark_buffer_dirty(c);
...@@ -1261,6 +1275,8 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1261,6 +1275,8 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root
} }
btrfs_set_node_key(lower, key, slot); btrfs_set_node_key(lower, key, slot);
btrfs_set_node_blockptr(lower, slot, bytenr); btrfs_set_node_blockptr(lower, slot, bytenr);
WARN_ON(trans->transid == 0);
btrfs_set_node_ptr_generation(lower, slot, trans->transid);
btrfs_set_header_nritems(lower, nritems + 1); btrfs_set_header_nritems(lower, nritems + 1);
btrfs_mark_buffer_dirty(lower); btrfs_mark_buffer_dirty(lower);
return 0; return 0;
......
...@@ -110,7 +110,7 @@ struct btrfs_header { ...@@ -110,7 +110,7 @@ struct btrfs_header {
#define BTRFS_MAX_LEVEL 8 #define BTRFS_MAX_LEVEL 8
#define BTRFS_NODEPTRS_PER_BLOCK(r) (((r)->nodesize - \ #define BTRFS_NODEPTRS_PER_BLOCK(r) (((r)->nodesize - \
sizeof(struct btrfs_header)) / \ sizeof(struct btrfs_header)) / \
(sizeof(struct btrfs_disk_key) + sizeof(u64))) sizeof(struct btrfs_key_ptr))
#define __BTRFS_LEAF_DATA_SIZE(bs) ((bs) - sizeof(struct btrfs_header)) #define __BTRFS_LEAF_DATA_SIZE(bs) ((bs) - sizeof(struct btrfs_header))
#define BTRFS_LEAF_DATA_SIZE(r) (__BTRFS_LEAF_DATA_SIZE(r->leafsize)) #define BTRFS_LEAF_DATA_SIZE(r) (__BTRFS_LEAF_DATA_SIZE(r->leafsize))
#define BTRFS_MAX_INLINE_DATA_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \ #define BTRFS_MAX_INLINE_DATA_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \
...@@ -168,6 +168,7 @@ struct btrfs_leaf { ...@@ -168,6 +168,7 @@ struct btrfs_leaf {
struct btrfs_key_ptr { struct btrfs_key_ptr {
struct btrfs_disk_key key; struct btrfs_disk_key key;
__le64 blockptr; __le64 blockptr;
__le64 generation;
} __attribute__ ((__packed__)); } __attribute__ ((__packed__));
struct btrfs_node { struct btrfs_node {
...@@ -196,7 +197,13 @@ struct btrfs_path { ...@@ -196,7 +197,13 @@ struct btrfs_path {
*/ */
struct btrfs_extent_item { struct btrfs_extent_item {
__le32 refs; __le32 refs;
__le64 owner; } __attribute__ ((__packed__));
struct btrfs_extent_ref {
__le64 root;
__le64 generation;
__le64 objectid;
__le64 offset;
} __attribute__ ((__packed__)); } __attribute__ ((__packed__));
struct btrfs_inode_timespec { struct btrfs_inode_timespec {
...@@ -402,12 +409,13 @@ struct btrfs_root { ...@@ -402,12 +409,13 @@ struct btrfs_root {
* are used, and how many references there are to each block * are used, and how many references there are to each block
*/ */
#define BTRFS_EXTENT_ITEM_KEY 33 #define BTRFS_EXTENT_ITEM_KEY 33
#define BTRFS_EXTENT_REF_KEY 34
/* /*
* block groups give us hints into the extent allocation trees. Which * block groups give us hints into the extent allocation trees. Which
* blocks are free etc etc * 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 * string items are for debugging. They just store a short string of
...@@ -529,15 +537,25 @@ BTRFS_SETGET_FUNCS(timespec_nsec, struct btrfs_inode_timespec, nsec, 32); ...@@ -529,15 +537,25 @@ BTRFS_SETGET_FUNCS(timespec_nsec, struct btrfs_inode_timespec, nsec, 32);
/* struct btrfs_extent_item */ /* struct btrfs_extent_item */
BTRFS_SETGET_FUNCS(extent_refs, struct btrfs_extent_item, refs, 32); BTRFS_SETGET_FUNCS(extent_refs, struct btrfs_extent_item, refs, 32);
BTRFS_SETGET_FUNCS(extent_owner, struct btrfs_extent_item, owner, 64);
/* struct btrfs_extent_ref */
BTRFS_SETGET_FUNCS(ref_root, struct btrfs_extent_ref, root, 64);
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_offset, struct btrfs_extent_ref, offset, 64);
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);
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);
BTRFS_SETGET_STACK_FUNCS(stack_extent_owner, struct btrfs_extent_item,
owner, 64);
/* struct btrfs_node */ /* struct btrfs_node */
BTRFS_SETGET_FUNCS(key_blockptr, struct btrfs_key_ptr, blockptr, 64); BTRFS_SETGET_FUNCS(key_blockptr, struct btrfs_key_ptr, blockptr, 64);
BTRFS_SETGET_FUNCS(key_generation, struct btrfs_key_ptr, generation, 64);
static inline u64 btrfs_node_blockptr(struct extent_buffer *eb, int nr) static inline u64 btrfs_node_blockptr(struct extent_buffer *eb, int nr)
{ {
...@@ -556,6 +574,23 @@ static inline void btrfs_set_node_blockptr(struct extent_buffer *eb, ...@@ -556,6 +574,23 @@ static inline void btrfs_set_node_blockptr(struct extent_buffer *eb,
btrfs_set_key_blockptr(eb, (struct btrfs_key_ptr *)ptr, val); btrfs_set_key_blockptr(eb, (struct btrfs_key_ptr *)ptr, val);
} }
static inline u64 btrfs_node_ptr_generation(struct extent_buffer *eb, int nr)
{
unsigned long ptr;
ptr = offsetof(struct btrfs_node, ptrs) +
sizeof(struct btrfs_key_ptr) * nr;
return btrfs_key_generation(eb, (struct btrfs_key_ptr *)ptr);
}
static inline void btrfs_set_node_ptr_generation(struct extent_buffer *eb,
int nr, u64 val)
{
unsigned long ptr;
ptr = offsetof(struct btrfs_node, ptrs) +
sizeof(struct btrfs_key_ptr) * nr;
btrfs_set_key_generation(eb, (struct btrfs_key_ptr *)ptr, val);
}
static inline unsigned long btrfs_node_key_ptr_offset(int nr) static inline unsigned long btrfs_node_key_ptr_offset(int nr)
{ {
return offsetof(struct btrfs_node, ptrs) + return offsetof(struct btrfs_node, ptrs) +
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
*/ */
#include <linux/sched.h> #include <linux/sched.h>
#include "hash.h"
#include "ctree.h" #include "ctree.h"
#include "disk-io.h" #include "disk-io.h"
#include "print-tree.h" #include "print-tree.h"
...@@ -352,9 +353,63 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, ...@@ -352,9 +353,63 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
return found_group; return found_group;
} }
static u64 hash_extent_ref(u64 root_objectid, u64 root_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(root_generation);
high_crc = crc32c(high_crc, &lenum, sizeof(lenum));
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));
return ((u64)high_crc << 32) | (u64)low_crc;
}
int insert_extent_ref(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
struct btrfs_path *path,
u64 bytenr,
u64 root_objectid, u64 root_generation,
u64 owner, u64 owner_offset)
{
u64 hash;
struct btrfs_key key;
struct btrfs_extent_ref ref;
struct extent_buffer *l;
struct btrfs_extent_item *item;
int ret;
btrfs_set_stack_ref_root(&ref, root_objectid);
btrfs_set_stack_ref_generation(&ref, root_generation);
btrfs_set_stack_ref_objectid(&ref, owner);
btrfs_set_stack_ref_offset(&ref, owner_offset);
ret = btrfs_name_hash(&ref, sizeof(ref), &hash);
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) {
}
}
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 root_generation,
u64 owner, u64 owner_offset)
{ {
struct btrfs_path *path; struct btrfs_path *path;
int ret; int ret;
...@@ -386,9 +441,10 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, ...@@ -386,9 +441,10 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
btrfs_mark_buffer_dirty(path->nodes[0]); btrfs_mark_buffer_dirty(path->nodes[0]);
btrfs_release_path(root->fs_info->extent_root, path); btrfs_release_path(root->fs_info->extent_root, path);
btrfs_free_path(path);
finish_current_insert(trans, root->fs_info->extent_root); finish_current_insert(trans, root->fs_info->extent_root);
del_pending_extents(trans, root->fs_info->extent_root); del_pending_extents(trans, root->fs_info->extent_root);
btrfs_free_path(path);
return 0; return 0;
} }
......
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