diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-13 19:30:29 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-13 19:30:29 -0500 |
commit | e75cdf9898132f521df98a3ce1c280a2f85d360a (patch) | |
tree | 4f6a24cf7ab56b962cc8bead17895521b5985dc6 /fs/btrfs/inode.c | |
parent | ca4ba96e02e932a0c9997a40fd51253b5b2d0f9d (diff) | |
parent | d5f2e33b92b10b8007be50b570a27e9bacfb4c3a (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.c | 62 |
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 | ||
7512 | static 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 | |||
7506 | static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock, | 7534 | static 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: | |||
7696 | unlock_err: | 7715 | unlock_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); |
7718 | err: | ||
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 | ||