aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c33
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)
641found: 644found:
642 set_state_private(io_tree, start, csum); 645 set_state_private(io_tree, start, csum);
643out: 646out:
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
1411out_unlock:
1409 unlock_page(page); 1412 unlock_page(page);
1410 page_cache_release(page); 1413 page_cache_release(page);
1411out: 1414out: