On Wed, Jul 12, 2023 at 11:29:26AM -0700, Darrick J. Wong wrote: > On Tue, Jun 20, 2023 at 02:32:11PM -0700, Omar Sandoval wrote: > > From: Omar Sandoval <osandov@xxxxxx> > > > > Profiling a workload on a highly fragmented realtime device showed a ton > > of CPU cycles being spent in xfs_trans_read_buf() called by > > xfs_rtbuf_get(). Further tracing showed that much of that was repeated > > calls to xfs_rtbuf_get() for the same block of the realtime bitmap. > > These come from xfs_rtallocate_extent_block(): as it walks through > > ranges of free bits in the bitmap, each call to xfs_rtcheck_range() and > > xfs_rtfind_{forw,back}() gets the same bitmap block. If the bitmap block > > is very fragmented, then this is _a lot_ of buffer lookups. > > > > The realtime allocator already passes around a cache of the last used > > realtime summary block to avoid repeated reads (the parameters rbpp and > > rsb). We can do the same for the realtime bitmap. > > > > This replaces rbpp and rsb with a struct xfs_rtbuf_cache, which caches > > the most recently used block for both the realtime bitmap and summary. > > xfs_rtbuf_get() now handles the caching instead of the callers, which > > requires plumbing xfs_rtbuf_cache to more functions but also makes sure > > we don't miss anything. > > Hmm. I initially wondered why rtbitmap blocks wouldn't just stay > attached to the transaction, but then I realized -- this is the > /scanning/ phase that's repeatedly getting and releasing the rtbmp > block, right? The allocator hasn't dirtied any rtbitmap blocks yet, so > each xfs_trans_brelse actually drops the buffer, and that's how the > xfs_rtbuf_get ends up pounding on the bmapi and then the buffer cache? > Repeatedly? That's right. > > Signed-off-by: Omar Sandoval <osandov@xxxxxx> > > --- > > fs/xfs/libxfs/xfs_rtbitmap.c | 167 ++++++++++++++++++----------------- > > fs/xfs/xfs_rtalloc.c | 107 ++++++++++------------ > > fs/xfs/xfs_rtalloc.h | 28 ++++-- > > 3 files changed, 154 insertions(+), 148 deletions(-) > > > > diff --git a/fs/xfs/libxfs/xfs_rtbitmap.c b/fs/xfs/libxfs/xfs_rtbitmap.c > > index fa180ab66b73..1a832c9a412f 100644 > > --- a/fs/xfs/libxfs/xfs_rtbitmap.c > > +++ b/fs/xfs/libxfs/xfs_rtbitmap.c > > @@ -46,6 +46,21 @@ const struct xfs_buf_ops xfs_rtbuf_ops = { > > .verify_write = xfs_rtbuf_verify_write, > > }; > > > > +static void > > +xfs_rtbuf_cache_relse( > > + xfs_trans_t *tp, /* transaction pointer */ > > Please don't introduce more typedef usage. Oops, I was just copying the surrounding code. I'll fix this in my changes. > struct xfs_trans *tp, > struct xfs_rtbuf_cache *cache) > > (Also there's a lot of broken indenting in the lines added by this > patch.) I'll fix it in this new function. Should I also be reindenting all of the parameter lists where I added this parameter? > > + struct xfs_rtbuf_cache *cache) /* cached blocks */ > > +{ > > + if (cache->bbuf) { > > + xfs_trans_brelse(tp, cache->bbuf); > > + cache->bbuf = NULL; > > + } > > + if (cache->sbuf) { > > + xfs_trans_brelse(tp, cache->sbuf); > > + cache->sbuf = NULL; > > + } > > +} > > + > > /* > > * Get a buffer for the bitmap or summary file block specified. > > * The buffer is returned read and locked. > > @@ -56,14 +71,35 @@ xfs_rtbuf_get( > > xfs_trans_t *tp, /* transaction pointer */ > > xfs_rtblock_t block, /* block number in bitmap or summary */ > > int issum, /* is summary not bitmap */ > > + struct xfs_rtbuf_cache *cache, /* in/out: cached blocks */ > > struct xfs_buf **bpp) /* output: buffer for the block */ > > { > > + struct xfs_buf **cbpp; /* cached block buffer */ > > + xfs_fsblock_t *cbp; /* cached block number */ > > struct xfs_buf *bp; /* block buffer, result */ > > xfs_inode_t *ip; /* bitmap or summary inode */ > > xfs_bmbt_irec_t map; > > int nmap = 1; > > int error; /* error value */ > > > > + cbpp = issum ? &cache->bbuf : &cache->sbuf; > > + cbp = issum ? &cache->bblock : &cache->sblock; > > + /* > > + * If we have a cached buffer, and the block number matches, use that. > > + */ > > + if (*cbpp && *cbp == block) { > > + *bpp = *cbpp; > > + return 0; > > + } > > + /* > > + * 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(tp, *cbpp); > > + *cbpp = NULL; > > + } > > + > > ip = issum ? mp->m_rsumip : mp->m_rbmip; > > > > error = xfs_bmapi_read(ip, block, 1, &map, &nmap, 0); > > @@ -82,7 +118,8 @@ xfs_rtbuf_get( > > > > xfs_trans_buf_set_type(tp, bp, issum ? XFS_BLFT_RTSUMMARY_BUF > > : XFS_BLFT_RTBITMAP_BUF); > > - *bpp = bp; > > + *cbpp = *bpp = bp; > > + *cbp = block; > > return 0; > > } > > > > @@ -96,6 +133,7 @@ xfs_rtfind_back( > > xfs_trans_t *tp, /* transaction pointer */ > > xfs_rtblock_t start, /* starting block to look at */ > > xfs_rtblock_t limit, /* last block to look at */ > > + struct xfs_rtbuf_cache *rtbufc, /* in/out: cache of realtime blocks */ > > xfs_rtblock_t *rtblock) /* out: start block found */ > > { > > xfs_rtword_t *b; /* current word in buffer */ > > @@ -116,7 +154,7 @@ xfs_rtfind_back( > > * Compute and read in starting bitmap block for starting block. > > */ > > block = XFS_BITTOBLOCK(mp, start); > > - error = xfs_rtbuf_get(mp, tp, block, 0, &bp); > > + error = xfs_rtbuf_get(mp, tp, block, 0, rtbufc, &bp); > > if (error) { > > return error; > > } > > @@ -153,7 +191,6 @@ xfs_rtfind_back( > > /* > > * Different. Mark where we are and return. > > */ > > - xfs_trans_brelse(tp, bp); > > i = bit - XFS_RTHIBIT(wdiff); > > *rtblock = start - i + 1; > > return 0; > > @@ -167,8 +204,7 @@ 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); > > + error = xfs_rtbuf_get(mp, tp, --block, 0, rtbufc, &bp); > > if (error) { > > return error; > > } > > @@ -199,7 +235,6 @@ xfs_rtfind_back( > > /* > > * Different, mark where we are and return. > > */ > > - xfs_trans_brelse(tp, bp); > > i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff); > > *rtblock = start - i + 1; > > return 0; > > @@ -213,8 +248,7 @@ 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); > > + error = xfs_rtbuf_get(mp, tp, --block, 0, rtbufc, &bp); > > if (error) { > > return error; > > } > > @@ -246,7 +280,6 @@ xfs_rtfind_back( > > /* > > * Different, mark where we are and return. > > */ > > - xfs_trans_brelse(tp, bp); > > i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff); > > *rtblock = start - i + 1; > > return 0; > > @@ -256,7 +289,6 @@ xfs_rtfind_back( > > /* > > * No match, return that we scanned the whole area. > > */ > > - xfs_trans_brelse(tp, bp); > > *rtblock = start - i + 1; > > return 0; > > } > > @@ -271,6 +303,7 @@ xfs_rtfind_forw( > > xfs_trans_t *tp, /* transaction pointer */ > > xfs_rtblock_t start, /* starting block to look at */ > > xfs_rtblock_t limit, /* last block to look at */ > > + struct xfs_rtbuf_cache *rtbufc, /* in/out: cache of realtime blocks */ > > xfs_rtblock_t *rtblock) /* out: start block found */ > > { > > xfs_rtword_t *b; /* current word in buffer */ > > @@ -291,7 +324,7 @@ xfs_rtfind_forw( > > * Compute and read in starting bitmap block for starting block. > > */ > > block = XFS_BITTOBLOCK(mp, start); > > - error = xfs_rtbuf_get(mp, tp, block, 0, &bp); > > + error = xfs_rtbuf_get(mp, tp, block, 0, rtbufc, &bp); > > if (error) { > > return error; > > } > > @@ -327,7 +360,6 @@ xfs_rtfind_forw( > > /* > > * Different. Mark where we are and return. > > */ > > - xfs_trans_brelse(tp, bp); > > i = XFS_RTLOBIT(wdiff) - bit; > > *rtblock = start + i - 1; > > return 0; > > @@ -341,8 +373,7 @@ 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); > > + error = xfs_rtbuf_get(mp, tp, ++block, 0, rtbufc, &bp); > > if (error) { > > return error; > > } > > @@ -372,7 +403,6 @@ xfs_rtfind_forw( > > /* > > * Different, mark where we are and return. > > */ > > - xfs_trans_brelse(tp, bp); > > i += XFS_RTLOBIT(wdiff); > > *rtblock = start + i - 1; > > return 0; > > @@ -386,8 +416,7 @@ 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); > > + error = xfs_rtbuf_get(mp, tp, ++block, 0, rtbufc, &bp); > > if (error) { > > return error; > > } > > @@ -416,7 +445,6 @@ xfs_rtfind_forw( > > /* > > * Different, mark where we are and return. > > */ > > - xfs_trans_brelse(tp, bp); > > i += XFS_RTLOBIT(wdiff); > > *rtblock = start + i - 1; > > return 0; > > @@ -426,7 +454,6 @@ xfs_rtfind_forw( > > /* > > * No match, return that we scanned the whole area. > > */ > > - xfs_trans_brelse(tp, bp); > > *rtblock = start + i - 1; > > return 0; > > } > > @@ -447,8 +474,7 @@ xfs_rtmodify_summary_int( > > int log, /* log2 of extent size */ > > xfs_rtblock_t bbno, /* bitmap block number */ > > int delta, /* change to make to summary info */ > > - struct xfs_buf **rbpp, /* in/out: summary block buffer */ > > - xfs_fsblock_t *rsb, /* in/out: summary block number */ > > + struct xfs_rtbuf_cache *rtbufc, /* in/out: cache of realtime blocks */ > > xfs_suminfo_t *sum) /* out: summary info for this block */ > > { > > struct xfs_buf *bp; /* buffer for the summary block */ > > @@ -465,30 +491,9 @@ xfs_rtmodify_summary_int( > > * Compute the block number in the summary file. > > */ > > sb = XFS_SUMOFFSTOBLOCK(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) { > > - return error; > > - } > > - /* > > - * Remember this buffer and block for the next call. > > - */ > > - *rbpp = bp; > > - *rsb = sb; > > - } > > + error = xfs_rtbuf_get(mp, tp, sb, 1, rtbufc, &bp); > > + if (error) > > + return error; > > /* > > * Point to the summary information, modify/log it, and/or copy it out. > > */ > > @@ -517,11 +522,9 @@ xfs_rtmodify_summary( > > int log, /* log2 of extent size */ > > xfs_rtblock_t bbno, /* bitmap block number */ > > int delta, /* change to make to summary info */ > > - struct xfs_buf **rbpp, /* in/out: summary block buffer */ > > - xfs_fsblock_t *rsb) /* in/out: summary block number */ > > + struct xfs_rtbuf_cache *rtbufc) /* in/out: cache of realtime blocks */ > > { > > - return xfs_rtmodify_summary_int(mp, tp, log, bbno, > > - delta, rbpp, rsb, NULL); > > + return xfs_rtmodify_summary_int(mp, tp, log, bbno, delta, rtbufc, NULL); > > } > > > > /* > > @@ -534,7 +537,8 @@ xfs_rtmodify_range( > > xfs_trans_t *tp, /* transaction pointer */ > > xfs_rtblock_t start, /* starting block to modify */ > > xfs_extlen_t len, /* length of extent to modify */ > > - int val) /* 1 for free, 0 for allocated */ > > + int val, /* 1 for free, 0 for allocated */ > > + struct xfs_rtbuf_cache *rtbufc) /* in/out: cache of realtime blocks */ > > { > > xfs_rtword_t *b; /* current word in buffer */ > > int bit; /* bit number in the word */ > > @@ -555,7 +559,7 @@ xfs_rtmodify_range( > > /* > > * Read the bitmap block, and point to its data. > > */ > > - error = xfs_rtbuf_get(mp, tp, block, 0, &bp); > > + error = xfs_rtbuf_get(mp, tp, block, 0, rtbufc, &bp); > > if (error) { > > return error; > > } > > @@ -600,7 +604,7 @@ xfs_rtmodify_range( > > xfs_trans_log_buf(tp, bp, > > (uint)((char *)first - (char *)bufp), > > (uint)((char *)b - (char *)bufp)); > > - error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); > > + error = xfs_rtbuf_get(mp, tp, ++block, 0, rtbufc, &bp); > > if (error) { > > return error; > > } > > @@ -640,7 +644,7 @@ xfs_rtmodify_range( > > xfs_trans_log_buf(tp, bp, > > (uint)((char *)first - (char *)bufp), > > (uint)((char *)b - (char *)bufp)); > > - error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); > > + error = xfs_rtbuf_get(mp, tp, ++block, 0, rtbufc, &bp); > > if (error) { > > return error; > > } > > @@ -690,8 +694,7 @@ xfs_rtfree_range( > > xfs_trans_t *tp, /* transaction pointer */ > > xfs_rtblock_t start, /* starting block to free */ > > xfs_extlen_t len, /* length to free */ > > - struct xfs_buf **rbpp, /* in/out: summary block buffer */ > > - xfs_fsblock_t *rsb) /* in/out: summary block number */ > > + struct xfs_rtbuf_cache *rtbufc) /* in/out: cache of realtime blocks */ > > { > > xfs_rtblock_t end; /* end of the freed extent */ > > int error; /* error value */ > > @@ -702,7 +705,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(mp, tp, start, len, 1, rtbufc); > > if (error) { > > return error; > > } > > @@ -711,7 +714,7 @@ 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(mp, tp, start, 0, rtbufc, &preblock); > > if (error) { > > return error; > > } > > @@ -719,7 +722,7 @@ xfs_rtfree_range( > > * Find the next allocated block (end of allocated extent). > > */ > > error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1, > > - &postblock); > > + rtbufc, &postblock); > > if (error) > > return error; > > /* > > @@ -729,7 +732,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_BITTOBLOCK(mp, preblock), -1, rtbufc); > > if (error) { > > return error; > > } > > @@ -741,7 +744,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_BITTOBLOCK(mp, end + 1), -1, rtbufc); > > if (error) { > > return error; > > } > > @@ -752,7 +755,7 @@ xfs_rtfree_range( > > */ > > error = xfs_rtmodify_summary(mp, tp, > > XFS_RTBLOCKLOG(postblock + 1 - preblock), > > - XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb); > > + XFS_BITTOBLOCK(mp, preblock), 1, rtbufc); > > return error; > > } > > > > @@ -767,6 +770,7 @@ xfs_rtcheck_range( > > xfs_rtblock_t start, /* starting block number of extent */ > > xfs_extlen_t len, /* length of extent */ > > int val, /* 1 for free, 0 for allocated */ > > + struct xfs_rtbuf_cache *rtbufc, /* in/out: cache of realtime blocks */ > > xfs_rtblock_t *new, /* out: first block not matching */ > > int *stat) /* out: 1 for matches, 0 for not */ > > { > > @@ -789,7 +793,7 @@ xfs_rtcheck_range( > > /* > > * Read the bitmap block. > > */ > > - error = xfs_rtbuf_get(mp, tp, block, 0, &bp); > > + error = xfs_rtbuf_get(mp, tp, block, 0, rtbufc, &bp); > > if (error) { > > return error; > > } > > @@ -824,7 +828,6 @@ xfs_rtcheck_range( > > /* > > * Different, compute first wrong bit and return. > > */ > > - xfs_trans_brelse(tp, bp); > > i = XFS_RTLOBIT(wdiff) - bit; > > *new = start + i; > > *stat = 0; > > @@ -839,8 +842,7 @@ 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); > > + error = xfs_rtbuf_get(mp, tp, ++block, 0, rtbufc, &bp); > > if (error) { > > return error; > > } > > @@ -870,7 +872,6 @@ xfs_rtcheck_range( > > /* > > * Different, compute first wrong bit and return. > > */ > > - xfs_trans_brelse(tp, bp); > > i += XFS_RTLOBIT(wdiff); > > *new = start + i; > > *stat = 0; > > @@ -885,8 +886,7 @@ 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); > > + error = xfs_rtbuf_get(mp, tp, ++block, 0, rtbufc, &bp); > > if (error) { > > return error; > > } > > @@ -915,7 +915,6 @@ xfs_rtcheck_range( > > /* > > * Different, compute first wrong bit and return. > > */ > > - xfs_trans_brelse(tp, bp); > > i += XFS_RTLOBIT(wdiff); > > *new = start + i; > > *stat = 0; > > @@ -926,7 +925,6 @@ xfs_rtcheck_range( > > /* > > * Successful, return. > > */ > > - xfs_trans_brelse(tp, bp); > > *new = start + i; > > *stat = 1; > > return 0; > > @@ -941,20 +939,21 @@ xfs_rtcheck_alloc_range( > > xfs_mount_t *mp, /* file system mount point */ > > xfs_trans_t *tp, /* transaction pointer */ > > xfs_rtblock_t bno, /* starting block number of extent */ > > - xfs_extlen_t len) /* length of extent */ > > + xfs_extlen_t len, /* length of extent */ > > + struct xfs_rtbuf_cache *rtbufc) /* in/out: cached blocks */ > > { > > xfs_rtblock_t new; /* dummy for xfs_rtcheck_range */ > > int stat; > > int error; > > > > - error = xfs_rtcheck_range(mp, tp, bno, len, 0, &new, &stat); > > + error = xfs_rtcheck_range(mp, tp, bno, len, 0, rtbufc, &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(m,t,b,l,r) (0) > > #endif > > /* > > * Free an extent in the realtime subvolume. Length is expressed in > > @@ -968,22 +967,21 @@ xfs_rtfree_extent( > > { > > 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 */ > > + struct xfs_rtbuf_cache rtbufc = {}; /* cache of realtime blocks */ > > > > mp = tp->t_mountp; > > > > ASSERT(mp->m_rbmip->i_itemp != NULL); > > ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL)); > > > > - error = xfs_rtcheck_alloc_range(mp, tp, bno, len); > > + error = xfs_rtcheck_alloc_range(mp, tp, bno, len, &rtbufc); > > if (error) > > return error; > > > > /* > > * Free the range of realtime blocks. > > */ > > - error = xfs_rtfree_range(mp, tp, bno, len, &sumbp, &sb); > > + error = xfs_rtfree_range(mp, tp, bno, len, &rtbufc); > > if (error) { > > return error; > > } > > @@ -1021,6 +1019,7 @@ xfs_rtalloc_query_range( > > xfs_rtblock_t high_key; > > int is_free; > > int error = 0; > > + struct xfs_rtbuf_cache rtbufc = {}; > > > > if (low_rec->ar_startext > high_rec->ar_startext) > > return -EINVAL; > > @@ -1034,13 +1033,14 @@ 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, > > - &is_free); > > + error = xfs_rtcheck_range(mp, tp, rtstart, 1, 1, &rtbufc, > > + &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(mp, tp, rtstart, high_key, &rtbufc, > > + &rtend); > > if (error) > > break; > > > > @@ -1056,6 +1056,8 @@ xfs_rtalloc_query_range( > > rtstart = rtend + 1; > > } > > > > + xfs_rtbuf_cache_relse(tp, &rtbufc); > > + > > return error; > > } > > > > @@ -1085,11 +1087,14 @@ xfs_rtalloc_extent_is_free( > > xfs_extlen_t len, > > bool *is_free) > > { > > + struct xfs_rtbuf_cache rtbufc = {}; > > xfs_rtblock_t end; > > int matches; > > int error; > > > > - error = xfs_rtcheck_range(mp, tp, start, len, 1, &end, &matches); > > + error = xfs_rtcheck_range(mp, tp, start, len, 1, &rtbufc, &end, > > + &matches); > > + xfs_rtbuf_cache_relse(tp, &rtbufc); > > if (error) > > return error; > > > > diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c > > index 16534e9873f6..61ef13286654 100644 > > --- a/fs/xfs/xfs_rtalloc.c > > +++ b/fs/xfs/xfs_rtalloc.c > > @@ -32,11 +32,10 @@ xfs_rtget_summary( > > xfs_trans_t *tp, /* transaction pointer */ > > int log, /* log2 of extent size */ > > xfs_rtblock_t bbno, /* bitmap block number */ > > - struct xfs_buf **rbpp, /* in/out: summary block buffer */ > > - xfs_fsblock_t *rsb, /* in/out: summary block number */ > > + struct xfs_rtbuf_cache *rtbufc, /* in/out: cache of realtime blocks */ > > xfs_suminfo_t *sum) /* out: summary info for this block */ > > { > > - return xfs_rtmodify_summary_int(mp, tp, log, bbno, 0, rbpp, rsb, sum); > > + return xfs_rtmodify_summary_int(mp, tp, log, bbno, 0, rtbufc, sum); > > } > > > > /* > > @@ -50,8 +49,7 @@ xfs_rtany_summary( > > int low, /* low log2 extent size */ > > int high, /* high log2 extent size */ > > xfs_rtblock_t bbno, /* bitmap block number */ > > - struct xfs_buf **rbpp, /* in/out: summary block buffer */ > > - xfs_fsblock_t *rsb, /* in/out: summary block number */ > > + struct xfs_rtbuf_cache *rtbufc, /* in/out: cache of realtime blocks */ > > int *stat) /* out: any good extents here? */ > > { > > int error; /* error value */ > > @@ -69,7 +67,7 @@ xfs_rtany_summary( > > /* > > * Get one summary datum. > > */ > > - error = xfs_rtget_summary(mp, tp, log, bbno, rbpp, rsb, &sum); > > + error = xfs_rtget_summary(mp, tp, log, bbno, rtbufc, &sum); > > if (error) { > > return error; > > } > > @@ -104,29 +102,27 @@ xfs_rtcopy_summary( > > xfs_trans_t *tp) /* transaction pointer */ > > { > > xfs_rtblock_t bbno; /* bitmap block number */ > > - struct xfs_buf *bp; /* summary buffer */ > > + struct xfs_rtbuf_cache rtbufc = {}; /* cache of realtime blocks */ > > int error; /* error return value */ > > int log; /* summary level number (log length) */ > > xfs_suminfo_t sum; /* summary data */ > > - xfs_fsblock_t sumbno; /* summary block number */ > > > > - bp = NULL; > > for (log = omp->m_rsumlevels - 1; log >= 0; log--) { > > for (bbno = omp->m_sb.sb_rbmblocks - 1; > > (xfs_srtblock_t)bbno >= 0; > > bbno--) { > > - error = xfs_rtget_summary(omp, tp, log, bbno, &bp, > > - &sumbno, &sum); > > + error = xfs_rtget_summary(omp, tp, log, bbno, &rtbufc, > > + &sum); > > if (error) > > return error; > > if (sum == 0) > > continue; > > error = xfs_rtmodify_summary(omp, tp, log, bbno, -sum, > > - &bp, &sumbno); > > + &rtbufc); > > if (error) > > return error; > > error = xfs_rtmodify_summary(nmp, tp, log, bbno, sum, > > - &bp, &sumbno); > > + &rtbufc); > > if (error) > > return error; > > ASSERT(sum > 0); > > @@ -144,8 +140,7 @@ xfs_rtallocate_range( > > xfs_trans_t *tp, /* transaction pointer */ > > xfs_rtblock_t start, /* start block to allocate */ > > xfs_extlen_t len, /* length to allocate */ > > - struct xfs_buf **rbpp, /* in/out: summary block buffer */ > > - xfs_fsblock_t *rsb) /* in/out: summary block number */ > > + struct xfs_rtbuf_cache *rtbufc) /* in/out: cache of realtime blocks */ > > { > > xfs_rtblock_t end; /* end of the allocated extent */ > > int error; /* error value */ > > @@ -158,14 +153,14 @@ xfs_rtallocate_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(mp, tp, start, 0, rtbufc, &preblock); > > if (error) { > > return error; > > } > > /* > > * Find the next allocated block (end of free extent). > > */ > > - error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1, > > + error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1, rtbufc, > > &postblock); > > if (error) { > > return error; > > @@ -176,7 +171,7 @@ xfs_rtallocate_range( > > */ > > error = xfs_rtmodify_summary(mp, tp, > > XFS_RTBLOCKLOG(postblock + 1 - preblock), > > - XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb); > > + XFS_BITTOBLOCK(mp, preblock), -1, rtbufc); > > if (error) { > > return error; > > } > > @@ -187,7 +182,7 @@ xfs_rtallocate_range( > > if (preblock < start) { > > error = xfs_rtmodify_summary(mp, tp, > > XFS_RTBLOCKLOG(start - preblock), > > - XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb); > > + XFS_BITTOBLOCK(mp, preblock), 1, rtbufc); > > if (error) { > > return error; > > } > > @@ -199,7 +194,7 @@ xfs_rtallocate_range( > > if (postblock > end) { > > error = xfs_rtmodify_summary(mp, tp, > > XFS_RTBLOCKLOG(postblock - end), > > - XFS_BITTOBLOCK(mp, end + 1), 1, rbpp, rsb); > > + XFS_BITTOBLOCK(mp, end + 1), 1, rtbufc); > > if (error) { > > return error; > > } > > @@ -207,7 +202,7 @@ xfs_rtallocate_range( > > /* > > * Modify the bitmap to mark this extent allocated. > > */ > > - error = xfs_rtmodify_range(mp, tp, start, len, 0); > > + error = xfs_rtmodify_range(mp, tp, start, len, 0, rtbufc); > > return error; > > } > > > > @@ -226,8 +221,7 @@ xfs_rtallocate_extent_block( > > xfs_extlen_t maxlen, /* maximum length to allocate */ > > xfs_extlen_t *len, /* out: actual length allocated */ > > xfs_rtblock_t *nextp, /* out: next block to try */ > > - struct xfs_buf **rbpp, /* in/out: summary block buffer */ > > - xfs_fsblock_t *rsb, /* in/out: summary block number */ > > + struct xfs_rtbuf_cache *rtbufc, /* in/out: cache of realtime blocks */ > > xfs_extlen_t prod, /* extent product factor */ > > xfs_rtblock_t *rtblock) /* out: start block allocated */ > > { > > @@ -254,7 +248,8 @@ xfs_rtallocate_extent_block( > > * See if there's a free extent of maxlen starting at i. > > * If it's not so then next will contain the first non-free. > > */ > > - error = xfs_rtcheck_range(mp, tp, i, maxlen, 1, &next, &stat); > > + error = xfs_rtcheck_range(mp, tp, i, maxlen, 1, rtbufc, &next, > > + &stat); > > if (error) { > > return error; > > } > > @@ -262,8 +257,7 @@ xfs_rtallocate_extent_block( > > /* > > * i for maxlen is all free, allocate and return that. > > */ > > - error = xfs_rtallocate_range(mp, tp, i, maxlen, rbpp, > > - rsb); > > + error = xfs_rtallocate_range(mp, tp, i, maxlen, rtbufc); > > if (error) { > > return error; > > } > > @@ -290,7 +284,7 @@ xfs_rtallocate_extent_block( > > * If not done yet, find the start of the next free space. > > */ > > if (next < end) { > > - error = xfs_rtfind_forw(mp, tp, next, end, &i); > > + error = xfs_rtfind_forw(mp, tp, next, end, rtbufc, &i); > > if (error) { > > return error; > > } > > @@ -315,7 +309,7 @@ xfs_rtallocate_extent_block( > > /* > > * Allocate besti for bestlen & return that. > > */ > > - error = xfs_rtallocate_range(mp, tp, besti, bestlen, rbpp, rsb); > > + error = xfs_rtallocate_range(mp, tp, besti, bestlen, rtbufc); > > if (error) { > > return error; > > } > > @@ -344,9 +338,8 @@ xfs_rtallocate_extent_exact( > > xfs_rtblock_t bno, /* starting block number to allocate */ > > xfs_extlen_t minlen, /* minimum length to allocate */ > > xfs_extlen_t maxlen, /* maximum length to allocate */ > > + struct xfs_rtbuf_cache *rtbufc, /* in/out: cache of realtime blocks */ > > xfs_extlen_t *len, /* out: actual length allocated */ > > - struct xfs_buf **rbpp, /* in/out: summary block buffer */ > > - xfs_fsblock_t *rsb, /* in/out: summary block number */ > > xfs_extlen_t prod, /* extent product factor */ > > xfs_rtblock_t *rtblock) /* out: start block allocated */ > > { > > @@ -359,7 +352,8 @@ xfs_rtallocate_extent_exact( > > /* > > * Check if the range in question (for maxlen) is free. > > */ > > - error = xfs_rtcheck_range(mp, tp, bno, maxlen, 1, &next, &isfree); > > + error = xfs_rtcheck_range(mp, tp, bno, maxlen, 1, rtbufc, &next, > > + &isfree); > > if (error) { > > return error; > > } > > @@ -367,7 +361,7 @@ xfs_rtallocate_extent_exact( > > /* > > * If it is, allocate it and return success. > > */ > > - error = xfs_rtallocate_range(mp, tp, bno, maxlen, rbpp, rsb); > > + error = xfs_rtallocate_range(mp, tp, bno, maxlen, rtbufc); > > if (error) { > > return error; > > } > > @@ -402,7 +396,7 @@ xfs_rtallocate_extent_exact( > > /* > > * Allocate what we can and return it. > > */ > > - error = xfs_rtallocate_range(mp, tp, bno, maxlen, rbpp, rsb); > > + error = xfs_rtallocate_range(mp, tp, bno, maxlen, rtbufc); > > if (error) { > > return error; > > } > > @@ -424,8 +418,7 @@ xfs_rtallocate_extent_near( > > xfs_extlen_t minlen, /* minimum length to allocate */ > > xfs_extlen_t maxlen, /* maximum length to allocate */ > > xfs_extlen_t *len, /* out: actual length allocated */ > > - struct xfs_buf **rbpp, /* in/out: summary block buffer */ > > - xfs_fsblock_t *rsb, /* in/out: summary block number */ > > + struct xfs_rtbuf_cache *rtbufc, /* in/out: cache of realtime blocks */ > > xfs_extlen_t prod, /* extent product factor */ > > xfs_rtblock_t *rtblock) /* out: start block allocated */ > > { > > @@ -456,8 +449,8 @@ xfs_rtallocate_extent_near( > > /* > > * Try the exact allocation first. > > */ > > - error = xfs_rtallocate_extent_exact(mp, tp, bno, minlen, maxlen, len, > > - rbpp, rsb, prod, &r); > > + error = xfs_rtallocate_extent_exact(mp, tp, bno, minlen, maxlen, rtbufc, > > + len, prod, &r); > > if (error) { > > return error; > > } > > @@ -481,7 +474,7 @@ xfs_rtallocate_extent_near( > > * starting in this bitmap block. > > */ > > error = xfs_rtany_summary(mp, tp, log2len, mp->m_rsumlevels - 1, > > - bbno + i, rbpp, rsb, &any); > > + bbno + i, rtbufc, &any); > > if (error) { > > return error; > > } > > @@ -499,8 +492,8 @@ xfs_rtallocate_extent_near( > > * this block. > > */ > > error = xfs_rtallocate_extent_block(mp, tp, > > - bbno + i, minlen, maxlen, len, &n, rbpp, > > - rsb, prod, &r); > > + bbno + i, minlen, maxlen, len, &n, > > + rtbufc, prod, &r); > > if (error) { > > return error; > > } > > @@ -529,7 +522,7 @@ xfs_rtallocate_extent_near( > > */ > > error = xfs_rtany_summary(mp, tp, > > log2len, mp->m_rsumlevels - 1, > > - bbno + j, rbpp, rsb, &any); > > + bbno + j, rtbufc, &any); > > if (error) { > > return error; > > } > > @@ -545,7 +538,7 @@ xfs_rtallocate_extent_near( > > continue; > > error = xfs_rtallocate_extent_block(mp, > > tp, bbno + j, minlen, maxlen, > > - len, &n, rbpp, rsb, prod, &r); > > + len, &n, rtbufc, prod, &r); > > if (error) { > > return error; > > } > > @@ -566,8 +559,8 @@ xfs_rtallocate_extent_near( > > * that we found. > > */ > > error = xfs_rtallocate_extent_block(mp, tp, > > - bbno + i, minlen, maxlen, len, &n, rbpp, > > - rsb, prod, &r); > > + bbno + i, minlen, maxlen, len, &n, > > + rtbufc, prod, &r); > > if (error) { > > return error; > > } > > @@ -626,8 +619,7 @@ xfs_rtallocate_extent_size( > > xfs_extlen_t minlen, /* minimum length to allocate */ > > xfs_extlen_t maxlen, /* maximum length to allocate */ > > xfs_extlen_t *len, /* out: actual length allocated */ > > - struct xfs_buf **rbpp, /* in/out: summary block buffer */ > > - xfs_fsblock_t *rsb, /* in/out: summary block number */ > > + struct xfs_rtbuf_cache *rtbufc, /* in/out: cache of realtime blocks */ > > xfs_extlen_t prod, /* extent product factor */ > > xfs_rtblock_t *rtblock) /* out: start block allocated */ > > { > > @@ -656,7 +648,7 @@ xfs_rtallocate_extent_size( > > /* > > * Get the summary for this level/block. > > */ > > - error = xfs_rtget_summary(mp, tp, l, i, rbpp, rsb, > > + error = xfs_rtget_summary(mp, tp, l, i, rtbufc, > > &sum); > > if (error) { > > return error; > > @@ -670,7 +662,7 @@ xfs_rtallocate_extent_size( > > * Try allocating the extent. > > */ > > error = xfs_rtallocate_extent_block(mp, tp, i, maxlen, > > - maxlen, len, &n, rbpp, rsb, prod, &r); > > + maxlen, len, &n, rtbufc, prod, &r); > > if (error) { > > return error; > > } > > @@ -715,7 +707,7 @@ xfs_rtallocate_extent_size( > > /* > > * Get the summary information for this level/block. > > */ > > - error = xfs_rtget_summary(mp, tp, l, i, rbpp, rsb, > > + error = xfs_rtget_summary(mp, tp, l, i, rtbufc, > > &sum); > > if (error) { > > return error; > > @@ -733,7 +725,7 @@ xfs_rtallocate_extent_size( > > error = xfs_rtallocate_extent_block(mp, tp, i, > > XFS_RTMAX(minlen, 1 << l), > > XFS_RTMIN(maxlen, (1 << (l + 1)) - 1), > > - len, &n, rbpp, rsb, prod, &r); > > + len, &n, rtbufc, prod, &r); > > if (error) { > > return error; > > } > > @@ -922,7 +914,6 @@ xfs_growfs_rt( > > xfs_extlen_t rbmblocks; /* current number of rt bitmap blocks */ > > xfs_extlen_t rsumblocks; /* current number of rt summary blks */ > > xfs_sb_t *sbp; /* old superblock */ > > - xfs_fsblock_t sumbno; /* summary block number */ > > uint8_t *rsum_cache; /* old summary cache */ > > > > sbp = &mp->m_sb; > > @@ -1025,6 +1016,7 @@ xfs_growfs_rt( > > bmbno++) { > > struct xfs_trans *tp; > > xfs_rfsblock_t nrblocks_step; > > + struct xfs_rtbuf_cache rtbufc = {}; /* cache of realtime blocks */ > > > > *nmp = *mp; > > nsbp = &nmp->m_sb; > > @@ -1111,9 +1103,8 @@ xfs_growfs_rt( > > /* > > * Free new extent. > > */ > > - bp = NULL; > > error = xfs_rtfree_range(nmp, tp, sbp->sb_rextents, > > - nsbp->sb_rextents - sbp->sb_rextents, &bp, &sumbno); > > + nsbp->sb_rextents - sbp->sb_rextents, &rtbufc); > > if (error) { > > error_cancel: > > xfs_trans_cancel(tp); > > @@ -1185,8 +1176,7 @@ xfs_rtallocate_extent( > > xfs_mount_t *mp = tp->t_mountp; > > int error; /* error value */ > > xfs_rtblock_t r; /* result allocated block */ > > - xfs_fsblock_t sb; /* summary file block number */ > > - struct xfs_buf *sumbp; /* summary file block buffer */ > > + struct xfs_rtbuf_cache rtbufc = {}; /* cache of realtime blocks */ > > > > ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL)); > > ASSERT(minlen > 0 && minlen <= maxlen); > > @@ -1208,13 +1198,14 @@ xfs_rtallocate_extent( > > } > > > > retry: > > - sumbp = NULL; > > + rtbufc.bbuf = NULL; > > + rtbufc.sbuf = NULL; > > xfs_rtbuf_cache_relse? In this case, the cached blocks have been dirtied and attached to the transaction, so it's not strictly necessary (which is also why the old code didn't call xfs_trans_brelse()). But it's probably clearer to just use xfs_rtbuf_cache_relse() anyways rather than needing to justify that. > > if (bno == 0) { > > error = xfs_rtallocate_extent_size(mp, tp, minlen, maxlen, len, > > - &sumbp, &sb, prod, &r); > > + &rtbufc, prod, &r); > > } else { > > error = xfs_rtallocate_extent_near(mp, tp, bno, minlen, maxlen, > > - len, &sumbp, &sb, prod, &r); > > + len, &rtbufc, prod, &r); > > } > > > > if (error) > > diff --git a/fs/xfs/xfs_rtalloc.h b/fs/xfs/xfs_rtalloc.h > > index 62c7ad79cbb6..888552c4f287 100644 > > --- a/fs/xfs/xfs_rtalloc.h > > +++ b/fs/xfs/xfs_rtalloc.h > > @@ -101,29 +101,39 @@ xfs_growfs_rt( > > /* > > * From xfs_rtbitmap.c > > */ > > +struct xfs_rtbuf_cache { > > + struct xfs_buf *bbuf; /* bitmap block buffer */ > > + xfs_fsblock_t bblock; /* bitmap block number */ > > + struct xfs_buf *sbuf; /* summary block buffer */ > > + xfs_fsblock_t sblock; /* summary block number */ > > These are really offsets into the data fork, right? They ought to be > xfs_fileoff_t, except that none of the rtalloc code uses the correct > type? Yup, once again I was mimicking the surrounding code. I can fix it here. Thanks! > And yes I do want to merge the fixes for that: > https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux.git/log/?h=clean-up-realtime-units > > --D > > > +}; > > + > > int xfs_rtbuf_get(struct xfs_mount *mp, struct xfs_trans *tp, > > - xfs_rtblock_t block, int issum, struct xfs_buf **bpp); > > + xfs_rtblock_t block, int issum, struct xfs_rtbuf_cache *cache, > > + struct xfs_buf **bpp); > > int xfs_rtcheck_range(struct xfs_mount *mp, struct xfs_trans *tp, > > xfs_rtblock_t start, xfs_extlen_t len, int val, > > - xfs_rtblock_t *new, int *stat); > > + struct xfs_rtbuf_cache *rtbufc, xfs_rtblock_t *new, > > + int *stat); > > int xfs_rtfind_back(struct xfs_mount *mp, struct xfs_trans *tp, > > xfs_rtblock_t start, xfs_rtblock_t limit, > > - xfs_rtblock_t *rtblock); > > + struct xfs_rtbuf_cache *rtbufc, xfs_rtblock_t *rtblock); > > int xfs_rtfind_forw(struct xfs_mount *mp, struct xfs_trans *tp, > > xfs_rtblock_t start, xfs_rtblock_t limit, > > - xfs_rtblock_t *rtblock); > > + struct xfs_rtbuf_cache *rtbufc, xfs_rtblock_t *rtblock); > > int xfs_rtmodify_range(struct xfs_mount *mp, struct xfs_trans *tp, > > - xfs_rtblock_t start, xfs_extlen_t len, int val); > > + xfs_rtblock_t start, xfs_extlen_t len, int val, > > + struct xfs_rtbuf_cache *rtbufc); > > int xfs_rtmodify_summary_int(struct xfs_mount *mp, struct xfs_trans *tp, > > int log, xfs_rtblock_t bbno, int delta, > > - struct xfs_buf **rbpp, xfs_fsblock_t *rsb, > > + struct xfs_rtbuf_cache *rtbufc, > > xfs_suminfo_t *sum); > > int xfs_rtmodify_summary(struct xfs_mount *mp, struct xfs_trans *tp, int log, > > - xfs_rtblock_t bbno, int delta, struct xfs_buf **rbpp, > > - xfs_fsblock_t *rsb); > > + xfs_rtblock_t bbno, int delta, > > + struct xfs_rtbuf_cache *rtbufc); > > int xfs_rtfree_range(struct xfs_mount *mp, struct xfs_trans *tp, > > xfs_rtblock_t start, xfs_extlen_t len, > > - struct xfs_buf **rbpp, xfs_fsblock_t *rsb); > > + struct xfs_rtbuf_cache *rtbufc); > > int xfs_rtalloc_query_range(struct xfs_mount *mp, struct xfs_trans *tp, > > const struct xfs_rtalloc_rec *low_rec, > > const struct xfs_rtalloc_rec *high_rec, > > -- > > 2.41.0 > >