// SPDX-License-Identifier: GPL-2.0/* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. */#include "xfs_platform.h"#include "xfs_fs.h"#include "xfs_shared.h"#include "xfs_format.h"#include "xfs_log_format.h"#include "xfs_trans_resv.h"#include "xfs_bit.h"#include "xfs_mount.h"#include "xfs_inode.h"#include "xfs_alloc.h"#include "xfs_bmap.h"#include "xfs_bmap_btree.h"#include "xfs_bmap_util.h"#include "xfs_trans.h"#include "xfs_trans_space.h"#include "xfs_icache.h"#include "xfs_rtalloc.h"#include "xfs_sb.h"#include "xfs_rtbitmap.h"#include "xfs_rtrmap_btree.h"#include "xfs_quota.h"#include "xfs_log_priv.h"#include "xfs_health.h"#include "xfs_da_format.h"#include "xfs_metafile.h"#include "xfs_rtgroup.h"#include "xfs_error.h"#include "xfs_trace.h"#include "xfs_rtrefcount_btree.h"#include "xfs_reflink.h"#include "xfs_zone_alloc.h" /* * Return whether there are any free extents in the size range given * by low and high, for the bitmap block bbno. */STATIC intxfs_rtany_summary( struct xfs_rtalloc_args *args, int low, /* low log2 extent size */ int high, /* high log2 extent size */ xfs_fileoff_t bbno, /* bitmap block number */ int *maxlog) /* out: max log2 extent size free */{ uint8_t *rsum_cache = args->rtg->rtg_rsum_cache; int error; int log; /* loop counter, log2 of ext. size */ xfs_suminfo_t sum; /* summary data */ /* There are no extents at levels >= rsum_cache[bbno]. */ if (rsum_cache) { high = min(high, rsum_cache[bbno] - 1); if (low > high) { *maxlog = -1; return 0; } } /* * Loop over logs of extent sizes. */ for (log = high; log >= low; log--) { /* * Get one summary datum. */ error = xfs_rtget_summary(args, log, bbno, &sum); if (error) { return error; } /* * If there are any, return success. */ if (sum) { *maxlog = log; goto out; } } /* * Found nothing, return failure. */ *maxlog = -1;out: /* There were no extents at levels > log. */ if (rsum_cache && log + 1 < rsum_cache[bbno]) rsum_cache[bbno] = log + 1; return 0;} /* * Copy and transform the summary file, given the old and new * parameters in the mount structures. */STATIC intxfs_rtcopy_summary( struct xfs_rtalloc_args *oargs, struct xfs_rtalloc_args *nargs){ xfs_fileoff_t bbno; /* bitmap block number */ int error; int log; /* summary level number (log length) */ xfs_suminfo_t sum; /* summary data */ for (log = oargs->mp->m_rsumlevels - 1; log >= 0; log--) { for (bbno = oargs->mp->m_sb.sb_rbmblocks - 1; (xfs_srtblock_t)bbno >= 0; bbno--) { error = xfs_rtget_summary(oargs, log, bbno, &sum); if (error) goto out; if (XFS_IS_CORRUPT(oargs->mp, sum < 0)) { error = -EFSCORRUPTED; goto out; } if (sum == 0) continue; error = xfs_rtmodify_summary(oargs, log, bbno, -sum); if (error) goto out; error = xfs_rtmodify_summary(nargs, log, bbno, sum); if (error) goto out; } } error = 0;out: xfs_rtbuf_cache_relse(oargs); return error;}/* * Mark an extent specified by start and len allocated. * Updates all the summary information as well as the bitmap. */STATIC intxfs_rtallocate_range( struct xfs_rtalloc_args *args, xfs_rtxnum_t start, /* start rtext to allocate */ xfs_rtxlen_t len) /* in/out: summary block number */{ struct xfs_mount *mp = args->mp; xfs_rtxnum_t end; /* end of the allocated rtext */ int error; xfs_rtxnum_t postblock = 0; /* first rtext allocated > end */ xfs_rtxnum_t preblock = 0; /* first rtext allocated < start */ end = start + len - 1; /* * Assume we're allocating out of the middle of a free extent. * We need to find the beginning and end of the extent so we can * properly update the summary. */ error = xfs_rtfind_back(args, start, &preblock); if (error) return error; /* * Find the next allocated block (end of free extent). */ error = xfs_rtfind_forw(args, end, args->rtg->rtg_extents - 1, &postblock); if (error) return error; /* * Decrement the summary information corresponding to the entire * (old) free extent. */ error = xfs_rtmodify_summary(args, xfs_highbit64(postblock + 1 - preblock), xfs_rtx_to_rbmblock(mp, preblock), -1); if (error) return error; /* * If there are blocks not being allocated at the front of the * old extent, add summary data for them to be free. */ if (preblock < start) { error = xfs_rtmodify_summary(args, xfs_highbit64(start - preblock), xfs_rtx_to_rbmblock(mp, preblock), 1); if (error) return error; } /* * If there are blocks not being allocated at the end of the * old extent, add summary data for them to be free. */ if (postblock > end) { error = xfs_rtmodify_summary(args, xfs_highbit64(postblock - end), xfs_rtx_to_rbmblock(mp, end + 1), 1); if (error) return error; } /* * Modify the bitmap to mark this extent allocated. */ return xfs_rtmodify_range(args, start, len, 0);} /* Reduce @rtxlen until it is a multiple of @prod. */static inline xfs_rtxlen_txfs_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. */static inline xfs_rtxlen_txfs_rtallocate_clamp_len( struct xfs_rtgroup *rtg, xfs_rtxnum_t startrtx, xfs_rtxlen_t rtxlen, xfs_rtxlen_t prod){ xfs_rtxlen_t ret; ret = min(rtg->rtg_extents, startrtx + rtxlen) - startrtx; return xfs_rtalloc_align_len(ret, prod);} /* * Attempt to allocate an extent minlen<=len<=maxlen starting from * bitmap block bbno. If we don't get maxlen then use prod to trim * the length, if given. Returns error; returns starting block in *rtx. * The lengths are all in rtextents. */STATIC intxfs_rtallocate_extent_block( struct xfs_rtalloc_args *args, xfs_fileoff_t bbno, /* bitmap block number */ xfs_rtxlen_t minlen, /* minimum length to allocate */ xfs_rtxlen_t maxlen, /* maximum length to allocate */ xfs_rtxlen_t *len, /* out: actual length allocated */ xfs_rtxnum_t *nextp, /* out: next rtext to try */ xfs_rtxlen_t prod, /* extent product factor */ xfs_rtxnum_t *rtx) /* out: start rtext allocated */{ struct xfs_mount *mp = args->mp; xfs_rtxnum_t besti = -1; /* best rtext found so far */ xfs_rtxnum_t end; /* last rtext in chunk */ 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 up to the * end of the rt volume, looking for one that's long enough. */ end = min(args->rtg->rtg_extents, 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. */ scanlen = xfs_rtallocate_clamp_len(args->rtg, i, maxlen, prod); if (scanlen < minlen) break; /* * 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, scanlen, 1, &next, &stat); if (error) return error; if (stat) { /* * i to scanlen is all free, allocate and return that. */ *len = scanlen; *rtx = i; return 0; } /* * In the case where we have a variable-sized allocation * request, figure out how big this free piece is, * and if it's big enough for the minimum, and the best * so far, remember it. */ if (minlen < maxlen) { xfs_rtxnum_t thislen; /* this extent size */ thislen = next - i; if (thislen >= minlen && thislen > bestlen) { besti = i; bestlen = thislen; } } /* * If not done yet, find the start of the next free space. */ if (next >= end) break; error = xfs_rtfind_forw(args, next, end, &i); if (error) return error; } /* Searched the whole thing & didn't find a maxlen free extent. */ if (besti == -1) goto nospace; /* * Ensure bestlen is a multiple of prod, but don't return a too-short * extent. */ bestlen = xfs_rtalloc_align_len(bestlen, prod); if (bestlen < minlen) goto nospace; /* * Pick besti for bestlen & return that. */ *len = bestlen; *rtx = besti; return 0;nospace: /* Allocation failed. Set *nextp to the next block to try. */ *nextp = next; return -ENOSPC;} /* * Allocate an extent of length minlen<=len<=maxlen, starting at block * bno. If we don't get maxlen then use prod to trim the length, if given. * Returns error; returns starting block in *rtx. * The lengths are all in rtextents. */STATIC intxfs_rtallocate_extent_exact( struct xfs_rtalloc_args *args, xfs_rtxnum_t start, /* starting rtext number to allocate */ xfs_rtxlen_t minlen, /* minimum length to allocate */ xfs_rtxlen_t maxlen, /* maximum length to allocate */ xfs_rtxlen_t *len, /* out: actual length allocated */ xfs_rtxlen_t prod, /* extent product factor */ xfs_rtxnum_t *rtx) /* out: start rtext allocated */{ 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); /* Make sure we don't run off the end of the rt volume. */ scanlen = xfs_rtallocate_clamp_len(args->rtg, 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) { /* start to scanlen is all free; allocate it. */ *len = scanlen; *rtx = start; return 0; } /* * 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;} /* * Allocate an extent of length minlen<=len<=maxlen, starting as near * 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. */STATIC intxfs_rtallocate_extent_near( struct xfs_rtalloc_args *args, xfs_rtxnum_t start, /* starting rtext number to allocate */ xfs_rtxlen_t minlen, /* minimum length to allocate */ xfs_rtxlen_t maxlen, /* maximum length to allocate */ xfs_rtxlen_t *len, /* out: actual length allocated */ xfs_rtxlen_t prod, /* extent product factor */ xfs_rtxnum_t *rtx) /* out: start rtext allocated */{ struct xfs_mount *mp = args->mp; int maxlog; /* max useful extent from summary */ xfs_fileoff_t bbno; /* bitmap block number */ int error; int i; /* bitmap block offset (loop control) */ int j; /* secondary loop control */ int log2len; /* log2 of minlen */ xfs_rtxnum_t n; /* next rtext to try */ ASSERT(minlen % prod == 0); ASSERT(maxlen % prod == 0); /* * If the block number given is off the end, silently set it to the last * block. */ start = min(start, args->rtg->rtg_extents - 1); /* * Try the exact allocation first. */ error = xfs_rtallocate_extent_exact(args, start, minlen, maxlen, len, prod, rtx); if (error != -ENOSPC) return error; bbno = xfs_rtx_to_rbmblock(mp, start); i = 0; j = -1; ASSERT(minlen != 0); log2len = xfs_highbit32(minlen); /* * Loop over all bitmap blocks (bbno + i is current block). */ for (;;) { /* * Get summary information of extents of all useful levels * starting in this bitmap block. */ error = xfs_rtany_summary(args, log2len, mp->m_rsumlevels - 1, bbno + i, &maxlog); if (error) return error; /* * If there are any useful extents starting here, try * allocating one. */ 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. */ if (i >= 0) { /* * Try to allocate an extent starting in * this block. */ error = xfs_rtallocate_extent_block(args, bbno + i, minlen, maxavail, len, &n, prod, rtx); if (error != -ENOSPC) return error; } /* * On the negative side of the starting location. */ else { /* i < 0 */ int maxblocks; /* * Loop backwards to find the end of the extent * we found in the realtime summary. * * maxblocks is the maximum possible number of * bitmap blocks from the start of the extent * to the end of the extent. */ if (maxlog == 0) maxblocks = 0; else if (maxlog < mp->m_blkbit_log) maxblocks = 1; else maxblocks = 2 << (maxlog - mp->m_blkbit_log); Lines 1–500 of 2223. Load more
// SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. */ #include "xfs_platform.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_mount.h" #include "xfs_inode.h" #include "xfs_alloc.h" #include "xfs_bmap.h" #include "xfs_bmap_btree.h" #include "xfs_bmap_util.h" #include "xfs_trans.h" #include "xfs_trans_space.h" #include "xfs_icache.h" #include "xfs_rtalloc.h" #include "xfs_sb.h" #include "xfs_rtbitmap.h" #include "xfs_rtrmap_btree.h" #include "xfs_quota.h" #include "xfs_log_priv.h" #include "xfs_health.h" #include "xfs_da_format.h" #include "xfs_metafile.h" #include "xfs_rtgroup.h" #include "xfs_error.h" #include "xfs_trace.h" #include "xfs_rtrefcount_btree.h" #include "xfs_reflink.h" #include "xfs_zone_alloc.h" /* * Return whether there are any free extents in the size range given * by low and high, for the bitmap block bbno. */ STATIC int xfs_rtany_summary( struct xfs_rtalloc_args *args, int low, /* low log2 extent size */ int high, /* high log2 extent size */ xfs_fileoff_t bbno, /* bitmap block number */ int *maxlog) /* out: max log2 extent size free */ { uint8_t *rsum_cache = args->rtg->rtg_rsum_cache; int error; int log; /* loop counter, log2 of ext. size */ xfs_suminfo_t sum; /* summary data */ /* There are no extents at levels >= rsum_cache[bbno]. */ if (rsum_cache) { high = min(high, rsum_cache[bbno] - 1); if (low > high) { *maxlog = -1; return 0; } } /* * Loop over logs of extent sizes. */ for (log = high; log >= low; log--) { /* * Get one summary datum. */ error = xfs_rtget_summary(args, log, bbno, &sum); if (error) { return error; } /* * If there are any, return success. */ if (sum) { *maxlog = log; goto out; } } /* * Found nothing, return failure. */ *maxlog = -1; out: /* There were no extents at levels > log. */ if (rsum_cache && log + 1 < rsum_cache[bbno]) rsum_cache[bbno] = log + 1; return 0; } /* * Copy and transform the summary file, given the old and new * parameters in the mount structures. */ STATIC int xfs_rtcopy_summary( struct xfs_rtalloc_args *oargs, struct xfs_rtalloc_args *nargs) { xfs_fileoff_t bbno; /* bitmap block number */ int error; int log; /* summary level number (log length) */ xfs_suminfo_t sum; /* summary data */ for (log = oargs->mp->m_rsumlevels - 1; log >= 0; log--) { for (bbno = oargs->mp->m_sb.sb_rbmblocks - 1; (xfs_srtblock_t)bbno >= 0; bbno--) { error = xfs_rtget_summary(oargs, log, bbno, &sum); if (error) goto out; if (XFS_IS_CORRUPT(oargs->mp, sum < 0)) { error = -EFSCORRUPTED; goto out; } if (sum == 0) continue; error = xfs_rtmodify_summary(oargs, log, bbno, -sum); if (error) goto out; error = xfs_rtmodify_summary(nargs, log, bbno, sum); if (error) goto out; } } error = 0; out: xfs_rtbuf_cache_relse(oargs); return error; } /* * Mark an extent specified by start and len allocated. * Updates all the summary information as well as the bitmap. */ STATIC int xfs_rtallocate_range( struct xfs_rtalloc_args *args, xfs_rtxnum_t start, /* start rtext to allocate */ xfs_rtxlen_t len) /* in/out: summary block number */ { struct xfs_mount *mp = args->mp; xfs_rtxnum_t end; /* end of the allocated rtext */ int error; xfs_rtxnum_t postblock = 0; /* first rtext allocated > end */ xfs_rtxnum_t preblock = 0; /* first rtext allocated < start */ end = start + len - 1; /* * Assume we're allocating out of the middle of a free extent. * We need to find the beginning and end of the extent so we can * properly update the summary. */ error = xfs_rtfind_back(args, start, &preblock); if (error) return error; /* * Find the next allocated block (end of free extent). */ error = xfs_rtfind_forw(args, end, args->rtg->rtg_extents - 1, &postblock); if (error) return error; /* * Decrement the summary information corresponding to the entire * (old) free extent. */ error = xfs_rtmodify_summary(args, xfs_highbit64(postblock + 1 - preblock), xfs_rtx_to_rbmblock(mp, preblock), -1); if (error) return error; /* * If there are blocks not being allocated at the front of the * old extent, add summary data for them to be free. */ if (preblock < start) { error = xfs_rtmodify_summary(args, xfs_highbit64(start - preblock), xfs_rtx_to_rbmblock(mp, preblock), 1); if (error) return error; } /* * If there are blocks not being allocated at the end of the * old extent, add summary data for them to be free. */ if (postblock > end) { error = xfs_rtmodify_summary(args, xfs_highbit64(postblock - end), xfs_rtx_to_rbmblock(mp, end + 1), 1); if (error) return error; } /* * Modify the bitmap to mark this extent allocated. */ 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. */ static inline xfs_rtxlen_t xfs_rtallocate_clamp_len( struct xfs_rtgroup *rtg, xfs_rtxnum_t startrtx, xfs_rtxlen_t rtxlen, xfs_rtxlen_t prod) { xfs_rtxlen_t ret; ret = min(rtg->rtg_extents, startrtx + rtxlen) - startrtx; return xfs_rtalloc_align_len(ret, prod); } /* * Attempt to allocate an extent minlen<=len<=maxlen starting from * bitmap block bbno. If we don't get maxlen then use prod to trim * the length, if given. Returns error; returns starting block in *rtx. * The lengths are all in rtextents. */ STATIC int xfs_rtallocate_extent_block( struct xfs_rtalloc_args *args, xfs_fileoff_t bbno, /* bitmap block number */ xfs_rtxlen_t minlen, /* minimum length to allocate */ xfs_rtxlen_t maxlen, /* maximum length to allocate */ xfs_rtxlen_t *len, /* out: actual length allocated */ xfs_rtxnum_t *nextp, /* out: next rtext to try */ xfs_rtxlen_t prod, /* extent product factor */ xfs_rtxnum_t *rtx) /* out: start rtext allocated */ { struct xfs_mount *mp = args->mp; xfs_rtxnum_t besti = -1; /* best rtext found so far */ xfs_rtxnum_t end; /* last rtext in chunk */ 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 up to the * end of the rt volume, looking for one that's long enough. */ end = min(args->rtg->rtg_extents, 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. */ scanlen = xfs_rtallocate_clamp_len(args->rtg, i, maxlen, prod); if (scanlen < minlen) break; /* * 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, scanlen, 1, &next, &stat); if (error) return error; if (stat) { /* * i to scanlen is all free, allocate and return that. */ *len = scanlen; *rtx = i; return 0; } /* * In the case where we have a variable-sized allocation * request, figure out how big this free piece is, * and if it's big enough for the minimum, and the best * so far, remember it. */ if (minlen < maxlen) { xfs_rtxnum_t thislen; /* this extent size */ thislen = next - i; if (thislen >= minlen && thislen > bestlen) { besti = i; bestlen = thislen; } } /* * If not done yet, find the start of the next free space. */ if (next >= end) break; error = xfs_rtfind_forw(args, next, end, &i); if (error) return error; } /* Searched the whole thing & didn't find a maxlen free extent. */ if (besti == -1) goto nospace; /* * Ensure bestlen is a multiple of prod, but don't return a too-short * extent. */ bestlen = xfs_rtalloc_align_len(bestlen, prod); if (bestlen < minlen) goto nospace; /* * Pick besti for bestlen & return that. */ *len = bestlen; *rtx = besti; return 0; nospace: /* Allocation failed. Set *nextp to the next block to try. */ *nextp = next; return -ENOSPC; } /* * Allocate an extent of length minlen<=len<=maxlen, starting at block * bno. If we don't get maxlen then use prod to trim the length, if given. * Returns error; returns starting block in *rtx. * The lengths are all in rtextents. */ STATIC int xfs_rtallocate_extent_exact( struct xfs_rtalloc_args *args, xfs_rtxnum_t start, /* starting rtext number to allocate */ xfs_rtxlen_t minlen, /* minimum length to allocate */ xfs_rtxlen_t maxlen, /* maximum length to allocate */ xfs_rtxlen_t *len, /* out: actual length allocated */ xfs_rtxlen_t prod, /* extent product factor */ xfs_rtxnum_t *rtx) /* out: start rtext allocated */ { 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); /* Make sure we don't run off the end of the rt volume. */ scanlen = xfs_rtallocate_clamp_len(args->rtg, 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) { /* start to scanlen is all free; allocate it. */ *len = scanlen; *rtx = start; return 0; } /* * 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; } /* * Allocate an extent of length minlen<=len<=maxlen, starting as near * 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. */ STATIC int xfs_rtallocate_extent_near( struct xfs_rtalloc_args *args, xfs_rtxnum_t start, /* starting rtext number to allocate */ xfs_rtxlen_t minlen, /* minimum length to allocate */ xfs_rtxlen_t maxlen, /* maximum length to allocate */ xfs_rtxlen_t *len, /* out: actual length allocated */ xfs_rtxlen_t prod, /* extent product factor */ xfs_rtxnum_t *rtx) /* out: start rtext allocated */ { struct xfs_mount *mp = args->mp; int maxlog; /* max useful extent from summary */ xfs_fileoff_t bbno; /* bitmap block number */ int error; int i; /* bitmap block offset (loop control) */ int j; /* secondary loop control */ int log2len; /* log2 of minlen */ xfs_rtxnum_t n; /* next rtext to try */ ASSERT(minlen % prod == 0); ASSERT(maxlen % prod == 0); /* * If the block number given is off the end, silently set it to the last * block. */ start = min(start, args->rtg->rtg_extents - 1); /* * Try the exact allocation first. */ error = xfs_rtallocate_extent_exact(args, start, minlen, maxlen, len, prod, rtx); if (error != -ENOSPC) return error; bbno = xfs_rtx_to_rbmblock(mp, start); i = 0; j = -1; ASSERT(minlen != 0); log2len = xfs_highbit32(minlen); /* * Loop over all bitmap blocks (bbno + i is current block). */ for (;;) { /* * Get summary information of extents of all useful levels * starting in this bitmap block. */ error = xfs_rtany_summary(args, log2len, mp->m_rsumlevels - 1, bbno + i, &maxlog); if (error) return error; /* * If there are any useful extents starting here, try * allocating one. */ 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. */ if (i >= 0) { /* * Try to allocate an extent starting in * this block. */ error = xfs_rtallocate_extent_block(args, bbno + i, minlen, maxavail, len, &n, prod, rtx); if (error != -ENOSPC) return error; } /* * On the negative side of the starting location. */ else { /* i < 0 */ int maxblocks; /* * Loop backwards to find the end of the extent * we found in the realtime summary. * * maxblocks is the maximum possible number of * bitmap blocks from the start of the extent * to the end of the extent. */ if (maxlog == 0) maxblocks = 0; else if (maxlog < mp->m_blkbit_log) maxblocks = 1; else maxblocks = 2 << (maxlog - mp->m_blkbit_log);