aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/inode.c56
1 files changed, 43 insertions, 13 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index f81a48c47fe0..4f8fb1130cf3 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -7540,6 +7540,27 @@ static struct extent_map *create_io_em(struct inode *inode, u64 start, u64 len,
7540 return em; 7540 return em;
7541} 7541}
7542 7542
7543
7544static int btrfs_get_blocks_direct_read(struct extent_map *em,
7545 struct buffer_head *bh_result,
7546 struct inode *inode,
7547 u64 start, u64 len)
7548{
7549 if (em->block_start == EXTENT_MAP_HOLE ||
7550 test_bit(EXTENT_FLAG_PREALLOC, &em->flags))
7551 return -ENOENT;
7552
7553 len = min(len, em->len - (start - em->start));
7554
7555 bh_result->b_blocknr = (em->block_start + (start - em->start)) >>
7556 inode->i_blkbits;
7557 bh_result->b_size = len;
7558 bh_result->b_bdev = em->bdev;
7559 set_buffer_mapped(bh_result);
7560
7561 return 0;
7562}
7563
7543static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock, 7564static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
7544 struct buffer_head *bh_result, int create) 7565 struct buffer_head *bh_result, int create)
7545{ 7566{
@@ -7608,11 +7629,29 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
7608 goto unlock_err; 7629 goto unlock_err;
7609 } 7630 }
7610 7631
7611 /* Just a good old fashioned hole, return */ 7632 if (!create) {
7612 if (!create && (em->block_start == EXTENT_MAP_HOLE || 7633 ret = btrfs_get_blocks_direct_read(em, bh_result, inode,
7613 test_bit(EXTENT_FLAG_PREALLOC, &em->flags))) { 7634 start, len);
7635 /* Can be negative only if we read from a hole */
7636 if (ret < 0) {
7637 ret = 0;
7638 free_extent_map(em);
7639 goto unlock_err;
7640 }
7641 /*
7642 * We need to unlock only the end area that we aren't using.
7643 * The rest is going to be unlocked by the endio routine.
7644 */
7645 lockstart = start + bh_result->b_size;
7646 if (lockstart < lockend) {
7647 clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart,
7648 lockend, unlock_bits, 1, 0,
7649 &cached_state);
7650 } else {
7651 free_extent_state(cached_state);
7652 }
7614 free_extent_map(em); 7653 free_extent_map(em);
7615 goto unlock_err; 7654 return 0;
7616 } 7655 }
7617 7656
7618 /* 7657 /*
@@ -7624,12 +7663,6 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
7624 * just use the extent. 7663 * just use the extent.
7625 * 7664 *
7626 */ 7665 */
7627 if (!create) {
7628 len = min(len, em->len - (start - em->start));
7629 lockstart = start + len;
7630 goto unlock;
7631 }
7632
7633 if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags) || 7666 if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags) ||
7634 ((BTRFS_I(inode)->flags & BTRFS_INODE_NODATACOW) && 7667 ((BTRFS_I(inode)->flags & BTRFS_INODE_NODATACOW) &&
7635 em->block_start != EXTENT_MAP_HOLE)) { 7668 em->block_start != EXTENT_MAP_HOLE)) {
@@ -7716,10 +7749,7 @@ unlock:
7716 clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, 7749 clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart,
7717 lockend, unlock_bits, 1, 0, 7750 lockend, unlock_bits, 1, 0,
7718 &cached_state); 7751 &cached_state);
7719 } else {
7720 free_extent_state(cached_state);
7721 } 7752 }
7722
7723 free_extent_map(em); 7753 free_extent_map(em);
7724 7754
7725 return 0; 7755 return 0;