xfs: borrow indirect blocks from freed extent when available
authorBrian Foster <bfoster@redhat.com>
Tue, 15 Mar 2016 00:42:47 +0000 (11:42 +1100)
committerDave Chinner <david@fromorbit.com>
Tue, 15 Mar 2016 00:42:47 +0000 (11:42 +1100)
commitd34999c97ae87cd56514b8cbc6269651efe274fe
tree5740bd2757cdeebc962417b88a86c47a5831250f
parenta9bd24ac2becf69e896d88bf8b1b7b0f18c2157b
xfs: borrow indirect blocks from freed extent when available

xfs_bmap_del_extent() handles extent removal from the in-core and
on-disk extent lists. When removing a delalloc range, it updates the
indirect block reservation appropriately based on the removal. It
currently enforces that the new indirect block reservation is less than
or equal to the original. This is normally the case in all situations
except for in certain cases when the removed range creates a hole in a
single delalloc extent, thus splitting a single delalloc extent in two.

It is possible with small enough extents to split an indlen==1 extent
into two such slightly smaller extents. This leaves one extent with 0
indirect blocks and leads to assert failures in other areas (e.g.,
xfs_bunmapi() if the extent happens to be removed).

Update the indlen distribution code to steal blocks from the deleted
extent, if necessary, to satisfy the worst case total indirect
reservation for the new extents. This is safe as the caller does not
update the fdblocks counters until the extent is removed. Blocks stolen
in this manner simply remain accounted as allocated, having ownership
transferred from the data extent to an indirect reservation.

As a precaution, fall back to the original reservation algorithm if the
new indlen requirement is not met and warn if we end up with extents
without any reservation at all to detect this more easily in the future.

Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
fs/xfs/libxfs/xfs_bmap.c