xfs: fix indlen accounting error on partial delalloc conversion
authorBrian Foster <bfoster@redhat.com>
Fri, 12 May 2017 17:44:08 +0000 (10:44 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 7 Jun 2017 10:06:02 +0000 (12:06 +0200)
commit3ba13d7f5b2bad97a2df48f9bb6e4d52c244a979
tree11e702573c0d381a31c8540e2471c573f7832219
parent1d41dd5c1fd6dca4f7fa5980de2e2194e4f6d4d3
xfs: fix indlen accounting error on partial delalloc conversion

commit 0daaecacb83bc6b656a56393ab77a31c28139bc7 upstream.

The delalloc -> real block conversion path uses an incorrect
calculation in the case where the middle part of a delalloc extent
is being converted. This is documented as a rare situation because
XFS generally attempts to maximize contiguity by converting as much
of a delalloc extent as possible.

If this situation does occur, the indlen reservation for the two new
delalloc extents left behind by the conversion of the middle range
is calculated and compared with the original reservation. If more
blocks are required, the delta is allocated from the global block
pool. This delta value can be characterized as the difference
between the new total requirement (temp + temp2) and the currently
available reservation minus those blocks that have already been
allocated (startblockval(PREV.br_startblock) - allocated).

The problem is that the current code does not account for previously
allocated blocks correctly. It subtracts the current allocation
count from the (new - old) delta rather than the old indlen
reservation. This means that more indlen blocks than have been
allocated end up stashed in the remaining extents and free space
accounting is broken as a result.

Fix up the calculation to subtract the allocated block count from
the original extent indlen and thus correctly allocate the
reservation delta based on the difference between the new total
requirement and the unused blocks from the original reservation.
Also remove a bogus assert that contradicts the fact that the new
indlen reservation can be larger than the original indlen
reservation.

Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/xfs/libxfs/xfs_bmap.c