Commit 8cda6fc7 authored by yangerkun's avatar yangerkun Committed by Long Li
Browse files

xfs: longest free extent no need consider postalloc

hulk inclusion
category: bugfix
bugzilla: 188788, https://gitee.com/openeuler/kernel/issues/I76JSK


CVE: NA

--------------------------------

xfs_alloc_space_available need to make sure the longest free extent
can satisfy extra blocks needed for agfl fixup and also the really
needed block for the latter allocation. Or the latter agfl filling may
consume some blocks within the longest free extent, which can lead to
that all the free extent can not satisfy the really block allocation.

The arg 'min_free' show that actually blocks we need fill agfl up to.
But after commit aa1ab9a77d89 ("xfs: fix xfs shutdown since we reserve
more blocks in agfl fixup"), the 'min_free' will add the reserve blocks
for second fixup, but leave agfl blocks does not include this.

Actually, what we want was just reserve more blocks to satisfy second
fixup, we will not fill agfl with that so many blocks, so the args for
xfs_alloc_longest_free_extent should not consider postalloc. And fix
agflcount in xfs_alloc_space_available too.

Fixes: aa1ab9a77d89 ("xfs: fix xfs shutdown since we reserve more blocks in agfl fixup")
Signed-off-by: default avataryangerkun <yangerkun@huawei.com>
Signed-off-by: default avatarLong Li <leo.lilong@huawei.com>
parent 12a5c9f8
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -2339,6 +2339,7 @@ xfs_alloc_min_freelist(
static bool
xfs_alloc_space_available(
	struct xfs_alloc_arg	*args,
	xfs_extlen_t		need,
	xfs_extlen_t		min_free,
	int			flags)
{
@@ -2355,7 +2356,7 @@ xfs_alloc_space_available(

	/* 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(pag, min_free, reservation);
	longest = xfs_alloc_longest_free_extent(pag, need, reservation);
	if (longest < alloc_len)
		return false;

@@ -2364,7 +2365,7 @@ xfs_alloc_space_available(
	 * account extra agfl blocks because we are about to defer free them,
	 * making them unavailable until the current transaction commits.
	 */
	agflcount = min_t(xfs_extlen_t, pag->pagf_flcount, min_free);
	agflcount = min_t(xfs_extlen_t, pag->pagf_flcount, need);
	available = (int)(pag->pagf_freeblks + agflcount -
			  reservation - min_free - args->minleft);
	if (available < (int)max(args->total, alloc_len))
@@ -2651,7 +2652,7 @@ xfs_alloc_fix_freelist(
	if (args->postallocs)
		minfree += xfs_ag_fixup_aside(mp);

	if (!xfs_alloc_space_available(args, minfree, alloc_flags |
	if (!xfs_alloc_space_available(args, need, minfree, alloc_flags |
			XFS_ALLOC_FLAG_CHECK))
		goto out_agbp_relse;

@@ -2678,7 +2679,7 @@ xfs_alloc_fix_freelist(
	if (args->postallocs)
		minfree += xfs_ag_fixup_aside(mp);

	if (!xfs_alloc_space_available(args, minfree, alloc_flags))
	if (!xfs_alloc_space_available(args, need, minfree, alloc_flags))
		goto out_agbp_relse;

	/*