diff options
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 45 |
1 files changed, 23 insertions, 22 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index a0fa7253a2d7..611b66d73e80 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -5084,7 +5084,8 @@ void btrfs_evict_inode(struct inode *inode) | |||
5084 | goto no_delete; | 5084 | goto no_delete; |
5085 | } | 5085 | } |
5086 | /* do we really want it for ->i_nlink > 0 and zero btrfs_root_refs? */ | 5086 | /* do we really want it for ->i_nlink > 0 and zero btrfs_root_refs? */ |
5087 | btrfs_wait_ordered_range(inode, 0, (u64)-1); | 5087 | if (!special_file(inode->i_mode)) |
5088 | btrfs_wait_ordered_range(inode, 0, (u64)-1); | ||
5088 | 5089 | ||
5089 | btrfs_free_io_failure_record(inode, 0, (u64)-1); | 5090 | btrfs_free_io_failure_record(inode, 0, (u64)-1); |
5090 | 5091 | ||
@@ -7408,6 +7409,10 @@ static struct extent_map *create_pinned_em(struct inode *inode, u64 start, | |||
7408 | return em; | 7409 | return em; |
7409 | } | 7410 | } |
7410 | 7411 | ||
7412 | struct btrfs_dio_data { | ||
7413 | u64 outstanding_extents; | ||
7414 | u64 reserve; | ||
7415 | }; | ||
7411 | 7416 | ||
7412 | static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock, | 7417 | static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock, |
7413 | struct buffer_head *bh_result, int create) | 7418 | struct buffer_head *bh_result, int create) |
@@ -7415,10 +7420,10 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock, | |||
7415 | struct extent_map *em; | 7420 | struct extent_map *em; |
7416 | struct btrfs_root *root = BTRFS_I(inode)->root; | 7421 | struct btrfs_root *root = BTRFS_I(inode)->root; |
7417 | struct extent_state *cached_state = NULL; | 7422 | struct extent_state *cached_state = NULL; |
7423 | struct btrfs_dio_data *dio_data = NULL; | ||
7418 | u64 start = iblock << inode->i_blkbits; | 7424 | u64 start = iblock << inode->i_blkbits; |
7419 | u64 lockstart, lockend; | 7425 | u64 lockstart, lockend; |
7420 | u64 len = bh_result->b_size; | 7426 | u64 len = bh_result->b_size; |
7421 | u64 *outstanding_extents = NULL; | ||
7422 | int unlock_bits = EXTENT_LOCKED; | 7427 | int unlock_bits = EXTENT_LOCKED; |
7423 | int ret = 0; | 7428 | int ret = 0; |
7424 | 7429 | ||
@@ -7436,7 +7441,7 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock, | |||
7436 | * that anything that needs to check if there's a transction doesn't get | 7441 | * that anything that needs to check if there's a transction doesn't get |
7437 | * confused. | 7442 | * confused. |
7438 | */ | 7443 | */ |
7439 | outstanding_extents = current->journal_info; | 7444 | dio_data = current->journal_info; |
7440 | current->journal_info = NULL; | 7445 | current->journal_info = NULL; |
7441 | } | 7446 | } |
7442 | 7447 | ||
@@ -7568,17 +7573,18 @@ unlock: | |||
7568 | * within our reservation, otherwise we need to adjust our inode | 7573 | * within our reservation, otherwise we need to adjust our inode |
7569 | * counter appropriately. | 7574 | * counter appropriately. |
7570 | */ | 7575 | */ |
7571 | if (*outstanding_extents) { | 7576 | if (dio_data->outstanding_extents) { |
7572 | (*outstanding_extents)--; | 7577 | (dio_data->outstanding_extents)--; |
7573 | } else { | 7578 | } else { |
7574 | spin_lock(&BTRFS_I(inode)->lock); | 7579 | spin_lock(&BTRFS_I(inode)->lock); |
7575 | BTRFS_I(inode)->outstanding_extents++; | 7580 | BTRFS_I(inode)->outstanding_extents++; |
7576 | spin_unlock(&BTRFS_I(inode)->lock); | 7581 | spin_unlock(&BTRFS_I(inode)->lock); |
7577 | } | 7582 | } |
7578 | 7583 | ||
7579 | current->journal_info = outstanding_extents; | ||
7580 | btrfs_free_reserved_data_space(inode, len); | 7584 | btrfs_free_reserved_data_space(inode, len); |
7581 | set_bit(BTRFS_INODE_DIO_READY, &BTRFS_I(inode)->runtime_flags); | 7585 | WARN_ON(dio_data->reserve < len); |
7586 | dio_data->reserve -= len; | ||
7587 | current->journal_info = dio_data; | ||
7582 | } | 7588 | } |
7583 | 7589 | ||
7584 | /* | 7590 | /* |
@@ -7601,8 +7607,8 @@ unlock: | |||
7601 | unlock_err: | 7607 | unlock_err: |
7602 | clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, lockend, | 7608 | clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, lockend, |
7603 | unlock_bits, 1, 0, &cached_state, GFP_NOFS); | 7609 | unlock_bits, 1, 0, &cached_state, GFP_NOFS); |
7604 | if (outstanding_extents) | 7610 | if (dio_data) |
7605 | current->journal_info = outstanding_extents; | 7611 | current->journal_info = dio_data; |
7606 | return ret; | 7612 | return ret; |
7607 | } | 7613 | } |
7608 | 7614 | ||
@@ -8329,7 +8335,8 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter, | |||
8329 | { | 8335 | { |
8330 | struct file *file = iocb->ki_filp; | 8336 | struct file *file = iocb->ki_filp; |
8331 | struct inode *inode = file->f_mapping->host; | 8337 | struct inode *inode = file->f_mapping->host; |
8332 | u64 outstanding_extents = 0; | 8338 | struct btrfs_root *root = BTRFS_I(inode)->root; |
8339 | struct btrfs_dio_data dio_data = { 0 }; | ||
8333 | size_t count = 0; | 8340 | size_t count = 0; |
8334 | int flags = 0; | 8341 | int flags = 0; |
8335 | bool wakeup = true; | 8342 | bool wakeup = true; |
@@ -8367,7 +8374,7 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter, | |||
8367 | ret = btrfs_delalloc_reserve_space(inode, count); | 8374 | ret = btrfs_delalloc_reserve_space(inode, count); |
8368 | if (ret) | 8375 | if (ret) |
8369 | goto out; | 8376 | goto out; |
8370 | outstanding_extents = div64_u64(count + | 8377 | dio_data.outstanding_extents = div64_u64(count + |
8371 | BTRFS_MAX_EXTENT_SIZE - 1, | 8378 | BTRFS_MAX_EXTENT_SIZE - 1, |
8372 | BTRFS_MAX_EXTENT_SIZE); | 8379 | BTRFS_MAX_EXTENT_SIZE); |
8373 | 8380 | ||
@@ -8376,7 +8383,8 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter, | |||
8376 | * do the accounting properly if we go over the number we | 8383 | * do the accounting properly if we go over the number we |
8377 | * originally calculated. Abuse current->journal_info for this. | 8384 | * originally calculated. Abuse current->journal_info for this. |
8378 | */ | 8385 | */ |
8379 | current->journal_info = &outstanding_extents; | 8386 | dio_data.reserve = round_up(count, root->sectorsize); |
8387 | current->journal_info = &dio_data; | ||
8380 | } else if (test_bit(BTRFS_INODE_READDIO_NEED_LOCK, | 8388 | } else if (test_bit(BTRFS_INODE_READDIO_NEED_LOCK, |
8381 | &BTRFS_I(inode)->runtime_flags)) { | 8389 | &BTRFS_I(inode)->runtime_flags)) { |
8382 | inode_dio_end(inode); | 8390 | inode_dio_end(inode); |
@@ -8391,16 +8399,9 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter, | |||
8391 | if (iov_iter_rw(iter) == WRITE) { | 8399 | if (iov_iter_rw(iter) == WRITE) { |
8392 | current->journal_info = NULL; | 8400 | current->journal_info = NULL; |
8393 | if (ret < 0 && ret != -EIOCBQUEUED) { | 8401 | if (ret < 0 && ret != -EIOCBQUEUED) { |
8394 | /* | 8402 | if (dio_data.reserve) |
8395 | * If the error comes from submitting stage, | 8403 | btrfs_delalloc_release_space(inode, |
8396 | * btrfs_get_blocsk_direct() has free'd data space, | 8404 | dio_data.reserve); |
8397 | * and metadata space will be handled by | ||
8398 | * finish_ordered_fn, don't do that again to make | ||
8399 | * sure bytes_may_use is correct. | ||
8400 | */ | ||
8401 | if (!test_and_clear_bit(BTRFS_INODE_DIO_READY, | ||
8402 | &BTRFS_I(inode)->runtime_flags)) | ||
8403 | btrfs_delalloc_release_space(inode, count); | ||
8404 | } else if (ret >= 0 && (size_t)ret < count) | 8405 | } else if (ret >= 0 && (size_t)ret < count) |
8405 | btrfs_delalloc_release_space(inode, | 8406 | btrfs_delalloc_release_space(inode, |
8406 | count - (size_t)ret); | 8407 | count - (size_t)ret); |