|
@@ -37,6 +37,7 @@
|
|
#include "xfs_trans.h"
|
|
#include "xfs_trans.h"
|
|
#include "xfs_buf_item.h"
|
|
#include "xfs_buf_item.h"
|
|
#include "xfs_log.h"
|
|
#include "xfs_log.h"
|
|
|
|
+#include "xfs_ag_resv.h"
|
|
|
|
|
|
struct workqueue_struct *xfs_alloc_wq;
|
|
struct workqueue_struct *xfs_alloc_wq;
|
|
|
|
|
|
@@ -74,14 +75,8 @@ xfs_prealloc_blocks(
|
|
* extents need to be actually allocated. To get around this, we explicitly set
|
|
* extents need to be actually allocated. To get around this, we explicitly set
|
|
* aside a few blocks which will not be reserved in delayed allocation.
|
|
* aside a few blocks which will not be reserved in delayed allocation.
|
|
*
|
|
*
|
|
- * When rmap is disabled, we need to reserve 4 fsbs _per AG_ for the freelist
|
|
|
|
- * and 4 more to handle a potential split of the file's bmap btree.
|
|
|
|
- *
|
|
|
|
- * When rmap is enabled, we must also be able to handle two rmap btree inserts
|
|
|
|
- * to record both the file data extent and a new bmbt block. The bmbt block
|
|
|
|
- * might not be in the same AG as the file data extent. In the worst case
|
|
|
|
- * the bmap btree splits multiple levels and all the new blocks come from
|
|
|
|
- * different AGs, so set aside enough to handle rmap btree splits in all AGs.
|
|
|
|
|
|
+ * We need to reserve 4 fsbs _per AG_ for the freelist and 4 more to handle a
|
|
|
|
+ * potential split of the file's bmap btree.
|
|
*/
|
|
*/
|
|
unsigned int
|
|
unsigned int
|
|
xfs_alloc_set_aside(
|
|
xfs_alloc_set_aside(
|
|
@@ -90,8 +85,6 @@ xfs_alloc_set_aside(
|
|
unsigned int blocks;
|
|
unsigned int blocks;
|
|
|
|
|
|
blocks = 4 + (mp->m_sb.sb_agcount * XFS_ALLOC_AGFL_RESERVE);
|
|
blocks = 4 + (mp->m_sb.sb_agcount * XFS_ALLOC_AGFL_RESERVE);
|
|
- if (xfs_sb_version_hasrmapbt(&mp->m_sb))
|
|
|
|
- blocks += mp->m_sb.sb_agcount * mp->m_rmap_maxlevels;
|
|
|
|
return blocks;
|
|
return blocks;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -265,7 +258,7 @@ xfs_alloc_compute_diff(
|
|
xfs_agblock_t wantbno, /* target starting block */
|
|
xfs_agblock_t wantbno, /* target starting block */
|
|
xfs_extlen_t wantlen, /* target length */
|
|
xfs_extlen_t wantlen, /* target length */
|
|
xfs_extlen_t alignment, /* target alignment */
|
|
xfs_extlen_t alignment, /* target alignment */
|
|
- char userdata, /* are we allocating data? */
|
|
|
|
|
|
+ int datatype, /* are we allocating data? */
|
|
xfs_agblock_t freebno, /* freespace's starting block */
|
|
xfs_agblock_t freebno, /* freespace's starting block */
|
|
xfs_extlen_t freelen, /* freespace's length */
|
|
xfs_extlen_t freelen, /* freespace's length */
|
|
xfs_agblock_t *newbnop) /* result: best start block from free */
|
|
xfs_agblock_t *newbnop) /* result: best start block from free */
|
|
@@ -276,6 +269,7 @@ xfs_alloc_compute_diff(
|
|
xfs_extlen_t newlen1=0; /* length with newbno1 */
|
|
xfs_extlen_t newlen1=0; /* length with newbno1 */
|
|
xfs_extlen_t newlen2=0; /* length with newbno2 */
|
|
xfs_extlen_t newlen2=0; /* length with newbno2 */
|
|
xfs_agblock_t wantend; /* end of target extent */
|
|
xfs_agblock_t wantend; /* end of target extent */
|
|
|
|
+ bool userdata = xfs_alloc_is_userdata(datatype);
|
|
|
|
|
|
ASSERT(freelen >= wantlen);
|
|
ASSERT(freelen >= wantlen);
|
|
freeend = freebno + freelen;
|
|
freeend = freebno + freelen;
|
|
@@ -680,12 +674,29 @@ xfs_alloc_ag_vextent(
|
|
xfs_alloc_arg_t *args) /* argument structure for allocation */
|
|
xfs_alloc_arg_t *args) /* argument structure for allocation */
|
|
{
|
|
{
|
|
int error=0;
|
|
int error=0;
|
|
|
|
+ xfs_extlen_t reservation;
|
|
|
|
+ xfs_extlen_t oldmax;
|
|
|
|
|
|
ASSERT(args->minlen > 0);
|
|
ASSERT(args->minlen > 0);
|
|
ASSERT(args->maxlen > 0);
|
|
ASSERT(args->maxlen > 0);
|
|
ASSERT(args->minlen <= args->maxlen);
|
|
ASSERT(args->minlen <= args->maxlen);
|
|
ASSERT(args->mod < args->prod);
|
|
ASSERT(args->mod < args->prod);
|
|
ASSERT(args->alignment > 0);
|
|
ASSERT(args->alignment > 0);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Clamp maxlen to the amount of free space minus any reservations
|
|
|
|
+ * that have been made.
|
|
|
|
+ */
|
|
|
|
+ oldmax = args->maxlen;
|
|
|
|
+ reservation = xfs_ag_resv_needed(args->pag, args->resv);
|
|
|
|
+ if (args->maxlen > args->pag->pagf_freeblks - reservation)
|
|
|
|
+ args->maxlen = args->pag->pagf_freeblks - reservation;
|
|
|
|
+ if (args->maxlen == 0) {
|
|
|
|
+ args->agbno = NULLAGBLOCK;
|
|
|
|
+ args->maxlen = oldmax;
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Branch to correct routine based on the type.
|
|
* Branch to correct routine based on the type.
|
|
*/
|
|
*/
|
|
@@ -705,12 +716,14 @@ xfs_alloc_ag_vextent(
|
|
/* NOTREACHED */
|
|
/* NOTREACHED */
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ args->maxlen = oldmax;
|
|
|
|
+
|
|
if (error || args->agbno == NULLAGBLOCK)
|
|
if (error || args->agbno == NULLAGBLOCK)
|
|
return error;
|
|
return error;
|
|
|
|
|
|
ASSERT(args->len >= args->minlen);
|
|
ASSERT(args->len >= args->minlen);
|
|
ASSERT(args->len <= args->maxlen);
|
|
ASSERT(args->len <= args->maxlen);
|
|
- ASSERT(!args->wasfromfl || !args->isfl);
|
|
|
|
|
|
+ ASSERT(!args->wasfromfl || args->resv != XFS_AG_RESV_AGFL);
|
|
ASSERT(args->agbno % args->alignment == 0);
|
|
ASSERT(args->agbno % args->alignment == 0);
|
|
|
|
|
|
/* if not file data, insert new block into the reverse map btree */
|
|
/* if not file data, insert new block into the reverse map btree */
|
|
@@ -732,12 +745,7 @@ xfs_alloc_ag_vextent(
|
|
args->agbno, args->len));
|
|
args->agbno, args->len));
|
|
}
|
|
}
|
|
|
|
|
|
- if (!args->isfl) {
|
|
|
|
- xfs_trans_mod_sb(args->tp, args->wasdel ?
|
|
|
|
- XFS_TRANS_SB_RES_FDBLOCKS :
|
|
|
|
- XFS_TRANS_SB_FDBLOCKS,
|
|
|
|
- -((long)(args->len)));
|
|
|
|
- }
|
|
|
|
|
|
+ xfs_ag_resv_alloc_extent(args->pag, args->resv, args);
|
|
|
|
|
|
XFS_STATS_INC(args->mp, xs_allocx);
|
|
XFS_STATS_INC(args->mp, xs_allocx);
|
|
XFS_STATS_ADD(args->mp, xs_allocb, args->len);
|
|
XFS_STATS_ADD(args->mp, xs_allocb, args->len);
|
|
@@ -917,7 +925,7 @@ xfs_alloc_find_best_extent(
|
|
|
|
|
|
sdiff = xfs_alloc_compute_diff(args->agbno, args->len,
|
|
sdiff = xfs_alloc_compute_diff(args->agbno, args->len,
|
|
args->alignment,
|
|
args->alignment,
|
|
- args->userdata, *sbnoa,
|
|
|
|
|
|
+ args->datatype, *sbnoa,
|
|
*slena, &new);
|
|
*slena, &new);
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -1101,7 +1109,7 @@ restart:
|
|
if (args->len < blen)
|
|
if (args->len < blen)
|
|
continue;
|
|
continue;
|
|
ltdiff = xfs_alloc_compute_diff(args->agbno, args->len,
|
|
ltdiff = xfs_alloc_compute_diff(args->agbno, args->len,
|
|
- args->alignment, args->userdata, ltbnoa,
|
|
|
|
|
|
+ args->alignment, args->datatype, ltbnoa,
|
|
ltlena, <new);
|
|
ltlena, <new);
|
|
if (ltnew != NULLAGBLOCK &&
|
|
if (ltnew != NULLAGBLOCK &&
|
|
(args->len > blen || ltdiff < bdiff)) {
|
|
(args->len > blen || ltdiff < bdiff)) {
|
|
@@ -1254,7 +1262,7 @@ restart:
|
|
args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen);
|
|
args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen);
|
|
xfs_alloc_fix_len(args);
|
|
xfs_alloc_fix_len(args);
|
|
ltdiff = xfs_alloc_compute_diff(args->agbno, args->len,
|
|
ltdiff = xfs_alloc_compute_diff(args->agbno, args->len,
|
|
- args->alignment, args->userdata, ltbnoa,
|
|
|
|
|
|
+ args->alignment, args->datatype, ltbnoa,
|
|
ltlena, <new);
|
|
ltlena, <new);
|
|
|
|
|
|
error = xfs_alloc_find_best_extent(args,
|
|
error = xfs_alloc_find_best_extent(args,
|
|
@@ -1271,7 +1279,7 @@ restart:
|
|
args->len = XFS_EXTLEN_MIN(gtlena, args->maxlen);
|
|
args->len = XFS_EXTLEN_MIN(gtlena, args->maxlen);
|
|
xfs_alloc_fix_len(args);
|
|
xfs_alloc_fix_len(args);
|
|
gtdiff = xfs_alloc_compute_diff(args->agbno, args->len,
|
|
gtdiff = xfs_alloc_compute_diff(args->agbno, args->len,
|
|
- args->alignment, args->userdata, gtbnoa,
|
|
|
|
|
|
+ args->alignment, args->datatype, gtbnoa,
|
|
gtlena, >new);
|
|
gtlena, >new);
|
|
|
|
|
|
error = xfs_alloc_find_best_extent(args,
|
|
error = xfs_alloc_find_best_extent(args,
|
|
@@ -1331,7 +1339,7 @@ restart:
|
|
}
|
|
}
|
|
rlen = args->len;
|
|
rlen = args->len;
|
|
(void)xfs_alloc_compute_diff(args->agbno, rlen, args->alignment,
|
|
(void)xfs_alloc_compute_diff(args->agbno, rlen, args->alignment,
|
|
- args->userdata, ltbnoa, ltlena, <new);
|
|
|
|
|
|
+ args->datatype, ltbnoa, ltlena, <new);
|
|
ASSERT(ltnew >= ltbno);
|
|
ASSERT(ltnew >= ltbno);
|
|
ASSERT(ltnew + rlen <= ltbnoa + ltlena);
|
|
ASSERT(ltnew + rlen <= ltbnoa + ltlena);
|
|
ASSERT(ltnew + rlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length));
|
|
ASSERT(ltnew + rlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length));
|
|
@@ -1583,6 +1591,7 @@ xfs_alloc_ag_vextent_small(
|
|
int *stat) /* status: 0-freelist, 1-normal/none */
|
|
int *stat) /* status: 0-freelist, 1-normal/none */
|
|
{
|
|
{
|
|
struct xfs_owner_info oinfo;
|
|
struct xfs_owner_info oinfo;
|
|
|
|
+ struct xfs_perag *pag;
|
|
int error;
|
|
int error;
|
|
xfs_agblock_t fbno;
|
|
xfs_agblock_t fbno;
|
|
xfs_extlen_t flen;
|
|
xfs_extlen_t flen;
|
|
@@ -1600,7 +1609,8 @@ xfs_alloc_ag_vextent_small(
|
|
* to respect minleft even when pulling from the
|
|
* to respect minleft even when pulling from the
|
|
* freelist.
|
|
* freelist.
|
|
*/
|
|
*/
|
|
- else if (args->minlen == 1 && args->alignment == 1 && !args->isfl &&
|
|
|
|
|
|
+ else if (args->minlen == 1 && args->alignment == 1 &&
|
|
|
|
+ args->resv != XFS_AG_RESV_AGFL &&
|
|
(be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_flcount)
|
|
(be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_flcount)
|
|
> args->minleft)) {
|
|
> args->minleft)) {
|
|
error = xfs_alloc_get_freelist(args->tp, args->agbp, &fbno, 0);
|
|
error = xfs_alloc_get_freelist(args->tp, args->agbp, &fbno, 0);
|
|
@@ -1608,9 +1618,9 @@ xfs_alloc_ag_vextent_small(
|
|
goto error0;
|
|
goto error0;
|
|
if (fbno != NULLAGBLOCK) {
|
|
if (fbno != NULLAGBLOCK) {
|
|
xfs_extent_busy_reuse(args->mp, args->agno, fbno, 1,
|
|
xfs_extent_busy_reuse(args->mp, args->agno, fbno, 1,
|
|
- args->userdata);
|
|
|
|
|
|
+ xfs_alloc_allow_busy_reuse(args->datatype));
|
|
|
|
|
|
- if (args->userdata) {
|
|
|
|
|
|
+ if (xfs_alloc_is_userdata(args->datatype)) {
|
|
xfs_buf_t *bp;
|
|
xfs_buf_t *bp;
|
|
|
|
|
|
bp = xfs_btree_get_bufs(args->mp, args->tp,
|
|
bp = xfs_btree_get_bufs(args->mp, args->tp,
|
|
@@ -1629,13 +1639,18 @@ xfs_alloc_ag_vextent_small(
|
|
/*
|
|
/*
|
|
* If we're feeding an AGFL block to something that
|
|
* If we're feeding an AGFL block to something that
|
|
* doesn't live in the free space, we need to clear
|
|
* doesn't live in the free space, we need to clear
|
|
- * out the OWN_AG rmap.
|
|
|
|
|
|
+ * out the OWN_AG rmap and add the block back to
|
|
|
|
+ * the AGFL per-AG reservation.
|
|
*/
|
|
*/
|
|
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_AG);
|
|
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_AG);
|
|
error = xfs_rmap_free(args->tp, args->agbp, args->agno,
|
|
error = xfs_rmap_free(args->tp, args->agbp, args->agno,
|
|
fbno, 1, &oinfo);
|
|
fbno, 1, &oinfo);
|
|
if (error)
|
|
if (error)
|
|
goto error0;
|
|
goto error0;
|
|
|
|
+ pag = xfs_perag_get(args->mp, args->agno);
|
|
|
|
+ xfs_ag_resv_free_extent(pag, XFS_AG_RESV_AGFL,
|
|
|
|
+ args->tp, 1);
|
|
|
|
+ xfs_perag_put(pag);
|
|
|
|
|
|
*stat = 0;
|
|
*stat = 0;
|
|
return 0;
|
|
return 0;
|
|
@@ -1683,7 +1698,7 @@ xfs_free_ag_extent(
|
|
xfs_agblock_t bno,
|
|
xfs_agblock_t bno,
|
|
xfs_extlen_t len,
|
|
xfs_extlen_t len,
|
|
struct xfs_owner_info *oinfo,
|
|
struct xfs_owner_info *oinfo,
|
|
- int isfl)
|
|
|
|
|
|
+ enum xfs_ag_resv_type type)
|
|
{
|
|
{
|
|
xfs_btree_cur_t *bno_cur; /* cursor for by-block btree */
|
|
xfs_btree_cur_t *bno_cur; /* cursor for by-block btree */
|
|
xfs_btree_cur_t *cnt_cur; /* cursor for by-size btree */
|
|
xfs_btree_cur_t *cnt_cur; /* cursor for by-size btree */
|
|
@@ -1911,21 +1926,22 @@ xfs_free_ag_extent(
|
|
*/
|
|
*/
|
|
pag = xfs_perag_get(mp, agno);
|
|
pag = xfs_perag_get(mp, agno);
|
|
error = xfs_alloc_update_counters(tp, pag, agbp, len);
|
|
error = xfs_alloc_update_counters(tp, pag, agbp, len);
|
|
|
|
+ xfs_ag_resv_free_extent(pag, type, tp, len);
|
|
xfs_perag_put(pag);
|
|
xfs_perag_put(pag);
|
|
if (error)
|
|
if (error)
|
|
goto error0;
|
|
goto error0;
|
|
|
|
|
|
- if (!isfl)
|
|
|
|
- xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, (long)len);
|
|
|
|
XFS_STATS_INC(mp, xs_freex);
|
|
XFS_STATS_INC(mp, xs_freex);
|
|
XFS_STATS_ADD(mp, xs_freeb, len);
|
|
XFS_STATS_ADD(mp, xs_freeb, len);
|
|
|
|
|
|
- trace_xfs_free_extent(mp, agno, bno, len, isfl, haveleft, haveright);
|
|
|
|
|
|
+ trace_xfs_free_extent(mp, agno, bno, len, type == XFS_AG_RESV_AGFL,
|
|
|
|
+ haveleft, haveright);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
error0:
|
|
error0:
|
|
- trace_xfs_free_extent(mp, agno, bno, len, isfl, -1, -1);
|
|
|
|
|
|
+ trace_xfs_free_extent(mp, agno, bno, len, type == XFS_AG_RESV_AGFL,
|
|
|
|
+ -1, -1);
|
|
if (bno_cur)
|
|
if (bno_cur)
|
|
xfs_btree_del_cursor(bno_cur, XFS_BTREE_ERROR);
|
|
xfs_btree_del_cursor(bno_cur, XFS_BTREE_ERROR);
|
|
if (cnt_cur)
|
|
if (cnt_cur)
|
|
@@ -1950,21 +1966,43 @@ xfs_alloc_compute_maxlevels(
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
- * Find the length of the longest extent in an AG.
|
|
|
|
|
|
+ * Find the length of the longest extent in an AG. The 'need' parameter
|
|
|
|
+ * specifies how much space we're going to need for the AGFL and the
|
|
|
|
+ * 'reserved' parameter tells us how many blocks in this AG are reserved for
|
|
|
|
+ * other callers.
|
|
*/
|
|
*/
|
|
xfs_extlen_t
|
|
xfs_extlen_t
|
|
xfs_alloc_longest_free_extent(
|
|
xfs_alloc_longest_free_extent(
|
|
struct xfs_mount *mp,
|
|
struct xfs_mount *mp,
|
|
struct xfs_perag *pag,
|
|
struct xfs_perag *pag,
|
|
- xfs_extlen_t need)
|
|
|
|
|
|
+ xfs_extlen_t need,
|
|
|
|
+ xfs_extlen_t reserved)
|
|
{
|
|
{
|
|
xfs_extlen_t delta = 0;
|
|
xfs_extlen_t delta = 0;
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * If the AGFL needs a recharge, we'll have to subtract that from the
|
|
|
|
+ * longest extent.
|
|
|
|
+ */
|
|
if (need > pag->pagf_flcount)
|
|
if (need > pag->pagf_flcount)
|
|
delta = need - pag->pagf_flcount;
|
|
delta = need - pag->pagf_flcount;
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * If we cannot maintain others' reservations with space from the
|
|
|
|
+ * not-longest freesp extents, we'll have to subtract /that/ from
|
|
|
|
+ * the longest extent too.
|
|
|
|
+ */
|
|
|
|
+ if (pag->pagf_freeblks - pag->pagf_longest < reserved)
|
|
|
|
+ delta += reserved - (pag->pagf_freeblks - pag->pagf_longest);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * If the longest extent is long enough to satisfy all the
|
|
|
|
+ * reservations and AGFL rules in place, we can return this extent.
|
|
|
|
+ */
|
|
if (pag->pagf_longest > delta)
|
|
if (pag->pagf_longest > delta)
|
|
return pag->pagf_longest - delta;
|
|
return pag->pagf_longest - delta;
|
|
|
|
+
|
|
|
|
+ /* Otherwise, let the caller try for 1 block if there's space. */
|
|
return pag->pagf_flcount > 0 || pag->pagf_longest > 0;
|
|
return pag->pagf_flcount > 0 || pag->pagf_longest > 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2004,20 +2042,24 @@ xfs_alloc_space_available(
|
|
{
|
|
{
|
|
struct xfs_perag *pag = args->pag;
|
|
struct xfs_perag *pag = args->pag;
|
|
xfs_extlen_t longest;
|
|
xfs_extlen_t longest;
|
|
|
|
+ xfs_extlen_t reservation; /* blocks that are still reserved */
|
|
int available;
|
|
int available;
|
|
|
|
|
|
if (flags & XFS_ALLOC_FLAG_FREEING)
|
|
if (flags & XFS_ALLOC_FLAG_FREEING)
|
|
return true;
|
|
return true;
|
|
|
|
|
|
|
|
+ reservation = xfs_ag_resv_needed(pag, args->resv);
|
|
|
|
+
|
|
/* do we have enough contiguous free space for the allocation? */
|
|
/* do we have enough contiguous free space for the allocation? */
|
|
- longest = xfs_alloc_longest_free_extent(args->mp, pag, min_free);
|
|
|
|
|
|
+ longest = xfs_alloc_longest_free_extent(args->mp, pag, min_free,
|
|
|
|
+ reservation);
|
|
if ((args->minlen + args->alignment + args->minalignslop - 1) > longest)
|
|
if ((args->minlen + args->alignment + args->minalignslop - 1) > longest)
|
|
return false;
|
|
return false;
|
|
|
|
|
|
- /* do have enough free space remaining for the allocation? */
|
|
|
|
|
|
+ /* do we have enough free space remaining for the allocation? */
|
|
available = (int)(pag->pagf_freeblks + pag->pagf_flcount -
|
|
available = (int)(pag->pagf_freeblks + pag->pagf_flcount -
|
|
- min_free - args->total);
|
|
|
|
- if (available < (int)args->minleft)
|
|
|
|
|
|
+ reservation - min_free - args->total);
|
|
|
|
+ if (available < (int)args->minleft || available <= 0)
|
|
return false;
|
|
return false;
|
|
|
|
|
|
return true;
|
|
return true;
|
|
@@ -2058,7 +2100,7 @@ xfs_alloc_fix_freelist(
|
|
* somewhere else if we are not being asked to try harder at this
|
|
* somewhere else if we are not being asked to try harder at this
|
|
* point
|
|
* point
|
|
*/
|
|
*/
|
|
- if (pag->pagf_metadata && args->userdata &&
|
|
|
|
|
|
+ if (pag->pagf_metadata && xfs_alloc_is_userdata(args->datatype) &&
|
|
(flags & XFS_ALLOC_FLAG_TRYLOCK)) {
|
|
(flags & XFS_ALLOC_FLAG_TRYLOCK)) {
|
|
ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING));
|
|
ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING));
|
|
goto out_agbp_relse;
|
|
goto out_agbp_relse;
|
|
@@ -2124,7 +2166,7 @@ xfs_alloc_fix_freelist(
|
|
if (error)
|
|
if (error)
|
|
goto out_agbp_relse;
|
|
goto out_agbp_relse;
|
|
error = xfs_free_ag_extent(tp, agbp, args->agno, bno, 1,
|
|
error = xfs_free_ag_extent(tp, agbp, args->agno, bno, 1,
|
|
- &targs.oinfo, 1);
|
|
|
|
|
|
+ &targs.oinfo, XFS_AG_RESV_AGFL);
|
|
if (error)
|
|
if (error)
|
|
goto out_agbp_relse;
|
|
goto out_agbp_relse;
|
|
bp = xfs_btree_get_bufs(mp, tp, args->agno, bno, 0);
|
|
bp = xfs_btree_get_bufs(mp, tp, args->agno, bno, 0);
|
|
@@ -2135,7 +2177,7 @@ xfs_alloc_fix_freelist(
|
|
targs.mp = mp;
|
|
targs.mp = mp;
|
|
targs.agbp = agbp;
|
|
targs.agbp = agbp;
|
|
targs.agno = args->agno;
|
|
targs.agno = args->agno;
|
|
- targs.alignment = targs.minlen = targs.prod = targs.isfl = 1;
|
|
|
|
|
|
+ targs.alignment = targs.minlen = targs.prod = 1;
|
|
targs.type = XFS_ALLOCTYPE_THIS_AG;
|
|
targs.type = XFS_ALLOCTYPE_THIS_AG;
|
|
targs.pag = pag;
|
|
targs.pag = pag;
|
|
error = xfs_alloc_read_agfl(mp, tp, targs.agno, &agflbp);
|
|
error = xfs_alloc_read_agfl(mp, tp, targs.agno, &agflbp);
|
|
@@ -2146,6 +2188,7 @@ xfs_alloc_fix_freelist(
|
|
while (pag->pagf_flcount < need) {
|
|
while (pag->pagf_flcount < need) {
|
|
targs.agbno = 0;
|
|
targs.agbno = 0;
|
|
targs.maxlen = need - pag->pagf_flcount;
|
|
targs.maxlen = need - pag->pagf_flcount;
|
|
|
|
+ targs.resv = XFS_AG_RESV_AGFL;
|
|
|
|
|
|
/* Allocate as many blocks as possible at once. */
|
|
/* Allocate as many blocks as possible at once. */
|
|
error = xfs_alloc_ag_vextent(&targs);
|
|
error = xfs_alloc_ag_vextent(&targs);
|
|
@@ -2633,7 +2676,7 @@ xfs_alloc_vextent(
|
|
* Try near allocation first, then anywhere-in-ag after
|
|
* Try near allocation first, then anywhere-in-ag after
|
|
* the first a.g. fails.
|
|
* the first a.g. fails.
|
|
*/
|
|
*/
|
|
- if ((args->userdata & XFS_ALLOC_INITIAL_USER_DATA) &&
|
|
|
|
|
|
+ if ((args->datatype & XFS_ALLOC_INITIAL_USER_DATA) &&
|
|
(mp->m_flags & XFS_MOUNT_32BITINODES)) {
|
|
(mp->m_flags & XFS_MOUNT_32BITINODES)) {
|
|
args->fsbno = XFS_AGB_TO_FSB(mp,
|
|
args->fsbno = XFS_AGB_TO_FSB(mp,
|
|
((mp->m_agfrotor / rotorstep) %
|
|
((mp->m_agfrotor / rotorstep) %
|
|
@@ -2766,7 +2809,7 @@ xfs_alloc_vextent(
|
|
#endif
|
|
#endif
|
|
|
|
|
|
/* Zero the extent if we were asked to do so */
|
|
/* Zero the extent if we were asked to do so */
|
|
- if (args->userdata & XFS_ALLOC_USERDATA_ZERO) {
|
|
|
|
|
|
+ if (args->datatype & XFS_ALLOC_USERDATA_ZERO) {
|
|
error = xfs_zero_extent(args->ip, args->fsbno, args->len);
|
|
error = xfs_zero_extent(args->ip, args->fsbno, args->len);
|
|
if (error)
|
|
if (error)
|
|
goto error0;
|
|
goto error0;
|
|
@@ -2825,7 +2868,8 @@ xfs_free_extent(
|
|
struct xfs_trans *tp, /* transaction pointer */
|
|
struct xfs_trans *tp, /* transaction pointer */
|
|
xfs_fsblock_t bno, /* starting block number of extent */
|
|
xfs_fsblock_t bno, /* starting block number of extent */
|
|
xfs_extlen_t len, /* length of extent */
|
|
xfs_extlen_t len, /* length of extent */
|
|
- struct xfs_owner_info *oinfo) /* extent owner */
|
|
|
|
|
|
+ struct xfs_owner_info *oinfo, /* extent owner */
|
|
|
|
+ enum xfs_ag_resv_type type) /* block reservation type */
|
|
{
|
|
{
|
|
struct xfs_mount *mp = tp->t_mountp;
|
|
struct xfs_mount *mp = tp->t_mountp;
|
|
struct xfs_buf *agbp;
|
|
struct xfs_buf *agbp;
|
|
@@ -2834,6 +2878,7 @@ xfs_free_extent(
|
|
int error;
|
|
int error;
|
|
|
|
|
|
ASSERT(len != 0);
|
|
ASSERT(len != 0);
|
|
|
|
+ ASSERT(type != XFS_AG_RESV_AGFL);
|
|
|
|
|
|
if (XFS_TEST_ERROR(false, mp,
|
|
if (XFS_TEST_ERROR(false, mp,
|
|
XFS_ERRTAG_FREE_EXTENT,
|
|
XFS_ERRTAG_FREE_EXTENT,
|
|
@@ -2851,7 +2896,7 @@ xfs_free_extent(
|
|
agbno + len <= be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_length),
|
|
agbno + len <= be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_length),
|
|
err);
|
|
err);
|
|
|
|
|
|
- error = xfs_free_ag_extent(tp, agbp, agno, agbno, len, oinfo, 0);
|
|
|
|
|
|
+ error = xfs_free_ag_extent(tp, agbp, agno, agbno, len, oinfo, type);
|
|
if (error)
|
|
if (error)
|
|
goto err;
|
|
goto err;
|
|
|
|
|