Commit 936d7de5 authored by Dave Chinner's avatar Dave Chinner Committed by Long Li
Browse files

xfs: align args->minlen for forced allocation alignment

maillist inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I9VTE3
CVE: NA

Reference: https://lore.kernel.org/linux-xfs/20240705162450.3481169-1-john.g.garry@oracle.com



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

If args->minlen is not aligned to the constraints of forced
alignment, we may do minlen allocations that are not aligned when we
approach ENOSPC. Avoid this by always aligning args->minlen
appropriately. If alignment of minlen results in a value smaller
than the alignment constraint, fail the allocation immediately.

Fixes: 63f4d844 ("fs: xfs: Make file data allocations observe the 'forcealign' flag")
Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatar"Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: default avatarJohn Garry <john.g.garry@oracle.com>
Conflicts:
	fs/xfs/libxfs/xfs_bmap.c
[Conflicts in xfs_bmap_select_minlen()]
Signed-off-by: default avatarLong Li <leo.lilong@huawei.com>
parent 5ff073d1
Loading
Loading
Loading
Loading
+24 −7
Original line number Diff line number Diff line
@@ -3253,33 +3253,48 @@ xfs_bmap_longest_free_extent(
	return error;
}

static void
static int
xfs_bmap_select_minlen(
	struct xfs_bmalloca	*ap,
	struct xfs_alloc_arg	*args,
	xfs_extlen_t		*blen,
	int			notinit)
{
	xfs_extlen_t nlen = 0;

	if (notinit || *blen < ap->minlen) {
		/*
		 * Since we did a BUF_TRYLOCK above, it is possible that
		 * there is space for this request.
		 */
		args->minlen = ap->minlen;
		nlen = ap->minlen;
	} else if (*blen < args->maxlen) {
		/*
		 * If the best seen length is less than the request length,
		 * use the best as the minimum.
		 */
		args->minlen = *blen;

		nlen = *blen;
	} else {
		/*
		 * Otherwise we've seen an extent as big as maxlen, use that
		 * as the minimum.
		 */
		args->minlen = args->maxlen;
		nlen = args->maxlen;
	}

	if (args->alignment > 1) {
		nlen = rounddown(nlen, args->alignment);
		if (nlen < ap->minlen) {
			if (xfs_inode_forcealign(ap->ip) &&
				(ap->datatype & XFS_ALLOC_USERDATA))
				return -ENOSPC;
			nlen = ap->minlen;
		}
	}
	args->minlen = nlen;
	return 0;
}

STATIC int
xfs_bmap_btalloc_nullfb(
@@ -3311,8 +3326,8 @@ xfs_bmap_btalloc_nullfb(
			break;
	}

	xfs_bmap_select_minlen(ap, args, blen, notinit);
	return 0;
	error = xfs_bmap_select_minlen(ap, args, blen, notinit);
	return error;
}

STATIC int
@@ -3349,7 +3364,9 @@ xfs_bmap_btalloc_filestreams(

	}

	xfs_bmap_select_minlen(ap, args, blen, notinit);
	error = xfs_bmap_select_minlen(ap, args, blen, notinit);
	if (error)
		return error;

	/*
	 * Set the failure fallback case to look in the selected AG as stream