aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-11-13 19:30:29 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-11-13 19:30:29 -0500
commite75cdf9898132f521df98a3ce1c280a2f85d360a (patch)
tree4f6a24cf7ab56b962cc8bead17895521b5985dc6 /fs/btrfs/inode.c
parentca4ba96e02e932a0c9997a40fd51253b5b2d0f9d (diff)
parentd5f2e33b92b10b8007be50b570a27e9bacfb4c3a (diff)
Merge branch 'for-linus-4.4' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull btrfs fixes and cleanups from Chris Mason: "Some of this got cherry-picked from a github repo this week, but I verified the patches. We have three small scrub cleanups and a collection of fixes" * 'for-linus-4.4' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: btrfs: Use fs_info directly in btrfs_delete_unused_bgs btrfs: Fix lost-data-profile caused by balance bg btrfs: Fix lost-data-profile caused by auto removing bg btrfs: Remove len argument from scrub_find_csum btrfs: Reduce unnecessary arguments in scrub_recheck_block btrfs: Use scrub_checksum_data and scrub_checksum_tree_block for scrub_recheck_block_checksum btrfs: Reset sblock->xxx_error stats before calling scrub_recheck_block_checksum btrfs: scrub: setup all fields for sblock_to_check btrfs: scrub: set error stats when tree block spanning stripes Btrfs: fix race when listing an inode's xattrs Btrfs: fix race leading to BUG_ON when running delalloc for nodatacow Btrfs: fix race leading to incorrect item deletion when dropping extents Btrfs: fix sleeping inside atomic context in qgroup rescan worker Btrfs: fix race waiting for qgroup rescan worker btrfs: qgroup: exit the rescan worker during umount Btrfs: fix extent accounting for partial direct IO writes
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c62
1 files changed, 45 insertions, 17 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 0e4f2bfcc37d..994490d5fa64 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -1304,8 +1304,14 @@ next_slot:
1304 num_bytes = 0; 1304 num_bytes = 0;
1305 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); 1305 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
1306 1306
1307 if (found_key.objectid > ino || 1307 if (found_key.objectid > ino)
1308 found_key.type > BTRFS_EXTENT_DATA_KEY || 1308 break;
1309 if (WARN_ON_ONCE(found_key.objectid < ino) ||
1310 found_key.type < BTRFS_EXTENT_DATA_KEY) {
1311 path->slots[0]++;
1312 goto next_slot;
1313 }
1314 if (found_key.type > BTRFS_EXTENT_DATA_KEY ||
1309 found_key.offset > end) 1315 found_key.offset > end)
1310 break; 1316 break;
1311 1317
@@ -7503,6 +7509,28 @@ struct btrfs_dio_data {
7503 u64 reserve; 7509 u64 reserve;
7504}; 7510};
7505 7511
7512static void adjust_dio_outstanding_extents(struct inode *inode,
7513 struct btrfs_dio_data *dio_data,
7514 const u64 len)
7515{
7516 unsigned num_extents;
7517
7518 num_extents = (unsigned) div64_u64(len + BTRFS_MAX_EXTENT_SIZE - 1,
7519 BTRFS_MAX_EXTENT_SIZE);
7520 /*
7521 * If we have an outstanding_extents count still set then we're
7522 * within our reservation, otherwise we need to adjust our inode
7523 * counter appropriately.
7524 */
7525 if (dio_data->outstanding_extents) {
7526 dio_data->outstanding_extents -= num_extents;
7527 } else {
7528 spin_lock(&BTRFS_I(inode)->lock);
7529 BTRFS_I(inode)->outstanding_extents += num_extents;
7530 spin_unlock(&BTRFS_I(inode)->lock);
7531 }
7532}
7533
7506static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock, 7534static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
7507 struct buffer_head *bh_result, int create) 7535 struct buffer_head *bh_result, int create)
7508{ 7536{
@@ -7538,8 +7566,11 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
7538 * If this errors out it's because we couldn't invalidate pagecache for 7566 * If this errors out it's because we couldn't invalidate pagecache for
7539 * this range and we need to fallback to buffered. 7567 * this range and we need to fallback to buffered.
7540 */ 7568 */
7541 if (lock_extent_direct(inode, lockstart, lockend, &cached_state, create)) 7569 if (lock_extent_direct(inode, lockstart, lockend, &cached_state,
7542 return -ENOTBLK; 7570 create)) {
7571 ret = -ENOTBLK;
7572 goto err;
7573 }
7543 7574
7544 em = btrfs_get_extent(inode, NULL, 0, start, len, 0); 7575 em = btrfs_get_extent(inode, NULL, 0, start, len, 0);
7545 if (IS_ERR(em)) { 7576 if (IS_ERR(em)) {
@@ -7657,19 +7688,7 @@ unlock:
7657 if (start + len > i_size_read(inode)) 7688 if (start + len > i_size_read(inode))
7658 i_size_write(inode, start + len); 7689 i_size_write(inode, start + len);
7659 7690
7660 /* 7691 adjust_dio_outstanding_extents(inode, dio_data, len);
7661 * If we have an outstanding_extents count still set then we're
7662 * within our reservation, otherwise we need to adjust our inode
7663 * counter appropriately.
7664 */
7665 if (dio_data->outstanding_extents) {
7666 (dio_data->outstanding_extents)--;
7667 } else {
7668 spin_lock(&BTRFS_I(inode)->lock);
7669 BTRFS_I(inode)->outstanding_extents++;
7670 spin_unlock(&BTRFS_I(inode)->lock);
7671 }
7672
7673 btrfs_free_reserved_data_space(inode, start, len); 7692 btrfs_free_reserved_data_space(inode, start, len);
7674 WARN_ON(dio_data->reserve < len); 7693 WARN_ON(dio_data->reserve < len);
7675 dio_data->reserve -= len; 7694 dio_data->reserve -= len;
@@ -7696,8 +7715,17 @@ unlock:
7696unlock_err: 7715unlock_err:
7697 clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, lockend, 7716 clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, lockend,
7698 unlock_bits, 1, 0, &cached_state, GFP_NOFS); 7717 unlock_bits, 1, 0, &cached_state, GFP_NOFS);
7718err:
7699 if (dio_data) 7719 if (dio_data)
7700 current->journal_info = dio_data; 7720 current->journal_info = dio_data;
7721 /*
7722 * Compensate the delalloc release we do in btrfs_direct_IO() when we
7723 * write less data then expected, so that we don't underflow our inode's
7724 * outstanding extents counter.
7725 */
7726 if (create && dio_data)
7727 adjust_dio_outstanding_extents(inode, dio_data, len);
7728
7701 return ret; 7729 return ret;
7702} 7730}
7703 7731