diff options
-rw-r--r-- | fs/btrfs/extent-tree.c | 3 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 81 |
2 files changed, 43 insertions, 41 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 1818dd90c27e..51e1151a0a02 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -4748,7 +4748,8 @@ void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes) | |||
4748 | spin_lock(&BTRFS_I(inode)->lock); | 4748 | spin_lock(&BTRFS_I(inode)->lock); |
4749 | dropped = drop_outstanding_extent(inode); | 4749 | dropped = drop_outstanding_extent(inode); |
4750 | 4750 | ||
4751 | to_free = calc_csum_metadata_size(inode, num_bytes, 0); | 4751 | if (num_bytes) |
4752 | to_free = calc_csum_metadata_size(inode, num_bytes, 0); | ||
4752 | spin_unlock(&BTRFS_I(inode)->lock); | 4753 | spin_unlock(&BTRFS_I(inode)->lock); |
4753 | if (dropped > 0) | 4754 | if (dropped > 0) |
4754 | to_free += btrfs_calc_trans_metadata_size(root, dropped); | 4755 | to_free += btrfs_calc_trans_metadata_size(root, dropped); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 16925807a9ed..d11f38d8696c 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -6059,16 +6059,15 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock, | |||
6059 | u64 len = bh_result->b_size; | 6059 | u64 len = bh_result->b_size; |
6060 | struct btrfs_trans_handle *trans; | 6060 | struct btrfs_trans_handle *trans; |
6061 | int unlock_bits = EXTENT_LOCKED; | 6061 | int unlock_bits = EXTENT_LOCKED; |
6062 | int ret; | 6062 | int ret = 0; |
6063 | 6063 | ||
6064 | if (create) { | 6064 | if (create) { |
6065 | ret = btrfs_delalloc_reserve_space(inode, len); | 6065 | spin_lock(&BTRFS_I(inode)->lock); |
6066 | if (ret) | 6066 | BTRFS_I(inode)->outstanding_extents++; |
6067 | return ret; | 6067 | spin_unlock(&BTRFS_I(inode)->lock); |
6068 | unlock_bits |= EXTENT_DELALLOC | EXTENT_DIRTY; | 6068 | unlock_bits |= EXTENT_DELALLOC | EXTENT_DIRTY; |
6069 | } else { | 6069 | } else |
6070 | len = min_t(u64, len, root->sectorsize); | 6070 | len = min_t(u64, len, root->sectorsize); |
6071 | } | ||
6072 | 6071 | ||
6073 | lockstart = start; | 6072 | lockstart = start; |
6074 | lockend = start + len - 1; | 6073 | lockend = start + len - 1; |
@@ -6080,14 +6079,6 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock, | |||
6080 | if (lock_extent_direct(inode, lockstart, lockend, &cached_state, create)) | 6079 | if (lock_extent_direct(inode, lockstart, lockend, &cached_state, create)) |
6081 | return -ENOTBLK; | 6080 | return -ENOTBLK; |
6082 | 6081 | ||
6083 | if (create) { | ||
6084 | ret = set_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, | ||
6085 | lockend, EXTENT_DELALLOC, NULL, | ||
6086 | &cached_state, GFP_NOFS); | ||
6087 | if (ret) | ||
6088 | goto unlock_err; | ||
6089 | } | ||
6090 | |||
6091 | em = btrfs_get_extent(inode, NULL, 0, start, len, 0); | 6082 | em = btrfs_get_extent(inode, NULL, 0, start, len, 0); |
6092 | if (IS_ERR(em)) { | 6083 | if (IS_ERR(em)) { |
6093 | ret = PTR_ERR(em); | 6084 | ret = PTR_ERR(em); |
@@ -6119,7 +6110,6 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock, | |||
6119 | if (!create && (em->block_start == EXTENT_MAP_HOLE || | 6110 | if (!create && (em->block_start == EXTENT_MAP_HOLE || |
6120 | test_bit(EXTENT_FLAG_PREALLOC, &em->flags))) { | 6111 | test_bit(EXTENT_FLAG_PREALLOC, &em->flags))) { |
6121 | free_extent_map(em); | 6112 | free_extent_map(em); |
6122 | ret = 0; | ||
6123 | goto unlock_err; | 6113 | goto unlock_err; |
6124 | } | 6114 | } |
6125 | 6115 | ||
@@ -6217,6 +6207,11 @@ unlock: | |||
6217 | */ | 6207 | */ |
6218 | if (start + len > i_size_read(inode)) | 6208 | if (start + len > i_size_read(inode)) |
6219 | i_size_write(inode, start + len); | 6209 | i_size_write(inode, start + len); |
6210 | |||
6211 | ret = set_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, | ||
6212 | lockstart + len - 1, EXTENT_DELALLOC, NULL, | ||
6213 | &cached_state, GFP_NOFS); | ||
6214 | BUG_ON(ret); | ||
6220 | } | 6215 | } |
6221 | 6216 | ||
6222 | /* | 6217 | /* |
@@ -6225,24 +6220,9 @@ unlock: | |||
6225 | * aren't using if there is any left over space. | 6220 | * aren't using if there is any left over space. |
6226 | */ | 6221 | */ |
6227 | if (lockstart < lockend) { | 6222 | if (lockstart < lockend) { |
6228 | if (create && len < lockend - lockstart) { | 6223 | clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, |
6229 | clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, | 6224 | lockend, unlock_bits, 1, 0, |
6230 | lockstart + len - 1, | 6225 | &cached_state, GFP_NOFS); |
6231 | unlock_bits | EXTENT_DEFRAG, 1, 0, | ||
6232 | &cached_state, GFP_NOFS); | ||
6233 | /* | ||
6234 | * Beside unlock, we also need to cleanup reserved space | ||
6235 | * for the left range by attaching EXTENT_DO_ACCOUNTING. | ||
6236 | */ | ||
6237 | clear_extent_bit(&BTRFS_I(inode)->io_tree, | ||
6238 | lockstart + len, lockend, | ||
6239 | unlock_bits | EXTENT_DO_ACCOUNTING | | ||
6240 | EXTENT_DEFRAG, 1, 0, NULL, GFP_NOFS); | ||
6241 | } else { | ||
6242 | clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, | ||
6243 | lockend, unlock_bits, 1, 0, | ||
6244 | &cached_state, GFP_NOFS); | ||
6245 | } | ||
6246 | } else { | 6226 | } else { |
6247 | free_extent_state(cached_state); | 6227 | free_extent_state(cached_state); |
6248 | } | 6228 | } |
@@ -6252,9 +6232,6 @@ unlock: | |||
6252 | return 0; | 6232 | return 0; |
6253 | 6233 | ||
6254 | unlock_err: | 6234 | unlock_err: |
6255 | if (create) | ||
6256 | unlock_bits |= EXTENT_DO_ACCOUNTING; | ||
6257 | |||
6258 | clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, lockend, | 6235 | clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, lockend, |
6259 | unlock_bits, 1, 0, &cached_state, GFP_NOFS); | 6236 | unlock_bits, 1, 0, &cached_state, GFP_NOFS); |
6260 | return ret; | 6237 | return ret; |
@@ -6692,15 +6669,39 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb, | |||
6692 | { | 6669 | { |
6693 | struct file *file = iocb->ki_filp; | 6670 | struct file *file = iocb->ki_filp; |
6694 | struct inode *inode = file->f_mapping->host; | 6671 | struct inode *inode = file->f_mapping->host; |
6672 | size_t count = 0; | ||
6673 | ssize_t ret; | ||
6695 | 6674 | ||
6696 | if (check_direct_IO(BTRFS_I(inode)->root, rw, iocb, iov, | 6675 | if (check_direct_IO(BTRFS_I(inode)->root, rw, iocb, iov, |
6697 | offset, nr_segs)) | 6676 | offset, nr_segs)) |
6698 | return 0; | 6677 | return 0; |
6699 | 6678 | ||
6700 | return __blockdev_direct_IO(rw, iocb, inode, | 6679 | if (rw & WRITE) { |
6701 | BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev, | 6680 | count = iov_length(iov, nr_segs); |
6702 | iov, offset, nr_segs, btrfs_get_blocks_direct, NULL, | 6681 | ret = btrfs_delalloc_reserve_space(inode, count); |
6703 | btrfs_submit_direct, 0); | 6682 | if (ret) |
6683 | return ret; | ||
6684 | } | ||
6685 | |||
6686 | ret = __blockdev_direct_IO(rw, iocb, inode, | ||
6687 | BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev, | ||
6688 | iov, offset, nr_segs, btrfs_get_blocks_direct, NULL, | ||
6689 | btrfs_submit_direct, 0); | ||
6690 | |||
6691 | if (rw & WRITE) { | ||
6692 | if (ret < 0 && ret != -EIOCBQUEUED) | ||
6693 | btrfs_delalloc_release_space(inode, count); | ||
6694 | else if (ret > 0 && (size_t)ret < count) { | ||
6695 | spin_lock(&BTRFS_I(inode)->lock); | ||
6696 | BTRFS_I(inode)->outstanding_extents++; | ||
6697 | spin_unlock(&BTRFS_I(inode)->lock); | ||
6698 | btrfs_delalloc_release_space(inode, | ||
6699 | count - (size_t)ret); | ||
6700 | } | ||
6701 | btrfs_delalloc_release_metadata(inode, 0); | ||
6702 | } | ||
6703 | |||
6704 | return ret; | ||
6704 | } | 6705 | } |
6705 | 6706 | ||
6706 | #define BTRFS_FIEMAP_FLAGS (FIEMAP_FLAG_SYNC) | 6707 | #define BTRFS_FIEMAP_FLAGS (FIEMAP_FLAG_SYNC) |