aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosef Bacik2013-04-24 15:32:55 -0500
committerGreg Kroah-Hartman2013-05-11 15:54:10 -0500
commitc665070565cc75380d09c4a94142781191e8c22e (patch)
tree3753938d89ed0f0d42bfc6d6e2a2c707da14825c
parent02cfa2ab3ec610411e30dd15b1df2df0e31afde7 (diff)
downloadkernel-omap-c665070565cc75380d09c4a94142781191e8c22e.tar.gz
kernel-omap-c665070565cc75380d09c4a94142781191e8c22e.tar.xz
kernel-omap-c665070565cc75380d09c4a94142781191e8c22e.zip
Btrfs: fix extent logging with O_DIRECT into prealloc
commit eb384b55ae9c2055ea00c5cc87971e182d47aefa upstream. 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, Signed-off-by: Josef Bacik <jbacik@fusionio.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/btrfs/inode.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 7c4e6ccdba3f..4b5398c9f62b 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -5794,7 +5794,9 @@ out:
5794 * block must be cow'd 5794 * block must be cow'd
5795 */ 5795 */
5796static noinline int can_nocow_odirect(struct btrfs_trans_handle *trans, 5796static noinline int can_nocow_odirect(struct btrfs_trans_handle *trans,
5797 struct inode *inode, u64 offset, u64 len) 5797 struct inode *inode, u64 offset, u64 *len,
5798 u64 *orig_start, u64 *orig_block_len,
5799 u64 *ram_bytes)
5798{ 5800{
5799 struct btrfs_path *path; 5801 struct btrfs_path *path;
5800 int ret; 5802 int ret;
@@ -5851,8 +5853,12 @@ static noinline int can_nocow_odirect(struct btrfs_trans_handle *trans,
5851 disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); 5853 disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
5852 backref_offset = btrfs_file_extent_offset(leaf, fi); 5854 backref_offset = btrfs_file_extent_offset(leaf, fi);
5853 5855
5856 *orig_start = key.offset - backref_offset;
5857 *orig_block_len = btrfs_file_extent_disk_num_bytes(leaf, fi);
5858 *ram_bytes = btrfs_file_extent_ram_bytes(leaf, fi);
5859
5854 extent_end = key.offset + btrfs_file_extent_num_bytes(leaf, fi); 5860 extent_end = key.offset + btrfs_file_extent_num_bytes(leaf, fi);
5855 if (extent_end < offset + len) { 5861 if (extent_end < offset + *len) {
5856 /* extent doesn't include our full range, must cow */ 5862 /* extent doesn't include our full range, must cow */
5857 goto out; 5863 goto out;
5858 } 5864 }
@@ -5876,13 +5882,14 @@ static noinline int can_nocow_odirect(struct btrfs_trans_handle *trans,
5876 */ 5882 */
5877 disk_bytenr += backref_offset; 5883 disk_bytenr += backref_offset;
5878 disk_bytenr += offset - key.offset; 5884 disk_bytenr += offset - key.offset;
5879 num_bytes = min(offset + len, extent_end) - offset; 5885 num_bytes = min(offset + *len, extent_end) - offset;
5880 if (csum_exist_in_range(root, disk_bytenr, num_bytes)) 5886 if (csum_exist_in_range(root, disk_bytenr, num_bytes))
5881 goto out; 5887 goto out;
5882 /* 5888 /*
5883 * all of the above have passed, it is safe to overwrite this extent 5889 * all of the above have passed, it is safe to overwrite this extent
5884 * without cow 5890 * without cow
5885 */ 5891 */
5892 *len = num_bytes;
5886 ret = 1; 5893 ret = 1;
5887out: 5894out:
5888 btrfs_free_path(path); 5895 btrfs_free_path(path);
@@ -6092,7 +6099,7 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
6092 em->block_start != EXTENT_MAP_HOLE)) { 6099 em->block_start != EXTENT_MAP_HOLE)) {
6093 int type; 6100 int type;
6094 int ret; 6101 int ret;
6095 u64 block_start; 6102 u64 block_start, orig_start, orig_block_len, ram_bytes;
6096 6103
6097 if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) 6104 if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags))
6098 type = BTRFS_ORDERED_PREALLOC; 6105 type = BTRFS_ORDERED_PREALLOC;
@@ -6110,10 +6117,8 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
6110 if (IS_ERR(trans)) 6117 if (IS_ERR(trans))
6111 goto must_cow; 6118 goto must_cow;
6112 6119
6113 if (can_nocow_odirect(trans, inode, start, len) == 1) { 6120 if (can_nocow_odirect(trans, inode, start, &len, &orig_start,
6114 u64 orig_start = em->orig_start; 6121 &orig_block_len, &ram_bytes) == 1) {
6115 u64 orig_block_len = em->orig_block_len;
6116
6117 if (type == BTRFS_ORDERED_PREALLOC) { 6122 if (type == BTRFS_ORDERED_PREALLOC) {
6118 free_extent_map(em); 6123 free_extent_map(em);
6119 em = create_pinned_em(inode, start, len, 6124 em = create_pinned_em(inode, start, len,