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

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
...@@ -47,25 +47,69 @@ const struct xfs_buf_ops xfs_rtbuf_ops = { ...@@ -47,25 +47,69 @@ const struct xfs_buf_ops xfs_rtbuf_ops = {
.verify_write = xfs_rtbuf_verify_write, .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. * Get a buffer for the bitmap or summary file block specified.
* The buffer is returned read and locked. * The buffer is returned read and locked.
*/ */
int int
xfs_rtbuf_get( xfs_rtbuf_get(
xfs_mount_t *mp, /* file system mount structure */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */ xfs_fileoff_t block, /* block number in bitmap or summary */
xfs_fileoff_t block, /* block number in bitmap or summary */ int issum) /* is summary not bitmap */
int issum, /* is summary not bitmap */
struct xfs_buf **bpp) /* output: buffer for the block */
{ {
struct xfs_buf *bp; /* block buffer, result */ struct xfs_mount *mp = args->mp;
xfs_inode_t *ip; /* bitmap or summary inode */ struct xfs_buf **cbpp; /* cached block buffer */
xfs_bmbt_irec_t map; xfs_fileoff_t *coffp; /* cached block number */
int nmap = 1; struct xfs_buf *bp; /* block buffer, result */
int error; /* error value */ struct xfs_inode *ip; /* bitmap or summary inode */
struct xfs_bmbt_irec map;
enum xfs_blft type;
int nmap = 1;
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); error = xfs_bmapi_read(ip, block, 1, &map, &nmap, 0);
if (error) if (error)
...@@ -75,15 +119,15 @@ xfs_rtbuf_get( ...@@ -75,15 +119,15 @@ xfs_rtbuf_get(
return -EFSCORRUPTED; return -EFSCORRUPTED;
ASSERT(map.br_startblock != NULLFSBLOCK); 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), XFS_FSB_TO_DADDR(mp, map.br_startblock),
mp->m_bsize, 0, &bp, &xfs_rtbuf_ops); mp->m_bsize, 0, &bp, &xfs_rtbuf_ops);
if (error) if (error)
return error; return error;
xfs_trans_buf_set_type(tp, bp, issum ? XFS_BLFT_RTSUMMARY_BUF xfs_trans_buf_set_type(args->tp, bp, type);
: XFS_BLFT_RTBITMAP_BUF); *cbpp = bp;
*bpp = bp; *coffp = block;
return 0; return 0;
} }
...@@ -93,33 +137,31 @@ xfs_rtbuf_get( ...@@ -93,33 +137,31 @@ xfs_rtbuf_get(
*/ */
int int
xfs_rtfind_back( xfs_rtfind_back(
xfs_mount_t *mp, /* file system mount point */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */ xfs_rtxnum_t start, /* starting rtext to look at */
xfs_rtxnum_t start, /* starting rtext to look at */ xfs_rtxnum_t limit, /* last rtext to look at */
xfs_rtxnum_t limit, /* last rtext to look at */ xfs_rtxnum_t *rtx) /* out: start rtext found */
xfs_rtxnum_t *rtx) /* out: start rtext found */
{ {
int bit; /* bit number in the word */ struct xfs_mount *mp = args->mp;
xfs_fileoff_t block; /* bitmap block number */ int bit; /* bit number in the word */
struct xfs_buf *bp; /* buf for the block */ xfs_fileoff_t block; /* bitmap block number */
int error; /* error value */ int error; /* error value */
xfs_rtxnum_t firstbit; /* first useful bit in the word */ xfs_rtxnum_t firstbit; /* first useful bit in the word */
xfs_rtxnum_t i; /* current bit number rel. to start */ xfs_rtxnum_t i; /* current bit number rel. to start */
xfs_rtxnum_t len; /* length of inspected area */ xfs_rtxnum_t len; /* length of inspected area */
xfs_rtword_t mask; /* mask of relevant bits for value */ xfs_rtword_t mask; /* mask of relevant bits for value */
xfs_rtword_t want; /* mask for "good" values */ xfs_rtword_t want; /* mask for "good" values */
xfs_rtword_t wdiff; /* difference from wanted value */ xfs_rtword_t wdiff; /* difference from wanted value */
xfs_rtword_t incore; xfs_rtword_t incore;
unsigned 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. * Compute and read in starting bitmap block for starting block.
*/ */
block = xfs_rtx_to_rbmblock(mp, start); block = xfs_rtx_to_rbmblock(mp, start);
error = xfs_rtbuf_get(mp, tp, block, 0, &bp); error = xfs_rtbitmap_read_buf(args, block);
if (error) { if (error)
return error; return error;
}
/* /*
* Get the first word's index & point to it. * Get the first word's index & point to it.
...@@ -131,7 +173,7 @@ xfs_rtfind_back( ...@@ -131,7 +173,7 @@ xfs_rtfind_back(
* Compute match value, based on the bit at start: if 1 (free) * Compute match value, based on the bit at start: if 1 (free)
* then all-ones, else all-zeroes. * 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; want = (incore & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
/* /*
* If the starting position is not word-aligned, deal with the * If the starting position is not word-aligned, deal with the
...@@ -153,7 +195,6 @@ xfs_rtfind_back( ...@@ -153,7 +195,6 @@ xfs_rtfind_back(
/* /*
* Different. Mark where we are and return. * Different. Mark where we are and return.
*/ */
xfs_trans_brelse(tp, bp);
i = bit - XFS_RTHIBIT(wdiff); i = bit - XFS_RTHIBIT(wdiff);
*rtx = start - i + 1; *rtx = start - i + 1;
return 0; return 0;
...@@ -167,11 +208,9 @@ xfs_rtfind_back( ...@@ -167,11 +208,9 @@ xfs_rtfind_back(
/* /*
* If done with this block, get the previous one. * If done with this block, get the previous one.
*/ */
xfs_trans_brelse(tp, bp); error = xfs_rtbitmap_read_buf(args, --block);
error = xfs_rtbuf_get(mp, tp, --block, 0, &bp); if (error)
if (error) {
return error; return error;
}
word = mp->m_blockwsize - 1; word = mp->m_blockwsize - 1;
} }
...@@ -189,12 +228,11 @@ xfs_rtfind_back( ...@@ -189,12 +228,11 @@ xfs_rtfind_back(
/* /*
* Compute difference between actual and desired value. * Compute difference between actual and desired value.
*/ */
incore = xfs_rtbitmap_getword(bp, word); incore = xfs_rtbitmap_getword(args, word);
if ((wdiff = incore ^ want)) { if ((wdiff = incore ^ want)) {
/* /*
* Different, mark where we are and return. * Different, mark where we are and return.
*/ */
xfs_trans_brelse(tp, bp);
i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff); i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
*rtx = start - i + 1; *rtx = start - i + 1;
return 0; return 0;
...@@ -208,11 +246,9 @@ xfs_rtfind_back( ...@@ -208,11 +246,9 @@ xfs_rtfind_back(
/* /*
* If done with this block, get the previous one. * If done with this block, get the previous one.
*/ */
xfs_trans_brelse(tp, bp); error = xfs_rtbitmap_read_buf(args, --block);
error = xfs_rtbuf_get(mp, tp, --block, 0, &bp); if (error)
if (error) {
return error; return error;
}
word = mp->m_blockwsize - 1; word = mp->m_blockwsize - 1;
} }
...@@ -231,12 +267,11 @@ xfs_rtfind_back( ...@@ -231,12 +267,11 @@ xfs_rtfind_back(
/* /*
* Compute difference between actual and desired value. * Compute difference between actual and desired value.
*/ */
incore = xfs_rtbitmap_getword(bp, word); incore = xfs_rtbitmap_getword(args, word);
if ((wdiff = (incore ^ want) & mask)) { if ((wdiff = (incore ^ want) & mask)) {
/* /*
* Different, mark where we are and return. * Different, mark where we are and return.
*/ */
xfs_trans_brelse(tp, bp);
i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff); i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
*rtx = start - i + 1; *rtx = start - i + 1;
return 0; return 0;
...@@ -246,7 +281,6 @@ xfs_rtfind_back( ...@@ -246,7 +281,6 @@ xfs_rtfind_back(
/* /*
* No match, return that we scanned the whole area. * No match, return that we scanned the whole area.
*/ */
xfs_trans_brelse(tp, bp);
*rtx = start - i + 1; *rtx = start - i + 1;
return 0; return 0;
} }
...@@ -257,33 +291,31 @@ xfs_rtfind_back( ...@@ -257,33 +291,31 @@ xfs_rtfind_back(
*/ */
int int
xfs_rtfind_forw( xfs_rtfind_forw(
xfs_mount_t *mp, /* file system mount point */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */ xfs_rtxnum_t start, /* starting rtext to look at */
xfs_rtxnum_t start, /* starting rtext to look at */ xfs_rtxnum_t limit, /* last rtext to look at */
xfs_rtxnum_t limit, /* last rtext to look at */ xfs_rtxnum_t *rtx) /* out: start rtext found */
xfs_rtxnum_t *rtx) /* out: start rtext found */
{ {
int bit; /* bit number in the word */ struct xfs_mount *mp = args->mp;
xfs_fileoff_t block; /* bitmap block number */ int bit; /* bit number in the word */
struct xfs_buf *bp; /* buf for the block */ xfs_fileoff_t block; /* bitmap block number */
int error; /* error value */ int error;
xfs_rtxnum_t i; /* current bit number rel. to start */ xfs_rtxnum_t i; /* current bit number rel. to start */
xfs_rtxnum_t lastbit; /* last useful bit in the word */ xfs_rtxnum_t lastbit;/* last useful bit in the word */
xfs_rtxnum_t len; /* length of inspected area */ xfs_rtxnum_t len; /* length of inspected area */
xfs_rtword_t mask; /* mask of relevant bits for value */ xfs_rtword_t mask; /* mask of relevant bits for value */
xfs_rtword_t want; /* mask for "good" values */ xfs_rtword_t want; /* mask for "good" values */
xfs_rtword_t wdiff; /* difference from wanted value */ xfs_rtword_t wdiff; /* difference from wanted value */
xfs_rtword_t incore; xfs_rtword_t incore;
unsigned 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. * Compute and read in starting bitmap block for starting block.
*/ */
block = xfs_rtx_to_rbmblock(mp, start); block = xfs_rtx_to_rbmblock(mp, start);
error = xfs_rtbuf_get(mp, tp, block, 0, &bp); error = xfs_rtbitmap_read_buf(args, block);
if (error) { if (error)
return error; return error;
}
/* /*
* Get the first word's index & point to it. * Get the first word's index & point to it.
...@@ -295,7 +327,7 @@ xfs_rtfind_forw( ...@@ -295,7 +327,7 @@ xfs_rtfind_forw(
* Compute match value, based on the bit at start: if 1 (free) * Compute match value, based on the bit at start: if 1 (free)
* then all-ones, else all-zeroes. * 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; want = (incore & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
/* /*
* If the starting position is not word-aligned, deal with the * If the starting position is not word-aligned, deal with the
...@@ -316,7 +348,6 @@ xfs_rtfind_forw( ...@@ -316,7 +348,6 @@ xfs_rtfind_forw(
/* /*
* Different. Mark where we are and return. * Different. Mark where we are and return.
*/ */
xfs_trans_brelse(tp, bp);
i = XFS_RTLOBIT(wdiff) - bit; i = XFS_RTLOBIT(wdiff) - bit;
*rtx = start + i - 1; *rtx = start + i - 1;
return 0; return 0;
...@@ -330,11 +361,9 @@ xfs_rtfind_forw( ...@@ -330,11 +361,9 @@ xfs_rtfind_forw(
/* /*
* If done with this block, get the previous one. * If done with this block, get the previous one.
*/ */
xfs_trans_brelse(tp, bp); error = xfs_rtbitmap_read_buf(args, ++block);
error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); if (error)
if (error) {
return error; return error;
}
word = 0; word = 0;
} }
...@@ -352,12 +381,11 @@ xfs_rtfind_forw( ...@@ -352,12 +381,11 @@ xfs_rtfind_forw(
/* /*
* Compute difference between actual and desired value. * Compute difference between actual and desired value.
*/ */
incore = xfs_rtbitmap_getword(bp, word); incore = xfs_rtbitmap_getword(args, word);
if ((wdiff = incore ^ want)) { if ((wdiff = incore ^ want)) {
/* /*
* Different, mark where we are and return. * Different, mark where we are and return.
*/ */
xfs_trans_brelse(tp, bp);
i += XFS_RTLOBIT(wdiff); i += XFS_RTLOBIT(wdiff);
*rtx = start + i - 1; *rtx = start + i - 1;
return 0; return 0;
...@@ -371,11 +399,9 @@ xfs_rtfind_forw( ...@@ -371,11 +399,9 @@ xfs_rtfind_forw(
/* /*
* If done with this block, get the next one. * If done with this block, get the next one.
*/ */
xfs_trans_brelse(tp, bp); error = xfs_rtbitmap_read_buf(args, ++block);
error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); if (error)
if (error) {
return error; return error;
}
word = 0; word = 0;
} }
...@@ -392,12 +418,11 @@ xfs_rtfind_forw( ...@@ -392,12 +418,11 @@ xfs_rtfind_forw(
/* /*
* Compute difference between actual and desired value. * Compute difference between actual and desired value.
*/ */
incore = xfs_rtbitmap_getword(bp, word); incore = xfs_rtbitmap_getword(args, word);
if ((wdiff = (incore ^ want) & mask)) { if ((wdiff = (incore ^ want) & mask)) {
/* /*
* Different, mark where we are and return. * Different, mark where we are and return.
*/ */
xfs_trans_brelse(tp, bp);
i += XFS_RTLOBIT(wdiff); i += XFS_RTLOBIT(wdiff);
*rtx = start + i - 1; *rtx = start + i - 1;
return 0; return 0;
...@@ -407,7 +432,6 @@ xfs_rtfind_forw( ...@@ -407,7 +432,6 @@ xfs_rtfind_forw(
/* /*
* No match, return that we scanned the whole area. * No match, return that we scanned the whole area.
*/ */
xfs_trans_brelse(tp, bp);
*rtx = start + i - 1; *rtx = start + i - 1;
return 0; return 0;
} }
...@@ -415,16 +439,16 @@ xfs_rtfind_forw( ...@@ -415,16 +439,16 @@ xfs_rtfind_forw(
/* Log rtsummary counter at @infoword. */ /* Log rtsummary counter at @infoword. */
static inline void static inline void
xfs_trans_log_rtsummary( xfs_trans_log_rtsummary(
struct xfs_trans *tp, struct xfs_rtalloc_args *args,
struct xfs_buf *bp,
unsigned int infoword) unsigned int infoword)
{ {
struct xfs_buf *bp = args->sumbp;
size_t first, last; 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; 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,20 +462,17 @@ xfs_trans_log_rtsummary( ...@@ -438,20 +462,17 @@ xfs_trans_log_rtsummary(
*/ */
int int
xfs_rtmodify_summary_int( xfs_rtmodify_summary_int(
xfs_mount_t *mp, /* file system mount structure */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */ int log, /* log2 of extent size */
int log, /* log2 of extent size */ xfs_fileoff_t bbno, /* bitmap block number */
xfs_fileoff_t bbno, /* bitmap block number */ int delta, /* change to make to summary info */
int delta, /* change to make to summary info */ xfs_suminfo_t *sum) /* out: summary info for this block */
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 */ struct xfs_mount *mp = args->mp;
int error; /* error value */ int error;
xfs_fileoff_t sb; /* summary fsblock */ xfs_fileoff_t sb; /* summary fsblock */
xfs_rtsumoff_t so; /* index into the summary file */ xfs_rtsumoff_t so; /* index into the summary file */
unsigned int infoword; unsigned int infoword;
/* /*
* Compute entry number in the summary file. * Compute entry number in the summary file.
...@@ -461,80 +482,57 @@ xfs_rtmodify_summary_int( ...@@ -461,80 +482,57 @@ xfs_rtmodify_summary_int(
* Compute the block number in the summary file. * Compute the block number in the summary file.
*/ */
sb = xfs_rtsumoffs_to_block(mp, so); sb = xfs_rtsumoffs_to_block(mp, so);
/*
* If we have an old buffer, and the block number matches, use that. error = xfs_rtsummary_read_buf(args, sb);
*/ if (error)
if (*rbpp && *rsb == sb) return error;
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;
}
/* /*
* Point to the summary information, modify/log it, and/or copy it out. * Point to the summary information, modify/log it, and/or copy it out.
*/ */
infoword = xfs_rtsumoffs_to_infoword(mp, so); infoword = xfs_rtsumoffs_to_infoword(mp, so);
if (delta) { 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 (mp->m_rsum_cache) {
if (val == 0 && log == mp->m_rsum_cache[bbno]) if (val == 0 && log + 1 == mp->m_rsum_cache[bbno])
mp->m_rsum_cache[bbno]++;
if (val != 0 && log < mp->m_rsum_cache[bbno])
mp->m_rsum_cache[bbno] = log; 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) if (sum)
*sum = val; *sum = val;
} else if (sum) { } else if (sum) {
*sum = xfs_suminfo_get(bp, infoword); *sum = xfs_suminfo_get(args, infoword);
} }
return 0; return 0;
} }
int int
xfs_rtmodify_summary( xfs_rtmodify_summary(
xfs_mount_t *mp, /* file system mount structure */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */ int log, /* log2 of extent size */
int log, /* log2 of extent size */ xfs_fileoff_t bbno, /* bitmap block number */
xfs_fileoff_t bbno, /* bitmap block number */ int delta) /* in/out: summary 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 */
{ {
return xfs_rtmodify_summary_int(mp, tp, log, bbno, return xfs_rtmodify_summary_int(args, log, bbno, delta, NULL);
delta, rbpp, rsb, NULL);
} }
/* Log rtbitmap block from the word @from to the byte before @next. */ /* Log rtbitmap block from the word @from to the byte before @next. */
static inline void static inline void
xfs_trans_log_rtbitmap( xfs_trans_log_rtbitmap(
struct xfs_trans *tp, struct xfs_rtalloc_args *args,
struct xfs_buf *bp,
unsigned int from, unsigned int from,
unsigned int next) unsigned int next)
{ {
struct xfs_buf *bp = args->rbmbp;
size_t first, last; size_t first, last;
first = (void *)xfs_rbmblock_wordptr(bp, from) - bp->b_addr; first = (void *)xfs_rbmblock_wordptr(args, from) - bp->b_addr;
last = ((void *)xfs_rbmblock_wordptr(bp, next) - 1) - 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,22 +541,21 @@ xfs_trans_log_rtbitmap( ...@@ -543,22 +541,21 @@ xfs_trans_log_rtbitmap(
*/ */
int int
xfs_rtmodify_range( xfs_rtmodify_range(
xfs_mount_t *mp, /* file system mount point */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */ xfs_rtxnum_t start, /* starting rtext to modify */
xfs_rtxnum_t start, /* starting rtext to modify */ xfs_rtxlen_t len, /* length of extent to modify */
xfs_rtxlen_t len, /* length of extent to modify */ int val) /* 1 for free, 0 for allocated */
int val) /* 1 for free, 0 for allocated */
{ {
int bit; /* bit number in the word */ struct xfs_mount *mp = args->mp;
xfs_fileoff_t block; /* bitmap block number */ int bit; /* bit number in the word */
struct xfs_buf *bp; /* buf for the block */ xfs_fileoff_t block; /* bitmap block number */
int error; /* error value */ int error;
int i; /* current bit number rel. to start */ int i; /* current bit number rel. to start */
int lastbit; /* last useful bit in word */ int lastbit; /* last useful bit in word */
xfs_rtword_t mask; /* mask o frelevant bits for value */ xfs_rtword_t mask; /* mask of relevant bits for value */
xfs_rtword_t incore; xfs_rtword_t incore;
unsigned int firstword; /* first word used in the buffer */ unsigned int firstword; /* first word used in the buffer */
unsigned int word; /* word number in the buffer */ unsigned int word; /* word number in the buffer */
/* /*
* Compute starting bitmap block number. * Compute starting bitmap block number.
...@@ -567,10 +564,9 @@ xfs_rtmodify_range( ...@@ -567,10 +564,9 @@ xfs_rtmodify_range(
/* /*
* Read the bitmap block, and point to its data. * Read the bitmap block, and point to its data.
*/ */
error = xfs_rtbuf_get(mp, tp, block, 0, &bp); error = xfs_rtbitmap_read_buf(args, block);
if (error) { if (error)
return error; return error;
}
/* /*
* Compute the starting word's address, and starting bit. * Compute the starting word's address, and starting bit.
...@@ -594,12 +590,12 @@ xfs_rtmodify_range( ...@@ -594,12 +590,12 @@ xfs_rtmodify_range(
/* /*
* Set/clear the active bits. * Set/clear the active bits.
*/ */
incore = xfs_rtbitmap_getword(bp, word); incore = xfs_rtbitmap_getword(args, word);
if (val) if (val)
incore |= mask; incore |= mask;
else else
incore &= ~mask; incore &= ~mask;
xfs_rtbitmap_setword(bp, word, incore); xfs_rtbitmap_setword(args, word, incore);
i = lastbit - bit; i = lastbit - bit;
/* /*
* Go on to the next block if that's where the next word is * Go on to the next block if that's where the next word is
...@@ -610,11 +606,10 @@ xfs_rtmodify_range( ...@@ -610,11 +606,10 @@ xfs_rtmodify_range(
* Log the changed part of this block. * Log the changed part of this block.
* Get the next one. * Get the next one.
*/ */
xfs_trans_log_rtbitmap(tp, bp, firstword, word); xfs_trans_log_rtbitmap(args, firstword, word);
error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); error = xfs_rtbitmap_read_buf(args, ++block);
if (error) { if (error)
return error; return error;
}
firstword = word = 0; firstword = word = 0;
} }
...@@ -632,7 +627,7 @@ xfs_rtmodify_range( ...@@ -632,7 +627,7 @@ xfs_rtmodify_range(
/* /*
* Set the word value correctly. * Set the word value correctly.
*/ */
xfs_rtbitmap_setword(bp, word, val); xfs_rtbitmap_setword(args, word, val);
i += XFS_NBWORD; i += XFS_NBWORD;
/* /*
* Go on to the next block if that's where the next word is * Go on to the next block if that's where the next word is
...@@ -643,11 +638,10 @@ xfs_rtmodify_range( ...@@ -643,11 +638,10 @@ xfs_rtmodify_range(
* Log the changed part of this block. * Log the changed part of this block.
* Get the next one. * Get the next one.
*/ */
xfs_trans_log_rtbitmap(tp, bp, firstword, word); xfs_trans_log_rtbitmap(args, firstword, word);
error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); error = xfs_rtbitmap_read_buf(args, ++block);
if (error) { if (error)
return error; return error;
}
firstword = word = 0; firstword = word = 0;
} }
...@@ -664,19 +658,19 @@ xfs_rtmodify_range( ...@@ -664,19 +658,19 @@ xfs_rtmodify_range(
/* /*
* Set/clear the active bits. * Set/clear the active bits.
*/ */
incore = xfs_rtbitmap_getword(bp, word); incore = xfs_rtbitmap_getword(args, word);
if (val) if (val)
incore |= mask; incore |= mask;
else else
incore &= ~mask; incore &= ~mask;
xfs_rtbitmap_setword(bp, word, incore); xfs_rtbitmap_setword(args, word, incore);
word++; word++;
} }
/* /*
* Log any remaining changed bytes. * Log any remaining changed bytes.
*/ */
if (word > firstword) if (word > firstword)
xfs_trans_log_rtbitmap(tp, bp, firstword, word); xfs_trans_log_rtbitmap(args, firstword, word);
return 0; return 0;
} }
...@@ -686,23 +680,21 @@ xfs_rtmodify_range( ...@@ -686,23 +680,21 @@ xfs_rtmodify_range(
*/ */
int int
xfs_rtfree_range( xfs_rtfree_range(
xfs_mount_t *mp, /* file system mount point */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */ xfs_rtxnum_t start, /* starting rtext to free */
xfs_rtxnum_t start, /* starting rtext to free */ xfs_rtxlen_t len) /* in/out: summary block number */
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_rtxnum_t end; /* end of the freed extent */ struct xfs_mount *mp = args->mp;
int error; /* error value */ xfs_rtxnum_t end; /* end of the freed extent */
xfs_rtxnum_t postblock; /* first rtext freed > end */ int error; /* error value */
xfs_rtxnum_t preblock; /* first rtext freed < start */ xfs_rtxnum_t postblock; /* first rtext freed > end */
xfs_rtxnum_t preblock; /* first rtext freed < start */
end = start + len - 1; end = start + len - 1;
/* /*
* Modify the bitmap to mark this extent freed. * 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) { if (error) {
return error; return error;
} }
...@@ -711,15 +703,15 @@ xfs_rtfree_range( ...@@ -711,15 +703,15 @@ xfs_rtfree_range(
* We need to find the beginning and end of the extent so we can * We need to find the beginning and end of the extent so we can
* properly update the summary. * properly update the summary.
*/ */
error = xfs_rtfind_back(mp, tp, start, 0, &preblock); error = xfs_rtfind_back(args, start, 0, &preblock);
if (error) { if (error) {
return error; return error;
} }
/* /*
* Find the next allocated block (end of allocated extent). * 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); &postblock);
if (error) if (error)
return error; return error;
/* /*
...@@ -727,9 +719,9 @@ xfs_rtfree_range( ...@@ -727,9 +719,9 @@ xfs_rtfree_range(
* old extent, add summary data for them to be allocated. * old extent, add summary data for them to be allocated.
*/ */
if (preblock < start) { if (preblock < start) {
error = xfs_rtmodify_summary(mp, tp, error = xfs_rtmodify_summary(args,
XFS_RTBLOCKLOG(start - preblock), XFS_RTBLOCKLOG(start - preblock),
xfs_rtx_to_rbmblock(mp, preblock), -1, rbpp, rsb); xfs_rtx_to_rbmblock(mp, preblock), -1);
if (error) { if (error) {
return error; return error;
} }
...@@ -739,9 +731,9 @@ xfs_rtfree_range( ...@@ -739,9 +731,9 @@ xfs_rtfree_range(
* old extent, add summary data for them to be allocated. * old extent, add summary data for them to be allocated.
*/ */
if (postblock > end) { if (postblock > end) {
error = xfs_rtmodify_summary(mp, tp, error = xfs_rtmodify_summary(args,
XFS_RTBLOCKLOG(postblock - end), XFS_RTBLOCKLOG(postblock - end),
xfs_rtx_to_rbmblock(mp, end + 1), -1, rbpp, rsb); xfs_rtx_to_rbmblock(mp, end + 1), -1);
if (error) { if (error) {
return error; return error;
} }
...@@ -750,10 +742,9 @@ xfs_rtfree_range( ...@@ -750,10 +742,9 @@ xfs_rtfree_range(
* Increment the summary information corresponding to the entire * Increment the summary information corresponding to the entire
* (new) free extent. * (new) free extent.
*/ */
error = xfs_rtmodify_summary(mp, tp, return xfs_rtmodify_summary(args,
XFS_RTBLOCKLOG(postblock + 1 - preblock), XFS_RTBLOCKLOG(postblock + 1 - preblock),
xfs_rtx_to_rbmblock(mp, preblock), 1, rbpp, rsb); xfs_rtx_to_rbmblock(mp, preblock), 1);
return error;
} }
/* /*
...@@ -762,24 +753,23 @@ xfs_rtfree_range( ...@@ -762,24 +753,23 @@ xfs_rtfree_range(
*/ */
int int
xfs_rtcheck_range( xfs_rtcheck_range(
xfs_mount_t *mp, /* file system mount point */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */ xfs_rtxnum_t start, /* starting rtext number of extent */
xfs_rtxnum_t start, /* starting rtext number of extent */ xfs_rtxlen_t len, /* length of extent */
xfs_rtxlen_t len, /* length of extent */ int val, /* 1 for free, 0 for allocated */
int val, /* 1 for free, 0 for allocated */ xfs_rtxnum_t *new, /* out: first rtext not matching */
xfs_rtxnum_t *new, /* out: first rtext not matching */ int *stat) /* out: 1 for matches, 0 for not */
int *stat) /* out: 1 for matches, 0 for not */
{ {
int bit; /* bit number in the word */ struct xfs_mount *mp = args->mp;
xfs_fileoff_t block; /* bitmap block number */ int bit; /* bit number in the word */
struct xfs_buf *bp; /* buf for the block */ xfs_fileoff_t block; /* bitmap block number */
int error; /* error value */ int error;
xfs_rtxnum_t i; /* current bit number rel. to start */ xfs_rtxnum_t i; /* current bit number rel. to start */
xfs_rtxnum_t lastbit; /* last useful bit in word */ xfs_rtxnum_t lastbit; /* last useful bit in word */
xfs_rtword_t mask; /* mask of relevant bits for value */ xfs_rtword_t mask; /* mask of relevant bits for value */
xfs_rtword_t wdiff; /* difference from wanted value */ xfs_rtword_t wdiff; /* difference from wanted value */
xfs_rtword_t incore; xfs_rtword_t incore;
unsigned int word; /* word number in the buffer */ unsigned int word; /* word number in the buffer */
/* /*
* Compute starting bitmap block number * Compute starting bitmap block number
...@@ -788,10 +778,9 @@ xfs_rtcheck_range( ...@@ -788,10 +778,9 @@ xfs_rtcheck_range(
/* /*
* Read the bitmap block. * Read the bitmap block.
*/ */
error = xfs_rtbuf_get(mp, tp, block, 0, &bp); error = xfs_rtbitmap_read_buf(args, block);
if (error) { if (error)
return error; return error;
}
/* /*
* Compute the starting word's address, and starting bit. * Compute the starting word's address, and starting bit.
...@@ -818,12 +807,11 @@ xfs_rtcheck_range( ...@@ -818,12 +807,11 @@ xfs_rtcheck_range(
/* /*
* Compute difference between actual and desired value. * Compute difference between actual and desired value.
*/ */
incore = xfs_rtbitmap_getword(bp, word); incore = xfs_rtbitmap_getword(args, word);
if ((wdiff = (incore ^ val) & mask)) { if ((wdiff = (incore ^ val) & mask)) {
/* /*
* Different, compute first wrong bit and return. * Different, compute first wrong bit and return.
*/ */
xfs_trans_brelse(tp, bp);
i = XFS_RTLOBIT(wdiff) - bit; i = XFS_RTLOBIT(wdiff) - bit;
*new = start + i; *new = start + i;
*stat = 0; *stat = 0;
...@@ -838,11 +826,9 @@ xfs_rtcheck_range( ...@@ -838,11 +826,9 @@ xfs_rtcheck_range(
/* /*
* If done with this block, get the next one. * If done with this block, get the next one.
*/ */
xfs_trans_brelse(tp, bp); error = xfs_rtbitmap_read_buf(args, ++block);
error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); if (error)
if (error) {
return error; return error;
}
word = 0; word = 0;
} }
...@@ -860,12 +846,11 @@ xfs_rtcheck_range( ...@@ -860,12 +846,11 @@ xfs_rtcheck_range(
/* /*
* Compute difference between actual and desired value. * Compute difference between actual and desired value.
*/ */
incore = xfs_rtbitmap_getword(bp, word); incore = xfs_rtbitmap_getword(args, word);
if ((wdiff = incore ^ val)) { if ((wdiff = incore ^ val)) {
/* /*
* Different, compute first wrong bit and return. * Different, compute first wrong bit and return.
*/ */
xfs_trans_brelse(tp, bp);
i += XFS_RTLOBIT(wdiff); i += XFS_RTLOBIT(wdiff);
*new = start + i; *new = start + i;
*stat = 0; *stat = 0;
...@@ -880,11 +865,9 @@ xfs_rtcheck_range( ...@@ -880,11 +865,9 @@ xfs_rtcheck_range(
/* /*
* If done with this block, get the next one. * If done with this block, get the next one.
*/ */
xfs_trans_brelse(tp, bp); error = xfs_rtbitmap_read_buf(args, ++block);
error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); if (error)
if (error) {
return error; return error;
}
word = 0; word = 0;
} }
...@@ -901,12 +884,11 @@ xfs_rtcheck_range( ...@@ -901,12 +884,11 @@ xfs_rtcheck_range(
/* /*
* Compute difference between actual and desired value. * Compute difference between actual and desired value.
*/ */
incore = xfs_rtbitmap_getword(bp, word); incore = xfs_rtbitmap_getword(args, word);
if ((wdiff = (incore ^ val) & mask)) { if ((wdiff = (incore ^ val) & mask)) {
/* /*
* Different, compute first wrong bit and return. * Different, compute first wrong bit and return.
*/ */
xfs_trans_brelse(tp, bp);
i += XFS_RTLOBIT(wdiff); i += XFS_RTLOBIT(wdiff);
*new = start + i; *new = start + i;
*stat = 0; *stat = 0;
...@@ -917,7 +899,6 @@ xfs_rtcheck_range( ...@@ -917,7 +899,6 @@ xfs_rtcheck_range(
/* /*
* Successful, return. * Successful, return.
*/ */
xfs_trans_brelse(tp, bp);
*new = start + i; *new = start + i;
*stat = 1; *stat = 1;
return 0; return 0;
...@@ -927,57 +908,56 @@ xfs_rtcheck_range( ...@@ -927,57 +908,56 @@ xfs_rtcheck_range(
/* /*
* Check that the given extent (block range) is allocated already. * Check that the given extent (block range) is allocated already.
*/ */
STATIC int /* error */ STATIC int
xfs_rtcheck_alloc_range( xfs_rtcheck_alloc_range(
xfs_mount_t *mp, /* file system mount point */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */ xfs_rtxnum_t start, /* starting rtext number of extent */
xfs_rtxnum_t start, /* starting rtext number of extent */ xfs_rtxlen_t len) /* length of extent */
xfs_rtxlen_t len) /* length of extent */
{ {
xfs_rtxnum_t new; /* dummy for xfs_rtcheck_range */ xfs_rtxnum_t new; /* dummy for xfs_rtcheck_range */
int stat; int stat;
int error; 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) if (error)
return error; return error;
ASSERT(stat); ASSERT(stat);
return 0; return 0;
} }
#else #else
#define xfs_rtcheck_alloc_range(m,t,b,l) (0) #define xfs_rtcheck_alloc_range(a,b,l) (0)
#endif #endif
/* /*
* Free an extent in the realtime subvolume. Length is expressed in * Free an extent in the realtime subvolume. Length is expressed in
* realtime extents, as is the block number. * realtime extents, as is the block number.
*/ */
int /* error */ int
xfs_rtfree_extent( 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_rtxnum_t start, /* starting rtext number to free */
xfs_rtxlen_t len) /* length of extent freed */ xfs_rtxlen_t len) /* length of extent freed */
{ {
int error; /* error value */ struct xfs_mount *mp = tp->t_mountp;
xfs_mount_t *mp; /* file system mount structure */ struct xfs_rtalloc_args args = {
xfs_fsblock_t sb; /* summary file block number */ .mp = mp,
struct xfs_buf *sumbp = NULL; /* summary file block buffer */ .tp = tp,
};
mp = tp->t_mountp; int error;
ASSERT(mp->m_rbmip->i_itemp != NULL); ASSERT(mp->m_rbmip->i_itemp != NULL);
ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL)); 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) if (error)
return error; return error;
/* /*
* Free the range of realtime blocks. * Free the range of realtime blocks.
*/ */
error = xfs_rtfree_range(mp, tp, start, len, &sumbp, &sb); error = xfs_rtfree_range(&args, start, len);
if (error) { if (error)
return error; goto out;
}
/* /*
* Mark more blocks free in the superblock. * Mark more blocks free in the superblock.
*/ */
...@@ -993,7 +973,10 @@ xfs_rtfree_extent( ...@@ -993,7 +973,10 @@ xfs_rtfree_extent(
*(uint64_t *)&VFS_I(mp->m_rbmip)->i_atime = 0; *(uint64_t *)&VFS_I(mp->m_rbmip)->i_atime = 0;
xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE); 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( ...@@ -1039,6 +1022,10 @@ xfs_rtalloc_query_range(
xfs_rtalloc_query_range_fn fn, xfs_rtalloc_query_range_fn fn,
void *priv) void *priv)
{ {
struct xfs_rtalloc_args args = {
.mp = mp,
.tp = tp,
};
struct xfs_rtalloc_rec rec; struct xfs_rtalloc_rec rec;
xfs_rtxnum_t rtstart; xfs_rtxnum_t rtstart;
xfs_rtxnum_t rtend; xfs_rtxnum_t rtend;
...@@ -1058,13 +1045,13 @@ xfs_rtalloc_query_range( ...@@ -1058,13 +1045,13 @@ xfs_rtalloc_query_range(
rtstart = low_rec->ar_startext; rtstart = low_rec->ar_startext;
while (rtstart <= high_key) { while (rtstart <= high_key) {
/* Is the first block free? */ /* 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); &is_free);
if (error) if (error)
break; break;
/* How long does the extent go for? */ /* 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) if (error)
break; break;
...@@ -1080,6 +1067,7 @@ xfs_rtalloc_query_range( ...@@ -1080,6 +1067,7 @@ xfs_rtalloc_query_range(
rtstart = rtend + 1; rtstart = rtend + 1;
} }
xfs_rtbuf_cache_relse(&args);
return error; return error;
} }
...@@ -1109,11 +1097,16 @@ xfs_rtalloc_extent_is_free( ...@@ -1109,11 +1097,16 @@ xfs_rtalloc_extent_is_free(
xfs_rtxlen_t len, xfs_rtxlen_t len,
bool *is_free) bool *is_free)
{ {
struct xfs_rtalloc_args args = {
.mp = mp,
.tp = tp,
};
xfs_rtxnum_t end; xfs_rtxnum_t end;
int matches; int matches;
int error; 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) if (error)
return error; return error;
......
...@@ -6,6 +6,17 @@ ...@@ -6,6 +6,17 @@
#ifndef __XFS_RTBITMAP_H__ #ifndef __XFS_RTBITMAP_H__
#define __XFS_RTBITMAP_H__ #define __XFS_RTBITMAP_H__
struct xfs_rtalloc_args {
struct xfs_mount *mp;
struct xfs_trans *tp;
struct xfs_buf *rbmbp; /* bitmap block buffer */
struct xfs_buf *sumbp; /* summary block buffer */
xfs_fileoff_t rbmoff; /* bitmap block number */
xfs_fileoff_t sumoff; /* summary block number */
};
static inline xfs_rtblock_t static inline xfs_rtblock_t
xfs_rtx_to_rtb( xfs_rtx_to_rtb(
struct xfs_mount *mp, struct xfs_mount *mp,
...@@ -161,10 +172,10 @@ xfs_rbmblock_to_rtx( ...@@ -161,10 +172,10 @@ xfs_rbmblock_to_rtx(
/* Return a pointer to a bitmap word within a rt bitmap block. */ /* Return a pointer to a bitmap word within a rt bitmap block. */
static inline union xfs_rtword_raw * static inline union xfs_rtword_raw *
xfs_rbmblock_wordptr( xfs_rbmblock_wordptr(
struct xfs_buf *bp, struct xfs_rtalloc_args *args,
unsigned int index) unsigned int index)
{ {
union xfs_rtword_raw *words = bp->b_addr; union xfs_rtword_raw *words = args->rbmbp->b_addr;
return words + index; return words + index;
} }
...@@ -172,10 +183,10 @@ xfs_rbmblock_wordptr( ...@@ -172,10 +183,10 @@ xfs_rbmblock_wordptr(
/* Convert an ondisk bitmap word to its incore representation. */ /* Convert an ondisk bitmap word to its incore representation. */
static inline xfs_rtword_t static inline xfs_rtword_t
xfs_rtbitmap_getword( xfs_rtbitmap_getword(
struct xfs_buf *bp, struct xfs_rtalloc_args *args,
unsigned int index) unsigned int index)
{ {
union xfs_rtword_raw *word = xfs_rbmblock_wordptr(bp, index); union xfs_rtword_raw *word = xfs_rbmblock_wordptr(args, index);
return word->old; return word->old;
} }
...@@ -183,11 +194,11 @@ xfs_rtbitmap_getword( ...@@ -183,11 +194,11 @@ xfs_rtbitmap_getword(
/* Set an ondisk bitmap word from an incore representation. */ /* Set an ondisk bitmap word from an incore representation. */
static inline void static inline void
xfs_rtbitmap_setword( xfs_rtbitmap_setword(
struct xfs_buf *bp, struct xfs_rtalloc_args *args,
unsigned int index, unsigned int index,
xfs_rtword_t value) xfs_rtword_t value)
{ {
union xfs_rtword_raw *word = xfs_rbmblock_wordptr(bp, index); union xfs_rtword_raw *word = xfs_rbmblock_wordptr(args, index);
word->old = value; word->old = value;
} }
...@@ -234,10 +245,10 @@ xfs_rtsumoffs_to_infoword( ...@@ -234,10 +245,10 @@ xfs_rtsumoffs_to_infoword(
/* Return a pointer to a summary info word within a rt summary block. */ /* Return a pointer to a summary info word within a rt summary block. */
static inline union xfs_suminfo_raw * static inline union xfs_suminfo_raw *
xfs_rsumblock_infoptr( xfs_rsumblock_infoptr(
struct xfs_buf *bp, struct xfs_rtalloc_args *args,
unsigned int index) unsigned int index)
{ {
union xfs_suminfo_raw *info = bp->b_addr; union xfs_suminfo_raw *info = args->sumbp->b_addr;
return info + index; return info + index;
} }
...@@ -245,10 +256,10 @@ xfs_rsumblock_infoptr( ...@@ -245,10 +256,10 @@ xfs_rsumblock_infoptr(
/* Get the current value of a summary counter. */ /* Get the current value of a summary counter. */
static inline xfs_suminfo_t static inline xfs_suminfo_t
xfs_suminfo_get( xfs_suminfo_get(
struct xfs_buf *bp, struct xfs_rtalloc_args *args,
unsigned int index) unsigned int index)
{ {
union xfs_suminfo_raw *info = xfs_rsumblock_infoptr(bp, index); union xfs_suminfo_raw *info = xfs_rsumblock_infoptr(args, index);
return info->old; return info->old;
} }
...@@ -256,11 +267,11 @@ xfs_suminfo_get( ...@@ -256,11 +267,11 @@ xfs_suminfo_get(
/* Add to the current value of a summary counter and return the new value. */ /* Add to the current value of a summary counter and return the new value. */
static inline xfs_suminfo_t static inline xfs_suminfo_t
xfs_suminfo_add( xfs_suminfo_add(
struct xfs_buf *bp, struct xfs_rtalloc_args *args,
unsigned int index, unsigned int index,
int delta) int delta)
{ {
union xfs_suminfo_raw *info = xfs_rsumblock_infoptr(bp, index); union xfs_suminfo_raw *info = xfs_rsumblock_infoptr(args, index);
info->old += delta; info->old += delta;
return info->old; return info->old;
...@@ -281,29 +292,41 @@ typedef int (*xfs_rtalloc_query_range_fn)( ...@@ -281,29 +292,41 @@ typedef int (*xfs_rtalloc_query_range_fn)(
void *priv); void *priv);
#ifdef CONFIG_XFS_RT #ifdef CONFIG_XFS_RT
int xfs_rtbuf_get(struct xfs_mount *mp, struct xfs_trans *tp, void xfs_rtbuf_cache_relse(struct xfs_rtalloc_args *args);
xfs_fileoff_t block, int issum, struct xfs_buf **bpp);
int xfs_rtcheck_range(struct xfs_mount *mp, struct xfs_trans *tp, int xfs_rtbuf_get(struct xfs_rtalloc_args *args, xfs_fileoff_t block,
xfs_rtxnum_t start, xfs_rtxlen_t len, int val, int issum);
xfs_rtxnum_t *new, int *stat);
int xfs_rtfind_back(struct xfs_mount *mp, struct xfs_trans *tp, static inline int
xfs_rtxnum_t start, xfs_rtxnum_t limit, xfs_rtbitmap_read_buf(
xfs_rtxnum_t *rtblock); struct xfs_rtalloc_args *args,
int xfs_rtfind_forw(struct xfs_mount *mp, struct xfs_trans *tp, xfs_fileoff_t block)
xfs_rtxnum_t start, xfs_rtxnum_t limit, {
xfs_rtxnum_t *rtblock); return xfs_rtbuf_get(args, block, 0);
int xfs_rtmodify_range(struct xfs_mount *mp, struct xfs_trans *tp, }
xfs_rtxnum_t start, xfs_rtxlen_t len, int val);
int xfs_rtmodify_summary_int(struct xfs_mount *mp, struct xfs_trans *tp, static inline int
int log, xfs_fileoff_t bbno, int delta, xfs_rtsummary_read_buf(
struct xfs_buf **rbpp, xfs_fileoff_t *rsb, struct xfs_rtalloc_args *args,
xfs_suminfo_t *sum); xfs_fileoff_t block)
int xfs_rtmodify_summary(struct xfs_mount *mp, struct xfs_trans *tp, int log, {
xfs_fileoff_t bbno, int delta, struct xfs_buf **rbpp, return xfs_rtbuf_get(args, block, 1);
xfs_fileoff_t *rsb); }
int xfs_rtfree_range(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_rtxnum_t start, xfs_rtxlen_t len, int xfs_rtcheck_range(struct xfs_rtalloc_args *args, xfs_rtxnum_t start,
struct xfs_buf **rbpp, xfs_fileoff_t *rsb); xfs_rtxlen_t len, int val, xfs_rtxnum_t *new, int *stat);
int xfs_rtfind_back(struct xfs_rtalloc_args *args, xfs_rtxnum_t start,
xfs_rtxnum_t limit, xfs_rtxnum_t *rtblock);
int xfs_rtfind_forw(struct xfs_rtalloc_args *args, xfs_rtxnum_t start,
xfs_rtxnum_t limit, xfs_rtxnum_t *rtblock);
int xfs_rtmodify_range(struct xfs_rtalloc_args *args, xfs_rtxnum_t start,
xfs_rtxlen_t len, int val);
int xfs_rtmodify_summary_int(struct xfs_rtalloc_args *args, int log,
xfs_fileoff_t bbno, int delta, xfs_suminfo_t *sum);
int xfs_rtmodify_summary(struct xfs_rtalloc_args *args, int log,
xfs_fileoff_t bbno, int delta);
int xfs_rtfree_range(struct xfs_rtalloc_args *args, xfs_rtxnum_t start,
xfs_rtxlen_t len);
int xfs_rtalloc_query_range(struct xfs_mount *mp, struct xfs_trans *tp, 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 *low_rec,
const struct xfs_rtalloc_rec *high_rec, const struct xfs_rtalloc_rec *high_rec,
...@@ -342,7 +365,9 @@ unsigned long long xfs_rtsummary_wordcount(struct xfs_mount *mp, ...@@ -342,7 +365,9 @@ unsigned long long xfs_rtsummary_wordcount(struct xfs_mount *mp,
# define xfs_rtfree_blocks(t,rb,rl) (-ENOSYS) # define xfs_rtfree_blocks(t,rb,rl) (-ENOSYS)
# define xfs_rtalloc_query_range(m,t,l,h,f,p) (-ENOSYS) # define xfs_rtalloc_query_range(m,t,l,h,f,p) (-ENOSYS)
# define xfs_rtalloc_query_all(m,t,f,p) (-ENOSYS) # define xfs_rtalloc_query_all(m,t,f,p) (-ENOSYS)
# define xfs_rtbuf_get(m,t,b,i,p) (-ENOSYS) # define xfs_rtbitmap_read_buf(a,b) (-ENOSYS)
# define xfs_rtsummary_read_buf(a,b) (-ENOSYS)
# define xfs_rtbuf_cache_relse(a) (0)
# define xfs_rtalloc_extent_is_free(m,t,s,l,i) (-ENOSYS) # define xfs_rtalloc_extent_is_free(m,t,s,l,i) (-ENOSYS)
static inline xfs_filblks_t static inline xfs_filblks_t
xfs_rtbitmap_blockcount(struct xfs_mount *mp, xfs_rtbxlen_t rtextents) xfs_rtbitmap_blockcount(struct xfs_mount *mp, xfs_rtbxlen_t rtextents)
......
...@@ -188,8 +188,11 @@ STATIC int ...@@ -188,8 +188,11 @@ STATIC int
xchk_rtsum_compare( xchk_rtsum_compare(
struct xfs_scrub *sc) struct xfs_scrub *sc)
{ {
struct xfs_rtalloc_args args = {
.mp = sc->mp,
.tp = sc->tp,
};
struct xfs_mount *mp = sc->mp; struct xfs_mount *mp = sc->mp;
struct xfs_buf *bp;
struct xfs_bmbt_irec map; struct xfs_bmbt_irec map;
xfs_fileoff_t off; xfs_fileoff_t off;
xchk_rtsumoff_t sumoff = 0; xchk_rtsumoff_t sumoff = 0;
...@@ -217,23 +220,23 @@ xchk_rtsum_compare( ...@@ -217,23 +220,23 @@ xchk_rtsum_compare(
} }
/* Read a block's worth of ondisk rtsummary file. */ /* 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)) if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, off, &error))
return error; return error;
/* Read a block's worth of computed rtsummary file. */ /* Read a block's worth of computed rtsummary file. */
error = xfsum_copyout(sc, sumoff, sc->buf, mp->m_blockwsize); error = xfsum_copyout(sc, sumoff, sc->buf, mp->m_blockwsize);
if (error) { if (error) {
xfs_trans_brelse(sc->tp, bp); xfs_rtbuf_cache_relse(&args);
return error; return error;
} }
ondisk_info = xfs_rsumblock_infoptr(bp, 0); ondisk_info = xfs_rsumblock_infoptr(&args, 0);
if (memcmp(ondisk_info, sc->buf, if (memcmp(ondisk_info, sc->buf,
mp->m_blockwsize << XFS_WORDLOG) != 0) mp->m_blockwsize << XFS_WORDLOG) != 0)
xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, off); xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, off);
xfs_trans_brelse(sc->tp, bp); xfs_rtbuf_cache_relse(&args);
sumoff += mp->m_blockwsize; sumoff += mp->m_blockwsize;
} }
......
...@@ -101,9 +101,9 @@ typedef struct xfs_mount { ...@@ -101,9 +101,9 @@ typedef struct xfs_mount {
/* /*
* Optional cache of rt summary level per bitmap block with the * Optional cache of rt summary level per bitmap block with the
* invariant that m_rsum_cache[bbno] <= the minimum i for which * invariant that m_rsum_cache[bbno] > the maximum i for which
* rsum[i][bbno] != 0. Reads and writes are serialized by the rsumip * rsum[i][bbno] != 0, or 0 if rsum[i][bbno] == 0 for all i.
* inode lock. * Reads and writes are serialized by the rsumip inode lock.
*/ */
uint8_t *m_rsum_cache; uint8_t *m_rsum_cache;
struct xfs_mru_cache *m_filestream; /* per-mount filestream data */ struct xfs_mru_cache *m_filestream; /* per-mount filestream data */
......
...@@ -29,48 +29,48 @@ ...@@ -29,48 +29,48 @@
*/ */
static int static int
xfs_rtget_summary( xfs_rtget_summary(
xfs_mount_t *mp, /* file system mount structure */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */ int log, /* log2 of extent size */
int log, /* log2 of extent size */ xfs_fileoff_t bbno, /* bitmap block number */
xfs_fileoff_t bbno, /* bitmap block number */ xfs_suminfo_t *sum) /* out: summary info for this block */
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 */
{ {
return xfs_rtmodify_summary_int(mp, tp, log, bbno, 0, rbpp, rsb, sum); return xfs_rtmodify_summary_int(args, log, bbno, 0, sum);
} }
/* /*
* Return whether there are any free extents in the size range given * Return whether there are any free extents in the size range given
* by low and high, for the bitmap block bbno. * by low and high, for the bitmap block bbno.
*/ */
STATIC int /* error */ STATIC int
xfs_rtany_summary( xfs_rtany_summary(
xfs_mount_t *mp, /* file system mount structure */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */ int low, /* low log2 extent size */
int low, /* low log2 extent size */ int high, /* high log2 extent size */
int high, /* high log2 extent size */ xfs_fileoff_t bbno, /* bitmap block number */
xfs_fileoff_t bbno, /* bitmap block number */ int *maxlog) /* out: max log2 extent size free */
struct xfs_buf **rbpp, /* in/out: summary block buffer */
xfs_fileoff_t *rsb, /* in/out: summary block number */
int *stat) /* out: any good extents here? */
{ {
int error; /* error value */ struct xfs_mount *mp = args->mp;
int log; /* loop counter, log2 of ext. size */ int error;
xfs_suminfo_t sum; /* summary data */ int log; /* loop counter, log2 of ext. size */
xfs_suminfo_t sum; /* summary data */
/* There are no extents at levels < m_rsum_cache[bbno]. */
if (mp->m_rsum_cache && low < mp->m_rsum_cache[bbno]) /* There are no extents at levels >= m_rsum_cache[bbno]. */
low = mp->m_rsum_cache[bbno]; if (mp->m_rsum_cache) {
high = min(high, mp->m_rsum_cache[bbno] - 1);
if (low > high) {
*maxlog = -1;
return 0;
}
}
/* /*
* Loop over logs of extent sizes. * Loop over logs of extent sizes.
*/ */
for (log = low; log <= high; log++) { for (log = high; log >= low; log--) {
/* /*
* Get one summary datum. * Get one summary datum.
*/ */
error = xfs_rtget_summary(mp, tp, log, bbno, rbpp, rsb, &sum); error = xfs_rtget_summary(args, log, bbno, &sum);
if (error) { if (error) {
return error; return error;
} }
...@@ -78,18 +78,18 @@ xfs_rtany_summary( ...@@ -78,18 +78,18 @@ xfs_rtany_summary(
* If there are any, return success. * If there are any, return success.
*/ */
if (sum) { if (sum) {
*stat = 1; *maxlog = log;
goto out; goto out;
} }
} }
/* /*
* Found nothing, return failure. * Found nothing, return failure.
*/ */
*stat = 0; *maxlog = -1;
out: out:
/* There were no extents at levels < log. */ /* There were no extents at levels > log. */
if (mp->m_rsum_cache && log > mp->m_rsum_cache[bbno]) if (mp->m_rsum_cache && log + 1 < mp->m_rsum_cache[bbno])
mp->m_rsum_cache[bbno] = log; mp->m_rsum_cache[bbno] = log + 1;
return 0; return 0;
} }
...@@ -98,60 +98,54 @@ xfs_rtany_summary( ...@@ -98,60 +98,54 @@ xfs_rtany_summary(
* Copy and transform the summary file, given the old and new * Copy and transform the summary file, given the old and new
* parameters in the mount structures. * parameters in the mount structures.
*/ */
STATIC int /* error */ STATIC int
xfs_rtcopy_summary( xfs_rtcopy_summary(
xfs_mount_t *omp, /* old file system mount point */ struct xfs_rtalloc_args *oargs,
xfs_mount_t *nmp, /* new file system mount point */ struct xfs_rtalloc_args *nargs)
xfs_trans_t *tp) /* transaction pointer */
{ {
xfs_fileoff_t bbno; /* bitmap block number */ xfs_fileoff_t bbno; /* bitmap block number */
struct xfs_buf *bp; /* summary buffer */ int error;
int error; /* error return value */ int log; /* summary level number (log length) */
int log; /* summary level number (log length) */ xfs_suminfo_t sum; /* summary data */
xfs_suminfo_t sum; /* summary data */
xfs_fileoff_t sumbno; /* summary block number */
bp = NULL; for (log = oargs->mp->m_rsumlevels - 1; log >= 0; log--) {
for (log = omp->m_rsumlevels - 1; log >= 0; log--) { for (bbno = oargs->mp->m_sb.sb_rbmblocks - 1;
for (bbno = omp->m_sb.sb_rbmblocks - 1;
(xfs_srtblock_t)bbno >= 0; (xfs_srtblock_t)bbno >= 0;
bbno--) { bbno--) {
error = xfs_rtget_summary(omp, tp, log, bbno, &bp, error = xfs_rtget_summary(oargs, log, bbno, &sum);
&sumbno, &sum);
if (error) if (error)
return error; goto out;
if (sum == 0) if (sum == 0)
continue; continue;
error = xfs_rtmodify_summary(omp, tp, log, bbno, -sum, error = xfs_rtmodify_summary(oargs, log, bbno, -sum);
&bp, &sumbno);
if (error) if (error)
return error; goto out;
error = xfs_rtmodify_summary(nmp, tp, log, bbno, sum, error = xfs_rtmodify_summary(nargs, log, bbno, sum);
&bp, &sumbno);
if (error) if (error)
return error; goto out;
ASSERT(sum > 0); ASSERT(sum > 0);
} }
} }
error = 0;
out:
xfs_rtbuf_cache_relse(oargs);
return 0; return 0;
} }
/* /*
* Mark an extent specified by start and len allocated. * Mark an extent specified by start and len allocated.
* Updates all the summary information as well as the bitmap. * Updates all the summary information as well as the bitmap.
*/ */
STATIC int /* error */ STATIC int
xfs_rtallocate_range( xfs_rtallocate_range(
xfs_mount_t *mp, /* file system mount point */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */ xfs_rtxnum_t start, /* start rtext to allocate */
xfs_rtxnum_t start, /* start rtext to allocate */ xfs_rtxlen_t len) /* in/out: summary block number */
xfs_rtxlen_t len, /* length to allocate */
struct xfs_buf **rbpp, /* in/out: summary block buffer */
xfs_fileoff_t *rsb) /* in/out: summary block number */
{ {
xfs_rtxnum_t end; /* end of the allocated rtext */ struct xfs_mount *mp = args->mp;
int error; /* error value */ xfs_rtxnum_t end; /* end of the allocated rtext */
xfs_rtxnum_t postblock = 0; /* first rtext allocated > end */ int error;
xfs_rtxnum_t preblock = 0; /* first rtext allocated < start */ xfs_rtxnum_t postblock = 0; /* first rtext allocated > end */
xfs_rtxnum_t preblock = 0; /* first rtext allocated < start */
end = start + len - 1; end = start + len - 1;
/* /*
...@@ -159,15 +153,15 @@ xfs_rtallocate_range( ...@@ -159,15 +153,15 @@ xfs_rtallocate_range(
* We need to find the beginning and end of the extent so we can * We need to find the beginning and end of the extent so we can
* properly update the summary. * properly update the summary.
*/ */
error = xfs_rtfind_back(mp, tp, start, 0, &preblock); error = xfs_rtfind_back(args, start, 0, &preblock);
if (error) { if (error) {
return error; return error;
} }
/* /*
* Find the next allocated block (end of free extent). * 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(args, end, mp->m_sb.sb_rextents - 1,
&postblock); &postblock);
if (error) { if (error) {
return error; return error;
} }
...@@ -175,9 +169,9 @@ xfs_rtallocate_range( ...@@ -175,9 +169,9 @@ xfs_rtallocate_range(
* Decrement the summary information corresponding to the entire * Decrement the summary information corresponding to the entire
* (old) free extent. * (old) free extent.
*/ */
error = xfs_rtmodify_summary(mp, tp, error = xfs_rtmodify_summary(args,
XFS_RTBLOCKLOG(postblock + 1 - preblock), XFS_RTBLOCKLOG(postblock + 1 - preblock),
xfs_rtx_to_rbmblock(mp, preblock), -1, rbpp, rsb); xfs_rtx_to_rbmblock(mp, preblock), -1);
if (error) { if (error) {
return error; return error;
} }
...@@ -186,9 +180,9 @@ xfs_rtallocate_range( ...@@ -186,9 +180,9 @@ xfs_rtallocate_range(
* old extent, add summary data for them to be free. * old extent, add summary data for them to be free.
*/ */
if (preblock < start) { if (preblock < start) {
error = xfs_rtmodify_summary(mp, tp, error = xfs_rtmodify_summary(args,
XFS_RTBLOCKLOG(start - preblock), XFS_RTBLOCKLOG(start - preblock),
xfs_rtx_to_rbmblock(mp, preblock), 1, rbpp, rsb); xfs_rtx_to_rbmblock(mp, preblock), 1);
if (error) { if (error) {
return error; return error;
} }
...@@ -198,9 +192,9 @@ xfs_rtallocate_range( ...@@ -198,9 +192,9 @@ xfs_rtallocate_range(
* old extent, add summary data for them to be free. * old extent, add summary data for them to be free.
*/ */
if (postblock > end) { if (postblock > end) {
error = xfs_rtmodify_summary(mp, tp, error = xfs_rtmodify_summary(args,
XFS_RTBLOCKLOG(postblock - end), XFS_RTBLOCKLOG(postblock - end),
xfs_rtx_to_rbmblock(mp, end + 1), 1, rbpp, rsb); xfs_rtx_to_rbmblock(mp, end + 1), 1);
if (error) { if (error) {
return error; return error;
} }
...@@ -208,7 +202,7 @@ xfs_rtallocate_range( ...@@ -208,7 +202,7 @@ xfs_rtallocate_range(
/* /*
* Modify the bitmap to mark this extent allocated. * Modify the bitmap to mark this extent allocated.
*/ */
error = xfs_rtmodify_range(mp, tp, start, len, 0); error = xfs_rtmodify_range(args, start, len, 0);
return error; return error;
} }
...@@ -235,27 +229,25 @@ xfs_rtallocate_clamp_len( ...@@ -235,27 +229,25 @@ xfs_rtallocate_clamp_len(
* the length, if given. Returns error; returns starting block in *rtx. * the length, if given. Returns error; returns starting block in *rtx.
* The lengths are all in rtextents. * The lengths are all in rtextents.
*/ */
STATIC int /* error */ STATIC int
xfs_rtallocate_extent_block( xfs_rtallocate_extent_block(
xfs_mount_t *mp, /* file system mount point */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */ xfs_fileoff_t bbno, /* bitmap block number */
xfs_fileoff_t bbno, /* bitmap block number */ xfs_rtxlen_t minlen, /* minimum length to allocate */
xfs_rtxlen_t minlen, /* minimum length to allocate */ xfs_rtxlen_t maxlen, /* maximum length to allocate */
xfs_rtxlen_t maxlen, /* maximum length to allocate */ xfs_rtxlen_t *len, /* out: actual length allocated */
xfs_rtxlen_t *len, /* out: actual length allocated */ xfs_rtxnum_t *nextp, /* out: next rtext to try */
xfs_rtxnum_t *nextp, /* out: next rtext to try */ xfs_rtxlen_t prod, /* extent product factor */
struct xfs_buf **rbpp, /* in/out: summary block buffer */ xfs_rtxnum_t *rtx) /* out: start rtext allocated */
xfs_fileoff_t *rsb, /* in/out: summary block number */
xfs_rtxlen_t prod, /* extent product factor */
xfs_rtxnum_t *rtx) /* out: start rtext allocated */
{ {
xfs_rtxnum_t besti; /* best rtext found so far */ struct xfs_mount *mp = args->mp;
xfs_rtxnum_t bestlen; /* best length found so far */ xfs_rtxnum_t besti; /* best rtext found so far */
xfs_rtxnum_t end; /* last rtext in chunk */ xfs_rtxnum_t bestlen;/* best length found so far */
int error; /* error value */ xfs_rtxnum_t end; /* last rtext in chunk */
xfs_rtxnum_t i; /* current rtext trying */ int error;
xfs_rtxnum_t next; /* next rtext to try */ xfs_rtxnum_t i; /* current rtext trying */
int stat; /* status from internal calls */ xfs_rtxnum_t next; /* next rtext to try */
int stat; /* status from internal calls */
/* /*
* Loop over all the extents starting in this bitmap block, * Loop over all the extents starting in this bitmap block,
...@@ -272,7 +264,7 @@ xfs_rtallocate_extent_block( ...@@ -272,7 +264,7 @@ xfs_rtallocate_extent_block(
* See if there's a free extent of maxlen starting at i. * 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. * 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(args, i, maxlen, 1, &next, &stat);
if (error) { if (error) {
return error; return error;
} }
...@@ -280,8 +272,7 @@ xfs_rtallocate_extent_block( ...@@ -280,8 +272,7 @@ xfs_rtallocate_extent_block(
/* /*
* i for maxlen is all free, allocate and return that. * i for maxlen is all free, allocate and return that.
*/ */
error = xfs_rtallocate_range(mp, tp, i, maxlen, rbpp, error = xfs_rtallocate_range(args, i, maxlen);
rsb);
if (error) { if (error) {
return error; return error;
} }
...@@ -308,7 +299,7 @@ xfs_rtallocate_extent_block( ...@@ -308,7 +299,7 @@ xfs_rtallocate_extent_block(
* If not done yet, find the start of the next free space. * If not done yet, find the start of the next free space.
*/ */
if (next < end) { if (next < end) {
error = xfs_rtfind_forw(mp, tp, next, end, &i); error = xfs_rtfind_forw(args, next, end, &i);
if (error) { if (error) {
return error; return error;
} }
...@@ -333,7 +324,7 @@ xfs_rtallocate_extent_block( ...@@ -333,7 +324,7 @@ xfs_rtallocate_extent_block(
/* /*
* Allocate besti for bestlen & return that. * Allocate besti for bestlen & return that.
*/ */
error = xfs_rtallocate_range(mp, tp, besti, bestlen, rbpp, rsb); error = xfs_rtallocate_range(args, besti, bestlen);
if (error) { if (error) {
return error; return error;
} }
...@@ -355,30 +346,27 @@ xfs_rtallocate_extent_block( ...@@ -355,30 +346,27 @@ xfs_rtallocate_extent_block(
* Returns error; returns starting block in *rtx. * Returns error; returns starting block in *rtx.
* The lengths are all in rtextents. * The lengths are all in rtextents.
*/ */
STATIC int /* error */ STATIC int
xfs_rtallocate_extent_exact( xfs_rtallocate_extent_exact(
xfs_mount_t *mp, /* file system mount point */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */ xfs_rtxnum_t start, /* starting rtext number to allocate */
xfs_rtxnum_t start, /* starting rtext number to allocate */ xfs_rtxlen_t minlen, /* minimum length to allocate */
xfs_rtxlen_t minlen, /* minimum length to allocate */ xfs_rtxlen_t maxlen, /* maximum length to allocate */
xfs_rtxlen_t maxlen, /* maximum length to allocate */ xfs_rtxlen_t *len, /* out: actual length allocated */
xfs_rtxlen_t *len, /* out: actual length allocated */ xfs_rtxlen_t prod, /* extent product factor */
struct xfs_buf **rbpp, /* in/out: summary block buffer */ xfs_rtxnum_t *rtx) /* out: start rtext allocated */
xfs_fileoff_t *rsb, /* in/out: summary block number */
xfs_rtxlen_t prod, /* extent product factor */
xfs_rtxnum_t *rtx) /* out: start rtext allocated */
{ {
int error; /* error value */ int error;
xfs_rtxlen_t i; /* extent length trimmed due to prod */ xfs_rtxlen_t i; /* extent length trimmed due to prod */
int isfree; /* extent is free */ int isfree; /* extent is free */
xfs_rtxnum_t next; /* next rtext to try (dummy) */ xfs_rtxnum_t next; /* next rtext to try (dummy) */
ASSERT(minlen % prod == 0); ASSERT(minlen % prod == 0);
ASSERT(maxlen % prod == 0); ASSERT(maxlen % prod == 0);
/* /*
* Check if the range in question (for maxlen) is free. * Check if the range in question (for maxlen) is free.
*/ */
error = xfs_rtcheck_range(mp, tp, start, maxlen, 1, &next, &isfree); error = xfs_rtcheck_range(args, start, maxlen, 1, &next, &isfree);
if (error) { if (error) {
return error; return error;
} }
...@@ -386,7 +374,7 @@ xfs_rtallocate_extent_exact( ...@@ -386,7 +374,7 @@ xfs_rtallocate_extent_exact(
/* /*
* If it is, allocate it and return success. * If it is, allocate it and return success.
*/ */
error = xfs_rtallocate_range(mp, tp, start, maxlen, rbpp, rsb); error = xfs_rtallocate_range(args, start, maxlen);
if (error) { if (error) {
return error; return error;
} }
...@@ -421,7 +409,7 @@ xfs_rtallocate_extent_exact( ...@@ -421,7 +409,7 @@ xfs_rtallocate_extent_exact(
/* /*
* Allocate what we can and return it. * Allocate what we can and return it.
*/ */
error = xfs_rtallocate_range(mp, tp, start, maxlen, rbpp, rsb); error = xfs_rtallocate_range(args, start, maxlen);
if (error) { if (error) {
return error; return error;
} }
...@@ -435,27 +423,25 @@ xfs_rtallocate_extent_exact( ...@@ -435,27 +423,25 @@ xfs_rtallocate_extent_exact(
* to start as possible. If we don't get maxlen then use prod to trim * to start as possible. If we don't get maxlen then use prod to trim
* the length, if given. The lengths are all in rtextents. * the length, if given. The lengths are all in rtextents.
*/ */
STATIC int /* error */ STATIC int
xfs_rtallocate_extent_near( xfs_rtallocate_extent_near(
xfs_mount_t *mp, /* file system mount point */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */ xfs_rtxnum_t start, /* starting rtext number to allocate */
xfs_rtxnum_t start, /* starting rtext number to allocate */ xfs_rtxlen_t minlen, /* minimum length to allocate */
xfs_rtxlen_t minlen, /* minimum length to allocate */ xfs_rtxlen_t maxlen, /* maximum length to allocate */
xfs_rtxlen_t maxlen, /* maximum length to allocate */ xfs_rtxlen_t *len, /* out: actual length allocated */
xfs_rtxlen_t *len, /* out: actual length allocated */ xfs_rtxlen_t prod, /* extent product factor */
struct xfs_buf **rbpp, /* in/out: summary block buffer */ xfs_rtxnum_t *rtx) /* out: start rtext allocated */
xfs_fileoff_t *rsb, /* in/out: summary block number */
xfs_rtxlen_t prod, /* extent product factor */
xfs_rtxnum_t *rtx) /* out: start rtext allocated */
{ {
int any; /* any useful extents from summary */ struct xfs_mount *mp = args->mp;
xfs_fileoff_t bbno; /* bitmap block number */ int maxlog; /* max useful extent from summary */
int error; /* error value */ xfs_fileoff_t bbno; /* bitmap block number */
int i; /* bitmap block offset (loop control) */ int error;
int j; /* secondary loop control */ int i; /* bitmap block offset (loop control) */
int log2len; /* log2 of minlen */ int j; /* secondary loop control */
xfs_rtxnum_t n; /* next rtext to try */ int log2len; /* log2 of minlen */
xfs_rtxnum_t r; /* result rtext */ xfs_rtxnum_t n; /* next rtext to try */
xfs_rtxnum_t r; /* result rtext */
ASSERT(minlen % prod == 0); ASSERT(minlen % prod == 0);
ASSERT(maxlen % prod == 0); ASSERT(maxlen % prod == 0);
...@@ -477,8 +463,8 @@ xfs_rtallocate_extent_near( ...@@ -477,8 +463,8 @@ xfs_rtallocate_extent_near(
/* /*
* Try the exact allocation first. * Try the exact allocation first.
*/ */
error = xfs_rtallocate_extent_exact(mp, tp, start, minlen, maxlen, len, error = xfs_rtallocate_extent_exact(args, start, minlen, maxlen, len,
rbpp, rsb, prod, &r); prod, &r);
if (error) { if (error) {
return error; return error;
} }
...@@ -491,6 +477,7 @@ xfs_rtallocate_extent_near( ...@@ -491,6 +477,7 @@ xfs_rtallocate_extent_near(
} }
bbno = xfs_rtx_to_rbmblock(mp, start); bbno = xfs_rtx_to_rbmblock(mp, start);
i = 0; i = 0;
j = -1;
ASSERT(minlen != 0); ASSERT(minlen != 0);
log2len = xfs_highbit32(minlen); log2len = xfs_highbit32(minlen);
/* /*
...@@ -501,8 +488,8 @@ xfs_rtallocate_extent_near( ...@@ -501,8 +488,8 @@ xfs_rtallocate_extent_near(
* Get summary information of extents of all useful levels * Get summary information of extents of all useful levels
* starting in this bitmap block. * starting in this bitmap block.
*/ */
error = xfs_rtany_summary(mp, tp, log2len, mp->m_rsumlevels - 1, error = xfs_rtany_summary(args, log2len, mp->m_rsumlevels - 1,
bbno + i, rbpp, rsb, &any); bbno + i, &maxlog);
if (error) { if (error) {
return error; return error;
} }
...@@ -510,7 +497,10 @@ xfs_rtallocate_extent_near( ...@@ -510,7 +497,10 @@ xfs_rtallocate_extent_near(
* If there are any useful extents starting here, try * If there are any useful extents starting here, try
* allocating one. * allocating one.
*/ */
if (any) { if (maxlog >= 0) {
xfs_extlen_t maxavail =
min_t(xfs_rtblock_t, maxlen,
(1ULL << (maxlog + 1)) - 1);
/* /*
* On the positive side of the starting location. * On the positive side of the starting location.
*/ */
...@@ -519,9 +509,9 @@ xfs_rtallocate_extent_near( ...@@ -519,9 +509,9 @@ xfs_rtallocate_extent_near(
* Try to allocate an extent starting in * Try to allocate an extent starting in
* this block. * this block.
*/ */
error = xfs_rtallocate_extent_block(mp, tp, error = xfs_rtallocate_extent_block(args,
bbno + i, minlen, maxlen, len, &n, rbpp, bbno + i, minlen, maxavail, len,
rsb, prod, &r); &n, prod, &r);
if (error) { if (error) {
return error; return error;
} }
...@@ -537,36 +527,35 @@ xfs_rtallocate_extent_near( ...@@ -537,36 +527,35 @@ xfs_rtallocate_extent_near(
* On the negative side of the starting location. * On the negative side of the starting location.
*/ */
else { /* i < 0 */ else { /* i < 0 */
int maxblocks;
/* /*
* Loop backwards through the bitmap blocks from * Loop backwards to find the end of the extent
* the starting point-1 up to where we are now. * we found in the realtime summary.
* There should be an extent which ends in this *
* bitmap block and is long enough. * maxblocks is the maximum possible number of
* bitmap blocks from the start of the extent
* to the end of the extent.
*/ */
for (j = -1; j > i; j--) { if (maxlog == 0)
/* maxblocks = 0;
* Grab the summary information for else if (maxlog < mp->m_blkbit_log)
* this bitmap block. maxblocks = 1;
*/ else
error = xfs_rtany_summary(mp, tp, maxblocks = 2 << (maxlog - mp->m_blkbit_log);
log2len, mp->m_rsumlevels - 1,
bbno + j, rbpp, rsb, &any); /*
if (error) { * We need to check bbno + i + maxblocks down to
return error; * bbno + i. We already checked bbno down to
} * bbno + j + 1, so we don't need to check those
/* * again.
* If there's no extent given in the */
* summary that means the extent we j = min(i + maxblocks, j);
* found must carry over from an for (; j >= i; j--) {
* earlier block. If there is an error = xfs_rtallocate_extent_block(args,
* extent given, we've already tried bbno + j, minlen,
* that allocation, don't do it again. maxavail, len, &n, prod,
*/ &r);
if (any)
continue;
error = xfs_rtallocate_extent_block(mp,
tp, bbno + j, minlen, maxlen,
len, &n, rbpp, rsb, prod, &r);
if (error) { if (error) {
return error; return error;
} }
...@@ -578,27 +567,6 @@ xfs_rtallocate_extent_near( ...@@ -578,27 +567,6 @@ xfs_rtallocate_extent_near(
return 0; return 0;
} }
} }
/*
* There weren't intervening bitmap blocks
* with a long enough extent, or the
* allocation didn't work for some reason
* (i.e. it's a little * too short).
* Try to allocate from the summary block
* that we found.
*/
error = xfs_rtallocate_extent_block(mp, tp,
bbno + i, minlen, maxlen, len, &n, rbpp,
rsb, prod, &r);
if (error) {
return error;
}
/*
* If it works, return the extent.
*/
if (r != NULLRTEXTNO) {
*rtx = r;
return 0;
}
} }
} }
/* /*
...@@ -640,24 +608,22 @@ xfs_rtallocate_extent_near( ...@@ -640,24 +608,22 @@ xfs_rtallocate_extent_near(
* specified. If we don't get maxlen then use prod to trim * specified. If we don't get maxlen then use prod to trim
* the length, if given. The lengths are all in rtextents. * the length, if given. The lengths are all in rtextents.
*/ */
STATIC int /* error */ STATIC int
xfs_rtallocate_extent_size( xfs_rtallocate_extent_size(
xfs_mount_t *mp, /* file system mount point */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */ xfs_rtxlen_t minlen, /* minimum length to allocate */
xfs_rtxlen_t minlen, /* minimum length to allocate */ xfs_rtxlen_t maxlen, /* maximum length to allocate */
xfs_rtxlen_t maxlen, /* maximum length to allocate */ xfs_rtxlen_t *len, /* out: actual length allocated */
xfs_rtxlen_t *len, /* out: actual length allocated */ xfs_rtxlen_t prod, /* extent product factor */
struct xfs_buf **rbpp, /* in/out: summary block buffer */ xfs_rtxnum_t *rtx) /* out: start rtext allocated */
xfs_fileoff_t *rsb, /* in/out: summary block number */
xfs_rtxlen_t prod, /* extent product factor */
xfs_rtxnum_t *rtx) /* out: start rtext allocated */
{ {
int error; /* error value */ struct xfs_mount *mp = args->mp;
xfs_fileoff_t i; /* bitmap block number */ int error;
int l; /* level number (loop control) */ xfs_fileoff_t i; /* bitmap block number */
xfs_rtxnum_t n; /* next rtext to be tried */ int l; /* level number (loop control) */
xfs_rtxnum_t r; /* result rtext number */ xfs_rtxnum_t n; /* next rtext to be tried */
xfs_suminfo_t sum; /* summary information for extents */ xfs_rtxnum_t r; /* result rtext number */
xfs_suminfo_t sum; /* summary information for extents */
ASSERT(minlen % prod == 0); ASSERT(minlen % prod == 0);
ASSERT(maxlen % prod == 0); ASSERT(maxlen % prod == 0);
...@@ -678,8 +644,7 @@ xfs_rtallocate_extent_size( ...@@ -678,8 +644,7 @@ xfs_rtallocate_extent_size(
/* /*
* Get the summary for this level/block. * Get the summary for this level/block.
*/ */
error = xfs_rtget_summary(mp, tp, l, i, rbpp, rsb, error = xfs_rtget_summary(args, l, i, &sum);
&sum);
if (error) { if (error) {
return error; return error;
} }
...@@ -691,8 +656,8 @@ xfs_rtallocate_extent_size( ...@@ -691,8 +656,8 @@ xfs_rtallocate_extent_size(
/* /*
* Try allocating the extent. * Try allocating the extent.
*/ */
error = xfs_rtallocate_extent_block(mp, tp, i, maxlen, error = xfs_rtallocate_extent_block(args, i, maxlen,
maxlen, len, &n, rbpp, rsb, prod, &r); maxlen, len, &n, prod, &r);
if (error) { if (error) {
return error; return error;
} }
...@@ -737,8 +702,7 @@ xfs_rtallocate_extent_size( ...@@ -737,8 +702,7 @@ xfs_rtallocate_extent_size(
/* /*
* Get the summary information for this level/block. * Get the summary information for this level/block.
*/ */
error = xfs_rtget_summary(mp, tp, l, i, rbpp, rsb, error = xfs_rtget_summary(args, l, i, &sum);
&sum);
if (error) { if (error) {
return error; return error;
} }
...@@ -752,10 +716,10 @@ xfs_rtallocate_extent_size( ...@@ -752,10 +716,10 @@ xfs_rtallocate_extent_size(
* minlen/maxlen are in the possible range for * minlen/maxlen are in the possible range for
* this summary level. * this summary level.
*/ */
error = xfs_rtallocate_extent_block(mp, tp, i, error = xfs_rtallocate_extent_block(args, i,
XFS_RTMAX(minlen, 1 << l), XFS_RTMAX(minlen, 1 << l),
XFS_RTMIN(maxlen, (1 << (l + 1)) - 1), XFS_RTMIN(maxlen, (1 << (l + 1)) - 1),
len, &n, rbpp, rsb, prod, &r); len, &n, prod, &r);
if (error) { if (error) {
return error; return error;
} }
...@@ -908,12 +872,14 @@ xfs_alloc_rsum_cache( ...@@ -908,12 +872,14 @@ xfs_alloc_rsum_cache(
xfs_extlen_t rbmblocks) /* number of rt bitmap blocks */ xfs_extlen_t rbmblocks) /* number of rt bitmap blocks */
{ {
/* /*
* The rsum cache is initialized to all zeroes, which is trivially a * The rsum cache is initialized to the maximum value, which is
* lower bound on the minimum level with any free extents. We can * trivially an upper bound on the maximum level with any free extents.
* continue without the cache if it couldn't be allocated. * We can continue without the cache if it couldn't be allocated.
*/ */
mp->m_rsum_cache = kvzalloc(rbmblocks, GFP_KERNEL); mp->m_rsum_cache = kvmalloc(rbmblocks, GFP_KERNEL);
if (!mp->m_rsum_cache) if (mp->m_rsum_cache)
memset(mp->m_rsum_cache, -1, rbmblocks);
else
xfs_warn(mp, "could not allocate realtime summary cache"); xfs_warn(mp, "could not allocate realtime summary cache");
} }
...@@ -944,7 +910,6 @@ xfs_growfs_rt( ...@@ -944,7 +910,6 @@ xfs_growfs_rt(
xfs_extlen_t rbmblocks; /* current number of rt bitmap blocks */ xfs_extlen_t rbmblocks; /* current number of rt bitmap blocks */
xfs_extlen_t rsumblocks; /* current number of rt summary blks */ xfs_extlen_t rsumblocks; /* current number of rt summary blks */
xfs_sb_t *sbp; /* old superblock */ xfs_sb_t *sbp; /* old superblock */
xfs_fileoff_t sumbno; /* summary block number */
uint8_t *rsum_cache; /* old summary cache */ uint8_t *rsum_cache; /* old summary cache */
sbp = &mp->m_sb; sbp = &mp->m_sb;
...@@ -1044,6 +1009,12 @@ xfs_growfs_rt( ...@@ -1044,6 +1009,12 @@ xfs_growfs_rt(
((sbp->sb_rextents & ((1 << mp->m_blkbit_log) - 1)) != 0); ((sbp->sb_rextents & ((1 << mp->m_blkbit_log) - 1)) != 0);
bmbno < nrbmblocks; bmbno < nrbmblocks;
bmbno++) { bmbno++) {
struct xfs_rtalloc_args args = {
.mp = mp,
};
struct xfs_rtalloc_args nargs = {
.mp = nmp,
};
struct xfs_trans *tp; struct xfs_trans *tp;
xfs_rfsblock_t nrblocks_step; xfs_rfsblock_t nrblocks_step;
...@@ -1072,6 +1043,9 @@ xfs_growfs_rt( ...@@ -1072,6 +1043,9 @@ xfs_growfs_rt(
&tp); &tp);
if (error) if (error)
break; break;
args.tp = tp;
nargs.tp = tp;
/* /*
* Lock out other callers by grabbing the bitmap inode lock. * Lock out other callers by grabbing the bitmap inode lock.
*/ */
...@@ -1105,7 +1079,7 @@ xfs_growfs_rt( ...@@ -1105,7 +1079,7 @@ xfs_growfs_rt(
*/ */
if (sbp->sb_rbmblocks != nsbp->sb_rbmblocks || if (sbp->sb_rbmblocks != nsbp->sb_rbmblocks ||
mp->m_rsumlevels != nmp->m_rsumlevels) { mp->m_rsumlevels != nmp->m_rsumlevels) {
error = xfs_rtcopy_summary(mp, nmp, tp); error = xfs_rtcopy_summary(&args, &nargs);
if (error) if (error)
goto error_cancel; goto error_cancel;
} }
...@@ -1130,9 +1104,9 @@ xfs_growfs_rt( ...@@ -1130,9 +1104,9 @@ xfs_growfs_rt(
/* /*
* Free new extent. * Free new extent.
*/ */
bp = NULL; error = xfs_rtfree_range(&nargs, sbp->sb_rextents,
error = xfs_rtfree_range(nmp, tp, sbp->sb_rextents, nsbp->sb_rextents - sbp->sb_rextents);
nsbp->sb_rextents - sbp->sb_rextents, &bp, &sumbno); xfs_rtbuf_cache_relse(&nargs);
if (error) { if (error) {
error_cancel: error_cancel:
xfs_trans_cancel(tp); xfs_trans_cancel(tp);
...@@ -1190,24 +1164,25 @@ xfs_growfs_rt( ...@@ -1190,24 +1164,25 @@ xfs_growfs_rt(
* parameters. The length units are all in realtime extents, as is the * parameters. The length units are all in realtime extents, as is the
* result block number. * result block number.
*/ */
int /* error */ int
xfs_rtallocate_extent( xfs_rtallocate_extent(
xfs_trans_t *tp, /* transaction pointer */ struct xfs_trans *tp,
xfs_rtxnum_t start, /* starting rtext number to allocate */ xfs_rtxnum_t start, /* starting rtext number to allocate */
xfs_rtxlen_t minlen, /* minimum length to allocate */ xfs_rtxlen_t minlen, /* minimum length to allocate */
xfs_rtxlen_t maxlen, /* maximum length to allocate */ xfs_rtxlen_t maxlen, /* maximum length to allocate */
xfs_rtxlen_t *len, /* out: actual length allocated */ xfs_rtxlen_t *len, /* out: actual length allocated */
int wasdel, /* was a delayed allocation extent */ int wasdel, /* was a delayed allocation extent */
xfs_rtxlen_t prod, /* extent product factor */ xfs_rtxlen_t prod, /* extent product factor */
xfs_rtxnum_t *rtblock) /* out: start rtext allocated */ xfs_rtxnum_t *rtblock) /* out: start rtext allocated */
{ {
xfs_mount_t *mp = tp->t_mountp; struct xfs_rtalloc_args args = {
int error; /* error value */ .mp = tp->t_mountp,
xfs_rtxnum_t r; /* result allocated rtext */ .tp = tp,
xfs_fileoff_t sb; /* summary file block number */ };
struct xfs_buf *sumbp; /* summary file block buffer */ int error; /* error value */
xfs_rtxnum_t r; /* result allocated rtext */
ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
ASSERT(xfs_isilocked(args.mp->m_rbmip, XFS_ILOCK_EXCL));
ASSERT(minlen > 0 && minlen <= maxlen); ASSERT(minlen > 0 && minlen <= maxlen);
/* /*
...@@ -1227,15 +1202,15 @@ xfs_rtallocate_extent( ...@@ -1227,15 +1202,15 @@ xfs_rtallocate_extent(
} }
retry: retry:
sumbp = NULL;
if (start == 0) { if (start == 0) {
error = xfs_rtallocate_extent_size(mp, tp, minlen, maxlen, len, error = xfs_rtallocate_extent_size(&args, minlen,
&sumbp, &sb, prod, &r); maxlen, len, prod, &r);
} else { } else {
error = xfs_rtallocate_extent_near(mp, tp, start, minlen, maxlen, error = xfs_rtallocate_extent_near(&args, start, minlen,
len, &sumbp, &sb, prod, &r); maxlen, len, prod, &r);
} }
xfs_rtbuf_cache_relse(&args);
if (error) if (error)
return error; return error;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment