diff options
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 6df921f218fb..0f34cae0a633 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -5602,15 +5602,18 @@ static void btrfs_endio_direct_write(struct bio *bio, int err) | |||
5602 | struct btrfs_trans_handle *trans; | 5602 | struct btrfs_trans_handle *trans; |
5603 | struct btrfs_ordered_extent *ordered = NULL; | 5603 | struct btrfs_ordered_extent *ordered = NULL; |
5604 | struct extent_state *cached_state = NULL; | 5604 | struct extent_state *cached_state = NULL; |
5605 | u64 ordered_offset = dip->logical_offset; | ||
5606 | u64 ordered_bytes = dip->bytes; | ||
5605 | int ret; | 5607 | int ret; |
5606 | 5608 | ||
5607 | if (err) | 5609 | if (err) |
5608 | goto out_done; | 5610 | goto out_done; |
5609 | 5611 | again: | |
5610 | ret = btrfs_dec_test_ordered_pending(inode, &ordered, | 5612 | ret = btrfs_dec_test_first_ordered_pending(inode, &ordered, |
5611 | dip->logical_offset, dip->bytes); | 5613 | &ordered_offset, |
5614 | ordered_bytes); | ||
5612 | if (!ret) | 5615 | if (!ret) |
5613 | goto out_done; | 5616 | goto out_test; |
5614 | 5617 | ||
5615 | BUG_ON(!ordered); | 5618 | BUG_ON(!ordered); |
5616 | 5619 | ||
@@ -5670,8 +5673,20 @@ out_unlock: | |||
5670 | out: | 5673 | out: |
5671 | btrfs_delalloc_release_metadata(inode, ordered->len); | 5674 | btrfs_delalloc_release_metadata(inode, ordered->len); |
5672 | btrfs_end_transaction(trans, root); | 5675 | btrfs_end_transaction(trans, root); |
5676 | ordered_offset = ordered->file_offset + ordered->len; | ||
5673 | btrfs_put_ordered_extent(ordered); | 5677 | btrfs_put_ordered_extent(ordered); |
5674 | btrfs_put_ordered_extent(ordered); | 5678 | btrfs_put_ordered_extent(ordered); |
5679 | |||
5680 | out_test: | ||
5681 | /* | ||
5682 | * our bio might span multiple ordered extents. If we haven't | ||
5683 | * completed the accounting for the whole dio, go back and try again | ||
5684 | */ | ||
5685 | if (ordered_offset < dip->logical_offset + dip->bytes) { | ||
5686 | ordered_bytes = dip->logical_offset + dip->bytes - | ||
5687 | ordered_offset; | ||
5688 | goto again; | ||
5689 | } | ||
5675 | out_done: | 5690 | out_done: |
5676 | bio->bi_private = dip->private; | 5691 | bio->bi_private = dip->private; |
5677 | 5692 | ||