summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ctree.h8
-rw-r--r--disk-io.c26
-rw-r--r--mkfs.c1
-rw-r--r--utils.c2
4 files changed, 33 insertions, 4 deletions
diff --git a/ctree.h b/ctree.h
index 9b16275b..ede36540 100644
--- a/ctree.h
+++ b/ctree.h
@@ -279,6 +279,7 @@ struct btrfs_super_block {
__le32 leafsize;
__le32 stripesize;
__le32 sys_chunk_array_size;
+ __le64 chunk_root_generation;
u8 root_level;
u8 chunk_root_level;
u8 log_root_level;
@@ -421,6 +422,7 @@ struct btrfs_dir_item {
struct btrfs_root_item {
struct btrfs_inode_item inode;
+ __le64 generation;
__le64 root_dirid;
__le64 bytenr;
__le64 byte_limit;
@@ -1234,10 +1236,14 @@ static inline int btrfs_is_leaf(struct extent_buffer *eb)
}
/* struct btrfs_root_item */
+BTRFS_SETGET_FUNCS(disk_root_generation, struct btrfs_root_item,
+ generation, 64);
BTRFS_SETGET_FUNCS(disk_root_refs, struct btrfs_root_item, refs, 32);
BTRFS_SETGET_FUNCS(disk_root_bytenr, struct btrfs_root_item, bytenr, 64);
BTRFS_SETGET_FUNCS(disk_root_level, struct btrfs_root_item, level, 8);
+BTRFS_SETGET_STACK_FUNCS(root_generation, struct btrfs_root_item,
+ generation, 64);
BTRFS_SETGET_STACK_FUNCS(root_bytenr, struct btrfs_root_item, bytenr, 64);
BTRFS_SETGET_STACK_FUNCS(root_level, struct btrfs_root_item, level, 8);
BTRFS_SETGET_STACK_FUNCS(root_dirid, struct btrfs_root_item, root_dirid, 64);
@@ -1253,6 +1259,8 @@ BTRFS_SETGET_STACK_FUNCS(super_generation, struct btrfs_super_block,
BTRFS_SETGET_STACK_FUNCS(super_root, struct btrfs_super_block, root, 64);
BTRFS_SETGET_STACK_FUNCS(super_sys_array_size,
struct btrfs_super_block, sys_chunk_array_size, 32);
+BTRFS_SETGET_STACK_FUNCS(super_chunk_root_generation,
+ struct btrfs_super_block, chunk_root_generation, 64);
BTRFS_SETGET_STACK_FUNCS(super_root_level, struct btrfs_super_block,
root_level, 8);
BTRFS_SETGET_STACK_FUNCS(super_chunk_root, struct btrfs_super_block,
diff --git a/disk-io.c b/disk-io.c
index f2cbd4af..06815728 100644
--- a/disk-io.c
+++ b/disk-io.c
@@ -274,6 +274,8 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,
break;
btrfs_set_root_bytenr(&root->root_item,
root->node->start);
+ btrfs_set_root_generation(&root->root_item,
+ trans->transid);
root->root_item.level = btrfs_header_level(root->node);
ret = btrfs_update_root(trans, tree_root,
&root->root_key,
@@ -289,6 +291,12 @@ static int commit_tree_roots(struct btrfs_trans_handle *trans,
{
struct btrfs_root *root;
struct list_head *next;
+ struct extent_buffer *eb;
+
+ eb = fs_info->tree_root->node;
+ extent_buffer_get(eb);
+ btrfs_cow_block(trans, fs_info->tree_root, eb, NULL, 0, &eb);
+ free_extent_buffer(eb);
while(!list_empty(&fs_info->dirty_cowonly_roots)) {
next = fs_info->dirty_cowonly_roots.next;
@@ -345,6 +353,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
root->root_key.offset = trans->transid;
btrfs_set_root_bytenr(&root->root_item, root->node->start);
+ btrfs_set_root_generation(&root->root_item, root->root_key.offset);
root->root_item.level = btrfs_header_level(root->node);
ret = btrfs_insert_root(trans, fs_info->tree_root,
&root->root_key, &root->root_item);
@@ -395,6 +404,7 @@ static int find_and_setup_root(struct btrfs_root *tree_root,
{
int ret;
u32 blocksize;
+ u64 generation;
__setup_root(tree_root->nodesize, tree_root->leafsize,
tree_root->sectorsize, tree_root->stripesize,
@@ -404,8 +414,9 @@ static int find_and_setup_root(struct btrfs_root *tree_root,
BUG_ON(ret);
blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item));
+ generation = btrfs_root_generation(&root->root_item);
root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item),
- blocksize, 0);
+ blocksize, generation);
BUG_ON(!root->node);
return 0;
}
@@ -428,6 +439,7 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
struct btrfs_root *tree_root = fs_info->tree_root;
struct btrfs_path *path;
struct extent_buffer *l;
+ u64 generation;
u32 blocksize;
int ret = 0;
@@ -470,9 +482,10 @@ out:
free(root);
return ERR_PTR(ret);
}
+ generation = btrfs_root_generation(&root->root_item);
blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item));
root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item),
- blocksize, 0);
+ blocksize, generation);
BUG_ON(!root->node);
insert:
root->ref_cows = 1;
@@ -506,6 +519,7 @@ struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
u32 leafsize;
u32 blocksize;
u32 stripesize;
+ u64 generation;
struct btrfs_root *root = malloc(sizeof(struct btrfs_root));
struct btrfs_root *tree_root = malloc(sizeof(struct btrfs_root));
struct btrfs_root *extent_root = malloc(sizeof(struct btrfs_root));
@@ -604,13 +618,14 @@ struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
BUG_ON(ret);
blocksize = btrfs_level_size(tree_root,
btrfs_super_chunk_root_level(disk_super));
+ generation = btrfs_super_chunk_root_generation(disk_super);
__setup_root(nodesize, leafsize, sectorsize, stripesize,
chunk_root, fs_info, BTRFS_CHUNK_TREE_OBJECTID);
chunk_root->node = read_tree_block(chunk_root,
btrfs_super_chunk_root(disk_super),
- blocksize, 0);
+ blocksize, generation);
BUG_ON(!chunk_root->node);
@@ -623,10 +638,11 @@ struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
blocksize = btrfs_level_size(tree_root,
btrfs_super_root_level(disk_super));
+ generation = btrfs_super_generation(disk_super);
tree_root->node = read_tree_block(tree_root,
btrfs_super_root(disk_super),
- blocksize, 0);
+ blocksize, generation);
BUG_ON(!tree_root->node);
ret = find_and_setup_root(tree_root, fs_info,
BTRFS_EXTENT_TREE_OBJECTID, extent_root);
@@ -706,6 +722,8 @@ int write_ctree_super(struct btrfs_trans_handle *trans,
chunk_root->node->start);
btrfs_set_super_chunk_root_level(&root->fs_info->super_copy,
btrfs_header_level(chunk_root->node));
+ btrfs_set_super_chunk_root_generation(&root->fs_info->super_copy,
+ btrfs_header_generation(chunk_root->node));
write_extent_buffer(root->fs_info->sb_buffer,
&root->fs_info->super_copy, 0,
sizeof(root->fs_info->super_copy));
diff --git a/mkfs.c b/mkfs.c
index 3c09c3a9..dae43e97 100644
--- a/mkfs.c
+++ b/mkfs.c
@@ -247,6 +247,7 @@ static int create_data_reloc_tree(struct btrfs_trans_handle *trans,
memcpy(&root_item, &root->root_item, sizeof(root_item));
btrfs_set_root_bytenr(&root_item, tmp->start);
btrfs_set_root_level(&root_item, btrfs_header_level(tmp));
+ btrfs_set_root_generation(&root_item, trans->transid);
free_extent_buffer(tmp);
location.objectid = objectid;
diff --git a/utils.c b/utils.c
index 6b76dd3c..fa3cef46 100644
--- a/utils.c
+++ b/utils.c
@@ -101,6 +101,7 @@ int make_btrfs(int fd, const char *device, const char *label,
btrfs_set_super_leafsize(&super, leafsize);
btrfs_set_super_nodesize(&super, nodesize);
btrfs_set_super_stripesize(&super, stripesize);
+ btrfs_set_super_chunk_root_generation(&super, 1);
if (label)
strcpy(super.label, label);
@@ -130,6 +131,7 @@ int make_btrfs(int fd, const char *device, const char *label,
btrfs_set_stack_inode_mode(inode_item, S_IFDIR | 0755);
btrfs_set_root_refs(&root_item, 1);
btrfs_set_root_used(&root_item, leafsize);
+ btrfs_set_root_generation(&root_item, 1);
memset(&disk_key, 0, sizeof(disk_key));
btrfs_set_disk_key_type(&disk_key, BTRFS_ROOT_ITEM_KEY);