Ensure that an allocation that may be part of a multiple-allocation transaction has enough space in the AGFL reserve to refill the AGFL in a subsequent transaction. The AGFL reserve was established to make sure that there is enough space reserved for multiple allocation transactions to use this space to refill the AGFL close to ENOSPC. Check an allocation against this reserve and refuse to let it proceed if the AGFL reserve cannot meet the needs of a subsequent allocation. Without this, the second transaction may ENOSPC if the first uses all of the AGFL blocks and the AG is close enough to the limits that it cannot refill. Signed-off-by: Krister Johansen <kjlx@xxxxxxxxxxxxxxxxxx> --- fs/xfs/libxfs/xfs_alloc.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 3fc8448e02d9..7b0302f7e960 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -2389,11 +2389,13 @@ xfs_alloc_space_available( int flags) { struct xfs_perag *pag = args->pag; + struct xfs_ag_resv *resv; enum xfs_ag_resv_type resv_type = args->resv; xfs_extlen_t alloc_len, longest; xfs_extlen_t reservation; /* blocks that are still reserved */ int available; xfs_extlen_t agflcount; + unsigned int agfl_refill; if (flags & XFS_ALLOC_FLAG_FREEING) return true; @@ -2429,6 +2431,21 @@ xfs_alloc_space_available( if (available < (int)max(args->total, alloc_len)) return false; + /* + * If this is the first allocation in a transaction that may perform + * multiple allocations, check the AGFL reserve to see if it contains + * enough blocks to refill the AGFL if freespace b-trees split as part + * of the first allocation. This is done to ensure that subsequent + * allocations can utilize the reserve space instead of running out and + * triggering a shutdown. + */ + if (args->tp->t_highest_agno == NULLAGNUMBER && args->minleft > 0) { + agfl_refill = xfs_alloc_min_freelist(args->mp, pag, 1); + resv = xfs_perag_resv(pag, XFS_AG_RESV_AGFL); + if (resv->ar_asked > 0 && agfl_refill > resv->ar_reserved) + return false; + } + /* * Clamp maxlen to the amount of free space available for the actual * extent allocation. -- 2.25.1