Commit fd048a1b authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Darrick J. Wong
Browse files

xfs: rework the rtalloc fallback handling



xfs_rtallocate currently has two fallbacks, when an allocation fails:

 1) drop the requested extent size alignment, if any, and retry
 2) ignore the locality hint

Oddly enough it does those in order, as trying a different location
is more in line with what the user asked for, and does it in a very
unstructured way.

Lift the fallback to try to allocate without the locality hint into
xfs_rtallocate to both perform them in a more sensible order and to
clean up the code.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDarrick J. Wong <djwong@kernel.org>
Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
parent a9f646af
Loading
Loading
Loading
Loading
+34 −35
Original line number Diff line number Diff line
@@ -1271,6 +1271,8 @@ xfs_rtallocate(
	xfs_rtxlen_t		maxlen,
	xfs_rtxlen_t		prod,
	bool			wasdel,
	bool			initial_user_data,
	bool			*rtlocked,
	xfs_rtblock_t		*bno,
	xfs_extlen_t		*blen)
{
@@ -1280,12 +1282,38 @@ xfs_rtallocate(
	};
	xfs_rtxnum_t		rtx;
	xfs_rtxlen_t		len = 0;
	int			error;
	int			error = 0;

	/*
	 * Lock out modifications to both the RT bitmap and summary inodes.
	 */
	if (!*rtlocked) {
		xfs_rtbitmap_lock(args.mp);
		xfs_rtbitmap_trans_join(tp);
		*rtlocked = true;
	}

	/*
	 * For an allocation to an empty file at offset 0, pick an extent that
	 * will space things out in the rt area.
	 */
	if (!start && initial_user_data)
		start = xfs_rtpick_extent(args.mp, tp, maxlen);

	if (start) {
		error = xfs_rtallocate_extent_near(&args, start, minlen, maxlen,
				&len, prod, &rtx);
	} else {
		/*
		 * If we can't allocate near a specific rt extent, try again
		 * without locality criteria.
		 */
		if (error == -ENOSPC) {
			xfs_rtbuf_cache_relse(&args);
			error = 0;
		}
	}

	if (!error) {
		error = xfs_rtallocate_extent_size(&args, minlen, maxlen, &len,
				prod, &rtx);
	}
@@ -1314,7 +1342,7 @@ xfs_bmap_rtalloc(
{
	struct xfs_mount	*mp = ap->ip->i_mount;
	xfs_fileoff_t		orig_offset = ap->offset;
	xfs_rtxnum_t		start;	   /* allocation hint rtextent no */
	xfs_rtxnum_t		start = 0;   /* allocation hint rtextent no */
	xfs_rtxlen_t		prod = 0;  /* product factor for allocators */
	xfs_extlen_t		mod = 0;   /* product factor for allocators */
	xfs_rtxlen_t		ralen = 0; /* realtime allocation length */
@@ -1323,7 +1351,6 @@ xfs_bmap_rtalloc(
	xfs_extlen_t		minlen = mp->m_sb.sb_rextsize;
	xfs_rtxlen_t		raminlen;
	bool			rtlocked = false;
	bool			ignore_locality = false;
	int			error;

	align = xfs_get_extsz_hint(ap->ip);
@@ -1361,28 +1388,8 @@ xfs_bmap_rtalloc(
	ASSERT(raminlen > 0);
	ASSERT(raminlen <= ralen);

	/*
	 * Lock out modifications to both the RT bitmap and summary inodes
	 */
	if (!rtlocked) {
		xfs_rtbitmap_lock(mp);
		xfs_rtbitmap_trans_join(ap->tp);
		rtlocked = true;
	}

	if (ignore_locality) {
		start = 0;
	} else if (xfs_bmap_adjacent(ap)) {
	if (xfs_bmap_adjacent(ap))
		start = xfs_rtb_to_rtx(mp, ap->blkno);
	} else if (ap->datatype & XFS_ALLOC_INITIAL_USER_DATA) {
		/*
		 * If it's an allocation to an empty file at offset 0, pick an
		 * extent that will space things out in the rt area.
		 */
		start = xfs_rtpick_extent(mp, ap->tp, ralen);
	} else {
		start = 0;
	}

	/*
	 * Only bother calculating a real prod factor if offset & length are
@@ -1398,6 +1405,7 @@ xfs_bmap_rtalloc(
	}

	error = xfs_rtallocate(ap->tp, start, raminlen, ralen, prod, ap->wasdel,
			ap->datatype & XFS_ALLOC_INITIAL_USER_DATA, &rtlocked,
			&ap->blkno, &ap->length);
	if (error == -ENOSPC) {
		if (align > mp->m_sb.sb_rextsize) {
@@ -1414,15 +1422,6 @@ xfs_bmap_rtalloc(
			goto retry;
		}

		if (!ignore_locality && start != 0) {
			/*
			 * If we can't allocate near a specific rt extent, try
			 * again without locality criteria.
			 */
			ignore_locality = true;
			goto retry;
		}

		ap->blkno = NULLFSBLOCK;
		ap->length = 0;
		return 0;