Skip to content

Commit 84234f3

Browse files
Yan Zhengchrismason-xx
authored andcommitted
Btrfs: Add root tree pointer transaction ids
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 <[email protected]>
1 parent 2517920 commit 84234f3

File tree

6 files changed

+39
-7
lines changed

6 files changed

+39
-7
lines changed

fs/btrfs/ctree.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ struct btrfs_super_block {
297297
__le32 leafsize;
298298
__le32 stripesize;
299299
__le32 sys_chunk_array_size;
300+
__le64 chunk_root_generation;
300301
u8 root_level;
301302
u8 chunk_root_level;
302303
u8 log_root_level;
@@ -448,6 +449,7 @@ struct btrfs_dir_item {
448449

449450
struct btrfs_root_item {
450451
struct btrfs_inode_item inode;
452+
__le64 generation;
451453
__le64 root_dirid;
452454
__le64 bytenr;
453455
__le64 byte_limit;
@@ -1396,10 +1398,14 @@ static inline int btrfs_is_leaf(struct extent_buffer *eb)
13961398
}
13971399

13981400
/* struct btrfs_root_item */
1401+
BTRFS_SETGET_FUNCS(disk_root_generation, struct btrfs_root_item,
1402+
generation, 64);
13991403
BTRFS_SETGET_FUNCS(disk_root_refs, struct btrfs_root_item, refs, 32);
14001404
BTRFS_SETGET_FUNCS(disk_root_bytenr, struct btrfs_root_item, bytenr, 64);
14011405
BTRFS_SETGET_FUNCS(disk_root_level, struct btrfs_root_item, level, 8);
14021406

1407+
BTRFS_SETGET_STACK_FUNCS(root_generation, struct btrfs_root_item,
1408+
generation, 64);
14031409
BTRFS_SETGET_STACK_FUNCS(root_bytenr, struct btrfs_root_item, bytenr, 64);
14041410
BTRFS_SETGET_STACK_FUNCS(root_level, struct btrfs_root_item, level, 8);
14051411
BTRFS_SETGET_STACK_FUNCS(root_dirid, struct btrfs_root_item, root_dirid, 64);
@@ -1416,6 +1422,8 @@ BTRFS_SETGET_STACK_FUNCS(super_generation, struct btrfs_super_block,
14161422
BTRFS_SETGET_STACK_FUNCS(super_root, struct btrfs_super_block, root, 64);
14171423
BTRFS_SETGET_STACK_FUNCS(super_sys_array_size,
14181424
struct btrfs_super_block, sys_chunk_array_size, 32);
1425+
BTRFS_SETGET_STACK_FUNCS(super_chunk_root_generation,
1426+
struct btrfs_super_block, chunk_root_generation, 64);
14191427
BTRFS_SETGET_STACK_FUNCS(super_root_level, struct btrfs_super_block,
14201428
root_level, 8);
14211429
BTRFS_SETGET_STACK_FUNCS(super_chunk_root, struct btrfs_super_block,

fs/btrfs/disk-io.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,7 @@ static int find_and_setup_root(struct btrfs_root *tree_root,
832832
{
833833
int ret;
834834
u32 blocksize;
835+
u64 generation;
835836

836837
__setup_root(tree_root->nodesize, tree_root->leafsize,
837838
tree_root->sectorsize, tree_root->stripesize,
@@ -840,9 +841,10 @@ static int find_and_setup_root(struct btrfs_root *tree_root,
840841
&root->root_item, &root->root_key);
841842
BUG_ON(ret);
842843

844+
generation = btrfs_root_generation(&root->root_item);
843845
blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item));
844846
root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item),
845-
blocksize, 0);
847+
blocksize, generation);
846848
BUG_ON(!root->node);
847849
return 0;
848850
}
@@ -929,6 +931,7 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root,
929931
struct btrfs_path *path;
930932
struct extent_buffer *l;
931933
u64 highest_inode;
934+
u64 generation;
932935
u32 blocksize;
933936
int ret = 0;
934937

@@ -970,9 +973,10 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root,
970973
kfree(root);
971974
return ERR_PTR(ret);
972975
}
976+
generation = btrfs_root_generation(&root->root_item);
973977
blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item));
974978
root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item),
975-
blocksize, 0);
979+
blocksize, generation);
976980
BUG_ON(!root->node);
977981
insert:
978982
if (location->objectid != BTRFS_TREE_LOG_OBJECTID) {
@@ -1357,6 +1361,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
13571361
u32 leafsize;
13581362
u32 blocksize;
13591363
u32 stripesize;
1364+
u64 generation;
13601365
struct buffer_head *bh;
13611366
struct btrfs_root *extent_root = kzalloc(sizeof(struct btrfs_root),
13621367
GFP_NOFS);
@@ -1596,13 +1601,14 @@ struct btrfs_root *open_ctree(struct super_block *sb,
15961601

15971602
blocksize = btrfs_level_size(tree_root,
15981603
btrfs_super_chunk_root_level(disk_super));
1604+
generation = btrfs_super_chunk_root_generation(disk_super);
15991605

16001606
__setup_root(nodesize, leafsize, sectorsize, stripesize,
16011607
chunk_root, fs_info, BTRFS_CHUNK_TREE_OBJECTID);
16021608

16031609
chunk_root->node = read_tree_block(chunk_root,
16041610
btrfs_super_chunk_root(disk_super),
1605-
blocksize, 0);
1611+
blocksize, generation);
16061612
BUG_ON(!chunk_root->node);
16071613

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

16191625
blocksize = btrfs_level_size(tree_root,
16201626
btrfs_super_root_level(disk_super));
1621-
1627+
generation = btrfs_super_generation(disk_super);
16221628

16231629
tree_root->node = read_tree_block(tree_root,
16241630
btrfs_super_root(disk_super),
1625-
blocksize, 0);
1631+
blocksize, generation);
16261632
if (!tree_root->node)
16271633
goto fail_sb_buffer;
16281634

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

16741680
log_tree_root->node = read_tree_block(tree_root, bytenr,
1675-
blocksize, 0);
1681+
blocksize,
1682+
generation + 1);
16761683
ret = btrfs_recover_log_trees(log_tree_root);
16771684
BUG_ON(ret);
16781685
}
1686+
fs_info->last_trans_committed = btrfs_super_generation(disk_super);
16791687

16801688
ret = btrfs_cleanup_reloc_trees(tree_root);
16811689
BUG_ON(ret);
16821690

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

16861693
fail_cleaner:

fs/btrfs/extent-tree.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4428,6 +4428,7 @@ static int noinline init_reloc_tree(struct btrfs_trans_handle *trans,
44284428
btrfs_set_root_refs(root_item, 0);
44294429
btrfs_set_root_bytenr(root_item, eb->start);
44304430
btrfs_set_root_level(root_item, btrfs_header_level(eb));
4431+
btrfs_set_root_generation(root_item, trans->transid);
44314432

44324433
btrfs_tree_unlock(eb);
44334434
free_extent_buffer(eb);

fs/btrfs/ioctl.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ static noinline int create_subvol(struct btrfs_root *root,
108108
inode_item->mode = cpu_to_le32(S_IFDIR | 0755);
109109

110110
btrfs_set_root_bytenr(&root_item, leaf->start);
111+
btrfs_set_root_generation(&root_item, trans->transid);
111112
btrfs_set_root_level(&root_item, 0);
112113
btrfs_set_root_refs(&root_item, 1);
113114
btrfs_set_root_used(&root_item, 0);

fs/btrfs/transaction.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,7 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,
439439
root->node->start);
440440
btrfs_set_root_level(&root->root_item,
441441
btrfs_header_level(root->node));
442+
btrfs_set_root_generation(&root->root_item, trans->transid);
442443
ret = btrfs_update_root(trans, tree_root,
443444
&root->root_key,
444445
&root->root_item);
@@ -456,6 +457,12 @@ int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans,
456457
{
457458
struct btrfs_fs_info *fs_info = root->fs_info;
458459
struct list_head *next;
460+
struct extent_buffer *eb;
461+
462+
eb = btrfs_lock_root_node(fs_info->tree_root);
463+
btrfs_cow_block(trans, fs_info->tree_root, eb, NULL, 0, &eb, 0);
464+
btrfs_tree_unlock(eb);
465+
free_extent_buffer(eb);
459466

460467
while(!list_empty(&fs_info->dirty_cowonly_roots)) {
461468
next = fs_info->dirty_cowonly_roots.next;
@@ -559,6 +566,9 @@ static noinline int add_dirty_roots(struct btrfs_trans_handle *trans,
559566
root->node->start);
560567
btrfs_set_root_level(&root->root_item,
561568
btrfs_header_level(root->node));
569+
btrfs_set_root_generation(&root->root_item,
570+
root->root_key.offset);
571+
562572
err = btrfs_insert_root(trans, root->fs_info->tree_root,
563573
&root->root_key,
564574
&root->root_item);
@@ -756,6 +766,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
756766

757767
btrfs_set_root_bytenr(new_root_item, tmp->start);
758768
btrfs_set_root_level(new_root_item, btrfs_header_level(tmp));
769+
btrfs_set_root_generation(new_root_item, trans->transid);
759770
ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key,
760771
new_root_item);
761772
btrfs_tree_unlock(tmp);
@@ -946,6 +957,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
946957
chunk_root->node->start);
947958
btrfs_set_super_chunk_root_level(&root->fs_info->super_copy,
948959
btrfs_header_level(chunk_root->node));
960+
btrfs_set_super_chunk_root_generation(&root->fs_info->super_copy,
961+
btrfs_header_generation(chunk_root->node));
949962

950963
if (!root->fs_info->log_root_recovering) {
951964
btrfs_set_super_log_root(&root->fs_info->super_copy, 0);

fs/btrfs/tree-log.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ int btrfs_add_log_tree(struct btrfs_trans_handle *trans,
117117
inode_item->mode = cpu_to_le32(S_IFDIR | 0755);
118118

119119
btrfs_set_root_bytenr(&root_item, leaf->start);
120+
btrfs_set_root_generation(&root_item, trans->transid);
120121
btrfs_set_root_level(&root_item, 0);
121122
btrfs_set_root_refs(&root_item, 0);
122123
btrfs_set_root_used(&root_item, 0);
@@ -2065,6 +2066,7 @@ static int update_log_root(struct btrfs_trans_handle *trans,
20652066
return 0;
20662067

20672068
btrfs_set_root_bytenr(&log->root_item, log->node->start);
2069+
btrfs_set_root_generation(&log->root_item, trans->transid);
20682070
btrfs_set_root_level(&log->root_item, btrfs_header_level(log->node));
20692071
ret = btrfs_update_root(trans, log->fs_info->log_root_tree,
20702072
&log->root_key, &log->root_item);

0 commit comments

Comments
 (0)