xfs: don't rely on ->total in xfs_alloc_space_available
->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: Christoph Hellwig <hch@lst.de> Reviewed-by: Brian Foster <bfoster@redhat.com> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
This commit is contained in:
parent
54fee133ad
commit
12ef830198
|
@ -1995,7 +1995,7 @@ xfs_alloc_space_available(
|
|||
int flags)
|
||||
{
|
||||
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 */
|
||||
int available;
|
||||
|
||||
|
@ -2005,15 +2005,16 @@ xfs_alloc_space_available(
|
|||
reservation = xfs_ag_resv_needed(pag, args->resv);
|
||||
|
||||
/* 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,
|
||||
reservation);
|
||||
if ((args->minlen + args->alignment + args->minalignslop - 1) > longest)
|
||||
if (longest < alloc_len)
|
||||
return false;
|
||||
|
||||
/* do we have enough free space remaining for the allocation? */
|
||||
available = (int)(pag->pagf_freeblks + pag->pagf_flcount -
|
||||
reservation - min_free - args->minleft);
|
||||
if (available < (int)args->total)
|
||||
if (available < (int)max(args->total, alloc_len))
|
||||
return false;
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue