diff options
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 52 |
1 files changed, 41 insertions, 11 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 13a4aa222861..00aefbdcc2df 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -5327,8 +5327,9 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock, | |||
5327 | return PTR_ERR(em); | 5327 | return PTR_ERR(em); |
5328 | len = min(len, em->block_len); | 5328 | len = min(len, em->block_len); |
5329 | } | 5329 | } |
5330 | unlock_extent(&BTRFS_I(inode)->io_tree, start, start + len - 1, | 5330 | clear_extent_bit(&BTRFS_I(inode)->io_tree, start, start + len - 1, |
5331 | GFP_NOFS); | 5331 | EXTENT_LOCKED | EXTENT_DELALLOC | EXTENT_DIRTY, 1, |
5332 | 0, NULL, GFP_NOFS); | ||
5332 | map: | 5333 | map: |
5333 | bh_result->b_blocknr = (em->block_start + (start - em->start)) >> | 5334 | bh_result->b_blocknr = (em->block_start + (start - em->start)) >> |
5334 | inode->i_blkbits; | 5335 | inode->i_blkbits; |
@@ -5596,14 +5597,18 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb, | |||
5596 | struct file *file = iocb->ki_filp; | 5597 | struct file *file = iocb->ki_filp; |
5597 | struct inode *inode = file->f_mapping->host; | 5598 | struct inode *inode = file->f_mapping->host; |
5598 | struct btrfs_ordered_extent *ordered; | 5599 | struct btrfs_ordered_extent *ordered; |
5600 | struct extent_state *cached_state = NULL; | ||
5599 | u64 lockstart, lockend; | 5601 | u64 lockstart, lockend; |
5600 | ssize_t ret; | 5602 | ssize_t ret; |
5603 | int writing = rw & WRITE; | ||
5604 | int write_bits = 0; | ||
5601 | 5605 | ||
5602 | lockstart = offset; | 5606 | lockstart = offset; |
5603 | lockend = offset + iov_length(iov, nr_segs) - 1; | 5607 | lockend = offset + iov_length(iov, nr_segs) - 1; |
5608 | |||
5604 | while (1) { | 5609 | while (1) { |
5605 | lock_extent(&BTRFS_I(inode)->io_tree, lockstart, lockend, | 5610 | lock_extent_bits(&BTRFS_I(inode)->io_tree, lockstart, lockend, |
5606 | GFP_NOFS); | 5611 | 0, &cached_state, GFP_NOFS); |
5607 | /* | 5612 | /* |
5608 | * We're concerned with the entire range that we're going to be | 5613 | * We're concerned with the entire range that we're going to be |
5609 | * doing DIO to, so we need to make sure theres no ordered | 5614 | * doing DIO to, so we need to make sure theres no ordered |
@@ -5613,29 +5618,54 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb, | |||
5613 | lockend - lockstart + 1); | 5618 | lockend - lockstart + 1); |
5614 | if (!ordered) | 5619 | if (!ordered) |
5615 | break; | 5620 | break; |
5616 | unlock_extent(&BTRFS_I(inode)->io_tree, lockstart, lockend, | 5621 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart, lockend, |
5617 | GFP_NOFS); | 5622 | &cached_state, GFP_NOFS); |
5618 | btrfs_start_ordered_extent(inode, ordered, 1); | 5623 | btrfs_start_ordered_extent(inode, ordered, 1); |
5619 | btrfs_put_ordered_extent(ordered); | 5624 | btrfs_put_ordered_extent(ordered); |
5620 | cond_resched(); | 5625 | cond_resched(); |
5621 | } | 5626 | } |
5622 | 5627 | ||
5628 | /* | ||
5629 | * we don't use btrfs_set_extent_delalloc because we don't want | ||
5630 | * the dirty or uptodate bits | ||
5631 | */ | ||
5632 | if (writing) { | ||
5633 | write_bits = EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING; | ||
5634 | ret = set_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, lockend, | ||
5635 | EXTENT_DELALLOC, 0, NULL, &cached_state, | ||
5636 | GFP_NOFS); | ||
5637 | if (ret) { | ||
5638 | clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, | ||
5639 | lockend, EXTENT_LOCKED | write_bits, | ||
5640 | 1, 0, &cached_state, GFP_NOFS); | ||
5641 | goto out; | ||
5642 | } | ||
5643 | } | ||
5644 | |||
5645 | free_extent_state(cached_state); | ||
5646 | cached_state = NULL; | ||
5647 | |||
5623 | ret = __blockdev_direct_IO(rw, iocb, inode, NULL, iov, offset, nr_segs, | 5648 | ret = __blockdev_direct_IO(rw, iocb, inode, NULL, iov, offset, nr_segs, |
5624 | btrfs_get_blocks_direct, NULL, | 5649 | btrfs_get_blocks_direct, NULL, |
5625 | btrfs_submit_direct, 0); | 5650 | btrfs_submit_direct, 0); |
5626 | 5651 | ||
5627 | if (ret < 0 && ret != -EIOCBQUEUED) { | 5652 | if (ret < 0 && ret != -EIOCBQUEUED) { |
5628 | unlock_extent(&BTRFS_I(inode)->io_tree, offset, | 5653 | clear_extent_bit(&BTRFS_I(inode)->io_tree, offset, |
5629 | offset + iov_length(iov, nr_segs) - 1, GFP_NOFS); | 5654 | offset + iov_length(iov, nr_segs) - 1, |
5655 | EXTENT_LOCKED | write_bits, 1, 0, | ||
5656 | &cached_state, GFP_NOFS); | ||
5630 | } else if (ret >= 0 && ret < iov_length(iov, nr_segs)) { | 5657 | } else if (ret >= 0 && ret < iov_length(iov, nr_segs)) { |
5631 | /* | 5658 | /* |
5632 | * We're falling back to buffered, unlock the section we didn't | 5659 | * We're falling back to buffered, unlock the section we didn't |
5633 | * do IO on. | 5660 | * do IO on. |
5634 | */ | 5661 | */ |
5635 | unlock_extent(&BTRFS_I(inode)->io_tree, offset + ret, | 5662 | clear_extent_bit(&BTRFS_I(inode)->io_tree, offset + ret, |
5636 | offset + iov_length(iov, nr_segs) - 1, GFP_NOFS); | 5663 | offset + iov_length(iov, nr_segs) - 1, |
5664 | EXTENT_LOCKED | write_bits, 1, 0, | ||
5665 | &cached_state, GFP_NOFS); | ||
5637 | } | 5666 | } |
5638 | 5667 | out: | |
5668 | free_extent_state(cached_state); | ||
5639 | return ret; | 5669 | return ret; |
5640 | } | 5670 | } |
5641 | 5671 | ||