diff options
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r-- | fs/btrfs/disk-io.c | 40 |
1 files changed, 24 insertions, 16 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 20196f411206..a7ffc88a7dbe 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -323,7 +323,8 @@ static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf, | |||
323 | * in the wrong place. | 323 | * in the wrong place. |
324 | */ | 324 | */ |
325 | static int verify_parent_transid(struct extent_io_tree *io_tree, | 325 | static int verify_parent_transid(struct extent_io_tree *io_tree, |
326 | struct extent_buffer *eb, u64 parent_transid) | 326 | struct extent_buffer *eb, u64 parent_transid, |
327 | int atomic) | ||
327 | { | 328 | { |
328 | struct extent_state *cached_state = NULL; | 329 | struct extent_state *cached_state = NULL; |
329 | int ret; | 330 | int ret; |
@@ -331,6 +332,9 @@ static int verify_parent_transid(struct extent_io_tree *io_tree, | |||
331 | if (!parent_transid || btrfs_header_generation(eb) == parent_transid) | 332 | if (!parent_transid || btrfs_header_generation(eb) == parent_transid) |
332 | return 0; | 333 | return 0; |
333 | 334 | ||
335 | if (atomic) | ||
336 | return -EAGAIN; | ||
337 | |||
334 | lock_extent_bits(io_tree, eb->start, eb->start + eb->len - 1, | 338 | lock_extent_bits(io_tree, eb->start, eb->start + eb->len - 1, |
335 | 0, &cached_state); | 339 | 0, &cached_state); |
336 | if (extent_buffer_uptodate(eb) && | 340 | if (extent_buffer_uptodate(eb) && |
@@ -372,7 +376,8 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root, | |||
372 | ret = read_extent_buffer_pages(io_tree, eb, start, | 376 | ret = read_extent_buffer_pages(io_tree, eb, start, |
373 | WAIT_COMPLETE, | 377 | WAIT_COMPLETE, |
374 | btree_get_extent, mirror_num); | 378 | btree_get_extent, mirror_num); |
375 | if (!ret && !verify_parent_transid(io_tree, eb, parent_transid)) | 379 | if (!ret && !verify_parent_transid(io_tree, eb, |
380 | parent_transid, 0)) | ||
376 | break; | 381 | break; |
377 | 382 | ||
378 | /* | 383 | /* |
@@ -383,17 +388,16 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root, | |||
383 | if (test_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags)) | 388 | if (test_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags)) |
384 | break; | 389 | break; |
385 | 390 | ||
386 | if (!failed_mirror) { | ||
387 | failed = 1; | ||
388 | printk(KERN_ERR "failed mirror was %d\n", eb->failed_mirror); | ||
389 | failed_mirror = eb->failed_mirror; | ||
390 | } | ||
391 | |||
392 | num_copies = btrfs_num_copies(&root->fs_info->mapping_tree, | 391 | num_copies = btrfs_num_copies(&root->fs_info->mapping_tree, |
393 | eb->start, eb->len); | 392 | eb->start, eb->len); |
394 | if (num_copies == 1) | 393 | if (num_copies == 1) |
395 | break; | 394 | break; |
396 | 395 | ||
396 | if (!failed_mirror) { | ||
397 | failed = 1; | ||
398 | failed_mirror = eb->read_mirror; | ||
399 | } | ||
400 | |||
397 | mirror_num++; | 401 | mirror_num++; |
398 | if (mirror_num == failed_mirror) | 402 | if (mirror_num == failed_mirror) |
399 | mirror_num++; | 403 | mirror_num++; |
@@ -564,7 +568,7 @@ struct extent_buffer *find_eb_for_page(struct extent_io_tree *tree, | |||
564 | } | 568 | } |
565 | 569 | ||
566 | static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end, | 570 | static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end, |
567 | struct extent_state *state) | 571 | struct extent_state *state, int mirror) |
568 | { | 572 | { |
569 | struct extent_io_tree *tree; | 573 | struct extent_io_tree *tree; |
570 | u64 found_start; | 574 | u64 found_start; |
@@ -589,6 +593,7 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end, | |||
589 | if (!reads_done) | 593 | if (!reads_done) |
590 | goto err; | 594 | goto err; |
591 | 595 | ||
596 | eb->read_mirror = mirror; | ||
592 | if (test_bit(EXTENT_BUFFER_IOERR, &eb->bflags)) { | 597 | if (test_bit(EXTENT_BUFFER_IOERR, &eb->bflags)) { |
593 | ret = -EIO; | 598 | ret = -EIO; |
594 | goto err; | 599 | goto err; |
@@ -652,7 +657,7 @@ static int btree_io_failed_hook(struct page *page, int failed_mirror) | |||
652 | 657 | ||
653 | eb = (struct extent_buffer *)page->private; | 658 | eb = (struct extent_buffer *)page->private; |
654 | set_bit(EXTENT_BUFFER_IOERR, &eb->bflags); | 659 | set_bit(EXTENT_BUFFER_IOERR, &eb->bflags); |
655 | eb->failed_mirror = failed_mirror; | 660 | eb->read_mirror = failed_mirror; |
656 | if (test_and_clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags)) | 661 | if (test_and_clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags)) |
657 | btree_readahead_hook(root, eb, eb->start, -EIO); | 662 | btree_readahead_hook(root, eb, eb->start, -EIO); |
658 | return -EIO; /* we fixed nothing */ | 663 | return -EIO; /* we fixed nothing */ |
@@ -1202,7 +1207,7 @@ static int __must_check find_and_setup_root(struct btrfs_root *tree_root, | |||
1202 | root->commit_root = NULL; | 1207 | root->commit_root = NULL; |
1203 | root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), | 1208 | root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), |
1204 | blocksize, generation); | 1209 | blocksize, generation); |
1205 | if (!root->node || !btrfs_buffer_uptodate(root->node, generation)) { | 1210 | if (!root->node || !btrfs_buffer_uptodate(root->node, generation, 0)) { |
1206 | free_extent_buffer(root->node); | 1211 | free_extent_buffer(root->node); |
1207 | root->node = NULL; | 1212 | root->node = NULL; |
1208 | return -EIO; | 1213 | return -EIO; |
@@ -2254,9 +2259,9 @@ int open_ctree(struct super_block *sb, | |||
2254 | goto fail_sb_buffer; | 2259 | goto fail_sb_buffer; |
2255 | } | 2260 | } |
2256 | 2261 | ||
2257 | if (sectorsize < PAGE_SIZE) { | 2262 | if (sectorsize != PAGE_SIZE) { |
2258 | printk(KERN_WARNING "btrfs: Incompatible sector size " | 2263 | printk(KERN_WARNING "btrfs: Incompatible sector size(%lu) " |
2259 | "found on %s\n", sb->s_id); | 2264 | "found on %s\n", (unsigned long)sectorsize, sb->s_id); |
2260 | goto fail_sb_buffer; | 2265 | goto fail_sb_buffer; |
2261 | } | 2266 | } |
2262 | 2267 | ||
@@ -3143,7 +3148,8 @@ int close_ctree(struct btrfs_root *root) | |||
3143 | return 0; | 3148 | return 0; |
3144 | } | 3149 | } |
3145 | 3150 | ||
3146 | int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid) | 3151 | int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid, |
3152 | int atomic) | ||
3147 | { | 3153 | { |
3148 | int ret; | 3154 | int ret; |
3149 | struct inode *btree_inode = buf->pages[0]->mapping->host; | 3155 | struct inode *btree_inode = buf->pages[0]->mapping->host; |
@@ -3153,7 +3159,9 @@ int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid) | |||
3153 | return ret; | 3159 | return ret; |
3154 | 3160 | ||
3155 | ret = verify_parent_transid(&BTRFS_I(btree_inode)->io_tree, buf, | 3161 | ret = verify_parent_transid(&BTRFS_I(btree_inode)->io_tree, buf, |
3156 | parent_transid); | 3162 | parent_transid, atomic); |
3163 | if (ret == -EAGAIN) | ||
3164 | return ret; | ||
3157 | return !ret; | 3165 | return !ret; |
3158 | } | 3166 | } |
3159 | 3167 | ||