diff options
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 33 |
1 files changed, 18 insertions, 15 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 28e667052ec3..0e90315ea803 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -611,22 +611,25 @@ int btrfs_readpage_io_hook(struct page *page, u64 start, u64 end) | |||
611 | btrfs_test_flag(inode, NODATASUM)) | 611 | btrfs_test_flag(inode, NODATASUM)) |
612 | return 0; | 612 | return 0; |
613 | 613 | ||
614 | /* | ||
615 | * It is possible there is an ordered extent that has | ||
616 | * not yet finished for this range in the file. If so, | ||
617 | * that extent will have a csum cached, and it will insert | ||
618 | * the sum after all the blocks in the extent are fully | ||
619 | * on disk. So, look for an ordered extent and use the | ||
620 | * sum if found. We have to do this before looking in the | ||
621 | * btree because csum items are pre-inserted based on | ||
622 | * the file size. btrfs_lookup_csum might find an item | ||
623 | * that still hasn't been fully filled. | ||
624 | */ | ||
625 | ret = btrfs_find_ordered_sum(inode, start, &csum); | ||
626 | if (ret == 0) | ||
627 | goto found; | ||
628 | |||
629 | ret = 0; | ||
614 | path = btrfs_alloc_path(); | 630 | path = btrfs_alloc_path(); |
615 | mutex_lock(&BTRFS_I(inode)->csum_mutex); | ||
616 | item = btrfs_lookup_csum(NULL, root, path, inode->i_ino, start, 0); | 631 | item = btrfs_lookup_csum(NULL, root, path, inode->i_ino, start, 0); |
617 | if (IS_ERR(item)) { | 632 | if (IS_ERR(item)) { |
618 | /* | ||
619 | * It is possible there is an ordered extent that has | ||
620 | * not yet finished for this range in the file. If so, | ||
621 | * that extent will have a csum cached, and it will insert | ||
622 | * the sum after all the blocks in the extent are fully | ||
623 | * on disk. So, look for an ordered extent and use the | ||
624 | * sum if found. | ||
625 | */ | ||
626 | ret = btrfs_find_ordered_sum(inode, start, &csum); | ||
627 | if (ret == 0) | ||
628 | goto found; | ||
629 | |||
630 | ret = PTR_ERR(item); | 633 | ret = PTR_ERR(item); |
631 | /* a csum that isn't present is a preallocated region. */ | 634 | /* a csum that isn't present is a preallocated region. */ |
632 | if (ret == -ENOENT || ret == -EFBIG) | 635 | if (ret == -ENOENT || ret == -EFBIG) |
@@ -641,7 +644,6 @@ int btrfs_readpage_io_hook(struct page *page, u64 start, u64 end) | |||
641 | found: | 644 | found: |
642 | set_state_private(io_tree, start, csum); | 645 | set_state_private(io_tree, start, csum); |
643 | out: | 646 | out: |
644 | mutex_unlock(&BTRFS_I(inode)->csum_mutex); | ||
645 | if (path) | 647 | if (path) |
646 | btrfs_free_path(path); | 648 | btrfs_free_path(path); |
647 | return ret; | 649 | return ret; |
@@ -1375,7 +1377,7 @@ again: | |||
1375 | } | 1377 | } |
1376 | if (!PageUptodate(page)) { | 1378 | if (!PageUptodate(page)) { |
1377 | ret = -EIO; | 1379 | ret = -EIO; |
1378 | goto out; | 1380 | goto out_unlock; |
1379 | } | 1381 | } |
1380 | } | 1382 | } |
1381 | wait_on_page_writeback(page); | 1383 | wait_on_page_writeback(page); |
@@ -1406,6 +1408,7 @@ again: | |||
1406 | set_page_dirty(page); | 1408 | set_page_dirty(page); |
1407 | unlock_extent(io_tree, page_start, page_end, GFP_NOFS); | 1409 | unlock_extent(io_tree, page_start, page_end, GFP_NOFS); |
1408 | 1410 | ||
1411 | out_unlock: | ||
1409 | unlock_page(page); | 1412 | unlock_page(page); |
1410 | page_cache_release(page); | 1413 | page_cache_release(page); |
1411 | out: | 1414 | out: |