[RFC PATCH 4/4] xfs: refuse allocations without agfl refill space

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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





[Index of Archives]     [XFS Filesystem Development (older mail)]     [Linux Filesystem Development]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux RAID]     [Linux SCSI]


  Powered by Linux