Commit 9fa8753a authored by Chandan Babu R's avatar Chandan Babu R
Browse files

Merge tag 'rtalloc-speedups-6.7_2023-10-19' of...

Merge tag 'rtalloc-speedups-6.7_2023-10-19' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux into xfs-6.7-mergeA

xfs: CPU usage optimizations for realtime allocator [v2.3]

This is version 2 of [Omar's] XFS realtime allocator opimization patch
series.

Changes since v1 [1]:

- Fixed potential overflow in patch 4.
- Changed deprecated typedefs to normal struct names
- Fixed broken indentation
- Used xfs_fileoff_t instead of xfs_fsblock_t where appropriate.
- Added calls to xfs_rtbuf_cache_relse anywhere that the cache is used
  instead of relying on the buffers being dirtied and thus attached to
  the transaction.
- Clarified comments and commit messages in a few places.
- Added Darrick's Reviewed-bys.

Cover letter from v1:

Our distributed storage system uses XFS's realtime device support as a
way to split an XFS filesystem between an SSD and an HDD -- we configure
the HDD as the realtime device so that metadata goes on the SSD and data
goes on the HDD.

We've been running this in production for a few years now, so we have
some fairly fragmented filesystems. This has exposed various CPU
inefficiencies in the realtime allocator. These became even worse when
we experimented with using XFS_XFLAG_EXTSIZE to force files to be
allocated contiguously.

This series adds several optimizations that don't change the realtime
allocator's decisions, but make them happen more efficiently, mainly by
avoiding redundant work. We've tested these in production and measured
~10%% lower CPU utilization. Furthermore, it made it possible to use
XFS_XFLAG_EXTSIZE to force contiguous allocations -- without these
patches, our most fragmented systems would become unresponsive due to
high CPU usage in the realtime allocator, but with them, CPU utilization
is actually ~4-6%% lower than before, and disk I/O utilization is 15-20%%
lower.

Patches 2 and 3 are preparations for later optimizations; the remaining
patches are the optimizations themselves.

1: https://lore.kernel.org/linux-xfs/cover.1687296675.git.osandov@osandov.com/



v2.1: djwong rebased everything atop his own cleanups, added dave's rtalloc_args
v2.2: rebase with new apis and clean them up too
v2.3: move struct definition around for lolz

With a bit of luck, this should all go splendidly.

Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
Signed-off-by: default avatarChandan Babu R <chandanbabu@kernel.org>

* tag 'rtalloc-speedups-6.7_2023-10-19' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux:
  xfs: don't look for end of extent further than necessary in xfs_rtallocate_extent_near()
  xfs: don't try redundant allocations in xfs_rtallocate_extent_near()
  xfs: limit maxlen based on available space in xfs_rtallocate_extent_near()
  xfs: return maximum free size from xfs_rtany_summary()
  xfs: invert the realtime summary cache
  xfs: simplify rt bitmap/summary block accessor functions
  xfs: simplify xfs_rtbuf_get calling conventions
  xfs: cache last bitmap block in realtime allocator
  xfs: consolidate realtime allocation arguments
parents 830b4abf e0f7422f
Loading
Loading
Loading
Loading
+259 −266
Original line number Diff line number Diff line
@@ -47,25 +47,69 @@ const struct xfs_buf_ops xfs_rtbuf_ops = {
	.verify_write = xfs_rtbuf_verify_write,
};

/* Release cached rt bitmap and summary buffers. */
void
xfs_rtbuf_cache_relse(
	struct xfs_rtalloc_args	*args)
{
	if (args->rbmbp) {
		xfs_trans_brelse(args->tp, args->rbmbp);
		args->rbmbp = NULL;
		args->rbmoff = NULLFILEOFF;
	}
	if (args->sumbp) {
		xfs_trans_brelse(args->tp, args->sumbp);
		args->sumbp = NULL;
		args->sumoff = NULLFILEOFF;
	}
}

/*
 * Get a buffer for the bitmap or summary file block specified.
 * The buffer is returned read and locked.
 */
int
xfs_rtbuf_get(
	xfs_mount_t	*mp,		/* file system mount structure */
	xfs_trans_t	*tp,		/* transaction pointer */
	struct xfs_rtalloc_args	*args,
	xfs_fileoff_t		block,	/* block number in bitmap or summary */
	int		issum,		/* is summary not bitmap */
	struct xfs_buf	**bpp)		/* output: buffer for the block */
	int			issum)	/* is summary not bitmap */
{
	struct xfs_mount	*mp = args->mp;
	struct xfs_buf		**cbpp;	/* cached block buffer */
	xfs_fileoff_t		*coffp;	/* cached block number */
	struct xfs_buf		*bp;	/* block buffer, result */
	xfs_inode_t	*ip;		/* bitmap or summary inode */
	xfs_bmbt_irec_t	map;
	struct xfs_inode	*ip;	/* bitmap or summary inode */
	struct xfs_bmbt_irec	map;
	enum xfs_blft		type;
	int			nmap = 1;
	int		error;		/* error value */
	int			error;

	if (issum) {
		cbpp = &args->sumbp;
		coffp = &args->sumoff;
		ip = mp->m_rsumip;
		type = XFS_BLFT_RTSUMMARY_BUF;
	} else {
		cbpp = &args->rbmbp;
		coffp = &args->rbmoff;
		ip = mp->m_rbmip;
		type = XFS_BLFT_RTBITMAP_BUF;
	}

	/*
	 * If we have a cached buffer, and the block number matches, use that.
	 */
	if (*cbpp && *coffp == block)
		return 0;

	ip = issum ? mp->m_rsumip : mp->m_rbmip;
	/*
	 * Otherwise we have to have to get the buffer.  If there was an old
	 * one, get rid of it first.
	 */
	if (*cbpp) {
		xfs_trans_brelse(args->tp, *cbpp);
		*cbpp = NULL;
	}

	error = xfs_bmapi_read(ip, block, 1, &map, &nmap, 0);
	if (error)
@@ -75,15 +119,15 @@ xfs_rtbuf_get(
		return -EFSCORRUPTED;

	ASSERT(map.br_startblock != NULLFSBLOCK);
	error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
	error = xfs_trans_read_buf(mp, args->tp, mp->m_ddev_targp,
				   XFS_FSB_TO_DADDR(mp, map.br_startblock),
				   mp->m_bsize, 0, &bp, &xfs_rtbuf_ops);
	if (error)
		return error;

	xfs_trans_buf_set_type(tp, bp, issum ? XFS_BLFT_RTSUMMARY_BUF
					     : XFS_BLFT_RTBITMAP_BUF);
	*bpp = bp;
	xfs_trans_buf_set_type(args->tp, bp, type);
	*cbpp = bp;
	*coffp = block;
	return 0;
}

@@ -93,15 +137,14 @@ xfs_rtbuf_get(
 */
int
xfs_rtfind_back(
	xfs_mount_t	*mp,		/* file system mount point */
	xfs_trans_t	*tp,		/* transaction pointer */
	struct xfs_rtalloc_args	*args,
	xfs_rtxnum_t		start,	/* starting rtext to look at */
	xfs_rtxnum_t		limit,	/* last rtext to look at */
	xfs_rtxnum_t		*rtx)	/* out: start rtext found */
{
	struct xfs_mount	*mp = args->mp;
	int			bit;	/* bit number in the word */
	xfs_fileoff_t		block;	/* bitmap block number */
	struct xfs_buf	*bp;		/* buf for the block */
	int			error;	/* error value */
	xfs_rtxnum_t		firstbit; /* first useful bit in the word */
	xfs_rtxnum_t		i;	/* current bit number rel. to start */
@@ -116,10 +159,9 @@ xfs_rtfind_back(
	 * Compute and read in starting bitmap block for starting block.
	 */
	block = xfs_rtx_to_rbmblock(mp, start);
	error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
	if (error) {
	error = xfs_rtbitmap_read_buf(args, block);
	if (error)
		return error;
	}

	/*
	 * Get the first word's index & point to it.
@@ -131,7 +173,7 @@ xfs_rtfind_back(
	 * Compute match value, based on the bit at start: if 1 (free)
	 * then all-ones, else all-zeroes.
	 */
	incore = xfs_rtbitmap_getword(bp, word);
	incore = xfs_rtbitmap_getword(args, word);
	want = (incore & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
	/*
	 * If the starting position is not word-aligned, deal with the
@@ -153,7 +195,6 @@ xfs_rtfind_back(
			/*
			 * Different.  Mark where we are and return.
			 */
			xfs_trans_brelse(tp, bp);
			i = bit - XFS_RTHIBIT(wdiff);
			*rtx = start - i + 1;
			return 0;
@@ -167,11 +208,9 @@ xfs_rtfind_back(
			/*
			 * If done with this block, get the previous one.
			 */
			xfs_trans_brelse(tp, bp);
			error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
			if (error) {
			error = xfs_rtbitmap_read_buf(args, --block);
			if (error)
				return error;
			}

			word = mp->m_blockwsize - 1;
		}
@@ -189,12 +228,11 @@ xfs_rtfind_back(
		/*
		 * Compute difference between actual and desired value.
		 */
		incore = xfs_rtbitmap_getword(bp, word);
		incore = xfs_rtbitmap_getword(args, word);
		if ((wdiff = incore ^ want)) {
			/*
			 * Different, mark where we are and return.
			 */
			xfs_trans_brelse(tp, bp);
			i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
			*rtx = start - i + 1;
			return 0;
@@ -208,11 +246,9 @@ xfs_rtfind_back(
			/*
			 * If done with this block, get the previous one.
			 */
			xfs_trans_brelse(tp, bp);
			error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
			if (error) {
			error = xfs_rtbitmap_read_buf(args, --block);
			if (error)
				return error;
			}

			word = mp->m_blockwsize - 1;
		}
@@ -231,12 +267,11 @@ xfs_rtfind_back(
		/*
		 * Compute difference between actual and desired value.
		 */
		incore = xfs_rtbitmap_getword(bp, word);
		incore = xfs_rtbitmap_getword(args, word);
		if ((wdiff = (incore ^ want) & mask)) {
			/*
			 * Different, mark where we are and return.
			 */
			xfs_trans_brelse(tp, bp);
			i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
			*rtx = start - i + 1;
			return 0;
@@ -246,7 +281,6 @@ xfs_rtfind_back(
	/*
	 * No match, return that we scanned the whole area.
	 */
	xfs_trans_brelse(tp, bp);
	*rtx = start - i + 1;
	return 0;
}
@@ -257,16 +291,15 @@ xfs_rtfind_back(
 */
int
xfs_rtfind_forw(
	xfs_mount_t	*mp,		/* file system mount point */
	xfs_trans_t	*tp,		/* transaction pointer */
	struct xfs_rtalloc_args	*args,
	xfs_rtxnum_t		start,	/* starting rtext to look at */
	xfs_rtxnum_t		limit,	/* last rtext to look at */
	xfs_rtxnum_t		*rtx)	/* out: start rtext found */
{
	struct xfs_mount	*mp = args->mp;
	int			bit;	/* bit number in the word */
	xfs_fileoff_t		block;	/* bitmap block number */
	struct xfs_buf	*bp;		/* buf for the block */
	int		error;		/* error value */
	int			error;
	xfs_rtxnum_t		i;	/* current bit number rel. to start */
	xfs_rtxnum_t		lastbit;/* last useful bit in the word */
	xfs_rtxnum_t		len;	/* length of inspected area */
@@ -280,10 +313,9 @@ xfs_rtfind_forw(
	 * Compute and read in starting bitmap block for starting block.
	 */
	block = xfs_rtx_to_rbmblock(mp, start);
	error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
	if (error) {
	error = xfs_rtbitmap_read_buf(args, block);
	if (error)
		return error;
	}

	/*
	 * Get the first word's index & point to it.
@@ -295,7 +327,7 @@ xfs_rtfind_forw(
	 * Compute match value, based on the bit at start: if 1 (free)
	 * then all-ones, else all-zeroes.
	 */
	incore = xfs_rtbitmap_getword(bp, word);
	incore = xfs_rtbitmap_getword(args, word);
	want = (incore & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
	/*
	 * If the starting position is not word-aligned, deal with the
@@ -316,7 +348,6 @@ xfs_rtfind_forw(
			/*
			 * Different.  Mark where we are and return.
			 */
			xfs_trans_brelse(tp, bp);
			i = XFS_RTLOBIT(wdiff) - bit;
			*rtx = start + i - 1;
			return 0;
@@ -330,11 +361,9 @@ xfs_rtfind_forw(
			/*
			 * If done with this block, get the previous one.
			 */
			xfs_trans_brelse(tp, bp);
			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
			if (error) {
			error = xfs_rtbitmap_read_buf(args, ++block);
			if (error)
				return error;
			}

			word = 0;
		}
@@ -352,12 +381,11 @@ xfs_rtfind_forw(
		/*
		 * Compute difference between actual and desired value.
		 */
		incore = xfs_rtbitmap_getword(bp, word);
		incore = xfs_rtbitmap_getword(args, word);
		if ((wdiff = incore ^ want)) {
			/*
			 * Different, mark where we are and return.
			 */
			xfs_trans_brelse(tp, bp);
			i += XFS_RTLOBIT(wdiff);
			*rtx = start + i - 1;
			return 0;
@@ -371,11 +399,9 @@ xfs_rtfind_forw(
			/*
			 * If done with this block, get the next one.
			 */
			xfs_trans_brelse(tp, bp);
			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
			if (error) {
			error = xfs_rtbitmap_read_buf(args, ++block);
			if (error)
				return error;
			}

			word = 0;
		}
@@ -392,12 +418,11 @@ xfs_rtfind_forw(
		/*
		 * Compute difference between actual and desired value.
		 */
		incore = xfs_rtbitmap_getword(bp, word);
		incore = xfs_rtbitmap_getword(args, word);
		if ((wdiff = (incore ^ want) & mask)) {
			/*
			 * Different, mark where we are and return.
			 */
			xfs_trans_brelse(tp, bp);
			i += XFS_RTLOBIT(wdiff);
			*rtx = start + i - 1;
			return 0;
@@ -407,7 +432,6 @@ xfs_rtfind_forw(
	/*
	 * No match, return that we scanned the whole area.
	 */
	xfs_trans_brelse(tp, bp);
	*rtx = start + i - 1;
	return 0;
}
@@ -415,16 +439,16 @@ xfs_rtfind_forw(
/* Log rtsummary counter at @infoword. */
static inline void
xfs_trans_log_rtsummary(
	struct xfs_trans	*tp,
	struct xfs_buf		*bp,
	struct xfs_rtalloc_args	*args,
	unsigned int		infoword)
{
	struct xfs_buf		*bp = args->sumbp;
	size_t			first, last;

	first = (void *)xfs_rsumblock_infoptr(bp, infoword) - bp->b_addr;
	first = (void *)xfs_rsumblock_infoptr(args, infoword) - bp->b_addr;
	last = first + sizeof(xfs_suminfo_t) - 1;

	xfs_trans_log_buf(tp, bp, first, last);
	xfs_trans_log_buf(args->tp, bp, first, last);
}

/*
@@ -438,17 +462,14 @@ xfs_trans_log_rtsummary(
 */
int
xfs_rtmodify_summary_int(
	xfs_mount_t	*mp,		/* file system mount structure */
	xfs_trans_t	*tp,		/* transaction pointer */
	struct xfs_rtalloc_args	*args,
	int			log,	/* log2 of extent size */
	xfs_fileoff_t		bbno,	/* bitmap block number */
	int			delta,	/* change to make to summary info */
	struct xfs_buf	**rbpp,		/* in/out: summary block buffer */
	xfs_fileoff_t	*rsb,		/* in/out: summary block number */
	xfs_suminfo_t		*sum)	/* out: summary info for this block */
{
	struct xfs_buf	*bp;		/* buffer for the summary block */
	int		error;		/* error value */
	struct xfs_mount	*mp = args->mp;
	int			error;
	xfs_fileoff_t		sb;	/* summary fsblock */
	xfs_rtsumoff_t		so;	/* index into the summary file */
	unsigned int		infoword;
@@ -461,80 +482,57 @@ xfs_rtmodify_summary_int(
	 * Compute the block number in the summary file.
	 */
	sb = xfs_rtsumoffs_to_block(mp, so);
	/*
	 * If we have an old buffer, and the block number matches, use that.
	 */
	if (*rbpp && *rsb == sb)
		bp = *rbpp;
	/*
	 * Otherwise we have to get the buffer.
	 */
	else {
		/*
		 * If there was an old one, get rid of it first.
		 */
		if (*rbpp)
			xfs_trans_brelse(tp, *rbpp);
		error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
		if (error) {

	error = xfs_rtsummary_read_buf(args, sb);
	if (error)
		return error;
		}
		/*
		 * Remember this buffer and block for the next call.
		 */
		*rbpp = bp;
		*rsb = sb;
	}

	/*
	 * Point to the summary information, modify/log it, and/or copy it out.
	 */
	infoword = xfs_rtsumoffs_to_infoword(mp, so);
	if (delta) {
		xfs_suminfo_t	val = xfs_suminfo_add(bp, infoword, delta);
		xfs_suminfo_t	val = xfs_suminfo_add(args, infoword, delta);

		if (mp->m_rsum_cache) {
			if (val == 0 && log == mp->m_rsum_cache[bbno])
				mp->m_rsum_cache[bbno]++;
			if (val != 0 && log < mp->m_rsum_cache[bbno])
			if (val == 0 && log + 1 == mp->m_rsum_cache[bbno])
				mp->m_rsum_cache[bbno] = log;
			if (val != 0 && log >= mp->m_rsum_cache[bbno])
				mp->m_rsum_cache[bbno] = log + 1;
		}
		xfs_trans_log_rtsummary(tp, bp, infoword);
		xfs_trans_log_rtsummary(args, infoword);
		if (sum)
			*sum = val;
	} else if (sum) {
		*sum = xfs_suminfo_get(bp, infoword);
		*sum = xfs_suminfo_get(args, infoword);
	}
	return 0;
}

int
xfs_rtmodify_summary(
	xfs_mount_t	*mp,		/* file system mount structure */
	xfs_trans_t	*tp,		/* transaction pointer */
	struct xfs_rtalloc_args	*args,
	int			log,	/* log2 of extent size */
	xfs_fileoff_t		bbno,	/* bitmap block number */
	int		delta,		/* change to make to summary info */
	struct xfs_buf	**rbpp,		/* in/out: summary block buffer */
	xfs_fileoff_t	*rsb)		/* in/out: summary block number */
	int			delta)	/* in/out: summary block number */
{
	return xfs_rtmodify_summary_int(mp, tp, log, bbno,
					delta, rbpp, rsb, NULL);
	return xfs_rtmodify_summary_int(args, log, bbno, delta, NULL);
}

/* Log rtbitmap block from the word @from to the byte before @next. */
static inline void
xfs_trans_log_rtbitmap(
	struct xfs_trans	*tp,
	struct xfs_buf		*bp,
	struct xfs_rtalloc_args	*args,
	unsigned int		from,
	unsigned int		next)
{
	struct xfs_buf		*bp = args->rbmbp;
	size_t			first, last;

	first = (void *)xfs_rbmblock_wordptr(bp, from) - bp->b_addr;
	last = ((void *)xfs_rbmblock_wordptr(bp, next) - 1) - bp->b_addr;
	first = (void *)xfs_rbmblock_wordptr(args, from) - bp->b_addr;
	last = ((void *)xfs_rbmblock_wordptr(args, next) - 1) - bp->b_addr;

	xfs_trans_log_buf(tp, bp, first, last);
	xfs_trans_log_buf(args->tp, bp, first, last);
}

/*
@@ -543,16 +541,15 @@ xfs_trans_log_rtbitmap(
 */
int
xfs_rtmodify_range(
	xfs_mount_t	*mp,		/* file system mount point */
	xfs_trans_t	*tp,		/* transaction pointer */
	struct xfs_rtalloc_args	*args,
	xfs_rtxnum_t		start,	/* starting rtext to modify */
	xfs_rtxlen_t		len,	/* length of extent to modify */
	int			val)	/* 1 for free, 0 for allocated */
{
	struct xfs_mount	*mp = args->mp;
	int			bit;	/* bit number in the word */
	xfs_fileoff_t		block;	/* bitmap block number */
	struct xfs_buf	*bp;		/* buf for the block */
	int		error;		/* error value */
	int			error;
	int			i;	/* current bit number rel. to start */
	int			lastbit; /* last useful bit in word */
	xfs_rtword_t		mask;	 /* mask of relevant bits for value */
@@ -567,10 +564,9 @@ xfs_rtmodify_range(
	/*
	 * Read the bitmap block, and point to its data.
	 */
	error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
	if (error) {
	error = xfs_rtbitmap_read_buf(args, block);
	if (error)
		return error;
	}

	/*
	 * Compute the starting word's address, and starting bit.
@@ -594,12 +590,12 @@ xfs_rtmodify_range(
		/*
		 * Set/clear the active bits.
		 */
		incore = xfs_rtbitmap_getword(bp, word);
		incore = xfs_rtbitmap_getword(args, word);
		if (val)
			incore |= mask;
		else
			incore &= ~mask;
		xfs_rtbitmap_setword(bp, word, incore);
		xfs_rtbitmap_setword(args, word, incore);
		i = lastbit - bit;
		/*
		 * Go on to the next block if that's where the next word is
@@ -610,11 +606,10 @@ xfs_rtmodify_range(
			 * Log the changed part of this block.
			 * Get the next one.
			 */
			xfs_trans_log_rtbitmap(tp, bp, firstword, word);
			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
			if (error) {
			xfs_trans_log_rtbitmap(args, firstword, word);
			error = xfs_rtbitmap_read_buf(args, ++block);
			if (error)
				return error;
			}

			firstword = word = 0;
		}
@@ -632,7 +627,7 @@ xfs_rtmodify_range(
		/*
		 * Set the word value correctly.
		 */
		xfs_rtbitmap_setword(bp, word, val);
		xfs_rtbitmap_setword(args, word, val);
		i += XFS_NBWORD;
		/*
		 * Go on to the next block if that's where the next word is
@@ -643,11 +638,10 @@ xfs_rtmodify_range(
			 * Log the changed part of this block.
			 * Get the next one.
			 */
			xfs_trans_log_rtbitmap(tp, bp, firstword, word);
			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
			if (error) {
			xfs_trans_log_rtbitmap(args, firstword, word);
			error = xfs_rtbitmap_read_buf(args, ++block);
			if (error)
				return error;
			}

			firstword = word = 0;
		}
@@ -664,19 +658,19 @@ xfs_rtmodify_range(
		/*
		 * Set/clear the active bits.
		 */
		incore = xfs_rtbitmap_getword(bp, word);
		incore = xfs_rtbitmap_getword(args, word);
		if (val)
			incore |= mask;
		else
			incore &= ~mask;
		xfs_rtbitmap_setword(bp, word, incore);
		xfs_rtbitmap_setword(args, word, incore);
		word++;
	}
	/*
	 * Log any remaining changed bytes.
	 */
	if (word > firstword)
		xfs_trans_log_rtbitmap(tp, bp, firstword, word);
		xfs_trans_log_rtbitmap(args, firstword, word);
	return 0;
}

@@ -686,13 +680,11 @@ xfs_rtmodify_range(
 */
int
xfs_rtfree_range(
	xfs_mount_t	*mp,		/* file system mount point */
	xfs_trans_t	*tp,		/* transaction pointer */
	struct xfs_rtalloc_args	*args,
	xfs_rtxnum_t		start,	/* starting rtext to free */
	xfs_rtxlen_t	len,		/* length to free */
	struct xfs_buf	**rbpp,		/* in/out: summary block buffer */
	xfs_fileoff_t	*rsb)		/* in/out: summary block number */
	xfs_rtxlen_t		len)	/* in/out: summary block number */
{
	struct xfs_mount	*mp = args->mp;
	xfs_rtxnum_t		end;	/* end of the freed extent */
	int			error;	/* error value */
	xfs_rtxnum_t		postblock; /* first rtext freed > end */
@@ -702,7 +694,7 @@ xfs_rtfree_range(
	/*
	 * Modify the bitmap to mark this extent freed.
	 */
	error = xfs_rtmodify_range(mp, tp, start, len, 1);
	error = xfs_rtmodify_range(args, start, len, 1);
	if (error) {
		return error;
	}
@@ -711,14 +703,14 @@ xfs_rtfree_range(
	 * We need to find the beginning and end of the extent so we can
	 * properly update the summary.
	 */
	error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
	error = xfs_rtfind_back(args, start, 0, &preblock);
	if (error) {
		return error;
	}
	/*
	 * Find the next allocated block (end of allocated extent).
	 */
	error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
	error = xfs_rtfind_forw(args, end, mp->m_sb.sb_rextents - 1,
			&postblock);
	if (error)
		return error;
@@ -727,9 +719,9 @@ xfs_rtfree_range(
	 * old extent, add summary data for them to be allocated.
	 */
	if (preblock < start) {
		error = xfs_rtmodify_summary(mp, tp,
		error = xfs_rtmodify_summary(args,
				XFS_RTBLOCKLOG(start - preblock),
			xfs_rtx_to_rbmblock(mp, preblock), -1, rbpp, rsb);
				xfs_rtx_to_rbmblock(mp, preblock), -1);
		if (error) {
			return error;
		}
@@ -739,9 +731,9 @@ xfs_rtfree_range(
	 * old extent, add summary data for them to be allocated.
	 */
	if (postblock > end) {
		error = xfs_rtmodify_summary(mp, tp,
		error = xfs_rtmodify_summary(args,
				XFS_RTBLOCKLOG(postblock - end),
			xfs_rtx_to_rbmblock(mp, end + 1), -1, rbpp, rsb);
				xfs_rtx_to_rbmblock(mp, end + 1), -1);
		if (error) {
			return error;
		}
@@ -750,10 +742,9 @@ xfs_rtfree_range(
	 * Increment the summary information corresponding to the entire
	 * (new) free extent.
	 */
	error = xfs_rtmodify_summary(mp, tp,
	return xfs_rtmodify_summary(args,
			XFS_RTBLOCKLOG(postblock + 1 - preblock),
		xfs_rtx_to_rbmblock(mp, preblock), 1, rbpp, rsb);
	return error;
			xfs_rtx_to_rbmblock(mp, preblock), 1);
}

/*
@@ -762,18 +753,17 @@ xfs_rtfree_range(
 */
int
xfs_rtcheck_range(
	xfs_mount_t	*mp,		/* file system mount point */
	xfs_trans_t	*tp,		/* transaction pointer */
	struct xfs_rtalloc_args	*args,
	xfs_rtxnum_t		start,	/* starting rtext number of extent */
	xfs_rtxlen_t		len,	/* length of extent */
	int			val,	/* 1 for free, 0 for allocated */
	xfs_rtxnum_t		*new,	/* out: first rtext not matching */
	int			*stat)	/* out: 1 for matches, 0 for not */
{
	struct xfs_mount	*mp = args->mp;
	int			bit;	/* bit number in the word */
	xfs_fileoff_t		block;	/* bitmap block number */
	struct xfs_buf	*bp;		/* buf for the block */
	int		error;		/* error value */
	int			error;
	xfs_rtxnum_t		i;	/* current bit number rel. to start */
	xfs_rtxnum_t		lastbit; /* last useful bit in word */
	xfs_rtword_t		mask;	/* mask of relevant bits for value */
@@ -788,10 +778,9 @@ xfs_rtcheck_range(
	/*
	 * Read the bitmap block.
	 */
	error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
	if (error) {
	error = xfs_rtbitmap_read_buf(args, block);
	if (error)
		return error;
	}

	/*
	 * Compute the starting word's address, and starting bit.
@@ -818,12 +807,11 @@ xfs_rtcheck_range(
		/*
		 * Compute difference between actual and desired value.
		 */
		incore = xfs_rtbitmap_getword(bp, word);
		incore = xfs_rtbitmap_getword(args, word);
		if ((wdiff = (incore ^ val) & mask)) {
			/*
			 * Different, compute first wrong bit and return.
			 */
			xfs_trans_brelse(tp, bp);
			i = XFS_RTLOBIT(wdiff) - bit;
			*new = start + i;
			*stat = 0;
@@ -838,11 +826,9 @@ xfs_rtcheck_range(
			/*
			 * If done with this block, get the next one.
			 */
			xfs_trans_brelse(tp, bp);
			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
			if (error) {
			error = xfs_rtbitmap_read_buf(args, ++block);
			if (error)
				return error;
			}

			word = 0;
		}
@@ -860,12 +846,11 @@ xfs_rtcheck_range(
		/*
		 * Compute difference between actual and desired value.
		 */
		incore = xfs_rtbitmap_getword(bp, word);
		incore = xfs_rtbitmap_getword(args, word);
		if ((wdiff = incore ^ val)) {
			/*
			 * Different, compute first wrong bit and return.
			 */
			xfs_trans_brelse(tp, bp);
			i += XFS_RTLOBIT(wdiff);
			*new = start + i;
			*stat = 0;
@@ -880,11 +865,9 @@ xfs_rtcheck_range(
			/*
			 * If done with this block, get the next one.
			 */
			xfs_trans_brelse(tp, bp);
			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
			if (error) {
			error = xfs_rtbitmap_read_buf(args, ++block);
			if (error)
				return error;
			}

			word = 0;
		}
@@ -901,12 +884,11 @@ xfs_rtcheck_range(
		/*
		 * Compute difference between actual and desired value.
		 */
		incore = xfs_rtbitmap_getword(bp, word);
		incore = xfs_rtbitmap_getword(args, word);
		if ((wdiff = (incore ^ val) & mask)) {
			/*
			 * Different, compute first wrong bit and return.
			 */
			xfs_trans_brelse(tp, bp);
			i += XFS_RTLOBIT(wdiff);
			*new = start + i;
			*stat = 0;
@@ -917,7 +899,6 @@ xfs_rtcheck_range(
	/*
	 * Successful, return.
	 */
	xfs_trans_brelse(tp, bp);
	*new = start + i;
	*stat = 1;
	return 0;
@@ -927,10 +908,9 @@ xfs_rtcheck_range(
/*
 * Check that the given extent (block range) is allocated already.
 */
STATIC int				/* error */
STATIC int
xfs_rtcheck_alloc_range(
	xfs_mount_t	*mp,		/* file system mount point */
	xfs_trans_t	*tp,		/* transaction pointer */
	struct xfs_rtalloc_args	*args,
	xfs_rtxnum_t		start,	/* starting rtext number of extent */
	xfs_rtxlen_t		len)	/* length of extent */
{
@@ -938,46 +918,46 @@ xfs_rtcheck_alloc_range(
	int			stat;
	int			error;

	error = xfs_rtcheck_range(mp, tp, start, len, 0, &new, &stat);
	error = xfs_rtcheck_range(args, start, len, 0, &new, &stat);
	if (error)
		return error;
	ASSERT(stat);
	return 0;
}
#else
#define xfs_rtcheck_alloc_range(m,t,b,l)	(0)
#define xfs_rtcheck_alloc_range(a,b,l)	(0)
#endif
/*
 * Free an extent in the realtime subvolume.  Length is expressed in
 * realtime extents, as is the block number.
 */
int					/* error */
int
xfs_rtfree_extent(
	xfs_trans_t	*tp,		/* transaction pointer */
	struct xfs_trans	*tp,	/* transaction pointer */
	xfs_rtxnum_t		start,	/* starting rtext number to free */
	xfs_rtxlen_t		len)	/* length of extent freed */
{
	int		error;		/* error value */
	xfs_mount_t	*mp;		/* file system mount structure */
	xfs_fsblock_t	sb;		/* summary file block number */
	struct xfs_buf	*sumbp = NULL;	/* summary file block buffer */

	mp = tp->t_mountp;
	struct xfs_mount	*mp = tp->t_mountp;
	struct xfs_rtalloc_args	args = {
		.mp		= mp,
		.tp		= tp,
	};
	int			error;

	ASSERT(mp->m_rbmip->i_itemp != NULL);
	ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));

	error = xfs_rtcheck_alloc_range(mp, tp, start, len);
	error = xfs_rtcheck_alloc_range(&args, start, len);
	if (error)
		return error;

	/*
	 * Free the range of realtime blocks.
	 */
	error = xfs_rtfree_range(mp, tp, start, len, &sumbp, &sb);
	if (error) {
		return error;
	}
	error = xfs_rtfree_range(&args, start, len);
	if (error)
		goto out;

	/*
	 * Mark more blocks free in the superblock.
	 */
@@ -993,7 +973,10 @@ xfs_rtfree_extent(
		*(uint64_t *)&VFS_I(mp->m_rbmip)->i_atime = 0;
		xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
	}
	return 0;
	error = 0;
out:
	xfs_rtbuf_cache_relse(&args);
	return error;
}

/*
@@ -1039,6 +1022,10 @@ xfs_rtalloc_query_range(
	xfs_rtalloc_query_range_fn	fn,
	void				*priv)
{
	struct xfs_rtalloc_args		args = {
		.mp			= mp,
		.tp			= tp,
	};
	struct xfs_rtalloc_rec		rec;
	xfs_rtxnum_t			rtstart;
	xfs_rtxnum_t			rtend;
@@ -1058,13 +1045,13 @@ xfs_rtalloc_query_range(
	rtstart = low_rec->ar_startext;
	while (rtstart <= high_key) {
		/* Is the first block free? */
		error = xfs_rtcheck_range(mp, tp, rtstart, 1, 1, &rtend,
		error = xfs_rtcheck_range(&args, rtstart, 1, 1, &rtend,
				&is_free);
		if (error)
			break;

		/* How long does the extent go for? */
		error = xfs_rtfind_forw(mp, tp, rtstart, high_key, &rtend);
		error = xfs_rtfind_forw(&args, rtstart, high_key, &rtend);
		if (error)
			break;

@@ -1080,6 +1067,7 @@ xfs_rtalloc_query_range(
		rtstart = rtend + 1;
	}

	xfs_rtbuf_cache_relse(&args);
	return error;
}

@@ -1109,11 +1097,16 @@ xfs_rtalloc_extent_is_free(
	xfs_rtxlen_t			len,
	bool				*is_free)
{
	struct xfs_rtalloc_args		args = {
		.mp			= mp,
		.tp			= tp,
	};
	xfs_rtxnum_t			end;
	int				matches;
	int				error;

	error = xfs_rtcheck_range(mp, tp, start, len, 1, &end, &matches);
	error = xfs_rtcheck_range(&args, start, len, 1, &end, &matches);
	xfs_rtbuf_cache_relse(&args);
	if (error)
		return error;

+61 −36

File changed.

Preview size limit exceeded, changes collapsed.

+8 −5
Original line number Diff line number Diff line
@@ -188,8 +188,11 @@ STATIC int
xchk_rtsum_compare(
	struct xfs_scrub	*sc)
{
	struct xfs_rtalloc_args args = {
		.mp		= sc->mp,
		.tp		= sc->tp,
	};
	struct xfs_mount	*mp = sc->mp;
	struct xfs_buf		*bp;
	struct xfs_bmbt_irec	map;
	xfs_fileoff_t		off;
	xchk_rtsumoff_t		sumoff = 0;
@@ -217,23 +220,23 @@ xchk_rtsum_compare(
		}

		/* Read a block's worth of ondisk rtsummary file. */
		error = xfs_rtbuf_get(mp, sc->tp, off, 1, &bp);
		error = xfs_rtsummary_read_buf(&args, off);
		if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, off, &error))
			return error;

		/* Read a block's worth of computed rtsummary file. */
		error = xfsum_copyout(sc, sumoff, sc->buf, mp->m_blockwsize);
		if (error) {
			xfs_trans_brelse(sc->tp, bp);
			xfs_rtbuf_cache_relse(&args);
			return error;
		}

		ondisk_info = xfs_rsumblock_infoptr(bp, 0);
		ondisk_info = xfs_rsumblock_infoptr(&args, 0);
		if (memcmp(ondisk_info, sc->buf,
					mp->m_blockwsize << XFS_WORDLOG) != 0)
			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, off);

		xfs_trans_brelse(sc->tp, bp);
		xfs_rtbuf_cache_relse(&args);
		sumoff += mp->m_blockwsize;
	}

+3 −3
Original line number Diff line number Diff line
@@ -101,9 +101,9 @@ typedef struct xfs_mount {

	/*
	 * Optional cache of rt summary level per bitmap block with the
	 * invariant that m_rsum_cache[bbno] <= the minimum i for which
	 * rsum[i][bbno] != 0. Reads and writes are serialized by the rsumip
	 * inode lock.
	 * invariant that m_rsum_cache[bbno] > the maximum i for which
	 * rsum[i][bbno] != 0, or 0 if rsum[i][bbno] == 0 for all i.
	 * Reads and writes are serialized by the rsumip inode lock.
	 */
	uint8_t			*m_rsum_cache;
	struct xfs_mru_cache	*m_filestream;  /* per-mount filestream data */
+225 −250

File changed.

Preview size limit exceeded, changes collapsed.