aboutsummaryrefslogtreecommitdiffstats
path: root/fs
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
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')
-rw-r--r--fs/btrfs/ctree.c2
-rw-r--r--fs/btrfs/disk-io.c56
-rw-r--r--fs/btrfs/disk-io.h2
-rw-r--r--fs/btrfs/extent-tree.c4
-rw-r--r--fs/btrfs/extent_io.c49
-rw-r--r--fs/btrfs/extent_io.h7
-rw-r--r--fs/btrfs/inode.c66
-rw-r--r--fs/btrfs/tree-defrag.c7
-rw-r--r--fs/btrfs/volumes.c11
9 files changed, 155 insertions, 49 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 289d71d8653a..02e571e6ee62 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -379,7 +379,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
379 379
380 cur = btrfs_find_tree_block(root, blocknr, blocksize); 380 cur = btrfs_find_tree_block(root, blocknr, blocksize);
381 if (cur) 381 if (cur)
382 uptodate = btrfs_buffer_uptodate(cur); 382 uptodate = btrfs_buffer_uptodate(cur, gen);
383 else 383 else
384 uptodate = 0; 384 uptodate = 0;
385 if (!cur || !uptodate) { 385 if (!cur || !uptodate) {
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index edee7a44f861..574b1245964e 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -205,6 +205,33 @@ static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
205 return 0; 205 return 0;
206} 206}
207 207
208static int verify_parent_transid(struct extent_io_tree *io_tree,
209 struct extent_buffer *eb, u64 parent_transid)
210{
211 int ret;
212
213 if (!parent_transid || btrfs_header_generation(eb) == parent_transid)
214 return 0;
215
216 lock_extent(io_tree, eb->start, eb->start + eb->len - 1, GFP_NOFS);
217 if (extent_buffer_uptodate(io_tree, eb) &&
218 btrfs_header_generation(eb) == parent_transid) {
219 ret = 0;
220 goto out;
221 }
222 printk("parent transid verify failed on %llu wanted %llu found %llu\n",
223 (unsigned long long)eb->start,
224 (unsigned long long)parent_transid,
225 (unsigned long long)btrfs_header_generation(eb));
226 ret = 1;
227out:
228 clear_extent_buffer_uptodate(io_tree, eb);
229 unlock_extent(io_tree, eb->start, eb->start + eb->len - 1,
230 GFP_NOFS);
231 return ret;
232
233}
234
208static int btree_read_extent_buffer_pages(struct btrfs_root *root, 235static int btree_read_extent_buffer_pages(struct btrfs_root *root,
209 struct extent_buffer *eb, 236 struct extent_buffer *eb,
210 u64 start, u64 parent_transid) 237 u64 start, u64 parent_transid)
@@ -218,7 +245,8 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root,
218 while (1) { 245 while (1) {
219 ret = read_extent_buffer_pages(io_tree, eb, start, 1, 246 ret = read_extent_buffer_pages(io_tree, eb, start, 1,
220 btree_get_extent, mirror_num); 247 btree_get_extent, mirror_num);
221 if (!ret) 248 if (!ret &&
249 !verify_parent_transid(io_tree, eb, parent_transid))
222 return ret; 250 return ret;
223 251
224 num_copies = btrfs_num_copies(&root->fs_info->mapping_tree, 252 num_copies = btrfs_num_copies(&root->fs_info->mapping_tree,
@@ -330,6 +358,13 @@ int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
330 ret = -EIO; 358 ret = -EIO;
331 goto err; 359 goto err;
332 } 360 }
361 if (memcmp_extent_buffer(eb, root->fs_info->fsid,
362 (unsigned long)btrfs_header_fsid(eb),
363 BTRFS_FSID_SIZE)) {
364 printk("bad fsid on block %Lu\n", eb->start);
365 ret = -EIO;
366 goto err;
367 }
333 found_level = btrfs_header_level(eb); 368 found_level = btrfs_header_level(eb);
334 369
335 ret = csum_tree_block(root, eb, 1); 370 ret = csum_tree_block(root, eb, 1);
@@ -1363,7 +1398,9 @@ static void btrfs_end_buffer_write_sync(struct buffer_head *bh, int uptodate)
1363 "I/O error on %s\n", 1398 "I/O error on %s\n",
1364 bdevname(bh->b_bdev, b)); 1399 bdevname(bh->b_bdev, b));
1365 } 1400 }
1366 set_buffer_write_io_error(bh); 1401 /* note, we dont' set_buffer_write_io_error because we have
1402 * our own ways of dealing with the IO errors
1403 */
1367 clear_buffer_uptodate(bh); 1404 clear_buffer_uptodate(bh);
1368 } 1405 }
1369 unlock_buffer(bh); 1406 unlock_buffer(bh);
@@ -1459,7 +1496,8 @@ int write_all_supers(struct btrfs_root *root)
1459 ret = submit_bh(WRITE, bh); 1496 ret = submit_bh(WRITE, bh);
1460 BUG_ON(ret); 1497 BUG_ON(ret);
1461 wait_on_buffer(bh); 1498 wait_on_buffer(bh);
1462 BUG_ON(!buffer_uptodate(bh)); 1499 if (!buffer_uptodate(bh))
1500 total_errors++;
1463 } else { 1501 } else {
1464 total_errors++; 1502 total_errors++;
1465 } 1503 }
@@ -1607,10 +1645,18 @@ int close_ctree(struct btrfs_root *root)
1607 return 0; 1645 return 0;
1608} 1646}
1609 1647
1610int btrfs_buffer_uptodate(struct extent_buffer *buf) 1648int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid)
1611{ 1649{
1650 int ret;
1612 struct inode *btree_inode = buf->first_page->mapping->host; 1651 struct inode *btree_inode = buf->first_page->mapping->host;
1613 return extent_buffer_uptodate(&BTRFS_I(btree_inode)->io_tree, buf); 1652
1653 ret = extent_buffer_uptodate(&BTRFS_I(btree_inode)->io_tree, buf);
1654 if (!ret)
1655 return ret;
1656
1657 ret = verify_parent_transid(&BTRFS_I(btree_inode)->io_tree, buf,
1658 parent_transid);
1659 return !ret;
1614} 1660}
1615 1661
1616int btrfs_set_buffer_uptodate(struct extent_buffer *buf) 1662int btrfs_set_buffer_uptodate(struct extent_buffer *buf)
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index e29c895d5230..30d1ed293c25 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -56,7 +56,7 @@ int btrfs_insert_dev_radix(struct btrfs_root *root,
56void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr); 56void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr);
57int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root); 57int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root);
58void btrfs_mark_buffer_dirty(struct extent_buffer *buf); 58void btrfs_mark_buffer_dirty(struct extent_buffer *buf);
59int btrfs_buffer_uptodate(struct extent_buffer *buf); 59int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid);
60int btrfs_set_buffer_uptodate(struct extent_buffer *buf); 60int btrfs_set_buffer_uptodate(struct extent_buffer *buf);
61int wait_on_tree_block_writeback(struct btrfs_root *root, 61int wait_on_tree_block_writeback(struct btrfs_root *root,
62 struct extent_buffer *buf); 62 struct extent_buffer *buf);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index db07dde4a870..605018c6045c 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -1366,7 +1366,7 @@ static int pin_down_bytes(struct btrfs_root *root, u64 bytenr, u32 num_bytes,
1366 if (!pending) { 1366 if (!pending) {
1367 buf = btrfs_find_tree_block(root, bytenr, num_bytes); 1367 buf = btrfs_find_tree_block(root, bytenr, num_bytes);
1368 if (buf) { 1368 if (buf) {
1369 if (btrfs_buffer_uptodate(buf)) { 1369 if (btrfs_buffer_uptodate(buf, 0)) {
1370 u64 transid = 1370 u64 transid =
1371 root->fs_info->running_transaction->transid; 1371 root->fs_info->running_transaction->transid;
1372 u64 header_transid = 1372 u64 header_transid =
@@ -2151,7 +2151,7 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans,
2151 continue; 2151 continue;
2152 } 2152 }
2153 next = btrfs_find_tree_block(root, bytenr, blocksize); 2153 next = btrfs_find_tree_block(root, bytenr, blocksize);
2154 if (!next || !btrfs_buffer_uptodate(next)) { 2154 if (!next || !btrfs_buffer_uptodate(next, ptr_gen)) {
2155 free_extent_buffer(next); 2155 free_extent_buffer(next);
2156 reada_walk_down(root, cur, path->slots[*level]); 2156 reada_walk_down(root, cur, path->slots[*level]);
2157 2157
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index dd403b426ff5..2a3624adc0cf 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -1366,7 +1366,7 @@ static int end_bio_extent_writepage(struct bio *bio,
1366 unsigned int bytes_done, int err) 1366 unsigned int bytes_done, int err)
1367#endif 1367#endif
1368{ 1368{
1369 const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); 1369 int uptodate = err == 0;
1370 struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; 1370 struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
1371 struct extent_state *state = bio->bi_private; 1371 struct extent_state *state = bio->bi_private;
1372 struct extent_io_tree *tree = state->tree; 1372 struct extent_io_tree *tree = state->tree;
@@ -1375,6 +1375,7 @@ static int end_bio_extent_writepage(struct bio *bio,
1375 u64 end; 1375 u64 end;
1376 u64 cur; 1376 u64 cur;
1377 int whole_page; 1377 int whole_page;
1378 int ret;
1378 unsigned long flags; 1379 unsigned long flags;
1379 1380
1380#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23) 1381#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23)
@@ -1395,17 +1396,30 @@ static int end_bio_extent_writepage(struct bio *bio,
1395 if (--bvec >= bio->bi_io_vec) 1396 if (--bvec >= bio->bi_io_vec)
1396 prefetchw(&bvec->bv_page->flags); 1397 prefetchw(&bvec->bv_page->flags);
1397 1398
1399 if (tree->ops && tree->ops->writepage_end_io_hook) {
1400 ret = tree->ops->writepage_end_io_hook(page, start,
1401 end, state);
1402 if (ret)
1403 uptodate = 0;
1404 }
1405
1406 if (!uptodate && tree->ops &&
1407 tree->ops->writepage_io_failed_hook) {
1408 ret = tree->ops->writepage_io_failed_hook(bio, page,
1409 start, end, state);
1410 if (ret == 0) {
1411 state = NULL;
1412 uptodate = (err == 0);
1413 continue;
1414 }
1415 }
1416
1398 if (!uptodate) { 1417 if (!uptodate) {
1399 clear_extent_uptodate(tree, start, end, GFP_ATOMIC); 1418 clear_extent_uptodate(tree, start, end, GFP_ATOMIC);
1400 ClearPageUptodate(page); 1419 ClearPageUptodate(page);
1401 SetPageError(page); 1420 SetPageError(page);
1402 } 1421 }
1403 1422
1404 if (tree->ops && tree->ops->writepage_end_io_hook) {
1405 tree->ops->writepage_end_io_hook(page, start, end,
1406 state);
1407 }
1408
1409 /* 1423 /*
1410 * bios can get merged in funny ways, and so we need to 1424 * bios can get merged in funny ways, and so we need to
1411 * be careful with the state variable. We know the 1425 * be careful with the state variable. We know the
@@ -2073,9 +2087,9 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc,
2073 } else { 2087 } else {
2074 ret = 0; 2088 ret = 0;
2075 } 2089 }
2076 if (ret) 2090 if (ret) {
2077 SetPageError(page); 2091 SetPageError(page);
2078 else { 2092 } else {
2079 unsigned long max_nr = end_index + 1; 2093 unsigned long max_nr = end_index + 1;
2080 set_range_writeback(tree, cur, cur + iosize - 1); 2094 set_range_writeback(tree, cur, cur + iosize - 1);
2081 if (!PageWriteback(page)) { 2095 if (!PageWriteback(page)) {
@@ -2948,6 +2962,25 @@ int set_extent_buffer_dirty(struct extent_io_tree *tree,
2948} 2962}
2949EXPORT_SYMBOL(set_extent_buffer_dirty); 2963EXPORT_SYMBOL(set_extent_buffer_dirty);
2950 2964
2965int clear_extent_buffer_uptodate(struct extent_io_tree *tree,
2966 struct extent_buffer *eb)
2967{
2968 unsigned long i;
2969 struct page *page;
2970 unsigned long num_pages;
2971
2972 num_pages = num_extent_pages(eb->start, eb->len);
2973 eb->flags &= ~EXTENT_UPTODATE;
2974
2975 clear_extent_uptodate(tree, eb->start, eb->start + eb->len - 1,
2976 GFP_NOFS);
2977 for (i = 0; i < num_pages; i++) {
2978 page = extent_buffer_page(eb, i);
2979 ClearPageUptodate(page);
2980 }
2981 return 0;
2982}
2983
2951int set_extent_buffer_uptodate(struct extent_io_tree *tree, 2984int set_extent_buffer_uptodate(struct extent_io_tree *tree,
2952 struct extent_buffer *eb) 2985 struct extent_buffer *eb)
2953{ 2986{
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
index e48346147514..f1960dafaa19 100644
--- a/fs/btrfs/extent_io.h
+++ b/fs/btrfs/extent_io.h
@@ -36,9 +36,12 @@ struct extent_io_ops {
36 int (*readpage_io_failed_hook)(struct bio *bio, struct page *page, 36 int (*readpage_io_failed_hook)(struct bio *bio, struct page *page,
37 u64 start, u64 end, 37 u64 start, u64 end,
38 struct extent_state *state); 38 struct extent_state *state);
39 int (*writepage_io_failed_hook)(struct bio *bio, struct page *page,
40 u64 start, u64 end,
41 struct extent_state *state);
39 int (*readpage_end_io_hook)(struct page *page, u64 start, u64 end, 42 int (*readpage_end_io_hook)(struct page *page, u64 start, u64 end,
40 struct extent_state *state); 43 struct extent_state *state);
41 void (*writepage_end_io_hook)(struct page *page, u64 start, u64 end, 44 int (*writepage_end_io_hook)(struct page *page, u64 start, u64 end,
42 struct extent_state *state); 45 struct extent_state *state);
43 int (*set_bit_hook)(struct inode *inode, u64 start, u64 end, 46 int (*set_bit_hook)(struct inode *inode, u64 start, u64 end,
44 unsigned long old, unsigned long bits); 47 unsigned long old, unsigned long bits);
@@ -212,6 +215,8 @@ int set_extent_buffer_dirty(struct extent_io_tree *tree,
212 struct extent_buffer *eb); 215 struct extent_buffer *eb);
213int set_extent_buffer_uptodate(struct extent_io_tree *tree, 216int set_extent_buffer_uptodate(struct extent_io_tree *tree,
214 struct extent_buffer *eb); 217 struct extent_buffer *eb);
218int clear_extent_buffer_uptodate(struct extent_io_tree *tree,
219 struct extent_buffer *eb);
215int extent_buffer_uptodate(struct extent_io_tree *tree, 220int extent_buffer_uptodate(struct extent_io_tree *tree,
216 struct extent_buffer *eb); 221 struct extent_buffer *eb);
217int map_extent_buffer(struct extent_buffer *eb, unsigned long offset, 222int map_extent_buffer(struct extent_buffer *eb, unsigned long offset,
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index a492fd238c88..08760ff9bab7 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -430,9 +430,9 @@ struct io_failure_record {
430 int last_mirror; 430 int last_mirror;
431}; 431};
432 432
433int btrfs_readpage_io_failed_hook(struct bio *failed_bio, 433int btrfs_io_failed_hook(struct bio *failed_bio,
434 struct page *page, u64 start, u64 end, 434 struct page *page, u64 start, u64 end,
435 struct extent_state *state) 435 struct extent_state *state)
436{ 436{
437 struct io_failure_record *failrec = NULL; 437 struct io_failure_record *failrec = NULL;
438 u64 private; 438 u64 private;
@@ -443,6 +443,7 @@ int btrfs_readpage_io_failed_hook(struct bio *failed_bio,
443 struct bio *bio; 443 struct bio *bio;
444 int num_copies; 444 int num_copies;
445 int ret; 445 int ret;
446 int rw;
446 u64 logical; 447 u64 logical;
447 448
448 ret = get_state_private(failure_tree, start, &private); 449 ret = get_state_private(failure_tree, start, &private);
@@ -505,7 +506,41 @@ int btrfs_readpage_io_failed_hook(struct bio *failed_bio,
505 bio->bi_bdev = failed_bio->bi_bdev; 506 bio->bi_bdev = failed_bio->bi_bdev;
506 bio->bi_size = 0; 507 bio->bi_size = 0;
507 bio_add_page(bio, page, failrec->len, start - page_offset(page)); 508 bio_add_page(bio, page, failrec->len, start - page_offset(page));
508 btrfs_submit_bio_hook(inode, READ, bio, failrec->last_mirror); 509 if (failed_bio->bi_rw & (1 << BIO_RW))
510 rw = WRITE;
511 else
512 rw = READ;
513
514 BTRFS_I(inode)->io_tree.ops->submit_bio_hook(inode, rw, bio,
515 failrec->last_mirror);
516 return 0;
517}
518
519int btrfs_clean_io_failures(struct inode *inode, u64 start)
520{
521 u64 private;
522 u64 private_failure;
523 struct io_failure_record *failure;
524 int ret;
525
526 private = 0;
527 if (count_range_bits(&BTRFS_I(inode)->io_failure_tree, &private,
528 (u64)-1, 1, EXTENT_DIRTY)) {
529 ret = get_state_private(&BTRFS_I(inode)->io_failure_tree,
530 start, &private_failure);
531 if (ret == 0) {
532 failure = (struct io_failure_record *)(unsigned long)
533 private_failure;
534 set_state_private(&BTRFS_I(inode)->io_failure_tree,
535 failure->start, 0);
536 clear_extent_bits(&BTRFS_I(inode)->io_failure_tree,
537 failure->start,
538 failure->start + failure->len - 1,
539 EXTENT_DIRTY | EXTENT_LOCKED,
540 GFP_NOFS);
541 kfree(failure);
542 }
543 }
509 return 0; 544 return 0;
510} 545}
511 546
@@ -547,26 +582,7 @@ int btrfs_readpage_end_io_hook(struct page *page, u64 start, u64 end,
547 /* if the io failure tree for this inode is non-empty, 582 /* if the io failure tree for this inode is non-empty,
548 * check to see if we've recovered from a failed IO 583 * check to see if we've recovered from a failed IO
549 */ 584 */
550 private = 0; 585 btrfs_clean_io_failures(inode, start);
551 if (count_range_bits(&BTRFS_I(inode)->io_failure_tree, &private,
552 (u64)-1, 1, EXTENT_DIRTY)) {
553 u64 private_failure;
554 struct io_failure_record *failure;
555 ret = get_state_private(&BTRFS_I(inode)->io_failure_tree,
556 start, &private_failure);
557 if (ret == 0) {
558 failure = (struct io_failure_record *)(unsigned long)
559 private_failure;
560 set_state_private(&BTRFS_I(inode)->io_failure_tree,
561 failure->start, 0);
562 clear_extent_bits(&BTRFS_I(inode)->io_failure_tree,
563 failure->start,
564 failure->start + failure->len - 1,
565 EXTENT_DIRTY | EXTENT_LOCKED,
566 GFP_NOFS);
567 kfree(failure);
568 }
569 }
570 return 0; 586 return 0;
571 587
572zeroit: 588zeroit:
@@ -3657,7 +3673,7 @@ static struct extent_io_ops btrfs_extent_io_ops = {
3657 .merge_bio_hook = btrfs_merge_bio_hook, 3673 .merge_bio_hook = btrfs_merge_bio_hook,
3658 .readpage_io_hook = btrfs_readpage_io_hook, 3674 .readpage_io_hook = btrfs_readpage_io_hook,
3659 .readpage_end_io_hook = btrfs_readpage_end_io_hook, 3675 .readpage_end_io_hook = btrfs_readpage_end_io_hook,
3660 .readpage_io_failed_hook = btrfs_readpage_io_failed_hook, 3676 .readpage_io_failed_hook = btrfs_io_failed_hook,
3661 .set_bit_hook = btrfs_set_bit_hook, 3677 .set_bit_hook = btrfs_set_bit_hook,
3662 .clear_bit_hook = btrfs_clear_bit_hook, 3678 .clear_bit_hook = btrfs_clear_bit_hook,
3663}; 3679};
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);
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index b5d7bd1915b4..5fc7fb481474 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -1807,14 +1807,19 @@ static int end_bio_multi_stripe(struct bio *bio,
1807 if (atomic_dec_and_test(&multi->stripes_pending)) { 1807 if (atomic_dec_and_test(&multi->stripes_pending)) {
1808 bio->bi_private = multi->private; 1808 bio->bi_private = multi->private;
1809 bio->bi_end_io = multi->end_io; 1809 bio->bi_end_io = multi->end_io;
1810
1811 /* only send an error to the higher layers if it is 1810 /* only send an error to the higher layers if it is
1812 * beyond the tolerance of the multi-bio 1811 * beyond the tolerance of the multi-bio
1813 */ 1812 */
1814 if (atomic_read(&multi->error) > multi->max_errors) 1813 if (atomic_read(&multi->error) > multi->max_errors) {
1815 err = -EIO; 1814 err = -EIO;
1816 else 1815 } else if (err) {
1816 /*
1817 * this bio is actually up to date, we didn't
1818 * go over the max number of errors
1819 */
1820 set_bit(BIO_UPTODATE, &bio->bi_flags);
1817 err = 0; 1821 err = 0;
1822 }
1818 kfree(multi); 1823 kfree(multi);
1819 1824
1820#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23) 1825#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23)