aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/tree-defrag.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-05-12 13:39:03 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:03 -0400
commit1259ab75c62462b8ffad90067b5e1f6312786a18 (patch)
treeccc6b795e524a74b3fb9666409ca2f7f33bf98dd /fs/btrfs/tree-defrag.c
parentca7a79ad8dbe24669a8ced01f9fc0126b872745d (diff)
Btrfs: Handle write errors on raid1 and raid10
When duplicate copies exist, writes are allowed to fail to one of those copies. This changeset includes a few changes that allow the FS to continue even when some IOs fail. It also adds verification of the parent generation number for btree blocks. This generation is stored in the pointer to a block, and it ensures that missed writes to are detected. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/tree-defrag.c')
-rw-r--r--fs/btrfs/tree-defrag.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/fs/btrfs/tree-defrag.c b/fs/btrfs/tree-defrag.c
index 5085e9e693b9..c02e2bf2f028 100644
--- a/fs/btrfs/tree-defrag.c
+++ b/fs/btrfs/tree-defrag.c
@@ -51,6 +51,7 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans,
51 struct extent_buffer *next; 51 struct extent_buffer *next;
52 struct extent_buffer *cur; 52 struct extent_buffer *cur;
53 u64 bytenr; 53 u64 bytenr;
54 u64 ptr_gen;
54 int ret = 0; 55 int ret = 0;
55 int is_extent = 0; 56 int is_extent = 0;
56 57
@@ -93,11 +94,12 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans,
93 break; 94 break;
94 } 95 }
95 bytenr = btrfs_node_blockptr(cur, path->slots[*level]); 96 bytenr = btrfs_node_blockptr(cur, path->slots[*level]);
97 ptr_gen = btrfs_node_ptr_generation(cur, path->slots[*level]);
96 98
97 if (cache_only) { 99 if (cache_only) {
98 next = btrfs_find_tree_block(root, bytenr, 100 next = btrfs_find_tree_block(root, bytenr,
99 btrfs_level_size(root, *level - 1)); 101 btrfs_level_size(root, *level - 1));
100 if (!next || !btrfs_buffer_uptodate(next) || 102 if (!next || !btrfs_buffer_uptodate(next, ptr_gen) ||
101 !btrfs_buffer_defrag(next)) { 103 !btrfs_buffer_defrag(next)) {
102 free_extent_buffer(next); 104 free_extent_buffer(next);
103 path->slots[*level]++; 105 path->slots[*level]++;
@@ -106,8 +108,7 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans,
106 } else { 108 } else {
107 next = read_tree_block(root, bytenr, 109 next = read_tree_block(root, bytenr,
108 btrfs_level_size(root, *level - 1), 110 btrfs_level_size(root, *level - 1),
109 btrfs_node_ptr_generation(cur, 111 ptr_gen);
110 path->slots[*level]));
111 } 112 }
112 ret = btrfs_cow_block(trans, root, next, path->nodes[*level], 113 ret = btrfs_cow_block(trans, root, next, path->nodes[*level],
113 path->slots[*level], &next); 114 path->slots[*level], &next);