Commit ecb6928f authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Alex Elder

xfs: factor agf counter updates into a helper

Updating the AGF and transactions counters is duplicated between allocating
and freeing extents.  Factor the code into a common helper.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
Signed-off-by: default avatarAlex Elder <aelder@sgi.com>
parent 86fa8af6
...@@ -463,6 +463,27 @@ xfs_alloc_read_agfl( ...@@ -463,6 +463,27 @@ xfs_alloc_read_agfl(
return 0; return 0;
} }
STATIC int
xfs_alloc_update_counters(
struct xfs_trans *tp,
struct xfs_perag *pag,
struct xfs_buf *agbp,
long len)
{
struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp);
pag->pagf_freeblks += len;
be32_add_cpu(&agf->agf_freeblks, len);
xfs_trans_agblocks_delta(tp, len);
if (unlikely(be32_to_cpu(agf->agf_freeblks) >
be32_to_cpu(agf->agf_length)))
return EFSCORRUPTED;
xfs_alloc_log_agf(tp, agbp, XFS_AGF_FREEBLKS);
return 0;
}
/* /*
* Allocation group level functions. * Allocation group level functions.
*/ */
...@@ -504,49 +525,44 @@ xfs_alloc_ag_vextent( ...@@ -504,49 +525,44 @@ xfs_alloc_ag_vextent(
ASSERT(0); ASSERT(0);
/* NOTREACHED */ /* NOTREACHED */
} }
if (error)
if (error || args->agbno == NULLAGBLOCK)
return error; return error;
/*
* If the allocation worked, need to change the agf structure
* (and log it), and the superblock.
*/
if (args->agbno != NULLAGBLOCK) {
xfs_agf_t *agf; /* allocation group freelist header */
long slen = (long)args->len;
ASSERT(args->len >= args->minlen && args->len <= args->maxlen); ASSERT(args->len >= args->minlen);
ASSERT(!(args->wasfromfl) || !args->isfl); ASSERT(args->len <= args->maxlen);
ASSERT(args->agbno % args->alignment == 0); ASSERT(!args->wasfromfl || !args->isfl);
if (!(args->wasfromfl)) { ASSERT(args->agbno % args->alignment == 0);
agf = XFS_BUF_TO_AGF(args->agbp); if (!args->wasfromfl) {
be32_add_cpu(&agf->agf_freeblks, -(args->len)); error = xfs_alloc_update_counters(args->tp, args->pag,
xfs_trans_agblocks_delta(args->tp, args->agbp,
-((long)(args->len))); -((long)(args->len)));
args->pag->pagf_freeblks -= args->len; if (error)
ASSERT(be32_to_cpu(agf->agf_freeblks) <= return error;
be32_to_cpu(agf->agf_length));
xfs_alloc_log_agf(args->tp, args->agbp, /*
XFS_AGF_FREEBLKS); * Search the busylist for these blocks and mark the
/* * transaction as synchronous if blocks are found. This
* Search the busylist for these blocks and mark the * avoids the need to block due to a synchronous log
* transaction as synchronous if blocks are found. This * force to ensure correct ordering as the synchronous
* avoids the need to block due to a synchronous log * transaction will guarantee that for us.
* force to ensure correct ordering as the synchronous */
* transaction will guarantee that for us. if (xfs_alloc_busy_search(args->mp, args->agno,
*/ args->agbno, args->len))
if (xfs_alloc_busy_search(args->mp, args->agno, xfs_trans_set_sync(args->tp);
args->agbno, args->len))
xfs_trans_set_sync(args->tp);
}
if (!args->isfl)
xfs_trans_mod_sb(args->tp,
args->wasdel ? XFS_TRANS_SB_RES_FDBLOCKS :
XFS_TRANS_SB_FDBLOCKS, -slen);
XFS_STATS_INC(xs_allocx);
XFS_STATS_ADD(xs_allocb, args->len);
} }
return 0;
if (!args->isfl) {
xfs_trans_mod_sb(args->tp, args->wasdel ?
XFS_TRANS_SB_RES_FDBLOCKS :
XFS_TRANS_SB_FDBLOCKS,
-((long)(args->len)));
}
XFS_STATS_INC(xs_allocx);
XFS_STATS_ADD(xs_allocb, args->len);
return error;
} }
/* /*
...@@ -1385,6 +1401,7 @@ xfs_free_ag_extent( ...@@ -1385,6 +1401,7 @@ xfs_free_ag_extent(
xfs_mount_t *mp; /* mount point struct for filesystem */ xfs_mount_t *mp; /* mount point struct for filesystem */
xfs_agblock_t nbno; /* new starting block of freespace */ xfs_agblock_t nbno; /* new starting block of freespace */
xfs_extlen_t nlen; /* new length of freespace */ xfs_extlen_t nlen; /* new length of freespace */
xfs_perag_t *pag; /* per allocation group data */
mp = tp->t_mountp; mp = tp->t_mountp;
/* /*
...@@ -1583,30 +1600,20 @@ xfs_free_ag_extent( ...@@ -1583,30 +1600,20 @@ xfs_free_ag_extent(
XFS_WANT_CORRUPTED_GOTO(i == 1, error0); XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
cnt_cur = NULL; cnt_cur = NULL;
/* /*
* Update the freespace totals in the ag and superblock. * Update the freespace totals in the ag and superblock.
*/ */
{ pag = xfs_perag_get(mp, agno);
xfs_agf_t *agf; error = xfs_alloc_update_counters(tp, pag, agbp, len);
xfs_perag_t *pag; /* per allocation group data */ xfs_perag_put(pag);
if (error)
pag = xfs_perag_get(mp, agno); goto error0;
pag->pagf_freeblks += len;
xfs_perag_put(pag); if (!isfl)
xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, (long)len);
agf = XFS_BUF_TO_AGF(agbp); XFS_STATS_INC(xs_freex);
be32_add_cpu(&agf->agf_freeblks, len); XFS_STATS_ADD(xs_freeb, len);
xfs_trans_agblocks_delta(tp, len);
XFS_WANT_CORRUPTED_GOTO(
be32_to_cpu(agf->agf_freeblks) <=
be32_to_cpu(agf->agf_length),
error0);
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(xs_freex);
XFS_STATS_ADD(xs_freeb, len);
}
trace_xfs_free_extent(mp, agno, bno, len, isfl, haveleft, haveright); trace_xfs_free_extent(mp, agno, bno, len, isfl, haveleft, haveright);
......
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