aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/inode.c37
1 files changed, 35 insertions, 2 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 3717b3d4c2ce..aa1fb534f69f 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -7239,7 +7239,7 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
7239 u64 start = iblock << inode->i_blkbits; 7239 u64 start = iblock << inode->i_blkbits;
7240 u64 lockstart, lockend; 7240 u64 lockstart, lockend;
7241 u64 len = bh_result->b_size; 7241 u64 len = bh_result->b_size;
7242 u64 orig_len = len; 7242 u64 *outstanding_extents = NULL;
7243 int unlock_bits = EXTENT_LOCKED; 7243 int unlock_bits = EXTENT_LOCKED;
7244 int ret = 0; 7244 int ret = 0;
7245 7245
@@ -7251,6 +7251,16 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
7251 lockstart = start; 7251 lockstart = start;
7252 lockend = start + len - 1; 7252 lockend = start + len - 1;
7253 7253
7254 if (current->journal_info) {
7255 /*
7256 * Need to pull our outstanding extents and set journal_info to NULL so
7257 * that anything that needs to check if there's a transction doesn't get
7258 * confused.
7259 */
7260 outstanding_extents = current->journal_info;
7261 current->journal_info = NULL;
7262 }
7263
7254 /* 7264 /*
7255 * If this errors out it's because we couldn't invalidate pagecache for 7265 * If this errors out it's because we couldn't invalidate pagecache for
7256 * this range and we need to fallback to buffered. 7266 * this range and we need to fallback to buffered.
@@ -7374,11 +7384,20 @@ unlock:
7374 if (start + len > i_size_read(inode)) 7384 if (start + len > i_size_read(inode))
7375 i_size_write(inode, start + len); 7385 i_size_write(inode, start + len);
7376 7386
7377 if (len < orig_len) { 7387 /*
7388 * If we have an outstanding_extents count still set then we're
7389 * within our reservation, otherwise we need to adjust our inode
7390 * counter appropriately.
7391 */
7392 if (*outstanding_extents) {
7393 (*outstanding_extents)--;
7394 } else {
7378 spin_lock(&BTRFS_I(inode)->lock); 7395 spin_lock(&BTRFS_I(inode)->lock);
7379 BTRFS_I(inode)->outstanding_extents++; 7396 BTRFS_I(inode)->outstanding_extents++;
7380 spin_unlock(&BTRFS_I(inode)->lock); 7397 spin_unlock(&BTRFS_I(inode)->lock);
7381 } 7398 }
7399
7400 current->journal_info = outstanding_extents;
7382 btrfs_free_reserved_data_space(inode, len); 7401 btrfs_free_reserved_data_space(inode, len);
7383 } 7402 }
7384 7403
@@ -7402,6 +7421,8 @@ unlock:
7402unlock_err: 7421unlock_err:
7403 clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, lockend, 7422 clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, lockend,
7404 unlock_bits, 1, 0, &cached_state, GFP_NOFS); 7423 unlock_bits, 1, 0, &cached_state, GFP_NOFS);
7424 if (outstanding_extents)
7425 current->journal_info = outstanding_extents;
7405 return ret; 7426 return ret;
7406} 7427}
7407 7428
@@ -8101,6 +8122,7 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
8101{ 8122{
8102 struct file *file = iocb->ki_filp; 8123 struct file *file = iocb->ki_filp;
8103 struct inode *inode = file->f_mapping->host; 8124 struct inode *inode = file->f_mapping->host;
8125 u64 outstanding_extents = 0;
8104 size_t count = 0; 8126 size_t count = 0;
8105 int flags = 0; 8127 int flags = 0;
8106 bool wakeup = true; 8128 bool wakeup = true;
@@ -8138,6 +8160,16 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
8138 ret = btrfs_delalloc_reserve_space(inode, count); 8160 ret = btrfs_delalloc_reserve_space(inode, count);
8139 if (ret) 8161 if (ret)
8140 goto out; 8162 goto out;
8163 outstanding_extents = div64_u64(count +
8164 BTRFS_MAX_EXTENT_SIZE - 1,
8165 BTRFS_MAX_EXTENT_SIZE);
8166
8167 /*
8168 * We need to know how many extents we reserved so that we can
8169 * do the accounting properly if we go over the number we
8170 * originally calculated. Abuse current->journal_info for this.
8171 */
8172 current->journal_info = &outstanding_extents;
8141 } else if (test_bit(BTRFS_INODE_READDIO_NEED_LOCK, 8173 } else if (test_bit(BTRFS_INODE_READDIO_NEED_LOCK,
8142 &BTRFS_I(inode)->runtime_flags)) { 8174 &BTRFS_I(inode)->runtime_flags)) {
8143 inode_dio_done(inode); 8175 inode_dio_done(inode);
@@ -8150,6 +8182,7 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
8150 iter, offset, btrfs_get_blocks_direct, NULL, 8182 iter, offset, btrfs_get_blocks_direct, NULL,
8151 btrfs_submit_direct, flags); 8183 btrfs_submit_direct, flags);
8152 if (rw & WRITE) { 8184 if (rw & WRITE) {
8185 current->journal_info = NULL;
8153 if (ret < 0 && ret != -EIOCBQUEUED) 8186 if (ret < 0 && ret != -EIOCBQUEUED)
8154 btrfs_delalloc_release_space(inode, count); 8187 btrfs_delalloc_release_space(inode, count);
8155 else if (ret >= 0 && (size_t)ret < count) 8188 else if (ret >= 0 && (size_t)ret < count)