提交 50adbcb4 编写于 作者: D Dave Chinner 提交者: Dave Chinner

xfs: xfs_alloc_fix_freelist() can use incore perag structures

At the moment, xfs_alloc_fix_freelist() uses a mix of per-ag based
access and agf buffer  based access to freelist and space usage
information. However, once the AGF buffer is locked inside this
function, it is guaranteed that both the in-memory and on-disk
values are identical. xfs_alloc_fix_freelist() doesn't modify the
values in the structures directly, so it is a read-only user of the
infomration, and hence can use the per-ag structure exclusively for
determining what it should do.

This opens up an avenue for cleaning up a lot of duplicated logic
whose only difference is the structure it gets the data from, and in
doing so removes a lot of needless byte swapping overhead when
fixing up the free list.
Signed-off-by: NDave Chinner <dchinner@redhat.com>
Reviewed-by: NBrian Foster <bfoster@redhat.com>
Signed-off-by: NDave Chinner <david@fromorbit.com>
上级 5ebe6afa
...@@ -1825,11 +1825,11 @@ xfs_alloc_compute_maxlevels( ...@@ -1825,11 +1825,11 @@ xfs_alloc_compute_maxlevels(
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, delta = 0; xfs_extlen_t delta = 0;
need = XFS_MIN_FREELIST_PAG(pag, mp);
if (need > pag->pagf_flcount) if (need > pag->pagf_flcount)
delta = need - pag->pagf_flcount; delta = need - pag->pagf_flcount;
...@@ -1848,10 +1848,8 @@ xfs_alloc_fix_freelist( ...@@ -1848,10 +1848,8 @@ xfs_alloc_fix_freelist(
int flags) /* XFS_ALLOC_FLAG_... */ int flags) /* XFS_ALLOC_FLAG_... */
{ {
xfs_buf_t *agbp; /* agf buffer pointer */ xfs_buf_t *agbp; /* agf buffer pointer */
xfs_agf_t *agf; /* a.g. freespace structure pointer */
xfs_buf_t *agflbp;/* agfl buffer pointer */ xfs_buf_t *agflbp;/* agfl buffer pointer */
xfs_agblock_t bno; /* freelist block */ xfs_agblock_t bno; /* freelist block */
xfs_extlen_t delta; /* new blocks needed in freelist */
int error; /* error result code */ int error; /* error result code */
xfs_extlen_t longest;/* longest extent in allocation group */ xfs_extlen_t longest;/* longest extent in allocation group */
xfs_mount_t *mp; /* file system mount point structure */ xfs_mount_t *mp; /* file system mount point structure */
...@@ -1895,7 +1893,7 @@ xfs_alloc_fix_freelist( ...@@ -1895,7 +1893,7 @@ xfs_alloc_fix_freelist(
* total blocks, reject it. * total blocks, reject it.
*/ */
need = XFS_MIN_FREELIST_PAG(pag, mp); need = XFS_MIN_FREELIST_PAG(pag, mp);
longest = xfs_alloc_longest_free_extent(mp, pag); longest = xfs_alloc_longest_free_extent(mp, pag, need);
if ((args->minlen + args->alignment + args->minalignslop - 1) > if ((args->minlen + args->alignment + args->minalignslop - 1) >
longest || longest ||
((int)(pag->pagf_freeblks + pag->pagf_flcount - ((int)(pag->pagf_freeblks + pag->pagf_flcount -
...@@ -1922,25 +1920,16 @@ xfs_alloc_fix_freelist( ...@@ -1922,25 +1920,16 @@ xfs_alloc_fix_freelist(
return 0; return 0;
} }
} }
/*
* Figure out how many blocks we should have in the freelist.
*/ /* If there isn't enough total space or single-extent, reject it. */
agf = XFS_BUF_TO_AGF(agbp); need = XFS_MIN_FREELIST_PAG(pag, mp);
need = XFS_MIN_FREELIST(agf, mp);
/*
* If there isn't enough total or single-extent, reject it.
*/
if (!(flags & XFS_ALLOC_FLAG_FREEING)) { if (!(flags & XFS_ALLOC_FLAG_FREEING)) {
delta = need > be32_to_cpu(agf->agf_flcount) ? longest = xfs_alloc_longest_free_extent(mp, pag, need);
(need - be32_to_cpu(agf->agf_flcount)) : 0;
longest = be32_to_cpu(agf->agf_longest);
longest = (longest > delta) ? (longest - delta) :
(be32_to_cpu(agf->agf_flcount) > 0 || longest > 0);
if ((args->minlen + args->alignment + args->minalignslop - 1) > if ((args->minlen + args->alignment + args->minalignslop - 1) >
longest || longest ||
((int)(be32_to_cpu(agf->agf_freeblks) + ((int)(pag->pagf_freeblks + pag->pagf_flcount -
be32_to_cpu(agf->agf_flcount) - need - args->total) < need - args->total) < (int)args->minleft)) {
(int)args->minleft)) {
xfs_trans_brelse(tp, agbp); xfs_trans_brelse(tp, agbp);
args->agbp = NULL; args->agbp = NULL;
return 0; return 0;
...@@ -1948,21 +1937,25 @@ xfs_alloc_fix_freelist( ...@@ -1948,21 +1937,25 @@ xfs_alloc_fix_freelist(
} }
/* /*
* Make the freelist shorter if it's too long. * Make the freelist shorter if it's too long.
*
* XXX (dgc): When we have lots of free space, does this buy us
* anything other than extra overhead when we need to put more blocks
* back on the free list? Maybe we should only do this when space is
* getting low or the AGFL is more than half full?
*/ */
while (be32_to_cpu(agf->agf_flcount) > need) { while (pag->pagf_flcount > need) {
xfs_buf_t *bp; struct xfs_buf *bp;
error = xfs_alloc_get_freelist(tp, agbp, &bno, 0); error = xfs_alloc_get_freelist(tp, agbp, &bno, 0);
if (error) if (error)
return error; return error;
if ((error = xfs_free_ag_extent(tp, agbp, args->agno, bno, 1, 1))) error = xfs_free_ag_extent(tp, agbp, args->agno, bno, 1, 1);
if (error)
return error; return error;
bp = xfs_btree_get_bufs(mp, tp, args->agno, bno, 0); bp = xfs_btree_get_bufs(mp, tp, args->agno, bno, 0);
xfs_trans_binval(tp, bp); xfs_trans_binval(tp, bp);
} }
/*
* Initialize the args structure.
*/
memset(&targs, 0, sizeof(targs)); memset(&targs, 0, sizeof(targs));
targs.tp = tp; targs.tp = tp;
targs.mp = mp; targs.mp = mp;
...@@ -1971,18 +1964,18 @@ xfs_alloc_fix_freelist( ...@@ -1971,18 +1964,18 @@ xfs_alloc_fix_freelist(
targs.alignment = targs.minlen = targs.prod = targs.isfl = 1; targs.alignment = targs.minlen = targs.prod = targs.isfl = 1;
targs.type = XFS_ALLOCTYPE_THIS_AG; targs.type = XFS_ALLOCTYPE_THIS_AG;
targs.pag = pag; targs.pag = pag;
if ((error = xfs_alloc_read_agfl(mp, tp, targs.agno, &agflbp))) error = xfs_alloc_read_agfl(mp, tp, targs.agno, &agflbp);
if (error)
return error; return error;
/*
* Make the freelist longer if it's too short. /* Make the freelist longer if it's too short. */
*/ while (pag->pagf_flcount < need) {
while (be32_to_cpu(agf->agf_flcount) < need) {
targs.agbno = 0; targs.agbno = 0;
targs.maxlen = need - be32_to_cpu(agf->agf_flcount); targs.maxlen = need - pag->pagf_flcount;
/*
* Allocate as many blocks as possible at once. /* Allocate as many blocks as possible at once. */
*/ error = xfs_alloc_ag_vextent(&targs);
if ((error = xfs_alloc_ag_vextent(&targs))) { if (error) {
xfs_trans_brelse(tp, agflbp); xfs_trans_brelse(tp, agflbp);
return error; return error;
} }
......
...@@ -128,12 +128,8 @@ typedef struct xfs_alloc_arg { ...@@ -128,12 +128,8 @@ typedef struct xfs_alloc_arg {
#define XFS_ALLOC_USERDATA 1 /* allocation is for user data*/ #define XFS_ALLOC_USERDATA 1 /* allocation is for user data*/
#define XFS_ALLOC_INITIAL_USER_DATA 2 /* special case start of file */ #define XFS_ALLOC_INITIAL_USER_DATA 2 /* special case start of file */
/* xfs_extlen_t xfs_alloc_longest_free_extent(struct xfs_mount *mp,
* Find the length of the longest extent in an AG. struct xfs_perag *pag, xfs_extlen_t need);
*/
xfs_extlen_t
xfs_alloc_longest_free_extent(struct xfs_mount *mp,
struct xfs_perag *pag);
/* /*
* Compute and fill in value of m_ag_maxlevels. * Compute and fill in value of m_ag_maxlevels.
......
...@@ -3507,7 +3507,8 @@ xfs_bmap_longest_free_extent( ...@@ -3507,7 +3507,8 @@ xfs_bmap_longest_free_extent(
} }
} }
longest = xfs_alloc_longest_free_extent(mp, pag); longest = xfs_alloc_longest_free_extent(mp, pag,
XFS_MIN_FREELIST_PAG(pag, mp));
if (*blen < longest) if (*blen < longest)
*blen = longest; *blen = longest;
......
...@@ -196,7 +196,8 @@ xfs_filestream_pick_ag( ...@@ -196,7 +196,8 @@ xfs_filestream_pick_ag(
goto next_ag; goto next_ag;
} }
longest = xfs_alloc_longest_free_extent(mp, pag); longest = xfs_alloc_longest_free_extent(mp, pag,
XFS_MIN_FREELIST_PAG(pag, mp));
if (((minlen && longest >= minlen) || if (((minlen && longest >= minlen) ||
(!minlen && pag->pagf_freeblks >= minfree)) && (!minlen && pag->pagf_freeblks >= minfree)) &&
(!pag->pagf_metadata || !(flags & XFS_PICK_USERDATA) || (!pag->pagf_metadata || !(flags & XFS_PICK_USERDATA) ||
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册