aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorYan Zheng <zheng.yan@oracle.com>2008-10-29 14:49:05 -0400
committerChris Mason <chris.mason@oracle.com>2008-10-29 14:49:05 -0400
commit84234f3a1f7c532e4afeba03cc8e7e4a8a5277ea (patch)
treec41f249b448f28b648b21c3898d0763b9c67ca6a /fs/btrfs
parent2517920135b0d29e70453e5b03d70d7b94207df3 (diff)
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 <zheng.yan@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/ctree.h8
-rw-r--r--fs/btrfs/disk-io.c21
-rw-r--r--fs/btrfs/extent-tree.c1
-rw-r--r--fs/btrfs/ioctl.c1
-rw-r--r--fs/btrfs/transaction.c13
-rw-r--r--fs/btrfs/tree-log.c2
6 files changed, 39 insertions, 7 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index fdba4f1b634e..0621ab90b1a5 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -297,6 +297,7 @@ struct btrfs_super_block {
297 __le32 leafsize; 297 __le32 leafsize;
298 __le32 stripesize; 298 __le32 stripesize;
299 __le32 sys_chunk_array_size; 299 __le32 sys_chunk_array_size;
300 __le64 chunk_root_generation;
300 u8 root_level; 301 u8 root_level;
301 u8 chunk_root_level; 302 u8 chunk_root_level;
302 u8 log_root_level; 303 u8 log_root_level;
@@ -448,6 +449,7 @@ struct btrfs_dir_item {
448 449
449struct btrfs_root_item { 450struct btrfs_root_item {
450 struct btrfs_inode_item inode; 451 struct btrfs_inode_item inode;
452 __le64 generation;
451 __le64 root_dirid; 453 __le64 root_dirid;
452 __le64 bytenr; 454 __le64 bytenr;
453 __le64 byte_limit; 455 __le64 byte_limit;
@@ -1396,10 +1398,14 @@ static inline int btrfs_is_leaf(struct extent_buffer *eb)
1396} 1398}
1397 1399
1398/* struct btrfs_root_item */ 1400/* struct btrfs_root_item */
1401BTRFS_SETGET_FUNCS(disk_root_generation, struct btrfs_root_item,
1402 generation, 64);
1399BTRFS_SETGET_FUNCS(disk_root_refs, struct btrfs_root_item, refs, 32); 1403BTRFS_SETGET_FUNCS(disk_root_refs, struct btrfs_root_item, refs, 32);
1400BTRFS_SETGET_FUNCS(disk_root_bytenr, struct btrfs_root_item, bytenr, 64); 1404BTRFS_SETGET_FUNCS(disk_root_bytenr, struct btrfs_root_item, bytenr, 64);
1401BTRFS_SETGET_FUNCS(disk_root_level, struct btrfs_root_item, level, 8); 1405BTRFS_SETGET_FUNCS(disk_root_level, struct btrfs_root_item, level, 8);
1402 1406
1407BTRFS_SETGET_STACK_FUNCS(root_generation, struct btrfs_root_item,
1408 generation, 64);
1403BTRFS_SETGET_STACK_FUNCS(root_bytenr, struct btrfs_root_item, bytenr, 64); 1409BTRFS_SETGET_STACK_FUNCS(root_bytenr, struct btrfs_root_item, bytenr, 64);
1404BTRFS_SETGET_STACK_FUNCS(root_level, struct btrfs_root_item, level, 8); 1410BTRFS_SETGET_STACK_FUNCS(root_level, struct btrfs_root_item, level, 8);
1405BTRFS_SETGET_STACK_FUNCS(root_dirid, struct btrfs_root_item, root_dirid, 64); 1411BTRFS_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,
1416BTRFS_SETGET_STACK_FUNCS(super_root, struct btrfs_super_block, root, 64); 1422BTRFS_SETGET_STACK_FUNCS(super_root, struct btrfs_super_block, root, 64);
1417BTRFS_SETGET_STACK_FUNCS(super_sys_array_size, 1423BTRFS_SETGET_STACK_FUNCS(super_sys_array_size,
1418 struct btrfs_super_block, sys_chunk_array_size, 32); 1424 struct btrfs_super_block, sys_chunk_array_size, 32);
1425BTRFS_SETGET_STACK_FUNCS(super_chunk_root_generation,
1426 struct btrfs_super_block, chunk_root_generation, 64);
1419BTRFS_SETGET_STACK_FUNCS(super_root_level, struct btrfs_super_block, 1427BTRFS_SETGET_STACK_FUNCS(super_root_level, struct btrfs_super_block,
1420 root_level, 8); 1428 root_level, 8);
1421BTRFS_SETGET_STACK_FUNCS(super_chunk_root, struct btrfs_super_block, 1429BTRFS_SETGET_STACK_FUNCS(super_chunk_root, struct btrfs_super_block,
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index d1137d7ea8d4..94b4e50f6b2c 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -832,6 +832,7 @@ static int find_and_setup_root(struct btrfs_root *tree_root,
832{ 832{
833 int ret; 833 int ret;
834 u32 blocksize; 834 u32 blocksize;
835 u64 generation;
835 836
836 __setup_root(tree_root->nodesize, tree_root->leafsize, 837 __setup_root(tree_root->nodesize, tree_root->leafsize,
837 tree_root->sectorsize, tree_root->stripesize, 838 tree_root->sectorsize, tree_root->stripesize,
@@ -840,9 +841,10 @@ static int find_and_setup_root(struct btrfs_root *tree_root,
840 &root->root_item, &root->root_key); 841 &root->root_item, &root->root_key);
841 BUG_ON(ret); 842 BUG_ON(ret);
842 843
844 generation = btrfs_root_generation(&root->root_item);
843 blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item)); 845 blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item));
844 root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), 846 root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item),
845 blocksize, 0); 847 blocksize, generation);
846 BUG_ON(!root->node); 848 BUG_ON(!root->node);
847 return 0; 849 return 0;
848} 850}
@@ -929,6 +931,7 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root,
929 struct btrfs_path *path; 931 struct btrfs_path *path;
930 struct extent_buffer *l; 932 struct extent_buffer *l;
931 u64 highest_inode; 933 u64 highest_inode;
934 u64 generation;
932 u32 blocksize; 935 u32 blocksize;
933 int ret = 0; 936 int ret = 0;
934 937
@@ -970,9 +973,10 @@ out:
970 kfree(root); 973 kfree(root);
971 return ERR_PTR(ret); 974 return ERR_PTR(ret);
972 } 975 }
976 generation = btrfs_root_generation(&root->root_item);
973 blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item)); 977 blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item));
974 root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), 978 root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item),
975 blocksize, 0); 979 blocksize, generation);
976 BUG_ON(!root->node); 980 BUG_ON(!root->node);
977insert: 981insert:
978 if (location->objectid != BTRFS_TREE_LOG_OBJECTID) { 982 if (location->objectid != BTRFS_TREE_LOG_OBJECTID) {
@@ -1357,6 +1361,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1357 u32 leafsize; 1361 u32 leafsize;
1358 u32 blocksize; 1362 u32 blocksize;
1359 u32 stripesize; 1363 u32 stripesize;
1364 u64 generation;
1360 struct buffer_head *bh; 1365 struct buffer_head *bh;
1361 struct btrfs_root *extent_root = kzalloc(sizeof(struct btrfs_root), 1366 struct btrfs_root *extent_root = kzalloc(sizeof(struct btrfs_root),
1362 GFP_NOFS); 1367 GFP_NOFS);
@@ -1596,13 +1601,14 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1596 1601
1597 blocksize = btrfs_level_size(tree_root, 1602 blocksize = btrfs_level_size(tree_root,
1598 btrfs_super_chunk_root_level(disk_super)); 1603 btrfs_super_chunk_root_level(disk_super));
1604 generation = btrfs_super_chunk_root_generation(disk_super);
1599 1605
1600 __setup_root(nodesize, leafsize, sectorsize, stripesize, 1606 __setup_root(nodesize, leafsize, sectorsize, stripesize,
1601 chunk_root, fs_info, BTRFS_CHUNK_TREE_OBJECTID); 1607 chunk_root, fs_info, BTRFS_CHUNK_TREE_OBJECTID);
1602 1608
1603 chunk_root->node = read_tree_block(chunk_root, 1609 chunk_root->node = read_tree_block(chunk_root,
1604 btrfs_super_chunk_root(disk_super), 1610 btrfs_super_chunk_root(disk_super),
1605 blocksize, 0); 1611 blocksize, generation);
1606 BUG_ON(!chunk_root->node); 1612 BUG_ON(!chunk_root->node);
1607 1613
1608 read_extent_buffer(chunk_root->node, fs_info->chunk_tree_uuid, 1614 read_extent_buffer(chunk_root->node, fs_info->chunk_tree_uuid,
@@ -1618,11 +1624,11 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1618 1624
1619 blocksize = btrfs_level_size(tree_root, 1625 blocksize = btrfs_level_size(tree_root,
1620 btrfs_super_root_level(disk_super)); 1626 btrfs_super_root_level(disk_super));
1621 1627 generation = btrfs_super_generation(disk_super);
1622 1628
1623 tree_root->node = read_tree_block(tree_root, 1629 tree_root->node = read_tree_block(tree_root,
1624 btrfs_super_root(disk_super), 1630 btrfs_super_root(disk_super),
1625 blocksize, 0); 1631 blocksize, generation);
1626 if (!tree_root->node) 1632 if (!tree_root->node)
1627 goto fail_sb_buffer; 1633 goto fail_sb_buffer;
1628 1634
@@ -1672,15 +1678,16 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1672 log_tree_root, fs_info, BTRFS_TREE_LOG_OBJECTID); 1678 log_tree_root, fs_info, BTRFS_TREE_LOG_OBJECTID);
1673 1679
1674 log_tree_root->node = read_tree_block(tree_root, bytenr, 1680 log_tree_root->node = read_tree_block(tree_root, bytenr,
1675 blocksize, 0); 1681 blocksize,
1682 generation + 1);
1676 ret = btrfs_recover_log_trees(log_tree_root); 1683 ret = btrfs_recover_log_trees(log_tree_root);
1677 BUG_ON(ret); 1684 BUG_ON(ret);
1678 } 1685 }
1686 fs_info->last_trans_committed = btrfs_super_generation(disk_super);
1679 1687
1680 ret = btrfs_cleanup_reloc_trees(tree_root); 1688 ret = btrfs_cleanup_reloc_trees(tree_root);
1681 BUG_ON(ret); 1689 BUG_ON(ret);
1682 1690
1683 fs_info->last_trans_committed = btrfs_super_generation(disk_super);
1684 return tree_root; 1691 return tree_root;
1685 1692
1686fail_cleaner: 1693fail_cleaner:
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 564260872c7e..155c8dc56a22 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -4428,6 +4428,7 @@ static int noinline init_reloc_tree(struct btrfs_trans_handle *trans,
4428 btrfs_set_root_refs(root_item, 0); 4428 btrfs_set_root_refs(root_item, 0);
4429 btrfs_set_root_bytenr(root_item, eb->start); 4429 btrfs_set_root_bytenr(root_item, eb->start);
4430 btrfs_set_root_level(root_item, btrfs_header_level(eb)); 4430 btrfs_set_root_level(root_item, btrfs_header_level(eb));
4431 btrfs_set_root_generation(root_item, trans->transid);
4431 4432
4432 btrfs_tree_unlock(eb); 4433 btrfs_tree_unlock(eb);
4433 free_extent_buffer(eb); 4434 free_extent_buffer(eb);
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 1136ce2febcc..fd3c8b5676c1 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -108,6 +108,7 @@ static noinline int create_subvol(struct btrfs_root *root,
108 inode_item->mode = cpu_to_le32(S_IFDIR | 0755); 108 inode_item->mode = cpu_to_le32(S_IFDIR | 0755);
109 109
110 btrfs_set_root_bytenr(&root_item, leaf->start); 110 btrfs_set_root_bytenr(&root_item, leaf->start);
111 btrfs_set_root_generation(&root_item, trans->transid);
111 btrfs_set_root_level(&root_item, 0); 112 btrfs_set_root_level(&root_item, 0);
112 btrfs_set_root_refs(&root_item, 1); 113 btrfs_set_root_refs(&root_item, 1);
113 btrfs_set_root_used(&root_item, 0); 114 btrfs_set_root_used(&root_item, 0);
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 48b455fdaac5..924af6f2aeac 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -439,6 +439,7 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,
439 root->node->start); 439 root->node->start);
440 btrfs_set_root_level(&root->root_item, 440 btrfs_set_root_level(&root->root_item,
441 btrfs_header_level(root->node)); 441 btrfs_header_level(root->node));
442 btrfs_set_root_generation(&root->root_item, trans->transid);
442 ret = btrfs_update_root(trans, tree_root, 443 ret = btrfs_update_root(trans, tree_root,
443 &root->root_key, 444 &root->root_key,
444 &root->root_item); 445 &root->root_item);
@@ -456,6 +457,12 @@ int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans,
456{ 457{
457 struct btrfs_fs_info *fs_info = root->fs_info; 458 struct btrfs_fs_info *fs_info = root->fs_info;
458 struct list_head *next; 459 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);
459 466
460 while(!list_empty(&fs_info->dirty_cowonly_roots)) { 467 while(!list_empty(&fs_info->dirty_cowonly_roots)) {
461 next = fs_info->dirty_cowonly_roots.next; 468 next = fs_info->dirty_cowonly_roots.next;
@@ -559,6 +566,9 @@ static noinline int add_dirty_roots(struct btrfs_trans_handle *trans,
559 root->node->start); 566 root->node->start);
560 btrfs_set_root_level(&root->root_item, 567 btrfs_set_root_level(&root->root_item,
561 btrfs_header_level(root->node)); 568 btrfs_header_level(root->node));
569 btrfs_set_root_generation(&root->root_item,
570 root->root_key.offset);
571
562 err = btrfs_insert_root(trans, root->fs_info->tree_root, 572 err = btrfs_insert_root(trans, root->fs_info->tree_root,
563 &root->root_key, 573 &root->root_key,
564 &root->root_item); 574 &root->root_item);
@@ -756,6 +766,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
756 766
757 btrfs_set_root_bytenr(new_root_item, tmp->start); 767 btrfs_set_root_bytenr(new_root_item, tmp->start);
758 btrfs_set_root_level(new_root_item, btrfs_header_level(tmp)); 768 btrfs_set_root_level(new_root_item, btrfs_header_level(tmp));
769 btrfs_set_root_generation(new_root_item, trans->transid);
759 ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key, 770 ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key,
760 new_root_item); 771 new_root_item);
761 btrfs_tree_unlock(tmp); 772 btrfs_tree_unlock(tmp);
@@ -946,6 +957,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
946 chunk_root->node->start); 957 chunk_root->node->start);
947 btrfs_set_super_chunk_root_level(&root->fs_info->super_copy, 958 btrfs_set_super_chunk_root_level(&root->fs_info->super_copy,
948 btrfs_header_level(chunk_root->node)); 959 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));
949 962
950 if (!root->fs_info->log_root_recovering) { 963 if (!root->fs_info->log_root_recovering) {
951 btrfs_set_super_log_root(&root->fs_info->super_copy, 0); 964 btrfs_set_super_log_root(&root->fs_info->super_copy, 0);
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 835daed5561f..e0201c3a7dc9 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -117,6 +117,7 @@ int btrfs_add_log_tree(struct btrfs_trans_handle *trans,
117 inode_item->mode = cpu_to_le32(S_IFDIR | 0755); 117 inode_item->mode = cpu_to_le32(S_IFDIR | 0755);
118 118
119 btrfs_set_root_bytenr(&root_item, leaf->start); 119 btrfs_set_root_bytenr(&root_item, leaf->start);
120 btrfs_set_root_generation(&root_item, trans->transid);
120 btrfs_set_root_level(&root_item, 0); 121 btrfs_set_root_level(&root_item, 0);
121 btrfs_set_root_refs(&root_item, 0); 122 btrfs_set_root_refs(&root_item, 0);
122 btrfs_set_root_used(&root_item, 0); 123 btrfs_set_root_used(&root_item, 0);
@@ -2065,6 +2066,7 @@ static int update_log_root(struct btrfs_trans_handle *trans,
2065 return 0; 2066 return 0;
2066 2067
2067 btrfs_set_root_bytenr(&log->root_item, log->node->start); 2068 btrfs_set_root_bytenr(&log->root_item, log->node->start);
2069 btrfs_set_root_generation(&log->root_item, trans->transid);
2068 btrfs_set_root_level(&log->root_item, btrfs_header_level(log->node)); 2070 btrfs_set_root_level(&log->root_item, btrfs_header_level(log->node));
2069 ret = btrfs_update_root(trans, log->fs_info->log_root_tree, 2071 ret = btrfs_update_root(trans, log->fs_info->log_root_tree,
2070 &log->root_key, &log->root_item); 2072 &log->root_key, &log->root_item);