Commit e9b77651 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Greg Kroah-Hartman

xfs: don't rely on ->total in xfs_alloc_space_available

commit 12ef8301 upstream.

->total is a bit of an odd parameter passed down to the low-level
allocator all the way from the high-level callers.  It's supposed to
contain the maximum number of blocks to be allocated for the whole
transaction [1].

But in xfs_iomap_write_allocate we only convert existing delayed
allocations and thus only have a minimal block reservation for the
current transaction, so xfs_alloc_space_available can't use it for
the allocation decisions.  Use the maximum of args->total and the
calculated block requirement to make a decision.  We probably should
get rid of args->total eventually and instead apply ->minleft more
broadly, but that will require some extensive changes all over.

[1] which creates lots of confusion as most callers don't decrement it
once doing a first allocation.  But that's for a separate series.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 6b81365b
...@@ -1995,7 +1995,7 @@ xfs_alloc_space_available( ...@@ -1995,7 +1995,7 @@ xfs_alloc_space_available(
int flags) int flags)
{ {
struct xfs_perag *pag = args->pag; struct xfs_perag *pag = args->pag;
xfs_extlen_t longest; xfs_extlen_t alloc_len, longest;
xfs_extlen_t reservation; /* blocks that are still reserved */ xfs_extlen_t reservation; /* blocks that are still reserved */
int available; int available;
...@@ -2005,15 +2005,16 @@ xfs_alloc_space_available( ...@@ -2005,15 +2005,16 @@ xfs_alloc_space_available(
reservation = xfs_ag_resv_needed(pag, args->resv); reservation = xfs_ag_resv_needed(pag, args->resv);
/* do we have enough contiguous free space for the allocation? */ /* do we have enough contiguous free space for the allocation? */
alloc_len = args->minlen + (args->alignment - 1) + args->minalignslop;
longest = xfs_alloc_longest_free_extent(args->mp, pag, min_free, longest = xfs_alloc_longest_free_extent(args->mp, pag, min_free,
reservation); reservation);
if ((args->minlen + args->alignment + args->minalignslop - 1) > longest) if (longest < alloc_len)
return false; return false;
/* do we have enough free space remaining for the allocation? */ /* do we have enough free space remaining for the allocation? */
available = (int)(pag->pagf_freeblks + pag->pagf_flcount - available = (int)(pag->pagf_freeblks + pag->pagf_flcount -
reservation - min_free - args->minleft); reservation - min_free - args->minleft);
if (available < (int)args->total) if (available < (int)max(args->total, alloc_len))
return false; return false;
/* /*
......
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