aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2013-04-24 16:32:55 -0400
committerJosef Bacik <jbacik@fusionio.com>2013-05-06 15:55:07 -0400
commiteb384b55ae9c2055ea00c5cc87971e182d47aefa (patch)
tree264ce025fdf750770e7e034345a923f2a9a9752b
parent416bc6580bb01ddf67befaaeb94f087b392e7f47 (diff)
Btrfs: fix extent logging with O_DIRECT into prealloc
This is the same as the fix from commit Btrfs: fix bad extent logging but for O_DIRECT. I missed this when I fixed the problem originally, we were still using the em for the orig_start and orig_block_len, which would be the merged extent. We need to use the actual extent from the on disk file extent item, which we have to lookup to make sure it's ok to nocow anyway so just pass in some pointers to hold this info. Thanks, Cc: stable@vger.kernel.org Signed-off-by: Josef Bacik <jbacik@fusionio.com>
-rw-r--r--fs/btrfs/inode.c22
1 files changed, 13 insertions, 9 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index d65a55c9be8a..33a9e9da726d 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -6504,7 +6504,9 @@ out:
6504 * block must be cow'd 6504 * block must be cow'd
6505 */ 6505 */
6506static noinline int can_nocow_odirect(struct btrfs_trans_handle *trans, 6506static noinline int can_nocow_odirect(struct btrfs_trans_handle *trans,
6507 struct inode *inode, u64 offset, u64 len) 6507 struct inode *inode, u64 offset, u64 *len,
6508 u64 *orig_start, u64 *orig_block_len,
6509 u64 *ram_bytes)
6508{ 6510{
6509 struct btrfs_path *path; 6511 struct btrfs_path *path;
6510 int ret; 6512 int ret;
@@ -6561,8 +6563,12 @@ static noinline int can_nocow_odirect(struct btrfs_trans_handle *trans,
6561 disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); 6563 disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
6562 backref_offset = btrfs_file_extent_offset(leaf, fi); 6564 backref_offset = btrfs_file_extent_offset(leaf, fi);
6563 6565
6566 *orig_start = key.offset - backref_offset;
6567 *orig_block_len = btrfs_file_extent_disk_num_bytes(leaf, fi);
6568 *ram_bytes = btrfs_file_extent_ram_bytes(leaf, fi);
6569
6564 extent_end = key.offset + btrfs_file_extent_num_bytes(leaf, fi); 6570 extent_end = key.offset + btrfs_file_extent_num_bytes(leaf, fi);
6565 if (extent_end < offset + len) { 6571 if (extent_end < offset + *len) {
6566 /* extent doesn't include our full range, must cow */ 6572 /* extent doesn't include our full range, must cow */
6567 goto out; 6573 goto out;
6568 } 6574 }
@@ -6586,13 +6592,14 @@ static noinline int can_nocow_odirect(struct btrfs_trans_handle *trans,
6586 */ 6592 */
6587 disk_bytenr += backref_offset; 6593 disk_bytenr += backref_offset;
6588 disk_bytenr += offset - key.offset; 6594 disk_bytenr += offset - key.offset;
6589 num_bytes = min(offset + len, extent_end) - offset; 6595 num_bytes = min(offset + *len, extent_end) - offset;
6590 if (csum_exist_in_range(root, disk_bytenr, num_bytes)) 6596 if (csum_exist_in_range(root, disk_bytenr, num_bytes))
6591 goto out; 6597 goto out;
6592 /* 6598 /*
6593 * all of the above have passed, it is safe to overwrite this extent 6599 * all of the above have passed, it is safe to overwrite this extent
6594 * without cow 6600 * without cow
6595 */ 6601 */
6602 *len = num_bytes;
6596 ret = 1; 6603 ret = 1;
6597out: 6604out:
6598 btrfs_free_path(path); 6605 btrfs_free_path(path);
@@ -6790,7 +6797,7 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
6790 em->block_start != EXTENT_MAP_HOLE)) { 6797 em->block_start != EXTENT_MAP_HOLE)) {
6791 int type; 6798 int type;
6792 int ret; 6799 int ret;
6793 u64 block_start; 6800 u64 block_start, orig_start, orig_block_len, ram_bytes;
6794 6801
6795 if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) 6802 if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags))
6796 type = BTRFS_ORDERED_PREALLOC; 6803 type = BTRFS_ORDERED_PREALLOC;
@@ -6808,11 +6815,8 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
6808 if (IS_ERR(trans)) 6815 if (IS_ERR(trans))
6809 goto must_cow; 6816 goto must_cow;
6810 6817
6811 if (can_nocow_odirect(trans, inode, start, len) == 1) { 6818 if (can_nocow_odirect(trans, inode, start, &len, &orig_start,
6812 u64 orig_start = em->orig_start; 6819 &orig_block_len, &ram_bytes) == 1) {
6813 u64 orig_block_len = em->orig_block_len;
6814 u64 ram_bytes = em->ram_bytes;
6815
6816 if (type == BTRFS_ORDERED_PREALLOC) { 6820 if (type == BTRFS_ORDERED_PREALLOC) {
6817 free_extent_map(em); 6821 free_extent_map(em);
6818 em = create_pinned_em(inode, start, len, 6822 em = create_pinned_em(inode, start, len,