Commit 035e32f7 authored by Chandan Babu R's avatar Chandan Babu R
Browse files

Merge tag 'refactor-rtbitmap-macros-6.7_2023-10-19' of...

Merge tag 'refactor-rtbitmap-macros-6.7_2023-10-19' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux

 into xfs-6.7-mergeA

xfs: refactor rtbitmap/summary macros [v1.1]

In preparation for adding block headers and enforcing endian order in
rtbitmap and rtsummary blocks, replace open-coded geometry computations
and fugly macros with proper helper functions that can be typechecked.
Soon we'll be needing to add more complex logic to the helpers.

v1.1: various cleanups suggested by hch

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 'refactor-rtbitmap-macros-6.7_2023-10-19' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux:
  xfs: create helpers for rtbitmap block/wordcount computations
  xfs: convert rt summary macros to helpers
  xfs: convert open-coded xfs_rtword_t pointer accesses to helper
  xfs: remove XFS_BLOCKWSIZE and XFS_BLOCKWMASK macros
  xfs: convert the rtbitmap block and bit macros to static inline functions
parents 9d4ca5af d0448fe7
Loading
Loading
Loading
Loading
+1 −15
Original line number Diff line number Diff line
@@ -1142,24 +1142,10 @@ static inline bool xfs_dinode_has_large_extent_counts(

#define	XFS_BLOCKSIZE(mp)	((mp)->m_sb.sb_blocksize)
#define	XFS_BLOCKMASK(mp)	((mp)->m_blockmask)
#define	XFS_BLOCKWSIZE(mp)	((mp)->m_blockwsize)
#define	XFS_BLOCKWMASK(mp)	((mp)->m_blockwmask)

/*
 * RT Summary and bit manipulation macros.
 * RT bit manipulation macros.
 */
#define	XFS_SUMOFFS(mp,ls,bb)	((int)((ls) * (mp)->m_sb.sb_rbmblocks + (bb)))
#define	XFS_SUMOFFSTOBLOCK(mp,s)	\
	(((s) * (uint)sizeof(xfs_suminfo_t)) >> (mp)->m_sb.sb_blocklog)
#define	XFS_SUMPTR(mp,bp,so)	\
	((xfs_suminfo_t *)((bp)->b_addr + \
		(((so) * (uint)sizeof(xfs_suminfo_t)) & XFS_BLOCKMASK(mp))))

#define	XFS_BITTOBLOCK(mp,bi)	((bi) >> (mp)->m_blkbit_log)
#define	XFS_BLOCKTOBIT(mp,bb)	((bb) << (mp)->m_blkbit_log)
#define	XFS_BITTOWORD(mp,bi)	\
	((int)(((bi) >> XFS_NBWORDLOG) & XFS_BLOCKWMASK(mp)))

#define	XFS_RTMIN(a,b)	((a) < (b) ? (a) : (b))
#define	XFS_RTMAX(a,b)	((a) > (b) ? (a) : (b))

+87 −55
Original line number Diff line number Diff line
@@ -103,7 +103,6 @@ xfs_rtfind_back(
	int		bit;		/* bit number in the word */
	xfs_fileoff_t	block;		/* bitmap block number */
	struct xfs_buf	*bp;		/* buf for the block */
	xfs_rtword_t	*bufp;		/* starting word in buffer */
	int		error;		/* error value */
	xfs_rtxnum_t	firstbit;	/* first useful bit in the word */
	xfs_rtxnum_t	i;		/* current bit number rel. to start */
@@ -111,22 +110,22 @@ xfs_rtfind_back(
	xfs_rtword_t	mask;		/* mask of relevant bits for value */
	xfs_rtword_t	want;		/* mask for "good" values */
	xfs_rtword_t	wdiff;		/* difference from wanted value */
	int		word;		/* word number in the buffer */
	unsigned int	word;		/* word number in the buffer */

	/*
	 * Compute and read in starting bitmap block for starting block.
	 */
	block = XFS_BITTOBLOCK(mp, start);
	block = xfs_rtx_to_rbmblock(mp, start);
	error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
	if (error) {
		return error;
	}
	bufp = bp->b_addr;

	/*
	 * Get the first word's index & point to it.
	 */
	word = XFS_BITTOWORD(mp, start);
	b = &bufp[word];
	word = xfs_rtx_to_rbmword(mp, start);
	b = xfs_rbmblock_wordptr(bp, word);
	bit = (int)(start & (XFS_NBWORD - 1));
	len = start - limit + 1;
	/*
@@ -173,9 +172,9 @@ xfs_rtfind_back(
			if (error) {
				return error;
			}
			bufp = bp->b_addr;
			word = XFS_BLOCKWMASK(mp);
			b = &bufp[word];

			word = mp->m_blockwsize - 1;
			b = xfs_rbmblock_wordptr(bp, word);
		} else {
			/*
			 * Go on to the previous word in the buffer.
@@ -219,9 +218,9 @@ xfs_rtfind_back(
			if (error) {
				return error;
			}
			bufp = bp->b_addr;
			word = XFS_BLOCKWMASK(mp);
			b = &bufp[word];

			word = mp->m_blockwsize - 1;
			b = xfs_rbmblock_wordptr(bp, word);
		} else {
			/*
			 * Go on to the previous word in the buffer.
@@ -278,7 +277,6 @@ xfs_rtfind_forw(
	int		bit;		/* bit number in the word */
	xfs_fileoff_t	block;		/* bitmap block number */
	struct xfs_buf	*bp;		/* buf for the block */
	xfs_rtword_t	*bufp;		/* starting word in buffer */
	int		error;		/* error value */
	xfs_rtxnum_t	i;		/* current bit number rel. to start */
	xfs_rtxnum_t	lastbit;	/* last useful bit in the word */
@@ -286,22 +284,22 @@ xfs_rtfind_forw(
	xfs_rtword_t	mask;		/* mask of relevant bits for value */
	xfs_rtword_t	want;		/* mask for "good" values */
	xfs_rtword_t	wdiff;		/* difference from wanted value */
	int		word;		/* word number in the buffer */
	unsigned int	word;		/* word number in the buffer */

	/*
	 * Compute and read in starting bitmap block for starting block.
	 */
	block = XFS_BITTOBLOCK(mp, start);
	block = xfs_rtx_to_rbmblock(mp, start);
	error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
	if (error) {
		return error;
	}
	bufp = bp->b_addr;

	/*
	 * Get the first word's index & point to it.
	 */
	word = XFS_BITTOWORD(mp, start);
	b = &bufp[word];
	word = xfs_rtx_to_rbmword(mp, start);
	b = xfs_rbmblock_wordptr(bp, word);
	bit = (int)(start & (XFS_NBWORD - 1));
	len = limit - start + 1;
	/*
@@ -338,7 +336,7 @@ xfs_rtfind_forw(
		 * Go on to next block if that's where the next word is
		 * and we need the next word.
		 */
		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
		if (++word == mp->m_blockwsize && i < len) {
			/*
			 * If done with this block, get the previous one.
			 */
@@ -347,8 +345,9 @@ xfs_rtfind_forw(
			if (error) {
				return error;
			}
			b = bufp = bp->b_addr;

			word = 0;
			b = xfs_rbmblock_wordptr(bp, word);
		} else {
			/*
			 * Go on to the previous word in the buffer.
@@ -383,7 +382,7 @@ xfs_rtfind_forw(
		 * Go on to next block if that's where the next word is
		 * and we need the next word.
		 */
		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
		if (++word == mp->m_blockwsize && i < len) {
			/*
			 * If done with this block, get the next one.
			 */
@@ -392,8 +391,9 @@ xfs_rtfind_forw(
			if (error) {
				return error;
			}
			b = bufp = bp->b_addr;

			word = 0;
			b = xfs_rbmblock_wordptr(bp, word);
		} else {
			/*
			 * Go on to the next word in the buffer.
@@ -455,17 +455,18 @@ xfs_rtmodify_summary_int(
	struct xfs_buf	*bp;		/* buffer for the summary block */
	int		error;		/* error value */
	xfs_fileoff_t	sb;		/* summary fsblock */
	int		so;		/* index into the summary file */
	xfs_rtsumoff_t	so;		/* index into the summary file */
	xfs_suminfo_t	*sp;		/* pointer to returned data */
	unsigned int	infoword;

	/*
	 * Compute entry number in the summary file.
	 */
	so = XFS_SUMOFFS(mp, log, bbno);
	so = xfs_rtsumoffs(mp, log, bbno);
	/*
	 * Compute the block number in the summary file.
	 */
	sb = XFS_SUMOFFSTOBLOCK(mp, so);
	sb = xfs_rtsumoffs_to_block(mp, so);
	/*
	 * If we have an old buffer, and the block number matches, use that.
	 */
@@ -493,7 +494,8 @@ xfs_rtmodify_summary_int(
	/*
	 * Point to the summary information, modify/log it, and/or copy it out.
	 */
	sp = XFS_SUMPTR(mp, bp, so);
	infoword = xfs_rtsumoffs_to_infoword(mp, so);
	sp = xfs_rsumblock_infoptr(bp, infoword);
	if (delta) {
		uint first = (uint)((char *)sp - (char *)bp->b_addr);

@@ -541,18 +543,17 @@ xfs_rtmodify_range(
	int		bit;		/* bit number in the word */
	xfs_fileoff_t	block;		/* bitmap block number */
	struct xfs_buf	*bp;		/* buf for the block */
	xfs_rtword_t	*bufp;		/* starting word in buffer */
	int		error;		/* error value */
	xfs_rtword_t	*first;		/* first used word in the buffer */
	int		i;		/* current bit number rel. to start */
	int		lastbit;	/* last useful bit in word */
	xfs_rtword_t	mask;		/* mask o frelevant bits for value */
	int		word;		/* word number in the buffer */
	unsigned int	word;		/* word number in the buffer */

	/*
	 * Compute starting bitmap block number.
	 */
	block = XFS_BITTOBLOCK(mp, start);
	block = xfs_rtx_to_rbmblock(mp, start);
	/*
	 * Read the bitmap block, and point to its data.
	 */
@@ -560,12 +561,12 @@ xfs_rtmodify_range(
	if (error) {
		return error;
	}
	bufp = bp->b_addr;

	/*
	 * Compute the starting word's address, and starting bit.
	 */
	word = XFS_BITTOWORD(mp, start);
	first = b = &bufp[word];
	word = xfs_rtx_to_rbmword(mp, start);
	first = b = xfs_rbmblock_wordptr(bp, word);
	bit = (int)(start & (XFS_NBWORD - 1));
	/*
	 * 0 (allocated) => all zeroes; 1 (free) => all ones.
@@ -593,20 +594,21 @@ xfs_rtmodify_range(
		 * Go on to the next block if that's where the next word is
		 * and we need the next word.
		 */
		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
		if (++word == mp->m_blockwsize && i < len) {
			/*
			 * Log the changed part of this block.
			 * Get the next one.
			 */
			xfs_trans_log_buf(tp, bp,
				(uint)((char *)first - (char *)bufp),
				(uint)((char *)b - (char *)bufp));
				(uint)((char *)first - (char *)bp->b_addr),
				(uint)((char *)b - (char *)bp->b_addr));
			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
			if (error) {
				return error;
			}
			first = b = bufp = bp->b_addr;

			word = 0;
			first = b = xfs_rbmblock_wordptr(bp, word);
		} else {
			/*
			 * Go on to the next word in the buffer
@@ -633,20 +635,21 @@ xfs_rtmodify_range(
		 * Go on to the next block if that's where the next word is
		 * and we need the next word.
		 */
		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
		if (++word == mp->m_blockwsize && i < len) {
			/*
			 * Log the changed part of this block.
			 * Get the next one.
			 */
			xfs_trans_log_buf(tp, bp,
				(uint)((char *)first - (char *)bufp),
				(uint)((char *)b - (char *)bufp));
				(uint)((char *)first - (char *)bp->b_addr),
				(uint)((char *)b - (char *)bp->b_addr));
			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
			if (error) {
				return error;
			}
			first = b = bufp = bp->b_addr;

			word = 0;
			first = b = xfs_rbmblock_wordptr(bp, word);
		} else {
			/*
			 * Go on to the next word in the buffer
@@ -676,8 +679,9 @@ xfs_rtmodify_range(
	 * Log any remaining changed bytes.
	 */
	if (b > first)
		xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp),
			(uint)((char *)b - (char *)bufp - 1));
		xfs_trans_log_buf(tp, bp,
			(uint)((char *)first - (char *)bp->b_addr),
			(uint)((char *)b - (char *)bp->b_addr - 1));
	return 0;
}

@@ -730,7 +734,7 @@ xfs_rtfree_range(
	if (preblock < start) {
		error = xfs_rtmodify_summary(mp, tp,
			XFS_RTBLOCKLOG(start - preblock),
			XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
			xfs_rtx_to_rbmblock(mp, preblock), -1, rbpp, rsb);
		if (error) {
			return error;
		}
@@ -742,7 +746,7 @@ xfs_rtfree_range(
	if (postblock > end) {
		error = xfs_rtmodify_summary(mp, tp,
			XFS_RTBLOCKLOG(postblock - end),
			XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb);
			xfs_rtx_to_rbmblock(mp, end + 1), -1, rbpp, rsb);
		if (error) {
			return error;
		}
@@ -753,7 +757,7 @@ xfs_rtfree_range(
	 */
	error = xfs_rtmodify_summary(mp, tp,
		XFS_RTBLOCKLOG(postblock + 1 - preblock),
		XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
		xfs_rtx_to_rbmblock(mp, preblock), 1, rbpp, rsb);
	return error;
}

@@ -775,18 +779,17 @@ xfs_rtcheck_range(
	int		bit;		/* bit number in the word */
	xfs_fileoff_t	block;		/* bitmap block number */
	struct xfs_buf	*bp;		/* buf for the block */
	xfs_rtword_t	*bufp;		/* starting word in buffer */
	int		error;		/* error value */
	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 */
	xfs_rtword_t	wdiff;		/* difference from wanted value */
	int		word;		/* word number in the buffer */
	unsigned int	word;		/* word number in the buffer */

	/*
	 * Compute starting bitmap block number
	 */
	block = XFS_BITTOBLOCK(mp, start);
	block = xfs_rtx_to_rbmblock(mp, start);
	/*
	 * Read the bitmap block.
	 */
@@ -794,12 +797,12 @@ xfs_rtcheck_range(
	if (error) {
		return error;
	}
	bufp = bp->b_addr;

	/*
	 * Compute the starting word's address, and starting bit.
	 */
	word = XFS_BITTOWORD(mp, start);
	b = &bufp[word];
	word = xfs_rtx_to_rbmword(mp, start);
	b = xfs_rbmblock_wordptr(bp, word);
	bit = (int)(start & (XFS_NBWORD - 1));
	/*
	 * 0 (allocated) => all zero's; 1 (free) => all one's.
@@ -836,7 +839,7 @@ xfs_rtcheck_range(
		 * Go on to next block if that's where the next word is
		 * and we need the next word.
		 */
		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
		if (++word == mp->m_blockwsize && i < len) {
			/*
			 * If done with this block, get the next one.
			 */
@@ -845,8 +848,9 @@ xfs_rtcheck_range(
			if (error) {
				return error;
			}
			b = bufp = bp->b_addr;

			word = 0;
			b = xfs_rbmblock_wordptr(bp, word);
		} else {
			/*
			 * Go on to the next word in the buffer.
@@ -882,7 +886,7 @@ xfs_rtcheck_range(
		 * Go on to next block if that's where the next word is
		 * and we need the next word.
		 */
		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
		if (++word == mp->m_blockwsize && i < len) {
			/*
			 * If done with this block, get the next one.
			 */
@@ -891,8 +895,9 @@ xfs_rtcheck_range(
			if (error) {
				return error;
			}
			b = bufp = bp->b_addr;

			word = 0;
			b = xfs_rbmblock_wordptr(bp, word);
		} else {
			/*
			 * Go on to the next word in the buffer.
@@ -1130,3 +1135,30 @@ xfs_rtalloc_extent_is_free(
	*is_free = matches;
	return 0;
}

/*
 * Compute the number of rtbitmap blocks needed to track the given number of rt
 * extents.
 */
xfs_filblks_t
xfs_rtbitmap_blockcount(
	struct xfs_mount	*mp,
	xfs_rtbxlen_t		rtextents)
{
	return howmany_64(rtextents, NBBY * mp->m_sb.sb_blocksize);
}

/*
 * Compute the number of rtbitmap words needed to populate every block of a
 * bitmap that is large enough to track the given number of rt extents.
 */
unsigned long long
xfs_rtbitmap_wordcount(
	struct xfs_mount	*mp,
	xfs_rtbxlen_t		rtextents)
{
	xfs_filblks_t		blocks;

	blocks = xfs_rtbitmap_blockcount(mp, rtextents);
	return XFS_FSB_TO_B(mp, blocks) >> XFS_WORDLOG;
}
+100 −0
Original line number Diff line number Diff line
@@ -131,6 +131,94 @@ xfs_rtb_rounddown_rtx(
	return rounddown_64(rtbno, mp->m_sb.sb_rextsize);
}

/* Convert an rt extent number to a file block offset in the rt bitmap file. */
static inline xfs_fileoff_t
xfs_rtx_to_rbmblock(
	struct xfs_mount	*mp,
	xfs_rtxnum_t		rtx)
{
	return rtx >> mp->m_blkbit_log;
}

/* Convert an rt extent number to a word offset within an rt bitmap block. */
static inline unsigned int
xfs_rtx_to_rbmword(
	struct xfs_mount	*mp,
	xfs_rtxnum_t		rtx)
{
	return (rtx >> XFS_NBWORDLOG) & (mp->m_blockwsize - 1);
}

/* Convert a file block offset in the rt bitmap file to an rt extent number. */
static inline xfs_rtxnum_t
xfs_rbmblock_to_rtx(
	struct xfs_mount	*mp,
	xfs_fileoff_t		rbmoff)
{
	return rbmoff << mp->m_blkbit_log;
}

/* Return a pointer to a bitmap word within a rt bitmap block. */
static inline xfs_rtword_t *
xfs_rbmblock_wordptr(
	struct xfs_buf		*bp,
	unsigned int		index)
{
	xfs_rtword_t		*words = bp->b_addr;

	return words + index;
}

/*
 * Convert a rt extent length and rt bitmap block number to a xfs_suminfo_t
 * offset within the rt summary file.
 */
static inline xfs_rtsumoff_t
xfs_rtsumoffs(
	struct xfs_mount	*mp,
	int			log2_len,
	xfs_fileoff_t		rbmoff)
{
	return log2_len * mp->m_sb.sb_rbmblocks + rbmoff;
}

/*
 * Convert an xfs_suminfo_t offset to a file block offset within the rt summary
 * file.
 */
static inline xfs_fileoff_t
xfs_rtsumoffs_to_block(
	struct xfs_mount	*mp,
	xfs_rtsumoff_t		rsumoff)
{
	return XFS_B_TO_FSBT(mp, rsumoff * sizeof(xfs_suminfo_t));
}

/*
 * Convert an xfs_suminfo_t offset to an info word offset within an rt summary
 * block.
 */
static inline unsigned int
xfs_rtsumoffs_to_infoword(
	struct xfs_mount	*mp,
	xfs_rtsumoff_t		rsumoff)
{
	unsigned int		mask = mp->m_blockmask >> XFS_SUMINFOLOG;

	return rsumoff & mask;
}

/* Return a pointer to a summary info word within a rt summary block. */
static inline xfs_suminfo_t *
xfs_rsumblock_infoptr(
	struct xfs_buf		*bp,
	unsigned int		index)
{
	xfs_suminfo_t		*info = bp->b_addr;

	return info + index;
}

/*
 * Functions for walking free space rtextents in the realtime bitmap.
 */
@@ -192,6 +280,11 @@ xfs_rtfree_extent(
/* Same as above, but in units of rt blocks. */
int xfs_rtfree_blocks(struct xfs_trans *tp, xfs_fsblock_t rtbno,
		xfs_filblks_t rtlen);

xfs_filblks_t xfs_rtbitmap_blockcount(struct xfs_mount *mp, xfs_rtbxlen_t
		rtextents);
unsigned long long xfs_rtbitmap_wordcount(struct xfs_mount *mp,
		xfs_rtbxlen_t rtextents);
#else /* CONFIG_XFS_RT */
# define xfs_rtfree_extent(t,b,l)			(-ENOSYS)
# define xfs_rtfree_blocks(t,rb,rl)			(-ENOSYS)
@@ -199,6 +292,13 @@ int xfs_rtfree_blocks(struct xfs_trans *tp, xfs_fsblock_t rtbno,
# define xfs_rtalloc_query_all(m,t,f,p)			(-ENOSYS)
# define xfs_rtbuf_get(m,t,b,i,p)			(-ENOSYS)
# define xfs_rtalloc_extent_is_free(m,t,s,l,i)		(-ENOSYS)
static inline xfs_filblks_t
xfs_rtbitmap_blockcount(struct xfs_mount *mp, xfs_rtbxlen_t rtextents)
{
	/* shut up gcc */
	return 0;
}
# define xfs_rtbitmap_wordcount(mp, r)			(0)
#endif /* CONFIG_XFS_RT */

#endif /* __XFS_RTBITMAP_H__ */
+5 −4
Original line number Diff line number Diff line
@@ -218,11 +218,12 @@ xfs_rtalloc_block_count(
	struct xfs_mount	*mp,
	unsigned int		num_ops)
{
	unsigned int		blksz = XFS_FSB_TO_B(mp, 1);
	unsigned int		rtbmp_bytes;
	unsigned int		rtbmp_blocks;
	xfs_rtxlen_t		rtxlen;

	rtbmp_bytes = xfs_extlen_to_rtxlen(mp, XFS_MAX_BMBT_EXTLEN) / NBBY;
	return (howmany(rtbmp_bytes, blksz) + 1) * num_ops;
	rtxlen = xfs_extlen_to_rtxlen(mp, XFS_MAX_BMBT_EXTLEN);
	rtbmp_blocks = xfs_rtbitmap_blockcount(mp, rtxlen);
	return (rtbmp_blocks + 1) * num_ops;
}

/*
+2 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ typedef int64_t xfs_fsize_t; /* bytes in a file */
typedef uint64_t	xfs_ufsize_t;	/* unsigned bytes in a file */

typedef int32_t		xfs_suminfo_t;	/* type of bitmap summary info */
typedef uint32_t	xfs_rtsumoff_t;	/* offset of an rtsummary info word */
typedef uint32_t	xfs_rtword_t;	/* word type for bitmap manipulations */

typedef int64_t		xfs_lsn_t;	/* log sequence number */
@@ -149,6 +150,7 @@ typedef uint32_t xfs_dqid_t;
 */
#define	XFS_NBBYLOG	3		/* log2(NBBY) */
#define	XFS_WORDLOG	2		/* log2(sizeof(xfs_rtword_t)) */
#define	XFS_SUMINFOLOG	2		/* log2(sizeof(xfs_suminfo_t)) */
#define	XFS_NBWORDLOG	(XFS_NBBYLOG + XFS_WORDLOG)
#define	XFS_NBWORD	(1 << XFS_NBWORDLOG)
#define	XFS_WORDMASK	((1 << XFS_WORDLOG) - 1)
Loading