summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2022-08-17 16:08:34 -0700
committerDarrick J. Wong <djwong@kernel.org>2022-10-14 14:17:07 -0700
commit3789edffaf0eeea736d50210c842398ad602c9ca (patch)
treef19198efd4cf6a5961fb910d3ddb54894a9532cb
parentbd7439c2e3d0a8779e4225c4fdf34ba93647d8b5 (diff)
xfs: use shifting and masking when converting rt extents, if possiblerefactor-rt-unit-conversions_2022-10-14
Avoid the costs of integer division (32-bit and 64-bit) if the realtime extent size is a power of two. Signed-off-by: Darrick J. Wong <djwong@kernel.org>
-rw-r--r--fs/xfs/libxfs/xfs_rtbitmap.h20
-rw-r--r--fs/xfs/libxfs/xfs_sb.c2
-rw-r--r--fs/xfs/xfs_linux.h12
-rw-r--r--fs/xfs/xfs_mount.h2
-rw-r--r--fs/xfs/xfs_rtalloc.c1
-rw-r--r--fs/xfs/xfs_trans.c4
6 files changed, 41 insertions, 0 deletions
diff --git a/fs/xfs/libxfs/xfs_rtbitmap.h b/fs/xfs/libxfs/xfs_rtbitmap.h
index fbed9ae19c51..08463805ad87 100644
--- a/fs/xfs/libxfs/xfs_rtbitmap.h
+++ b/fs/xfs/libxfs/xfs_rtbitmap.h
@@ -11,6 +11,9 @@ xfs_rtx_to_rtb(
struct xfs_mount *mp,
xfs_rtxnum_t rtx)
{
+ if (mp->m_rtxblklog >= 0)
+ return rtx << mp->m_rtxblklog;
+
return rtx * mp->m_sb.sb_rextsize;
}
@@ -19,6 +22,9 @@ xfs_rtxlen_to_extlen(
struct xfs_mount *mp,
xfs_rtxlen_t rtxlen)
{
+ if (mp->m_rtxblklog >= 0)
+ return rtxlen << mp->m_rtxblklog;
+
return rtxlen * mp->m_sb.sb_rextsize;
}
@@ -28,6 +34,9 @@ xfs_extlen_to_rtxmod(
struct xfs_mount *mp,
xfs_extlen_t len)
{
+ if (mp->m_rtxblklog >= 0)
+ return len & mp->m_rtxblkmask;
+
return len % mp->m_sb.sb_rextsize;
}
@@ -36,6 +45,9 @@ xfs_extlen_to_rtxlen(
struct xfs_mount *mp,
xfs_extlen_t len)
{
+ if (mp->m_rtxblklog >= 0)
+ return len >> mp->m_rtxblklog;
+
return len / mp->m_sb.sb_rextsize;
}
@@ -45,6 +57,11 @@ xfs_rtb_to_rtx(
xfs_rtblock_t rtbno,
xfs_extlen_t *mod)
{
+ if (mp->m_rtxblklog >= 0) {
+ *mod = rtbno & mp->m_rtxblkmask;
+ return rtbno >> mp->m_rtxblklog;
+ }
+
return div_u64_rem(rtbno, mp->m_sb.sb_rextsize, mod);
}
@@ -53,6 +70,9 @@ xfs_rtb_to_rtxt(
struct xfs_mount *mp,
xfs_rtblock_t rtbno)
{
+ if (mp->m_rtxblklog >= 0)
+ return rtbno >> mp->m_rtxblklog;
+
return div_u64(rtbno, mp->m_sb.sb_rextsize);
}
diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
index 537221129b54..504241e51b41 100644
--- a/fs/xfs/libxfs/xfs_sb.c
+++ b/fs/xfs/libxfs/xfs_sb.c
@@ -952,6 +952,8 @@ xfs_sb_mount_common(
mp->m_blockmask = sbp->sb_blocksize - 1;
mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG;
mp->m_blockwmask = mp->m_blockwsize - 1;
+ mp->m_rtxblklog = log2_if_power2(sbp->sb_rextsize);
+ mp->m_rtxblkmask = mask64_if_power2(sbp->sb_rextsize);
mp->m_alloc_mxr[0] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, true);
mp->m_alloc_mxr[1] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, false);
diff --git a/fs/xfs/xfs_linux.h b/fs/xfs/xfs_linux.h
index 4b14cf9a750f..4f40e57531ea 100644
--- a/fs/xfs/xfs_linux.h
+++ b/fs/xfs/xfs_linux.h
@@ -198,6 +198,18 @@ static inline bool isaligned_64(uint64_t x, uint32_t y)
return do_div(x, y) == 0;
}
+/* If @b is a power of 2, return log2(b). Else return -1. */
+static inline int8_t log2_if_power2(unsigned long b)
+{
+ return is_power_of_2(b) ? ilog2(b) : -1;
+}
+
+/* If @b is a power of 2, return a mask of the lower bits, else return zero. */
+static inline unsigned long long mask64_if_power2(unsigned long b)
+{
+ return is_power_of_2(b) ? b - 1 : 0;
+}
+
int xfs_rw_bdev(struct block_device *bdev, sector_t sector, unsigned int count,
char *data, enum req_op op);
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 3254ceb71424..6d0d57480577 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -245,6 +245,7 @@ typedef struct xfs_mount {
uint8_t m_blkbb_log; /* blocklog - BBSHIFT */
uint8_t m_agno_log; /* log #ag's */
uint8_t m_sectbb_log; /* sectlog - BBSHIFT */
+ int8_t m_rtxblklog; /* log2 of rextsize, if possible */
uint m_blockmask; /* sb_blocksize-1 */
uint m_blockwsize; /* sb_blocksize in words */
uint m_blockwmask; /* blockwsize-1 */
@@ -278,6 +279,7 @@ typedef struct xfs_mount {
uint64_t m_features; /* active filesystem features */
uint64_t m_low_space[XFS_LOWSP_MAX];
uint64_t m_low_rtexts[XFS_LOWSP_MAX];
+ uint64_t m_rtxblkmask; /* rt extent block mask */
struct xfs_ino_geometry m_ino_geo; /* inode geometry */
struct xfs_trans_resv m_resv; /* precomputed res values */
/* low free space thresholds */
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index b74ba5e51cf8..3573dfef5dd7 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -1052,6 +1052,7 @@ xfs_growfs_rt(
* Calculate new sb and mount fields for this round.
*/
nsbp->sb_rextsize = in->extsize;
+ nmp->m_rtxblklog = -1; /* don't use shift or masking */
nsbp->sb_rbmblocks = bmbno + 1;
nrblocks_step = (bmbno + 1) * NBBY * nsbp->sb_blocksize *
nsbp->sb_rextsize;
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 3e81826c9a0a..f39c5daeef86 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -710,6 +710,10 @@ xfs_trans_unreserve_and_mod_sb(
mp->m_sb.sb_agcount += tp->t_agcount_delta;
mp->m_sb.sb_imax_pct += tp->t_imaxpct_delta;
mp->m_sb.sb_rextsize += tp->t_rextsize_delta;
+ if (tp->t_rextsize_delta) {
+ mp->m_rtxblklog = log2_if_power2(mp->m_sb.sb_rextsize);
+ mp->m_rtxblkmask = mask64_if_power2(mp->m_sb.sb_rextsize);
+ }
mp->m_sb.sb_rbmblocks += tp->t_rbmblocks_delta;
mp->m_sb.sb_rblocks += tp->t_rblocks_delta;
mp->m_sb.sb_rextents += tp->t_rextents_delta;