Commit c2931667 authored by Liu Bo's avatar Liu Bo Committed by David Sterba

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: default avatarAnand Jain <anand.jain@oracle.com>
Tested-by: default avatarAnand Jain <anand.jain@oracle.com>
Signed-off-by: default avatarLiu Bo <bo.li.liu@oracle.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 781feef7
...@@ -7623,11 +7623,18 @@ static void adjust_dio_outstanding_extents(struct inode *inode, ...@@ -7623,11 +7623,18 @@ static void adjust_dio_outstanding_extents(struct inode *inode,
* within our reservation, otherwise we need to adjust our inode * within our reservation, otherwise we need to adjust our inode
* counter appropriately. * counter appropriately.
*/ */
if (dio_data->outstanding_extents) { if (dio_data->outstanding_extents >= num_extents) {
dio_data->outstanding_extents -= num_extents; dio_data->outstanding_extents -= num_extents;
} else { } else {
/*
* If dio write length has been split due to no large enough
* contiguous space, we need to compensate our inode counter
* appropriately.
*/
u64 num_needed = num_extents - dio_data->outstanding_extents;
spin_lock(&BTRFS_I(inode)->lock); spin_lock(&BTRFS_I(inode)->lock);
BTRFS_I(inode)->outstanding_extents += num_extents; BTRFS_I(inode)->outstanding_extents += num_needed;
spin_unlock(&BTRFS_I(inode)->lock); spin_unlock(&BTRFS_I(inode)->lock);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment