Skip to content

Commit

Permalink
Btrfs: Add root tree pointer transaction ids
Browse files Browse the repository at this point in the history
This patch adds transaction IDs to root tree pointers.
Transaction IDs in tree pointers are compared with the
generation numbers in block headers when reading root
blocks of trees. This can detect some types of IO errors.

Signed-off-by: Yan Zheng <zheng.yan@oracle.com>
  • Loading branch information
Yan Zheng authored and Chris Mason committed Oct 29, 2008
1 parent 2517920 commit 84234f3
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 7 deletions.
8 changes: 8 additions & 0 deletions fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,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;
Expand Down Expand Up @@ -448,6 +449,7 @@ struct btrfs_dir_item {

struct btrfs_root_item {
struct btrfs_inode_item inode;
__le64 generation;
__le64 root_dirid;
__le64 bytenr;
__le64 byte_limit;
Expand Down Expand Up @@ -1396,10 +1398,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);
Expand All @@ -1416,6 +1422,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,
Expand Down
21 changes: 14 additions & 7 deletions fs/btrfs/disk-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -832,6 +832,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,
Expand All @@ -840,9 +841,10 @@ static int find_and_setup_root(struct btrfs_root *tree_root,
&root->root_item, &root->root_key);
BUG_ON(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);
return 0;
}
Expand Down Expand Up @@ -929,6 +931,7 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root,
struct btrfs_path *path;
struct extent_buffer *l;
u64 highest_inode;
u64 generation;
u32 blocksize;
int ret = 0;

Expand Down Expand Up @@ -970,9 +973,10 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root,
kfree(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:
if (location->objectid != BTRFS_TREE_LOG_OBJECTID) {
Expand Down Expand Up @@ -1357,6 +1361,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
u32 leafsize;
u32 blocksize;
u32 stripesize;
u64 generation;
struct buffer_head *bh;
struct btrfs_root *extent_root = kzalloc(sizeof(struct btrfs_root),
GFP_NOFS);
Expand Down Expand Up @@ -1596,13 +1601,14 @@ struct btrfs_root *open_ctree(struct super_block *sb,

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

read_extent_buffer(chunk_root->node, fs_info->chunk_tree_uuid,
Expand All @@ -1618,11 +1624,11 @@ struct btrfs_root *open_ctree(struct super_block *sb,

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);
if (!tree_root->node)
goto fail_sb_buffer;

Expand Down Expand Up @@ -1672,15 +1678,16 @@ struct btrfs_root *open_ctree(struct super_block *sb,
log_tree_root, fs_info, BTRFS_TREE_LOG_OBJECTID);

log_tree_root->node = read_tree_block(tree_root, bytenr,
blocksize, 0);
blocksize,
generation + 1);
ret = btrfs_recover_log_trees(log_tree_root);
BUG_ON(ret);
}
fs_info->last_trans_committed = btrfs_super_generation(disk_super);

ret = btrfs_cleanup_reloc_trees(tree_root);
BUG_ON(ret);

fs_info->last_trans_committed = btrfs_super_generation(disk_super);
return tree_root;

fail_cleaner:
Expand Down
1 change: 1 addition & 0 deletions fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -4428,6 +4428,7 @@ static int noinline init_reloc_tree(struct btrfs_trans_handle *trans,
btrfs_set_root_refs(root_item, 0);
btrfs_set_root_bytenr(root_item, eb->start);
btrfs_set_root_level(root_item, btrfs_header_level(eb));
btrfs_set_root_generation(root_item, trans->transid);

btrfs_tree_unlock(eb);
free_extent_buffer(eb);
Expand Down
1 change: 1 addition & 0 deletions fs/btrfs/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ static noinline int create_subvol(struct btrfs_root *root,
inode_item->mode = cpu_to_le32(S_IFDIR | 0755);

btrfs_set_root_bytenr(&root_item, leaf->start);
btrfs_set_root_generation(&root_item, trans->transid);
btrfs_set_root_level(&root_item, 0);
btrfs_set_root_refs(&root_item, 1);
btrfs_set_root_used(&root_item, 0);
Expand Down
13 changes: 13 additions & 0 deletions fs/btrfs/transaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,7 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,
root->node->start);
btrfs_set_root_level(&root->root_item,
btrfs_header_level(root->node));
btrfs_set_root_generation(&root->root_item, trans->transid);
ret = btrfs_update_root(trans, tree_root,
&root->root_key,
&root->root_item);
Expand All @@ -456,6 +457,12 @@ int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans,
{
struct btrfs_fs_info *fs_info = root->fs_info;
struct list_head *next;
struct extent_buffer *eb;

eb = btrfs_lock_root_node(fs_info->tree_root);
btrfs_cow_block(trans, fs_info->tree_root, eb, NULL, 0, &eb, 0);
btrfs_tree_unlock(eb);
free_extent_buffer(eb);

while(!list_empty(&fs_info->dirty_cowonly_roots)) {
next = fs_info->dirty_cowonly_roots.next;
Expand Down Expand Up @@ -559,6 +566,9 @@ static noinline int add_dirty_roots(struct btrfs_trans_handle *trans,
root->node->start);
btrfs_set_root_level(&root->root_item,
btrfs_header_level(root->node));
btrfs_set_root_generation(&root->root_item,
root->root_key.offset);

err = btrfs_insert_root(trans, root->fs_info->tree_root,
&root->root_key,
&root->root_item);
Expand Down Expand Up @@ -756,6 +766,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,

btrfs_set_root_bytenr(new_root_item, tmp->start);
btrfs_set_root_level(new_root_item, btrfs_header_level(tmp));
btrfs_set_root_generation(new_root_item, trans->transid);
ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key,
new_root_item);
btrfs_tree_unlock(tmp);
Expand Down Expand Up @@ -946,6 +957,8 @@ int btrfs_commit_transaction(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));

if (!root->fs_info->log_root_recovering) {
btrfs_set_super_log_root(&root->fs_info->super_copy, 0);
Expand Down
2 changes: 2 additions & 0 deletions fs/btrfs/tree-log.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ int btrfs_add_log_tree(struct btrfs_trans_handle *trans,
inode_item->mode = cpu_to_le32(S_IFDIR | 0755);

btrfs_set_root_bytenr(&root_item, leaf->start);
btrfs_set_root_generation(&root_item, trans->transid);
btrfs_set_root_level(&root_item, 0);
btrfs_set_root_refs(&root_item, 0);
btrfs_set_root_used(&root_item, 0);
Expand Down Expand Up @@ -2065,6 +2066,7 @@ static int update_log_root(struct btrfs_trans_handle *trans,
return 0;

btrfs_set_root_bytenr(&log->root_item, log->node->start);
btrfs_set_root_generation(&log->root_item, trans->transid);
btrfs_set_root_level(&log->root_item, btrfs_header_level(log->node));
ret = btrfs_update_root(trans, log->fs_info->log_root_tree,
&log->root_key, &log->root_item);
Expand Down

0 comments on commit 84234f3

Please sign in to comment.