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);