/*
- * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
- * or the like. Any license provided herein, whether implied or
+ * or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
*/
STATIC void
xfs_alloc_fix_len(
- xfs_alloc_arg_t *args) /* allocation argument structure */
+ xfs_alloc_arg_t *args) /* allocation argument structure */
{
xfs_extlen_t k;
xfs_extlen_t rlen;
*/
STATIC int
xfs_alloc_fix_minleft(
- xfs_alloc_arg_t *args) /* allocation argument structure */
+ xfs_alloc_arg_t *args) /* allocation argument structure */
{
xfs_agf_t *agf; /* a.g. freelist header */
int diff; /* free space difference */
*/
STATIC int /* error code */
xfs_alloc_fixup_trees(
- xfs_btree_cur_t *cnt_cur, /* cursor for by-size 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 *bno_cur, /* cursor for by-block btree */
xfs_agblock_t fbno, /* starting block of free extent */
xfs_extlen_t flen, /* length of free extent */
xfs_agblock_t rbno, /* starting block of returned extent */
xfs_alloc_trace_alloc(
char *name, /* function tag string */
char *str, /* additional string */
- xfs_alloc_arg_t *args, /* allocation argument structure */
+ xfs_alloc_arg_t *args, /* allocation argument structure */
int line) /* source line number */
{
ktrace_enter(xfs_alloc_trace_buf,
*/
STATIC int /* error */
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;
#ifdef XFS_ALLOC_TRACE
xfs_trans_mod_sb(args->tp,
args->wasdel ? XFS_TRANS_SB_RES_FDBLOCKS :
XFS_TRANS_SB_FDBLOCKS, -slen);
- XFS_STATS_INC(xfsstats.xs_allocx);
- XFS_STATS_ADD(xfsstats.xs_allocb, args->len);
+ XFS_STATS_INC(xs_allocx);
+ XFS_STATS_ADD(xs_allocb, args->len);
}
return 0;
}
*/
STATIC int /* error */
xfs_alloc_ag_vextent_exact(
- xfs_alloc_arg_t *args) /* allocation argument structure */
+ xfs_alloc_arg_t *args) /* allocation argument structure */
{
- xfs_btree_cur_t *bno_cur;/* by block-number btree cursor */
- xfs_btree_cur_t *cnt_cur;/* by count btree cursor */
+ xfs_btree_cur_t *bno_cur;/* by block-number btree cursor */
+ xfs_btree_cur_t *cnt_cur;/* by count btree cursor */
xfs_agblock_t end; /* end of allocated extent */
int error;
xfs_agblock_t fbno; /* start block of found extent */
static char fname[] = "xfs_alloc_ag_vextent_exact";
#endif
int i; /* success/failure of operation */
- xfs_agblock_t maxend; /* end of maximal extent */
- xfs_agblock_t minend; /* end of minimal extent */
+ xfs_agblock_t maxend; /* end of maximal extent */
+ xfs_agblock_t minend; /* end of minimal extent */
xfs_extlen_t rlen; /* length of returned extent */
ASSERT(args->alignment == 1);
* Allocate/initialize a cursor for the by-number freespace btree.
*/
bno_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
- args->agno, XFS_BTNUM_BNO, 0, 0);
+ args->agno, XFS_BTNUM_BNO, NULL, 0);
/*
* Lookup bno and minlen in the btree (minlen is irrelevant, really).
* Look for the closest free block <= bno, it must contain bno
* Allocate/initialize a cursor for the by-size btree.
*/
cnt_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
- args->agno, XFS_BTNUM_CNT, 0, 0);
+ args->agno, XFS_BTNUM_CNT, NULL, 0);
ASSERT(args->agbno + args->len <=
INT_GET(XFS_BUF_TO_AGF(args->agbp)->agf_length,
ARCH_CONVERT));
*/
STATIC int /* error */
xfs_alloc_ag_vextent_near(
- xfs_alloc_arg_t *args) /* allocation argument structure */
+ xfs_alloc_arg_t *args) /* allocation argument structure */
{
- xfs_btree_cur_t *bno_cur_gt; /* cursor for bno btree, right side */
- xfs_btree_cur_t *bno_cur_lt; /* cursor for bno btree, left side */
- xfs_btree_cur_t *cnt_cur; /* cursor for count btree */
+ xfs_btree_cur_t *bno_cur_gt; /* cursor for bno btree, right side */
+ xfs_btree_cur_t *bno_cur_lt; /* cursor for bno btree, left side */
+ xfs_btree_cur_t *cnt_cur; /* cursor for count btree */
#ifdef XFS_ALLOC_TRACE
static char fname[] = "xfs_alloc_ag_vextent_near";
#endif
/*
* Randomly don't execute the first algorithm.
*/
- static int seed; /* randomizing seed value */
int dofirst; /* set to do first algorithm */
- timespec_t now; /* current time */
- if (!seed) {
- nanotime(&now);
- seed = (int)now.tv_sec ^ (int)now.tv_nsec;
- }
dofirst = random() & 1;
#endif
/*
* Get a cursor for the by-size btree.
*/
cnt_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
- args->agno, XFS_BTNUM_CNT, 0, 0);
+ args->agno, XFS_BTNUM_CNT, NULL, 0);
ltlen = 0;
bno_cur_lt = bno_cur_gt = NULL;
/*
* Set up a cursor for the by-bno tree.
*/
bno_cur_lt = xfs_btree_init_cursor(args->mp, args->tp,
- args->agbp, args->agno, XFS_BTNUM_BNO, 0, 0);
+ args->agbp, args->agno, XFS_BTNUM_BNO, NULL, 0);
/*
* Fix up the btree entries.
*/
* Allocate and initialize the cursor for the leftward search.
*/
bno_cur_lt = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
- args->agno, XFS_BTNUM_BNO, 0, 0);
+ args->agno, XFS_BTNUM_BNO, NULL, 0);
/*
* Lookup <= bno to find the leftward search's starting point.
*/
* search.
*/
bno_cur_gt = bno_cur_lt;
- bno_cur_lt = 0;
+ bno_cur_lt = NULL;
}
/*
* Found something. Duplicate the cursor for the rightward search.
*/
STATIC int /* error */
xfs_alloc_ag_vextent_size(
- xfs_alloc_arg_t *args) /* allocation argument structure */
+ xfs_alloc_arg_t *args) /* allocation argument structure */
{
- xfs_btree_cur_t *bno_cur; /* cursor for bno btree */
- xfs_btree_cur_t *cnt_cur; /* cursor for cnt btree */
+ xfs_btree_cur_t *bno_cur; /* cursor for bno btree */
+ xfs_btree_cur_t *cnt_cur; /* cursor for cnt btree */
int error; /* error result */
xfs_agblock_t fbno; /* start of found freespace */
xfs_extlen_t flen; /* length of found freespace */
* Allocate and initialize a cursor for the by-size btree.
*/
cnt_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
- args->agno, XFS_BTNUM_CNT, 0, 0);
+ args->agno, XFS_BTNUM_CNT, NULL, 0);
bno_cur = NULL;
/*
* Look for an entry >= maxlen+alignment-1 blocks.
* Allocate and initialize a cursor for the by-block tree.
*/
bno_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
- args->agno, XFS_BTNUM_BNO, 0, 0);
+ args->agno, XFS_BTNUM_BNO, NULL, 0);
if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen,
rbno, rlen, XFSA_FIXUP_CNT_OK)))
goto error0;
*/
STATIC int /* error */
xfs_alloc_ag_vextent_small(
- xfs_alloc_arg_t *args, /* allocation argument structure */
- xfs_btree_cur_t *ccur, /* by-size cursor */
- xfs_agblock_t *fbnop, /* result block number */
- xfs_extlen_t *flenp, /* result length */
+ xfs_alloc_arg_t *args, /* allocation argument structure */
+ xfs_btree_cur_t *ccur, /* by-size cursor */
+ xfs_agblock_t *fbnop, /* result block number */
+ xfs_extlen_t *flenp, /* result length */
int *stat) /* status: 0-freelist, 1-normal/none */
{
int error;
else if (args->minlen == 1 && args->alignment == 1 && !args->isfl &&
(INT_GET(XFS_BUF_TO_AGF(args->agbp)->agf_flcount,
ARCH_CONVERT) > args->minleft)) {
- if ((error = xfs_alloc_get_freelist(args->tp, args->agbp, &fbno)))
+ error = xfs_alloc_get_freelist(args->tp, args->agbp, &fbno);
+ if (error)
goto error0;
if (fbno != NULLAGBLOCK) {
if (args->userdata) {
STATIC int /* error */
xfs_free_ag_extent(
xfs_trans_t *tp, /* transaction pointer */
- xfs_buf_t *agbp, /* buffer for a.g. freelist header */
+ xfs_buf_t *agbp, /* buffer for a.g. freelist header */
xfs_agnumber_t agno, /* allocation group number */
xfs_agblock_t bno, /* starting block number */
xfs_extlen_t len, /* length of extent */
int isfl) /* set if is freelist blocks - no sb acctg */
{
- 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 *bno_cur; /* cursor for by-block btree */
+ xfs_btree_cur_t *cnt_cur; /* cursor for by-size btree */
int error; /* error return value */
#ifdef XFS_ALLOC_TRACE
static char fname[] = "xfs_free_ag_extent";
/*
* Allocate and initialize a cursor for the by-block btree.
*/
- bno_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_BNO, 0,
+ bno_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_BNO, NULL,
0);
cnt_cur = NULL;
/*
/*
* Now allocate and initialize a cursor for the by-size tree.
*/
- cnt_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_CNT, 0,
+ cnt_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_CNT, NULL,
0);
/*
* Have both left and right contiguous neighbors.
xfs_alloc_log_agf(tp, agbp, XFS_AGF_FREEBLKS);
if (!isfl)
xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, (long)len);
- XFS_STATS_INC(xfsstats.xs_freex);
- XFS_STATS_ADD(xfsstats.xs_freeb, len);
+ XFS_STATS_INC(xs_freex);
+ XFS_STATS_ADD(xs_freeb, len);
}
TRACE_FREE(haveleft ?
(haveright ? "both" : "left") :
* used in xfs_bmap_finish, we can't allow block to be available
* for reallocation and non-transaction writing (user data)
* until we know that the transaction that moved it to the free
- * list is permanently on disk. We track the blocks by declaring
+ * list is permanently on disk. We track the blocks by declaring
* these blocks as "busy"; the busy list is maintained on a per-ag
* basis and each transaction records which entries should be removed
* when the iclog commits to disk. If a busy block is allocated,
*/
int /* error */
xfs_alloc_fix_freelist(
- xfs_alloc_arg_t *args, /* allocation argument structure */
+ xfs_alloc_arg_t *args, /* allocation argument structure */
int flags) /* XFS_ALLOC_FLAG_... */
{
xfs_buf_t *agbp; /* agf buffer pointer */
xfs_mount_t *mp; /* file system mount point structure */
xfs_extlen_t need; /* total blocks needed in freelist */
xfs_perag_t *pag; /* per-ag information structure */
- xfs_alloc_arg_t targs; /* local allocation arguments */
+ xfs_alloc_arg_t targs; /* local allocation arguments */
xfs_trans_t *tp; /* transaction pointer */
mp = args->mp;
if ((error = xfs_alloc_ag_vextent(&targs)))
return error;
/*
- * Stop if we run out. Won't happen if callers are obeying
- * the restrictions correctly. Can happen for free calls
+ * Stop if we run out. Won't happen if callers are obeying
+ * the restrictions correctly. Can happen for free calls
* on a completely full ag.
*/
if (targs.agbno == NULLAGBLOCK)
/*
* Freelist is empty, give up.
*/
- if (INT_ISZERO(agf->agf_flcount, ARCH_CONVERT)) {
+ if (!agf->agf_flcount) {
*bnop = NULLAGBLOCK;
return 0;
}
INT_MOD(agf->agf_flfirst, ARCH_CONVERT, 1);
xfs_trans_brelse(tp, agflbp);
if (INT_GET(agf->agf_flfirst, ARCH_CONVERT) == XFS_AGFL_SIZE(mp))
- INT_ZERO(agf->agf_flfirst, ARCH_CONVERT);
+ agf->agf_flfirst = 0;
pag = &mp->m_perag[INT_GET(agf->agf_seqno, ARCH_CONVERT)];
INT_MOD(agf->agf_flcount, ARCH_CONVERT, -1);
xfs_trans_agflist_delta(tp, -1);
* As blocks are freed, they are added to the per-ag busy list
* and remain there until the freeing transaction is committed to
* disk. Now that we have allocated blocks, this list must be
- * searched to see if a block is being reused. If one is, then
+ * searched to see if a block is being reused. If one is, then
* the freeing transaction must be pushed to disk NOW by forcing
* to disk all iclogs up that transaction's LSN.
*/
xfs_alloc_log_agf(
xfs_trans_t *tp, /* transaction pointer */
xfs_buf_t *bp, /* buffer for a.g. freelist header */
- int fields) /* mask of fields to be logged (XFS_AGF_...) */
+ int fields) /* mask of fields to be logged (XFS_AGF_...) */
{
int first; /* first byte offset */
int last; /* last byte offset */
agfl = XFS_BUF_TO_AGFL(agflbp);
INT_MOD(agf->agf_fllast, ARCH_CONVERT, 1);
if (INT_GET(agf->agf_fllast, ARCH_CONVERT) == XFS_AGFL_SIZE(mp))
- INT_ZERO(agf->agf_fllast, ARCH_CONVERT);
+ agf->agf_fllast = 0;
pag = &mp->m_perag[INT_GET(agf->agf_seqno, ARCH_CONVERT)];
INT_MOD(agf->agf_flcount, ARCH_CONVERT, 1);
xfs_trans_agflist_delta(tp, 1);
*/
int /* error */
xfs_alloc_vextent(
- xfs_alloc_arg_t *args) /* allocation argument structure */
+ xfs_alloc_arg_t *args) /* allocation argument structure */
{
- xfs_agblock_t agsize; /* allocation group size */
+ xfs_agblock_t agsize; /* allocation group size */
int error;
int flags; /* XFS_ALLOC_FLAG_... locking flags */
#ifdef XFS_ALLOC_TRACE
xfs_extlen_t minleft;/* minimum left value, temp copy */
xfs_mount_t *mp; /* mount structure pointer */
xfs_agnumber_t sagno; /* starting allocation group number */
- xfs_alloctype_t type; /* input allocation type */
+ xfs_alloctype_t type; /* input allocation type */
int bump_rotor = 0;
int no_min = 0;
+ xfs_agnumber_t rotorstep = xfs_rotorstep; /* inode32 agf stepper */
mp = args->mp;
type = args->otype = args->type;
*/
if ((args->userdata == XFS_ALLOC_INITIAL_USER_DATA) &&
(mp->m_flags & XFS_MOUNT_32BITINODES)) {
- args->fsbno = XFS_AGB_TO_FSB(mp, mp->m_agfrotor, 0);
+ args->fsbno = XFS_AGB_TO_FSB(mp,
+ ((mp->m_agfrotor / rotorstep) %
+ mp->m_sb.sb_agcount), 0);
bump_rotor = 1;
}
args->agbno = XFS_FSB_TO_AGBNO(mp, args->fsbno);
/*
* Start with the last place we left off.
*/
- args->agno = sagno = mp->m_agfrotor;
+ args->agno = sagno = (mp->m_agfrotor / rotorstep) %
+ mp->m_sb.sb_agcount;
args->type = XFS_ALLOCTYPE_THIS_AG;
flags = XFS_ALLOC_FLAG_TRYLOCK;
} else if (type == XFS_ALLOCTYPE_FIRST_AG) {
}
}
up_read(&mp->m_peraglock);
- if (bump_rotor || (type == XFS_ALLOCTYPE_ANY_AG))
- mp->m_agfrotor = (args->agno + 1) % mp->m_sb.sb_agcount;
+ if (bump_rotor || (type == XFS_ALLOCTYPE_ANY_AG)) {
+ if (args->agno == sagno)
+ mp->m_agfrotor = (mp->m_agfrotor + 1) %
+ (mp->m_sb.sb_agcount * rotorstep);
+ else
+ mp->m_agfrotor = (args->agno * rotorstep + 1) %
+ (mp->m_sb.sb_agcount * rotorstep);
+ }
break;
default:
ASSERT(0);
#ifdef DEBUG
xfs_agf_t *agf; /* a.g. freespace header */
#endif
- xfs_alloc_arg_t args; /* allocation argument structure */
+ xfs_alloc_arg_t args; /* allocation argument structure */
int error;
ASSERT(len != 0);