mirror of
https://github.com/torvalds/linux.git
synced 2026-06-03 03:53:37 +02:00
xfs: fixes for the realtime allocator [v4.2 4/8]
While I was reviewing how to integrate realtime allocation groups with the rt allocator, I noticed several bugs in the existing allocation code with regards to calculating the maximum range of rtx to scan for free space. This series fixes those range bugs and cleans up a few things too. I also added a few cleanups from Christoph. With a bit of luck, this should all go splendidly. Signed-off-by: Darrick J. Wong <djwong@kernel.org> -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQQ2qTKExjcn+O1o2YRKO3ySh0YRpgUCZtX/YwAKCRBKO3ySh0YR pmXZAQD5t79H7c1Za2WkLlOMLOdBNKZU5Rfbr3ZFXZDJ22pWewEAoFa3+8vH5o6i P3c9yP/H4+FfA4ZgMGIg/eS/2NvX1QQ= =n6pm -----END PGP SIGNATURE----- Merge tag 'rtalloc-fixes-6.12_2024-09-02' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux into xfs-6.12-mergeA xfs: fixes for the realtime allocator [v4.2 4/8] While I was reviewing how to integrate realtime allocation groups with the rt allocator, I noticed several bugs in the existing allocation code with regards to calculating the maximum range of rtx to scan for free space. This series fixes those range bugs and cleans up a few things too. I also added a few cleanups from Christoph. With a bit of luck, this should all go splendidly. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Chandan Babu R <chandanbabu@kernel.org> * tag 'rtalloc-fixes-6.12_2024-09-02' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux: xfs: simplify xfs_rtalloc_query_range xfs: remove xfs_rtb_to_rtxrem xfs: fix broken variable-sized allocation detection in xfs_rtallocate_extent_block xfs: reduce excessive clamping of maxlen in xfs_rtallocate_extent_near xfs: clean up xfs_rtallocate_extent_exact a bit xfs: refactor aligning bestlen to prod xfs: don't scan off the end of the rt volume in xfs_rtallocate_extent_block xfs: don't return too-short extents from xfs_rtallocate_extent_block xfs: ensure rtx mask/shift are correct after growfs xfs: use the recalculated transaction reservation in xfs_growfs_rt_bmblock
This commit is contained in:
commit
b2138a591c
|
|
@ -1022,25 +1022,24 @@ xfs_rtfree_blocks(
|
|||
xfs_filblks_t rtlen)
|
||||
{
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
xfs_rtxnum_t start;
|
||||
xfs_filblks_t len;
|
||||
xfs_extlen_t mod;
|
||||
|
||||
ASSERT(rtlen <= XFS_MAX_BMBT_EXTLEN);
|
||||
|
||||
len = xfs_rtb_to_rtxrem(mp, rtlen, &mod);
|
||||
mod = xfs_rtb_to_rtxoff(mp, rtlen);
|
||||
if (mod) {
|
||||
ASSERT(mod == 0);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
start = xfs_rtb_to_rtxrem(mp, rtbno, &mod);
|
||||
mod = xfs_rtb_to_rtxoff(mp, rtbno);
|
||||
if (mod) {
|
||||
ASSERT(mod == 0);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return xfs_rtfree_extent(tp, start, len);
|
||||
return xfs_rtfree_extent(tp, xfs_rtb_to_rtx(mp, rtbno),
|
||||
xfs_rtb_to_rtx(mp, rtlen));
|
||||
}
|
||||
|
||||
/* Find all the free records within a given range. */
|
||||
|
|
@ -1048,8 +1047,8 @@ 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,
|
||||
xfs_rtxnum_t start,
|
||||
xfs_rtxnum_t end,
|
||||
xfs_rtalloc_query_range_fn fn,
|
||||
void *priv)
|
||||
{
|
||||
|
|
@ -1057,45 +1056,42 @@ xfs_rtalloc_query_range(
|
|||
.mp = mp,
|
||||
.tp = tp,
|
||||
};
|
||||
struct xfs_rtalloc_rec rec;
|
||||
xfs_rtxnum_t rtstart;
|
||||
xfs_rtxnum_t rtend;
|
||||
xfs_rtxnum_t high_key;
|
||||
int is_free;
|
||||
int error = 0;
|
||||
|
||||
if (low_rec->ar_startext > high_rec->ar_startext)
|
||||
if (start > end)
|
||||
return -EINVAL;
|
||||
if (low_rec->ar_startext >= mp->m_sb.sb_rextents ||
|
||||
low_rec->ar_startext == high_rec->ar_startext)
|
||||
if (start == end || start >= mp->m_sb.sb_rextents)
|
||||
return 0;
|
||||
|
||||
high_key = min(high_rec->ar_startext, mp->m_sb.sb_rextents - 1);
|
||||
end = min(end, mp->m_sb.sb_rextents - 1);
|
||||
|
||||
/* Iterate the bitmap, looking for discrepancies. */
|
||||
rtstart = low_rec->ar_startext;
|
||||
while (rtstart <= high_key) {
|
||||
while (start <= end) {
|
||||
struct xfs_rtalloc_rec rec;
|
||||
int is_free;
|
||||
xfs_rtxnum_t rtend;
|
||||
|
||||
/* Is the first block free? */
|
||||
error = xfs_rtcheck_range(&args, rtstart, 1, 1, &rtend,
|
||||
error = xfs_rtcheck_range(&args, start, 1, 1, &rtend,
|
||||
&is_free);
|
||||
if (error)
|
||||
break;
|
||||
|
||||
/* How long does the extent go for? */
|
||||
error = xfs_rtfind_forw(&args, rtstart, high_key, &rtend);
|
||||
error = xfs_rtfind_forw(&args, start, end, &rtend);
|
||||
if (error)
|
||||
break;
|
||||
|
||||
if (is_free) {
|
||||
rec.ar_startext = rtstart;
|
||||
rec.ar_extcount = rtend - rtstart + 1;
|
||||
rec.ar_startext = start;
|
||||
rec.ar_extcount = rtend - start + 1;
|
||||
|
||||
error = fn(mp, tp, &rec, priv);
|
||||
if (error)
|
||||
break;
|
||||
}
|
||||
|
||||
rtstart = rtend + 1;
|
||||
start = rtend + 1;
|
||||
}
|
||||
|
||||
xfs_rtbuf_cache_relse(&args);
|
||||
|
|
@ -1110,13 +1106,8 @@ xfs_rtalloc_query_all(
|
|||
xfs_rtalloc_query_range_fn fn,
|
||||
void *priv)
|
||||
{
|
||||
struct xfs_rtalloc_rec keys[2];
|
||||
|
||||
keys[0].ar_startext = 0;
|
||||
keys[1].ar_startext = mp->m_sb.sb_rextents - 1;
|
||||
keys[0].ar_extcount = keys[1].ar_extcount = 0;
|
||||
|
||||
return xfs_rtalloc_query_range(mp, tp, &keys[0], &keys[1], fn, priv);
|
||||
return xfs_rtalloc_query_range(mp, tp, 0, mp->m_sb.sb_rextents - 1, fn,
|
||||
priv);
|
||||
}
|
||||
|
||||
/* Is the given extent all free? */
|
||||
|
|
|
|||
|
|
@ -86,24 +86,6 @@ xfs_rtb_to_rtxoff(
|
|||
return do_div(rtbno, mp->m_sb.sb_rextsize);
|
||||
}
|
||||
|
||||
/*
|
||||
* Crack an rt block number into an rt extent number and an offset within that
|
||||
* rt extent. Returns the rt extent number directly and the offset in @off.
|
||||
*/
|
||||
static inline xfs_rtxnum_t
|
||||
xfs_rtb_to_rtxrem(
|
||||
struct xfs_mount *mp,
|
||||
xfs_rtblock_t rtbno,
|
||||
xfs_extlen_t *off)
|
||||
{
|
||||
if (likely(mp->m_rtxblklog >= 0)) {
|
||||
*off = rtbno & mp->m_rtxblkmask;
|
||||
return rtbno >> mp->m_rtxblklog;
|
||||
}
|
||||
|
||||
return div_u64_rem(rtbno, mp->m_sb.sb_rextsize, off);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an rt block number into an rt extent number, rounding up to the next
|
||||
* rt extent if the rt block is not aligned to an rt extent boundary.
|
||||
|
|
@ -310,8 +292,7 @@ int xfs_rtmodify_summary(struct xfs_rtalloc_args *args, int log,
|
|||
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,
|
||||
const struct xfs_rtalloc_rec *low_rec,
|
||||
const struct xfs_rtalloc_rec *high_rec,
|
||||
xfs_rtxnum_t start, xfs_rtxnum_t end,
|
||||
xfs_rtalloc_query_range_fn fn, void *priv);
|
||||
int xfs_rtalloc_query_all(struct xfs_mount *mp, struct xfs_trans *tp,
|
||||
xfs_rtalloc_query_range_fn fn,
|
||||
|
|
|
|||
|
|
@ -965,6 +965,15 @@ const struct xfs_buf_ops xfs_sb_quiet_buf_ops = {
|
|||
.verify_write = xfs_sb_write_verify,
|
||||
};
|
||||
|
||||
void
|
||||
xfs_mount_sb_set_rextsize(
|
||||
struct xfs_mount *mp,
|
||||
struct xfs_sb *sbp)
|
||||
{
|
||||
mp->m_rtxblklog = log2_if_power2(sbp->sb_rextsize);
|
||||
mp->m_rtxblkmask = mask64_if_power2(sbp->sb_rextsize);
|
||||
}
|
||||
|
||||
/*
|
||||
* xfs_mount_common
|
||||
*
|
||||
|
|
@ -989,8 +998,7 @@ xfs_sb_mount_common(
|
|||
mp->m_blockmask = sbp->sb_blocksize - 1;
|
||||
mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG;
|
||||
mp->m_blockwmask = mp->m_blockwsize - 1;
|
||||
mp->m_rtxblklog = log2_if_power2(sbp->sb_rextsize);
|
||||
mp->m_rtxblkmask = mask64_if_power2(sbp->sb_rextsize);
|
||||
xfs_mount_sb_set_rextsize(mp, sbp);
|
||||
|
||||
mp->m_alloc_mxr[0] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 1);
|
||||
mp->m_alloc_mxr[1] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 0);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ extern void xfs_log_sb(struct xfs_trans *tp);
|
|||
extern int xfs_sync_sb(struct xfs_mount *mp, bool wait);
|
||||
extern int xfs_sync_sb_buf(struct xfs_mount *mp);
|
||||
extern void xfs_sb_mount_common(struct xfs_mount *mp, struct xfs_sb *sbp);
|
||||
void xfs_mount_sb_set_rextsize(struct xfs_mount *mp,
|
||||
struct xfs_sb *sbp);
|
||||
extern void xfs_sb_from_disk(struct xfs_sb *to, struct xfs_dsb *from);
|
||||
extern void xfs_sb_to_disk(struct xfs_dsb *to, struct xfs_sb *from);
|
||||
extern void xfs_sb_quota_from_disk(struct xfs_sb *sbp);
|
||||
|
|
|
|||
|
|
@ -554,11 +554,10 @@ xfs_trim_rtdev_extents(
|
|||
xfs_daddr_t end,
|
||||
xfs_daddr_t minlen)
|
||||
{
|
||||
struct xfs_rtalloc_rec low = { };
|
||||
struct xfs_rtalloc_rec high = { };
|
||||
struct xfs_trim_rtdev tr = {
|
||||
.minlen_fsb = XFS_BB_TO_FSB(mp, minlen),
|
||||
};
|
||||
xfs_rtxnum_t low, high;
|
||||
struct xfs_trans *tp;
|
||||
xfs_daddr_t rtdev_daddr;
|
||||
int error;
|
||||
|
|
@ -584,17 +583,17 @@ xfs_trim_rtdev_extents(
|
|||
XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks) - 1);
|
||||
|
||||
/* Convert the rt blocks to rt extents */
|
||||
low.ar_startext = xfs_rtb_to_rtxup(mp, XFS_BB_TO_FSB(mp, start));
|
||||
high.ar_startext = xfs_rtb_to_rtx(mp, XFS_BB_TO_FSBT(mp, end));
|
||||
low = xfs_rtb_to_rtxup(mp, XFS_BB_TO_FSB(mp, start));
|
||||
high = xfs_rtb_to_rtx(mp, XFS_BB_TO_FSBT(mp, end));
|
||||
|
||||
/*
|
||||
* Walk the free ranges between low and high. The query_range function
|
||||
* trims the extents returned.
|
||||
*/
|
||||
do {
|
||||
tr.stop_rtx = low.ar_startext + (mp->m_sb.sb_blocksize * NBBY);
|
||||
tr.stop_rtx = low + (mp->m_sb.sb_blocksize * NBBY);
|
||||
xfs_rtbitmap_lock_shared(mp, XFS_RBMLOCK_BITMAP);
|
||||
error = xfs_rtalloc_query_range(mp, tp, &low, &high,
|
||||
error = xfs_rtalloc_query_range(mp, tp, low, high,
|
||||
xfs_trim_gather_rtextent, &tr);
|
||||
|
||||
if (error == -ECANCELED)
|
||||
|
|
@ -615,8 +614,8 @@ xfs_trim_rtdev_extents(
|
|||
if (error)
|
||||
break;
|
||||
|
||||
low.ar_startext = tr.restart_rtx;
|
||||
} while (!xfs_trim_should_stop() && low.ar_startext <= high.ar_startext);
|
||||
low = tr.restart_rtx;
|
||||
} while (!xfs_trim_should_stop() && low <= high);
|
||||
|
||||
xfs_trans_cancel(tp);
|
||||
return error;
|
||||
|
|
|
|||
|
|
@ -520,11 +520,11 @@ xfs_getfsmap_rtdev_rtbitmap(
|
|||
struct xfs_getfsmap_info *info)
|
||||
{
|
||||
|
||||
struct xfs_rtalloc_rec alow = { 0 };
|
||||
struct xfs_rtalloc_rec ahigh = { 0 };
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
xfs_rtblock_t start_rtb;
|
||||
xfs_rtblock_t end_rtb;
|
||||
xfs_rtxnum_t high;
|
||||
uint64_t eofs;
|
||||
int error;
|
||||
|
||||
|
|
@ -553,10 +553,9 @@ xfs_getfsmap_rtdev_rtbitmap(
|
|||
* Set up query parameters to return free rtextents covering the range
|
||||
* we want.
|
||||
*/
|
||||
alow.ar_startext = xfs_rtb_to_rtx(mp, start_rtb);
|
||||
ahigh.ar_startext = xfs_rtb_to_rtxup(mp, end_rtb);
|
||||
error = xfs_rtalloc_query_range(mp, tp, &alow, &ahigh,
|
||||
xfs_getfsmap_rtdev_rtbitmap_helper, info);
|
||||
high = xfs_rtb_to_rtxup(mp, end_rtb);
|
||||
error = xfs_rtalloc_query_range(mp, tp, xfs_rtb_to_rtx(mp, start_rtb),
|
||||
high, xfs_getfsmap_rtdev_rtbitmap_helper, info);
|
||||
if (error)
|
||||
goto err;
|
||||
|
||||
|
|
@ -565,7 +564,7 @@ xfs_getfsmap_rtdev_rtbitmap(
|
|||
* rmap starting at the block after the end of the query range.
|
||||
*/
|
||||
info->last = true;
|
||||
ahigh.ar_startext = min(mp->m_sb.sb_rextents, ahigh.ar_startext);
|
||||
ahigh.ar_startext = min(mp->m_sb.sb_rextents, high);
|
||||
|
||||
error = xfs_getfsmap_rtdev_rtbitmap_helper(mp, tp, &ahigh, info);
|
||||
if (error)
|
||||
|
|
|
|||
|
|
@ -194,6 +194,17 @@ xfs_rtallocate_range(
|
|||
return xfs_rtmodify_range(args, start, len, 0);
|
||||
}
|
||||
|
||||
/* Reduce @rtxlen until it is a multiple of @prod. */
|
||||
static inline xfs_rtxlen_t
|
||||
xfs_rtalloc_align_len(
|
||||
xfs_rtxlen_t rtxlen,
|
||||
xfs_rtxlen_t prod)
|
||||
{
|
||||
if (unlikely(prod > 1))
|
||||
return rounddown(rtxlen, prod);
|
||||
return rtxlen;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure we don't run off the end of the rt volume. Be careful that
|
||||
* adjusting maxlen downwards doesn't cause us to fail the alignment checks.
|
||||
|
|
@ -208,7 +219,7 @@ xfs_rtallocate_clamp_len(
|
|||
xfs_rtxlen_t ret;
|
||||
|
||||
ret = min(mp->m_sb.sb_rextents, startrtx + rtxlen) - startrtx;
|
||||
return rounddown(ret, prod);
|
||||
return xfs_rtalloc_align_len(ret, prod);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -229,37 +240,38 @@ xfs_rtallocate_extent_block(
|
|||
xfs_rtxnum_t *rtx) /* out: start rtext allocated */
|
||||
{
|
||||
struct xfs_mount *mp = args->mp;
|
||||
xfs_rtxnum_t besti; /* best rtext found so far */
|
||||
xfs_rtxnum_t bestlen;/* best length found so far */
|
||||
xfs_rtxnum_t besti = -1; /* best rtext found so far */
|
||||
xfs_rtxnum_t end; /* last rtext in chunk */
|
||||
int error;
|
||||
xfs_rtxnum_t i; /* current rtext trying */
|
||||
xfs_rtxnum_t next; /* next rtext to try */
|
||||
xfs_rtxlen_t scanlen; /* number of free rtx to look for */
|
||||
xfs_rtxlen_t bestlen = 0; /* best length found so far */
|
||||
int stat; /* status from internal calls */
|
||||
int error;
|
||||
|
||||
/*
|
||||
* Loop over all the extents starting in this bitmap block,
|
||||
* looking for one that's long enough.
|
||||
* Loop over all the extents starting in this bitmap block up to the
|
||||
* end of the rt volume, looking for one that's long enough.
|
||||
*/
|
||||
for (i = xfs_rbmblock_to_rtx(mp, bbno), besti = -1, bestlen = 0,
|
||||
end = xfs_rbmblock_to_rtx(mp, bbno + 1) - 1;
|
||||
i <= end;
|
||||
i++) {
|
||||
end = min(mp->m_sb.sb_rextents, xfs_rbmblock_to_rtx(mp, bbno + 1)) - 1;
|
||||
for (i = xfs_rbmblock_to_rtx(mp, bbno); i <= end; i++) {
|
||||
/* Make sure we don't scan off the end of the rt volume. */
|
||||
maxlen = xfs_rtallocate_clamp_len(mp, i, maxlen, prod);
|
||||
scanlen = xfs_rtallocate_clamp_len(mp, i, maxlen, prod);
|
||||
if (scanlen < minlen)
|
||||
break;
|
||||
|
||||
/*
|
||||
* See if there's a free extent of maxlen starting at i.
|
||||
* See if there's a free extent of scanlen starting at i.
|
||||
* If it's not so then next will contain the first non-free.
|
||||
*/
|
||||
error = xfs_rtcheck_range(args, i, maxlen, 1, &next, &stat);
|
||||
error = xfs_rtcheck_range(args, i, scanlen, 1, &next, &stat);
|
||||
if (error)
|
||||
return error;
|
||||
if (stat) {
|
||||
/*
|
||||
* i for maxlen is all free, allocate and return that.
|
||||
* i to scanlen is all free, allocate and return that.
|
||||
*/
|
||||
*len = maxlen;
|
||||
*len = scanlen;
|
||||
*rtx = i;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -289,27 +301,17 @@ xfs_rtallocate_extent_block(
|
|||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Searched the whole thing & didn't find a maxlen free extent.
|
||||
*/
|
||||
if (minlen > maxlen || besti == -1) {
|
||||
/*
|
||||
* Allocation failed. Set *nextp to the next block to try.
|
||||
*/
|
||||
*nextp = next;
|
||||
return -ENOSPC;
|
||||
}
|
||||
/* Searched the whole thing & didn't find a maxlen free extent. */
|
||||
if (besti == -1)
|
||||
goto nospace;
|
||||
|
||||
/*
|
||||
* If size should be a multiple of prod, make that so.
|
||||
* Ensure bestlen is a multiple of prod, but don't return a too-short
|
||||
* extent.
|
||||
*/
|
||||
if (prod > 1) {
|
||||
xfs_rtxlen_t p; /* amount to trim length by */
|
||||
|
||||
div_u64_rem(bestlen, prod, &p);
|
||||
if (p)
|
||||
bestlen -= p;
|
||||
}
|
||||
bestlen = xfs_rtalloc_align_len(bestlen, prod);
|
||||
if (bestlen < minlen)
|
||||
goto nospace;
|
||||
|
||||
/*
|
||||
* Pick besti for bestlen & return that.
|
||||
|
|
@ -317,6 +319,10 @@ xfs_rtallocate_extent_block(
|
|||
*len = bestlen;
|
||||
*rtx = besti;
|
||||
return 0;
|
||||
nospace:
|
||||
/* Allocation failed. Set *nextp to the next block to try. */
|
||||
*nextp = next;
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -335,39 +341,46 @@ xfs_rtallocate_extent_exact(
|
|||
xfs_rtxlen_t prod, /* extent product factor */
|
||||
xfs_rtxnum_t *rtx) /* out: start rtext allocated */
|
||||
{
|
||||
int error;
|
||||
xfs_rtxlen_t i; /* extent length trimmed due to prod */
|
||||
int isfree; /* extent is free */
|
||||
struct xfs_mount *mp = args->mp;
|
||||
xfs_rtxnum_t next; /* next rtext to try (dummy) */
|
||||
xfs_rtxlen_t alloclen; /* candidate length */
|
||||
xfs_rtxlen_t scanlen; /* number of free rtx to look for */
|
||||
int isfree; /* extent is free */
|
||||
int error;
|
||||
|
||||
ASSERT(minlen % prod == 0);
|
||||
ASSERT(maxlen % prod == 0);
|
||||
/*
|
||||
* Check if the range in question (for maxlen) is free.
|
||||
*/
|
||||
error = xfs_rtcheck_range(args, start, maxlen, 1, &next, &isfree);
|
||||
|
||||
/* Make sure we don't run off the end of the rt volume. */
|
||||
scanlen = xfs_rtallocate_clamp_len(mp, start, maxlen, prod);
|
||||
if (scanlen < minlen)
|
||||
return -ENOSPC;
|
||||
|
||||
/* Check if the range in question (for scanlen) is free. */
|
||||
error = xfs_rtcheck_range(args, start, scanlen, 1, &next, &isfree);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (!isfree) {
|
||||
/*
|
||||
* If not, allocate what there is, if it's at least minlen.
|
||||
*/
|
||||
maxlen = next - start;
|
||||
if (maxlen < minlen)
|
||||
return -ENOSPC;
|
||||
|
||||
/*
|
||||
* Trim off tail of extent, if prod is specified.
|
||||
*/
|
||||
if (prod > 1 && (i = maxlen % prod)) {
|
||||
maxlen -= i;
|
||||
if (maxlen < minlen)
|
||||
return -ENOSPC;
|
||||
}
|
||||
if (isfree) {
|
||||
/* start to scanlen is all free; allocate it. */
|
||||
*len = scanlen;
|
||||
*rtx = start;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*len = maxlen;
|
||||
/*
|
||||
* If not, allocate what there is, if it's at least minlen.
|
||||
*/
|
||||
alloclen = next - start;
|
||||
if (alloclen < minlen)
|
||||
return -ENOSPC;
|
||||
|
||||
/* Ensure alloclen is a multiple of prod. */
|
||||
alloclen = xfs_rtalloc_align_len(alloclen, prod);
|
||||
if (alloclen < minlen)
|
||||
return -ENOSPC;
|
||||
|
||||
*len = alloclen;
|
||||
*rtx = start;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -406,11 +419,6 @@ xfs_rtallocate_extent_near(
|
|||
if (start >= mp->m_sb.sb_rextents)
|
||||
start = mp->m_sb.sb_rextents - 1;
|
||||
|
||||
/* Make sure we don't run off the end of the rt volume. */
|
||||
maxlen = xfs_rtallocate_clamp_len(mp, start, maxlen, prod);
|
||||
if (maxlen < minlen)
|
||||
return -ENOSPC;
|
||||
|
||||
/*
|
||||
* Try the exact allocation first.
|
||||
*/
|
||||
|
|
@ -719,8 +727,8 @@ xfs_growfs_rt_bmblock(
|
|||
/*
|
||||
* Calculate new sb and mount fields for this round.
|
||||
*/
|
||||
nmp->m_rtxblklog = -1; /* don't use shift or masking */
|
||||
nmp->m_sb.sb_rextsize = rextsize;
|
||||
xfs_mount_sb_set_rextsize(nmp, &nmp->m_sb);
|
||||
nmp->m_sb.sb_rbmblocks = bmbno + 1;
|
||||
nmp->m_sb.sb_rblocks = min(nrblocks, nrblocks_step);
|
||||
nmp->m_sb.sb_rextents = xfs_rtb_to_rtx(nmp, nmp->m_sb.sb_rblocks);
|
||||
|
|
@ -730,10 +738,12 @@ xfs_growfs_rt_bmblock(
|
|||
xfs_rtsummary_blockcount(mp, nmp->m_rsumlevels,
|
||||
nmp->m_sb.sb_rbmblocks));
|
||||
|
||||
/* recompute growfsrt reservation from new rsumsize */
|
||||
/*
|
||||
* Recompute the growfsrt reservation from the new rsumsize, so that the
|
||||
* transaction below use the new, potentially larger value.
|
||||
* */
|
||||
xfs_trans_resv_calc(nmp, &nmp->m_resv);
|
||||
|
||||
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growrtfree, 0, 0, 0,
|
||||
error = xfs_trans_alloc(mp, &M_RES(nmp)->tr_growrtfree, 0, 0, 0,
|
||||
&args.tp);
|
||||
if (error)
|
||||
goto out_free;
|
||||
|
|
@ -805,10 +815,11 @@ xfs_growfs_rt_bmblock(
|
|||
xfs_trans_mod_sb(args.tp, XFS_TRANS_SB_FREXTENTS, freed_rtx);
|
||||
|
||||
/*
|
||||
* Update mp values into the real mp structure.
|
||||
* Update the calculated values in the real mount structure.
|
||||
*/
|
||||
mp->m_rsumlevels = nmp->m_rsumlevels;
|
||||
mp->m_rsumsize = nmp->m_rsumsize;
|
||||
xfs_mount_sb_set_rextsize(mp, &mp->m_sb);
|
||||
|
||||
/*
|
||||
* Recompute the growfsrt reservation from the new rsumsize.
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user