diff options
-rw-r--r-- | fs/btrfs/ctree.c | 2 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 56 | ||||
-rw-r--r-- | fs/btrfs/disk-io.h | 2 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 4 | ||||
-rw-r--r-- | fs/btrfs/extent_io.c | 49 | ||||
-rw-r--r-- | fs/btrfs/extent_io.h | 7 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 66 | ||||
-rw-r--r-- | fs/btrfs/tree-defrag.c | 7 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 11 |
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 | ||
208 | static 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; | ||
227 | out: | ||
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 | |||
208 | static int btree_read_extent_buffer_pages(struct btrfs_root *root, | 235 | static 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 | ||
1610 | int btrfs_buffer_uptodate(struct extent_buffer *buf) | 1648 | int 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 | ||
1616 | int btrfs_set_buffer_uptodate(struct extent_buffer *buf) | 1662 | int 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, | |||
56 | void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr); | 56 | void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr); |
57 | int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root); | 57 | int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root); |
58 | void btrfs_mark_buffer_dirty(struct extent_buffer *buf); | 58 | void btrfs_mark_buffer_dirty(struct extent_buffer *buf); |
59 | int btrfs_buffer_uptodate(struct extent_buffer *buf); | 59 | int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid); |
60 | int btrfs_set_buffer_uptodate(struct extent_buffer *buf); | 60 | int btrfs_set_buffer_uptodate(struct extent_buffer *buf); |
61 | int wait_on_tree_block_writeback(struct btrfs_root *root, | 61 | int 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 | } |
2949 | EXPORT_SYMBOL(set_extent_buffer_dirty); | 2963 | EXPORT_SYMBOL(set_extent_buffer_dirty); |
2950 | 2964 | ||
2965 | int 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 | |||
2951 | int set_extent_buffer_uptodate(struct extent_io_tree *tree, | 2984 | int 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); |
213 | int set_extent_buffer_uptodate(struct extent_io_tree *tree, | 216 | int set_extent_buffer_uptodate(struct extent_io_tree *tree, |
214 | struct extent_buffer *eb); | 217 | struct extent_buffer *eb); |
218 | int clear_extent_buffer_uptodate(struct extent_io_tree *tree, | ||
219 | struct extent_buffer *eb); | ||
215 | int extent_buffer_uptodate(struct extent_io_tree *tree, | 220 | int extent_buffer_uptodate(struct extent_io_tree *tree, |
216 | struct extent_buffer *eb); | 221 | struct extent_buffer *eb); |
217 | int map_extent_buffer(struct extent_buffer *eb, unsigned long offset, | 222 | int 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 | ||
433 | int btrfs_readpage_io_failed_hook(struct bio *failed_bio, | 433 | int 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 | |||
519 | int 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 | ||
572 | zeroit: | 588 | zeroit: |
@@ -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) |