aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorLiu Bo <bo.li.liu@oracle.com>2016-12-22 20:13:54 -0500
committerDavid Sterba <dsterba@suse.com>2017-01-03 11:29:50 -0500
commitc2931667c83ded6504b3857e99cc45b21fa496fb (patch)
treee427359939b7ae3c7ef9eda9839ca3ccd0739b98 /fs/btrfs/inode.c
parent781feef7e6befafd4d9787d1f7ada1f9ccd504e4 (diff)
Btrfs: adjust outstanding_extents counter properly when dio write is split
Currently how btrfs dio deals with split dio write is not good enough if dio write is split into several segments due to the lack of contiguous space, a large dio write like 'dd bs=1G count=1' can end up with incorrect outstanding_extents counter and endio would complain loudly with an assertion. This fixes the problem by compensating the outstanding_extents counter in inode if a large dio write gets split. Reported-by: Anand Jain <anand.jain@oracle.com> Tested-by: Anand Jain <anand.jain@oracle.com> Signed-off-by: Liu Bo <bo.li.liu@oracle.com> Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index a713d9d324b0..81b9d9d0450c 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -7623,11 +7623,18 @@ static void adjust_dio_outstanding_extents(struct inode *inode,
7623 * within our reservation, otherwise we need to adjust our inode 7623 * within our reservation, otherwise we need to adjust our inode
7624 * counter appropriately. 7624 * counter appropriately.
7625 */ 7625 */
7626 if (dio_data->outstanding_extents) { 7626 if (dio_data->outstanding_extents >= num_extents) {
7627 dio_data->outstanding_extents -= num_extents; 7627 dio_data->outstanding_extents -= num_extents;
7628 } else { 7628 } else {
7629 /*
7630 * If dio write length has been split due to no large enough
7631 * contiguous space, we need to compensate our inode counter
7632 * appropriately.
7633 */
7634 u64 num_needed = num_extents - dio_data->outstanding_extents;
7635
7629 spin_lock(&BTRFS_I(inode)->lock); 7636 spin_lock(&BTRFS_I(inode)->lock);
7630 BTRFS_I(inode)->outstanding_extents += num_extents; 7637 BTRFS_I(inode)->outstanding_extents += num_needed;
7631 spin_unlock(&BTRFS_I(inode)->lock); 7638 spin_unlock(&BTRFS_I(inode)->lock);
7632 } 7639 }
7633} 7640}