aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2010-11-28 19:56:33 -0500
committerChris Mason <chris.mason@oracle.com>2010-11-28 19:56:33 -0500
commit163cf09c2a0ee5cac6285f9347975bd1e97725da (patch)
tree5a83cd42d57fcc4d92d12965b5eafdb472e89b02 /fs/btrfs/inode.c
parent450ba0ea06b6ed3612d27f2b7127a9de4160f285 (diff)
Btrfs: deal with DIO bios that span more than one ordered extent
The new DIO bio splitting code has problems when the bio spans more than one ordered extent. This will happen as the generic DIO code merges our get_blocks calls together into a bigger single bio. This fixes things by walking forward in the ordered extent code finding all the overlapping ordered extents and completing them all at once. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c23
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 5611again:
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:
5670out: 5673out:
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
5680out_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 }
5675out_done: 5690out_done:
5676 bio->bi_private = dip->private; 5691 bio->bi_private = dip->private;
5677 5692