提交 fddb564f 编写于 作者: D Darrick J. Wong

Merge tag 'xfs-perag-conv-5.20' of...

Merge tag 'xfs-perag-conv-5.20' of git://git.kernel.org/pub/scm/linux/kernel/git/dgc/linux-xfs into xfs-5.20-mergeA

xfs: per-ag conversions for 5.20

This series drives the perag down into the AGI, AGF and AGFL access
routines and unifies the perag structure initialisation with the
high level AG header read functions. This largely replaces the
xfs_mount/agno pair that is passed to all these functions with a
perag, and in most places we already have a perag ready to pass in.
There are a few places where perags need to be grabbed before
reading the AG header buffers - some of these will need to be driven
to higher layers to ensure we can run operations on AGs without
getting stuck part way through waiting on a perag reference.

The latter section of this patchset moves some of the AG geometry
information from the xfs_mount to the xfs_perag, and starts
converting code that requires geometry validation to use a perag
instead of a mount and having to extract the AGNO from the object
location. This also allows us to store the AG size in the perag and
then we can stop having to compare the agno against sb_agcount to
determine if the AG is the last AG and so has a runt size.  This
greatly simplifies some of the type validity checking we do and
substantially reduces the CPU overhead of type validity checking. It
also cuts over 1.2kB out of the binary size.
Signed-off-by: NDave Chinner <dchinner@redhat.com>
Signed-off-by: NDarrick J. Wong <djwong@kernel.org>

* tag 'xfs-perag-conv-5.20' of git://git.kernel.org/pub/scm/linux/kernel/git/dgc/linux-xfs:
  xfs: make is_log_ag() a first class helper
  xfs: replace xfs_ag_block_count() with perag accesses
  xfs: Pre-calculate per-AG agino geometry
  xfs: Pre-calculate per-AG agbno geometry
  xfs: pass perag to xfs_alloc_read_agfl
  xfs: pass perag to xfs_alloc_put_freelist
  xfs: pass perag to xfs_alloc_get_freelist
  xfs: pass perag to xfs_read_agf
  xfs: pass perag to xfs_read_agi
  xfs: pass perag to xfs_alloc_read_agf()
  xfs: kill xfs_alloc_pagf_init()
  xfs: pass perag to xfs_ialloc_read_agi()
  xfs: kill xfs_ialloc_pagi_init()
  xfs: make last AG grow/shrink perag centric
...@@ -120,18 +120,18 @@ xfs_initialize_perag_data( ...@@ -120,18 +120,18 @@ xfs_initialize_perag_data(
for (index = 0; index < agcount; index++) { for (index = 0; index < agcount; index++) {
/* /*
* read the agf, then the agi. This gets us * Read the AGF and AGI buffers to populate the per-ag
* all the information we need and populates the * structures for us.
* per-ag structures for us.
*/ */
error = xfs_alloc_pagf_init(mp, NULL, index, 0); pag = xfs_perag_get(mp, index);
if (error) error = xfs_alloc_read_agf(pag, NULL, 0, NULL);
if (!error)
error = xfs_ialloc_read_agi(pag, NULL, NULL);
if (error) {
xfs_perag_put(pag);
return error; return error;
}
error = xfs_ialloc_pagi_init(mp, NULL, index);
if (error)
return error;
pag = xfs_perag_get(mp, index);
ifree += pag->pagi_freecount; ifree += pag->pagi_freecount;
ialloc += pag->pagi_count; ialloc += pag->pagi_count;
bfree += pag->pagf_freeblks; bfree += pag->pagf_freeblks;
...@@ -201,10 +201,70 @@ xfs_free_perag( ...@@ -201,10 +201,70 @@ xfs_free_perag(
} }
} }
/* Find the size of the AG, in blocks. */
static xfs_agblock_t
__xfs_ag_block_count(
struct xfs_mount *mp,
xfs_agnumber_t agno,
xfs_agnumber_t agcount,
xfs_rfsblock_t dblocks)
{
ASSERT(agno < agcount);
if (agno < agcount - 1)
return mp->m_sb.sb_agblocks;
return dblocks - (agno * mp->m_sb.sb_agblocks);
}
xfs_agblock_t
xfs_ag_block_count(
struct xfs_mount *mp,
xfs_agnumber_t agno)
{
return __xfs_ag_block_count(mp, agno, mp->m_sb.sb_agcount,
mp->m_sb.sb_dblocks);
}
/* Calculate the first and last possible inode number in an AG. */
static void
__xfs_agino_range(
struct xfs_mount *mp,
xfs_agblock_t eoag,
xfs_agino_t *first,
xfs_agino_t *last)
{
xfs_agblock_t bno;
/*
* Calculate the first inode, which will be in the first
* cluster-aligned block after the AGFL.
*/
bno = round_up(XFS_AGFL_BLOCK(mp) + 1, M_IGEO(mp)->cluster_align);
*first = XFS_AGB_TO_AGINO(mp, bno);
/*
* Calculate the last inode, which will be at the end of the
* last (aligned) cluster that can be allocated in the AG.
*/
bno = round_down(eoag, M_IGEO(mp)->cluster_align);
*last = XFS_AGB_TO_AGINO(mp, bno) - 1;
}
void
xfs_agino_range(
struct xfs_mount *mp,
xfs_agnumber_t agno,
xfs_agino_t *first,
xfs_agino_t *last)
{
return __xfs_agino_range(mp, xfs_ag_block_count(mp, agno), first, last);
}
int int
xfs_initialize_perag( xfs_initialize_perag(
struct xfs_mount *mp, struct xfs_mount *mp,
xfs_agnumber_t agcount, xfs_agnumber_t agcount,
xfs_rfsblock_t dblocks,
xfs_agnumber_t *maxagi) xfs_agnumber_t *maxagi)
{ {
struct xfs_perag *pag; struct xfs_perag *pag;
...@@ -270,6 +330,15 @@ xfs_initialize_perag( ...@@ -270,6 +330,15 @@ xfs_initialize_perag(
/* first new pag is fully initialized */ /* first new pag is fully initialized */
if (first_initialised == NULLAGNUMBER) if (first_initialised == NULLAGNUMBER)
first_initialised = index; first_initialised = index;
/*
* Pre-calculated geometry
*/
pag->block_count = __xfs_ag_block_count(mp, index, agcount,
dblocks);
pag->min_block = XFS_AGFL_BLOCK(mp);
__xfs_agino_range(mp, pag->block_count, &pag->agino_min,
&pag->agino_max);
} }
index = xfs_set_inode_alloc(mp, agcount); index = xfs_set_inode_alloc(mp, agcount);
...@@ -321,12 +390,6 @@ xfs_get_aghdr_buf( ...@@ -321,12 +390,6 @@ xfs_get_aghdr_buf(
return 0; return 0;
} }
static inline bool is_log_ag(struct xfs_mount *mp, struct aghdr_init_data *id)
{
return mp->m_sb.sb_logstart > 0 &&
id->agno == XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart);
}
/* /*
* Generic btree root block init function * Generic btree root block init function
*/ */
...@@ -352,7 +415,7 @@ xfs_freesp_init_recs( ...@@ -352,7 +415,7 @@ xfs_freesp_init_recs(
arec = XFS_ALLOC_REC_ADDR(mp, XFS_BUF_TO_BLOCK(bp), 1); arec = XFS_ALLOC_REC_ADDR(mp, XFS_BUF_TO_BLOCK(bp), 1);
arec->ar_startblock = cpu_to_be32(mp->m_ag_prealloc_blocks); arec->ar_startblock = cpu_to_be32(mp->m_ag_prealloc_blocks);
if (is_log_ag(mp, id)) { if (xfs_ag_contains_log(mp, id->agno)) {
struct xfs_alloc_rec *nrec; struct xfs_alloc_rec *nrec;
xfs_agblock_t start = XFS_FSB_TO_AGBNO(mp, xfs_agblock_t start = XFS_FSB_TO_AGBNO(mp,
mp->m_sb.sb_logstart); mp->m_sb.sb_logstart);
...@@ -479,7 +542,7 @@ xfs_rmaproot_init( ...@@ -479,7 +542,7 @@ xfs_rmaproot_init(
} }
/* account for the log space */ /* account for the log space */
if (is_log_ag(mp, id)) { if (xfs_ag_contains_log(mp, id->agno)) {
rrec = XFS_RMAP_REC_ADDR(block, rrec = XFS_RMAP_REC_ADDR(block,
be16_to_cpu(block->bb_numrecs) + 1); be16_to_cpu(block->bb_numrecs) + 1);
rrec->rm_startblock = cpu_to_be32( rrec->rm_startblock = cpu_to_be32(
...@@ -550,7 +613,7 @@ xfs_agfblock_init( ...@@ -550,7 +613,7 @@ xfs_agfblock_init(
agf->agf_refcount_blocks = cpu_to_be32(1); agf->agf_refcount_blocks = cpu_to_be32(1);
} }
if (is_log_ag(mp, id)) { if (xfs_ag_contains_log(mp, id->agno)) {
int64_t logblocks = mp->m_sb.sb_logblocks; int64_t logblocks = mp->m_sb.sb_logblocks;
be32_add_cpu(&agf->agf_freeblks, -logblocks); be32_add_cpu(&agf->agf_freeblks, -logblocks);
...@@ -761,11 +824,11 @@ xfs_ag_init_headers( ...@@ -761,11 +824,11 @@ xfs_ag_init_headers(
int int
xfs_ag_shrink_space( xfs_ag_shrink_space(
struct xfs_mount *mp, struct xfs_perag *pag,
struct xfs_trans **tpp, struct xfs_trans **tpp,
xfs_agnumber_t agno,
xfs_extlen_t delta) xfs_extlen_t delta)
{ {
struct xfs_mount *mp = pag->pag_mount;
struct xfs_alloc_arg args = { struct xfs_alloc_arg args = {
.tp = *tpp, .tp = *tpp,
.mp = mp, .mp = mp,
...@@ -782,14 +845,14 @@ xfs_ag_shrink_space( ...@@ -782,14 +845,14 @@ xfs_ag_shrink_space(
xfs_agblock_t aglen; xfs_agblock_t aglen;
int error, err2; int error, err2;
ASSERT(agno == mp->m_sb.sb_agcount - 1); ASSERT(pag->pag_agno == mp->m_sb.sb_agcount - 1);
error = xfs_ialloc_read_agi(mp, *tpp, agno, &agibp); error = xfs_ialloc_read_agi(pag, *tpp, &agibp);
if (error) if (error)
return error; return error;
agi = agibp->b_addr; agi = agibp->b_addr;
error = xfs_alloc_read_agf(mp, *tpp, agno, 0, &agfbp); error = xfs_alloc_read_agf(pag, *tpp, 0, &agfbp);
if (error) if (error)
return error; return error;
...@@ -801,13 +864,14 @@ xfs_ag_shrink_space( ...@@ -801,13 +864,14 @@ xfs_ag_shrink_space(
if (delta >= aglen) if (delta >= aglen)
return -EINVAL; return -EINVAL;
args.fsbno = XFS_AGB_TO_FSB(mp, agno, aglen - delta); args.fsbno = XFS_AGB_TO_FSB(mp, pag->pag_agno, aglen - delta);
/* /*
* Make sure that the last inode cluster cannot overlap with the new * Make sure that the last inode cluster cannot overlap with the new
* end of the AG, even if it's sparse. * end of the AG, even if it's sparse.
*/ */
error = xfs_ialloc_check_shrink(*tpp, agno, agibp, aglen - delta); error = xfs_ialloc_check_shrink(*tpp, pag->pag_agno, agibp,
aglen - delta);
if (error) if (error)
return error; return error;
...@@ -815,7 +879,7 @@ xfs_ag_shrink_space( ...@@ -815,7 +879,7 @@ xfs_ag_shrink_space(
* Disable perag reservations so it doesn't cause the allocation request * Disable perag reservations so it doesn't cause the allocation request
* to fail. We'll reestablish reservation before we return. * to fail. We'll reestablish reservation before we return.
*/ */
error = xfs_ag_resv_free(agibp->b_pag); error = xfs_ag_resv_free(pag);
if (error) if (error)
return error; return error;
...@@ -844,7 +908,7 @@ xfs_ag_shrink_space( ...@@ -844,7 +908,7 @@ xfs_ag_shrink_space(
be32_add_cpu(&agi->agi_length, -delta); be32_add_cpu(&agi->agi_length, -delta);
be32_add_cpu(&agf->agf_length, -delta); be32_add_cpu(&agf->agf_length, -delta);
err2 = xfs_ag_resv_init(agibp->b_pag, *tpp); err2 = xfs_ag_resv_init(pag, *tpp);
if (err2) { if (err2) {
be32_add_cpu(&agi->agi_length, delta); be32_add_cpu(&agi->agi_length, delta);
be32_add_cpu(&agf->agf_length, delta); be32_add_cpu(&agf->agf_length, delta);
...@@ -868,8 +932,9 @@ xfs_ag_shrink_space( ...@@ -868,8 +932,9 @@ xfs_ag_shrink_space(
xfs_ialloc_log_agi(*tpp, agibp, XFS_AGI_LENGTH); xfs_ialloc_log_agi(*tpp, agibp, XFS_AGI_LENGTH);
xfs_alloc_log_agf(*tpp, agfbp, XFS_AGF_LENGTH); xfs_alloc_log_agf(*tpp, agfbp, XFS_AGF_LENGTH);
return 0; return 0;
resv_init_out: resv_init_out:
err2 = xfs_ag_resv_init(agibp->b_pag, *tpp); err2 = xfs_ag_resv_init(pag, *tpp);
if (!err2) if (!err2)
return error; return error;
resv_err: resv_err:
...@@ -883,9 +948,8 @@ xfs_ag_shrink_space( ...@@ -883,9 +948,8 @@ xfs_ag_shrink_space(
*/ */
int int
xfs_ag_extend_space( xfs_ag_extend_space(
struct xfs_mount *mp, struct xfs_perag *pag,
struct xfs_trans *tp, struct xfs_trans *tp,
struct aghdr_init_data *id,
xfs_extlen_t len) xfs_extlen_t len)
{ {
struct xfs_buf *bp; struct xfs_buf *bp;
...@@ -893,23 +957,20 @@ xfs_ag_extend_space( ...@@ -893,23 +957,20 @@ xfs_ag_extend_space(
struct xfs_agf *agf; struct xfs_agf *agf;
int error; int error;
/* ASSERT(pag->pag_agno == pag->pag_mount->m_sb.sb_agcount - 1);
* Change the agi length.
*/ error = xfs_ialloc_read_agi(pag, tp, &bp);
error = xfs_ialloc_read_agi(mp, tp, id->agno, &bp);
if (error) if (error)
return error; return error;
agi = bp->b_addr; agi = bp->b_addr;
be32_add_cpu(&agi->agi_length, len); be32_add_cpu(&agi->agi_length, len);
ASSERT(id->agno == mp->m_sb.sb_agcount - 1 ||
be32_to_cpu(agi->agi_length) == mp->m_sb.sb_agblocks);
xfs_ialloc_log_agi(tp, bp, XFS_AGI_LENGTH); xfs_ialloc_log_agi(tp, bp, XFS_AGI_LENGTH);
/* /*
* Change agf length. * Change agf length.
*/ */
error = xfs_alloc_read_agf(mp, tp, id->agno, 0, &bp); error = xfs_alloc_read_agf(pag, tp, 0, &bp);
if (error) if (error)
return error; return error;
...@@ -924,49 +985,49 @@ xfs_ag_extend_space( ...@@ -924,49 +985,49 @@ xfs_ag_extend_space(
* XFS_RMAP_OINFO_SKIP_UPDATE is used here to tell the rmap btree that * XFS_RMAP_OINFO_SKIP_UPDATE is used here to tell the rmap btree that
* this doesn't actually exist in the rmap btree. * this doesn't actually exist in the rmap btree.
*/ */
error = xfs_rmap_free(tp, bp, bp->b_pag, error = xfs_rmap_free(tp, bp, pag, be32_to_cpu(agf->agf_length) - len,
be32_to_cpu(agf->agf_length) - len,
len, &XFS_RMAP_OINFO_SKIP_UPDATE); len, &XFS_RMAP_OINFO_SKIP_UPDATE);
if (error) if (error)
return error; return error;
return xfs_free_extent(tp, XFS_AGB_TO_FSB(mp, id->agno, error = xfs_free_extent(tp, XFS_AGB_TO_FSB(pag->pag_mount, pag->pag_agno,
be32_to_cpu(agf->agf_length) - len), be32_to_cpu(agf->agf_length) - len),
len, &XFS_RMAP_OINFO_SKIP_UPDATE, len, &XFS_RMAP_OINFO_SKIP_UPDATE,
XFS_AG_RESV_NONE); XFS_AG_RESV_NONE);
if (error)
return error;
/* Update perag geometry */
pag->block_count = be32_to_cpu(agf->agf_length);
__xfs_agino_range(pag->pag_mount, pag->block_count, &pag->agino_min,
&pag->agino_max);
return 0;
} }
/* Retrieve AG geometry. */ /* Retrieve AG geometry. */
int int
xfs_ag_get_geometry( xfs_ag_get_geometry(
struct xfs_mount *mp, struct xfs_perag *pag,
xfs_agnumber_t agno,
struct xfs_ag_geometry *ageo) struct xfs_ag_geometry *ageo)
{ {
struct xfs_buf *agi_bp; struct xfs_buf *agi_bp;
struct xfs_buf *agf_bp; struct xfs_buf *agf_bp;
struct xfs_agi *agi; struct xfs_agi *agi;
struct xfs_agf *agf; struct xfs_agf *agf;
struct xfs_perag *pag;
unsigned int freeblks; unsigned int freeblks;
int error; int error;
if (agno >= mp->m_sb.sb_agcount)
return -EINVAL;
/* Lock the AG headers. */ /* Lock the AG headers. */
error = xfs_ialloc_read_agi(mp, NULL, agno, &agi_bp); error = xfs_ialloc_read_agi(pag, NULL, &agi_bp);
if (error) if (error)
return error; return error;
error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agf_bp); error = xfs_alloc_read_agf(pag, NULL, 0, &agf_bp);
if (error) if (error)
goto out_agi; goto out_agi;
pag = agi_bp->b_pag;
/* Fill out form. */ /* Fill out form. */
memset(ageo, 0, sizeof(*ageo)); memset(ageo, 0, sizeof(*ageo));
ageo->ag_number = agno; ageo->ag_number = pag->pag_agno;
agi = agi_bp->b_addr; agi = agi_bp->b_addr;
ageo->ag_icount = be32_to_cpu(agi->agi_count); ageo->ag_icount = be32_to_cpu(agi->agi_count);
......
...@@ -67,6 +67,12 @@ struct xfs_perag { ...@@ -67,6 +67,12 @@ struct xfs_perag {
/* for rcu-safe freeing */ /* for rcu-safe freeing */
struct rcu_head rcu_head; struct rcu_head rcu_head;
/* Precalculated geometry info */
xfs_agblock_t block_count;
xfs_agblock_t min_block;
xfs_agino_t agino_min;
xfs_agino_t agino_max;
#ifdef __KERNEL__ #ifdef __KERNEL__
/* -- kernel only structures below this line -- */ /* -- kernel only structures below this line -- */
...@@ -107,7 +113,7 @@ struct xfs_perag { ...@@ -107,7 +113,7 @@ struct xfs_perag {
}; };
int xfs_initialize_perag(struct xfs_mount *mp, xfs_agnumber_t agcount, int xfs_initialize_perag(struct xfs_mount *mp, xfs_agnumber_t agcount,
xfs_agnumber_t *maxagi); xfs_rfsblock_t dcount, xfs_agnumber_t *maxagi);
int xfs_initialize_perag_data(struct xfs_mount *mp, xfs_agnumber_t agno); int xfs_initialize_perag_data(struct xfs_mount *mp, xfs_agnumber_t agno);
void xfs_free_perag(struct xfs_mount *mp); void xfs_free_perag(struct xfs_mount *mp);
...@@ -116,6 +122,56 @@ struct xfs_perag *xfs_perag_get_tag(struct xfs_mount *mp, xfs_agnumber_t agno, ...@@ -116,6 +122,56 @@ struct xfs_perag *xfs_perag_get_tag(struct xfs_mount *mp, xfs_agnumber_t agno,
unsigned int tag); unsigned int tag);
void xfs_perag_put(struct xfs_perag *pag); void xfs_perag_put(struct xfs_perag *pag);
/*
* Per-ag geometry infomation and validation
*/
xfs_agblock_t xfs_ag_block_count(struct xfs_mount *mp, xfs_agnumber_t agno);
void xfs_agino_range(struct xfs_mount *mp, xfs_agnumber_t agno,
xfs_agino_t *first, xfs_agino_t *last);
static inline bool
xfs_verify_agbno(struct xfs_perag *pag, xfs_agblock_t agbno)
{
if (agbno >= pag->block_count)
return false;
if (agbno <= pag->min_block)
return false;
return true;
}
/*
* Verify that an AG inode number pointer neither points outside the AG
* nor points at static metadata.
*/
static inline bool
xfs_verify_agino(struct xfs_perag *pag, xfs_agino_t agino)
{
if (agino < pag->agino_min)
return false;
if (agino > pag->agino_max)
return false;
return true;
}
/*
* Verify that an AG inode number pointer neither points outside the AG
* nor points at static metadata, or is NULLAGINO.
*/
static inline bool
xfs_verify_agino_or_null(struct xfs_perag *pag, xfs_agino_t agino)
{
if (agino == NULLAGINO)
return true;
return xfs_verify_agino(pag, agino);
}
static inline bool
xfs_ag_contains_log(struct xfs_mount *mp, xfs_agnumber_t agno)
{
return mp->m_sb.sb_logstart > 0 &&
agno == XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart);
}
/* /*
* Perag iteration APIs * Perag iteration APIs
*/ */
...@@ -168,11 +224,10 @@ struct aghdr_init_data { ...@@ -168,11 +224,10 @@ struct aghdr_init_data {
}; };
int xfs_ag_init_headers(struct xfs_mount *mp, struct aghdr_init_data *id); int xfs_ag_init_headers(struct xfs_mount *mp, struct aghdr_init_data *id);
int xfs_ag_shrink_space(struct xfs_mount *mp, struct xfs_trans **tpp, int xfs_ag_shrink_space(struct xfs_perag *pag, struct xfs_trans **tpp,
xfs_agnumber_t agno, xfs_extlen_t delta); xfs_extlen_t delta);
int xfs_ag_extend_space(struct xfs_mount *mp, struct xfs_trans *tp, int xfs_ag_extend_space(struct xfs_perag *pag, struct xfs_trans *tp,
struct aghdr_init_data *id, xfs_extlen_t len); xfs_extlen_t len);
int xfs_ag_get_geometry(struct xfs_mount *mp, xfs_agnumber_t agno, int xfs_ag_get_geometry(struct xfs_perag *pag, struct xfs_ag_geometry *ageo);
struct xfs_ag_geometry *ageo);
#endif /* __LIBXFS_AG_H */ #endif /* __LIBXFS_AG_H */
...@@ -322,7 +322,7 @@ xfs_ag_resv_init( ...@@ -322,7 +322,7 @@ xfs_ag_resv_init(
* address. * address.
*/ */
if (has_resv) { if (has_resv) {
error2 = xfs_alloc_pagf_init(mp, tp, pag->pag_agno, 0); error2 = xfs_alloc_read_agf(pag, tp, 0, NULL);
if (error2) if (error2)
return error2; return error2;
......
...@@ -248,7 +248,7 @@ xfs_alloc_get_rec( ...@@ -248,7 +248,7 @@ xfs_alloc_get_rec(
int *stat) /* output: success/failure */ int *stat) /* output: success/failure */
{ {
struct xfs_mount *mp = cur->bc_mp; struct xfs_mount *mp = cur->bc_mp;
xfs_agnumber_t agno = cur->bc_ag.pag->pag_agno; struct xfs_perag *pag = cur->bc_ag.pag;
union xfs_btree_rec *rec; union xfs_btree_rec *rec;
int error; int error;
...@@ -263,11 +263,11 @@ xfs_alloc_get_rec( ...@@ -263,11 +263,11 @@ xfs_alloc_get_rec(
goto out_bad_rec; goto out_bad_rec;
/* check for valid extent range, including overflow */ /* check for valid extent range, including overflow */
if (!xfs_verify_agbno(mp, agno, *bno)) if (!xfs_verify_agbno(pag, *bno))
goto out_bad_rec; goto out_bad_rec;
if (*bno > *bno + *len) if (*bno > *bno + *len)
goto out_bad_rec; goto out_bad_rec;
if (!xfs_verify_agbno(mp, agno, *bno + *len - 1)) if (!xfs_verify_agbno(pag, *bno + *len - 1))
goto out_bad_rec; goto out_bad_rec;
return 0; return 0;
...@@ -275,7 +275,8 @@ xfs_alloc_get_rec( ...@@ -275,7 +275,8 @@ xfs_alloc_get_rec(
out_bad_rec: out_bad_rec:
xfs_warn(mp, xfs_warn(mp,
"%s Freespace BTree record corruption in AG %d detected!", "%s Freespace BTree record corruption in AG %d detected!",
cur->bc_btnum == XFS_BTNUM_BNO ? "Block" : "Size", agno); cur->bc_btnum == XFS_BTNUM_BNO ? "Block" : "Size",
pag->pag_agno);
xfs_warn(mp, xfs_warn(mp,
"start block 0x%x block count 0x%x", *bno, *len); "start block 0x%x block count 0x%x", *bno, *len);
return -EFSCORRUPTED; return -EFSCORRUPTED;
...@@ -703,20 +704,19 @@ const struct xfs_buf_ops xfs_agfl_buf_ops = { ...@@ -703,20 +704,19 @@ const struct xfs_buf_ops xfs_agfl_buf_ops = {
/* /*
* Read in the allocation group free block array. * Read in the allocation group free block array.
*/ */
int /* error */ int
xfs_alloc_read_agfl( xfs_alloc_read_agfl(
xfs_mount_t *mp, /* mount point structure */ struct xfs_perag *pag,
xfs_trans_t *tp, /* transaction pointer */ struct xfs_trans *tp,
xfs_agnumber_t agno, /* allocation group number */ struct xfs_buf **bpp)
struct xfs_buf **bpp) /* buffer for the ag free block array */
{ {
struct xfs_buf *bp; /* return value */ struct xfs_mount *mp = pag->pag_mount;
struct xfs_buf *bp;
int error; int error;
ASSERT(agno != NULLAGNUMBER);
error = xfs_trans_read_buf( error = xfs_trans_read_buf(
mp, tp, mp->m_ddev_targp, mp, tp, mp->m_ddev_targp,
XFS_AG_DADDR(mp, agno, XFS_AGFL_DADDR(mp)), XFS_AG_DADDR(mp, pag->pag_agno, XFS_AGFL_DADDR(mp)),
XFS_FSS_TO_BB(mp, 1), 0, &bp, &xfs_agfl_buf_ops); XFS_FSS_TO_BB(mp, 1), 0, &bp, &xfs_agfl_buf_ops);
if (error) if (error)
return error; return error;
...@@ -1075,7 +1075,8 @@ xfs_alloc_ag_vextent_small( ...@@ -1075,7 +1075,8 @@ xfs_alloc_ag_vextent_small(
be32_to_cpu(agf->agf_flcount) <= args->minleft) be32_to_cpu(agf->agf_flcount) <= args->minleft)
goto out; goto out;
error = xfs_alloc_get_freelist(args->tp, args->agbp, &fbno, 0); error = xfs_alloc_get_freelist(args->pag, args->tp, args->agbp,
&fbno, 0);
if (error) if (error)
goto error; goto error;
if (fbno == NULLAGBLOCK) if (fbno == NULLAGBLOCK)
...@@ -2609,7 +2610,7 @@ xfs_alloc_fix_freelist( ...@@ -2609,7 +2610,7 @@ xfs_alloc_fix_freelist(
ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
if (!pag->pagf_init) { if (!pag->pagf_init) {
error = xfs_alloc_read_agf(mp, tp, args->agno, flags, &agbp); error = xfs_alloc_read_agf(pag, tp, flags, &agbp);
if (error) { if (error) {
/* Couldn't lock the AGF so skip this AG. */ /* Couldn't lock the AGF so skip this AG. */
if (error == -EAGAIN) if (error == -EAGAIN)
...@@ -2639,7 +2640,7 @@ xfs_alloc_fix_freelist( ...@@ -2639,7 +2640,7 @@ xfs_alloc_fix_freelist(
* Can fail if we're not blocking on locks, and it's held. * Can fail if we're not blocking on locks, and it's held.
*/ */
if (!agbp) { if (!agbp) {
error = xfs_alloc_read_agf(mp, tp, args->agno, flags, &agbp); error = xfs_alloc_read_agf(pag, tp, flags, &agbp);
if (error) { if (error) {
/* Couldn't lock the AGF so skip this AG. */ /* Couldn't lock the AGF so skip this AG. */
if (error == -EAGAIN) if (error == -EAGAIN)
...@@ -2697,7 +2698,7 @@ xfs_alloc_fix_freelist( ...@@ -2697,7 +2698,7 @@ xfs_alloc_fix_freelist(
else else
targs.oinfo = XFS_RMAP_OINFO_AG; targs.oinfo = XFS_RMAP_OINFO_AG;
while (!(flags & XFS_ALLOC_FLAG_NOSHRINK) && pag->pagf_flcount > need) { while (!(flags & XFS_ALLOC_FLAG_NOSHRINK) && pag->pagf_flcount > need) {
error = xfs_alloc_get_freelist(tp, agbp, &bno, 0); error = xfs_alloc_get_freelist(pag, tp, agbp, &bno, 0);
if (error) if (error)
goto out_agbp_relse; goto out_agbp_relse;
...@@ -2712,7 +2713,7 @@ xfs_alloc_fix_freelist( ...@@ -2712,7 +2713,7 @@ xfs_alloc_fix_freelist(
targs.alignment = targs.minlen = targs.prod = 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(pag, tp, &agflbp);
if (error) if (error)
goto out_agbp_relse; goto out_agbp_relse;
...@@ -2741,7 +2742,7 @@ xfs_alloc_fix_freelist( ...@@ -2741,7 +2742,7 @@ xfs_alloc_fix_freelist(
* Put each allocated block on the list. * Put each allocated block on the list.
*/ */
for (bno = targs.agbno; bno < targs.agbno + targs.len; bno++) { for (bno = targs.agbno; bno < targs.agbno + targs.len; bno++) {
error = xfs_alloc_put_freelist(tp, agbp, error = xfs_alloc_put_freelist(pag, tp, agbp,
agflbp, bno, 0); agflbp, bno, 0);
if (error) if (error)
goto out_agflbp_relse; goto out_agflbp_relse;
...@@ -2767,6 +2768,7 @@ xfs_alloc_fix_freelist( ...@@ -2767,6 +2768,7 @@ xfs_alloc_fix_freelist(
*/ */
int int
xfs_alloc_get_freelist( xfs_alloc_get_freelist(
struct xfs_perag *pag,
struct xfs_trans *tp, struct xfs_trans *tp,
struct xfs_buf *agbp, struct xfs_buf *agbp,
xfs_agblock_t *bnop, xfs_agblock_t *bnop,
...@@ -2779,7 +2781,6 @@ xfs_alloc_get_freelist( ...@@ -2779,7 +2781,6 @@ xfs_alloc_get_freelist(
int error; int error;
uint32_t logflags; uint32_t logflags;
struct xfs_mount *mp = tp->t_mountp; struct xfs_mount *mp = tp->t_mountp;
struct xfs_perag *pag;
/* /*
* Freelist is empty, give up. * Freelist is empty, give up.
...@@ -2791,8 +2792,7 @@ xfs_alloc_get_freelist( ...@@ -2791,8 +2792,7 @@ xfs_alloc_get_freelist(
/* /*
* Read the array of free blocks. * Read the array of free blocks.
*/ */
error = xfs_alloc_read_agfl(mp, tp, be32_to_cpu(agf->agf_seqno), error = xfs_alloc_read_agfl(pag, tp, &agflbp);
&agflbp);
if (error) if (error)
return error; return error;
...@@ -2807,7 +2807,6 @@ xfs_alloc_get_freelist( ...@@ -2807,7 +2807,6 @@ xfs_alloc_get_freelist(
if (be32_to_cpu(agf->agf_flfirst) == xfs_agfl_size(mp)) if (be32_to_cpu(agf->agf_flfirst) == xfs_agfl_size(mp))
agf->agf_flfirst = 0; agf->agf_flfirst = 0;
pag = agbp->b_pag;
ASSERT(!pag->pagf_agflreset); ASSERT(!pag->pagf_agflreset);
be32_add_cpu(&agf->agf_flcount, -1); be32_add_cpu(&agf->agf_flcount, -1);
pag->pagf_flcount--; pag->pagf_flcount--;
...@@ -2867,30 +2866,12 @@ xfs_alloc_log_agf( ...@@ -2867,30 +2866,12 @@ xfs_alloc_log_agf(
xfs_trans_log_buf(tp, bp, (uint)first, (uint)last); xfs_trans_log_buf(tp, bp, (uint)first, (uint)last);
} }
/*
* Interface for inode allocation to force the pag data to be initialized.
*/
int /* error */
xfs_alloc_pagf_init(
xfs_mount_t *mp, /* file system mount structure */
xfs_trans_t *tp, /* transaction pointer */
xfs_agnumber_t agno, /* allocation group number */
int flags) /* XFS_ALLOC_FLAGS_... */
{
struct xfs_buf *bp;
int error;
error = xfs_alloc_read_agf(mp, tp, agno, flags, &bp);
if (!error)
xfs_trans_brelse(tp, bp);
return error;
}
/* /*
* Put the block on the freelist for the allocation group. * Put the block on the freelist for the allocation group.
*/ */
int int
xfs_alloc_put_freelist( xfs_alloc_put_freelist(
struct xfs_perag *pag,
struct xfs_trans *tp, struct xfs_trans *tp,
struct xfs_buf *agbp, struct xfs_buf *agbp,
struct xfs_buf *agflbp, struct xfs_buf *agflbp,
...@@ -2899,21 +2880,22 @@ xfs_alloc_put_freelist( ...@@ -2899,21 +2880,22 @@ xfs_alloc_put_freelist(
{ {
struct xfs_mount *mp = tp->t_mountp; struct xfs_mount *mp = tp->t_mountp;
struct xfs_agf *agf = agbp->b_addr; struct xfs_agf *agf = agbp->b_addr;
struct xfs_perag *pag;
__be32 *blockp; __be32 *blockp;
int error; int error;
uint32_t logflags; uint32_t logflags;
__be32 *agfl_bno; __be32 *agfl_bno;
int startoff; int startoff;
if (!agflbp && (error = xfs_alloc_read_agfl(mp, tp, if (!agflbp) {
be32_to_cpu(agf->agf_seqno), &agflbp))) error = xfs_alloc_read_agfl(pag, tp, &agflbp);
if (error)
return error; return error;
}
be32_add_cpu(&agf->agf_fllast, 1); be32_add_cpu(&agf->agf_fllast, 1);
if (be32_to_cpu(agf->agf_fllast) == xfs_agfl_size(mp)) if (be32_to_cpu(agf->agf_fllast) == xfs_agfl_size(mp))
agf->agf_fllast = 0; agf->agf_fllast = 0;
pag = agbp->b_pag;
ASSERT(!pag->pagf_agflreset); ASSERT(!pag->pagf_agflreset);
be32_add_cpu(&agf->agf_flcount, 1); be32_add_cpu(&agf->agf_flcount, 1);
pag->pagf_flcount++; pag->pagf_flcount++;
...@@ -3070,61 +3052,57 @@ const struct xfs_buf_ops xfs_agf_buf_ops = { ...@@ -3070,61 +3052,57 @@ const struct xfs_buf_ops xfs_agf_buf_ops = {
/* /*
* Read in the allocation group header (free/alloc section). * Read in the allocation group header (free/alloc section).
*/ */
int /* error */ int
xfs_read_agf( xfs_read_agf(
struct xfs_mount *mp, /* mount point structure */ struct xfs_perag *pag,
struct xfs_trans *tp, /* transaction pointer */ struct xfs_trans *tp,
xfs_agnumber_t agno, /* allocation group number */ int flags,
int flags, /* XFS_BUF_ */ struct xfs_buf **agfbpp)
struct xfs_buf **bpp) /* buffer for the ag freelist header */
{ {
struct xfs_mount *mp = pag->pag_mount;
int error; int error;
trace_xfs_read_agf(mp, agno); trace_xfs_read_agf(pag->pag_mount, pag->pag_agno);
ASSERT(agno != NULLAGNUMBER);
error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)), XFS_AG_DADDR(mp, pag->pag_agno, XFS_AGF_DADDR(mp)),
XFS_FSS_TO_BB(mp, 1), flags, bpp, &xfs_agf_buf_ops); XFS_FSS_TO_BB(mp, 1), flags, agfbpp, &xfs_agf_buf_ops);
if (error) if (error)
return error; return error;
ASSERT(!(*bpp)->b_error); xfs_buf_set_ref(*agfbpp, XFS_AGF_REF);
xfs_buf_set_ref(*bpp, XFS_AGF_REF);
return 0; return 0;
} }
/* /*
* Read in the allocation group header (free/alloc section). * Read in the allocation group header (free/alloc section) and initialise the
* perag structure if necessary. If the caller provides @agfbpp, then return the
* locked buffer to the caller, otherwise free it.
*/ */
int /* error */ int
xfs_alloc_read_agf( xfs_alloc_read_agf(
struct xfs_mount *mp, /* mount point structure */ struct xfs_perag *pag,
struct xfs_trans *tp, /* transaction pointer */ struct xfs_trans *tp,
xfs_agnumber_t agno, /* allocation group number */ int flags,
int flags, /* XFS_ALLOC_FLAG_... */ struct xfs_buf **agfbpp)
struct xfs_buf **bpp) /* buffer for the ag freelist header */
{ {
struct xfs_agf *agf; /* ag freelist header */ struct xfs_buf *agfbp;
struct xfs_perag *pag; /* per allocation group data */ struct xfs_agf *agf;
int error; int error;
int allocbt_blks; int allocbt_blks;
trace_xfs_alloc_read_agf(mp, agno); trace_xfs_alloc_read_agf(pag->pag_mount, pag->pag_agno);
/* We don't support trylock when freeing. */ /* We don't support trylock when freeing. */
ASSERT((flags & (XFS_ALLOC_FLAG_FREEING | XFS_ALLOC_FLAG_TRYLOCK)) != ASSERT((flags & (XFS_ALLOC_FLAG_FREEING | XFS_ALLOC_FLAG_TRYLOCK)) !=
(XFS_ALLOC_FLAG_FREEING | XFS_ALLOC_FLAG_TRYLOCK)); (XFS_ALLOC_FLAG_FREEING | XFS_ALLOC_FLAG_TRYLOCK));
ASSERT(agno != NULLAGNUMBER); error = xfs_read_agf(pag, tp,
error = xfs_read_agf(mp, tp, agno,
(flags & XFS_ALLOC_FLAG_TRYLOCK) ? XBF_TRYLOCK : 0, (flags & XFS_ALLOC_FLAG_TRYLOCK) ? XBF_TRYLOCK : 0,
bpp); &agfbp);
if (error) if (error)
return error; return error;
ASSERT(!(*bpp)->b_error);
agf = (*bpp)->b_addr; agf = agfbp->b_addr;
pag = (*bpp)->b_pag;
if (!pag->pagf_init) { if (!pag->pagf_init) {
pag->pagf_freeblks = be32_to_cpu(agf->agf_freeblks); pag->pagf_freeblks = be32_to_cpu(agf->agf_freeblks);
pag->pagf_btreeblks = be32_to_cpu(agf->agf_btreeblks); pag->pagf_btreeblks = be32_to_cpu(agf->agf_btreeblks);
...@@ -3138,7 +3116,7 @@ xfs_alloc_read_agf( ...@@ -3138,7 +3116,7 @@ xfs_alloc_read_agf(
be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAPi]); be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAPi]);
pag->pagf_refcount_level = be32_to_cpu(agf->agf_refcount_level); pag->pagf_refcount_level = be32_to_cpu(agf->agf_refcount_level);
pag->pagf_init = 1; pag->pagf_init = 1;
pag->pagf_agflreset = xfs_agfl_needs_reset(mp, agf); pag->pagf_agflreset = xfs_agfl_needs_reset(pag->pag_mount, agf);
/* /*
* Update the in-core allocbt counter. Filter out the rmapbt * Update the in-core allocbt counter. Filter out the rmapbt
...@@ -3148,13 +3126,14 @@ xfs_alloc_read_agf( ...@@ -3148,13 +3126,14 @@ xfs_alloc_read_agf(
* counter only tracks non-root blocks. * counter only tracks non-root blocks.
*/ */
allocbt_blks = pag->pagf_btreeblks; allocbt_blks = pag->pagf_btreeblks;
if (xfs_has_rmapbt(mp)) if (xfs_has_rmapbt(pag->pag_mount))
allocbt_blks -= be32_to_cpu(agf->agf_rmap_blocks) - 1; allocbt_blks -= be32_to_cpu(agf->agf_rmap_blocks) - 1;
if (allocbt_blks > 0) if (allocbt_blks > 0)
atomic64_add(allocbt_blks, &mp->m_allocbt_blks); atomic64_add(allocbt_blks,
&pag->pag_mount->m_allocbt_blks);
} }
#ifdef DEBUG #ifdef DEBUG
else if (!xfs_is_shutdown(mp)) { else if (!xfs_is_shutdown(pag->pag_mount)) {
ASSERT(pag->pagf_freeblks == be32_to_cpu(agf->agf_freeblks)); ASSERT(pag->pagf_freeblks == be32_to_cpu(agf->agf_freeblks));
ASSERT(pag->pagf_btreeblks == be32_to_cpu(agf->agf_btreeblks)); ASSERT(pag->pagf_btreeblks == be32_to_cpu(agf->agf_btreeblks));
ASSERT(pag->pagf_flcount == be32_to_cpu(agf->agf_flcount)); ASSERT(pag->pagf_flcount == be32_to_cpu(agf->agf_flcount));
...@@ -3165,6 +3144,10 @@ xfs_alloc_read_agf( ...@@ -3165,6 +3144,10 @@ xfs_alloc_read_agf(
be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi])); be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]));
} }
#endif #endif
if (agfbpp)
*agfbpp = agfbp;
else
xfs_trans_brelse(tp, agfbp);
return 0; return 0;
} }
......
...@@ -95,6 +95,11 @@ xfs_extlen_t xfs_alloc_longest_free_extent(struct xfs_perag *pag, ...@@ -95,6 +95,11 @@ xfs_extlen_t xfs_alloc_longest_free_extent(struct xfs_perag *pag,
xfs_extlen_t need, xfs_extlen_t reserved); xfs_extlen_t need, xfs_extlen_t reserved);
unsigned int xfs_alloc_min_freelist(struct xfs_mount *mp, unsigned int xfs_alloc_min_freelist(struct xfs_mount *mp,
struct xfs_perag *pag); struct xfs_perag *pag);
int xfs_alloc_get_freelist(struct xfs_perag *pag, struct xfs_trans *tp,
struct xfs_buf *agfbp, xfs_agblock_t *bnop, int btreeblk);
int xfs_alloc_put_freelist(struct xfs_perag *pag, struct xfs_trans *tp,
struct xfs_buf *agfbp, struct xfs_buf *agflbp,
xfs_agblock_t bno, int btreeblk);
/* /*
* Compute and fill in value of m_alloc_maxlevels. * Compute and fill in value of m_alloc_maxlevels.
...@@ -103,17 +108,6 @@ void ...@@ -103,17 +108,6 @@ void
xfs_alloc_compute_maxlevels( xfs_alloc_compute_maxlevels(
struct xfs_mount *mp); /* file system mount structure */ struct xfs_mount *mp); /* file system mount structure */
/*
* Get a block from the freelist.
* Returns with the buffer for the block gotten.
*/
int /* error */
xfs_alloc_get_freelist(
struct xfs_trans *tp, /* transaction pointer */
struct xfs_buf *agbp, /* buffer containing the agf structure */
xfs_agblock_t *bnop, /* block address retrieved from freelist */
int btreeblk); /* destination is a AGF btree */
/* /*
* Log the given fields from the agf structure. * Log the given fields from the agf structure.
*/ */
...@@ -123,38 +117,6 @@ xfs_alloc_log_agf( ...@@ -123,38 +117,6 @@ xfs_alloc_log_agf(
struct xfs_buf *bp, /* buffer for a.g. freelist header */ struct xfs_buf *bp, /* buffer for a.g. freelist header */
uint32_t fields);/* mask of fields to be logged (XFS_AGF_...) */ uint32_t fields);/* mask of fields to be logged (XFS_AGF_...) */
/*
* Interface for inode allocation to force the pag data to be initialized.
*/
int /* error */
xfs_alloc_pagf_init(
struct xfs_mount *mp, /* file system mount structure */
struct xfs_trans *tp, /* transaction pointer */
xfs_agnumber_t agno, /* allocation group number */
int flags); /* XFS_ALLOC_FLAGS_... */
/*
* Put the block on the freelist for the allocation group.
*/
int /* error */
xfs_alloc_put_freelist(
struct xfs_trans *tp, /* transaction pointer */
struct xfs_buf *agbp, /* buffer for a.g. freelist header */
struct xfs_buf *agflbp,/* buffer for a.g. free block array */
xfs_agblock_t bno, /* block being freed */
int btreeblk); /* owner was a AGF btree */
/*
* Read in the allocation group header (free/alloc section).
*/
int /* error */
xfs_alloc_read_agf(
struct xfs_mount *mp, /* mount point structure */
struct xfs_trans *tp, /* transaction pointer */
xfs_agnumber_t agno, /* allocation group number */
int flags, /* XFS_ALLOC_FLAG_... */
struct xfs_buf **bpp); /* buffer for the ag freelist header */
/* /*
* Allocate an extent (variable-size). * Allocate an extent (variable-size).
*/ */
...@@ -206,10 +168,12 @@ xfs_alloc_get_rec( ...@@ -206,10 +168,12 @@ xfs_alloc_get_rec(
xfs_extlen_t *len, /* output: length of extent */ xfs_extlen_t *len, /* output: length of extent */
int *stat); /* output: success/failure */ int *stat); /* output: success/failure */
int xfs_read_agf(struct xfs_mount *mp, struct xfs_trans *tp, int xfs_read_agf(struct xfs_perag *pag, struct xfs_trans *tp, int flags,
xfs_agnumber_t agno, int flags, struct xfs_buf **bpp); struct xfs_buf **agfbpp);
int xfs_alloc_read_agfl(struct xfs_mount *mp, struct xfs_trans *tp, int xfs_alloc_read_agf(struct xfs_perag *pag, struct xfs_trans *tp, int flags,
xfs_agnumber_t agno, struct xfs_buf **bpp); struct xfs_buf **agfbpp);
int xfs_alloc_read_agfl(struct xfs_perag *pag, struct xfs_trans *tp,
struct xfs_buf **bpp);
int xfs_free_agfl_block(struct xfs_trans *, xfs_agnumber_t, xfs_agblock_t, int xfs_free_agfl_block(struct xfs_trans *, xfs_agnumber_t, xfs_agblock_t,
struct xfs_buf *, struct xfs_owner_info *); struct xfs_buf *, struct xfs_owner_info *);
int xfs_alloc_fix_freelist(struct xfs_alloc_arg *args, int flags); int xfs_alloc_fix_freelist(struct xfs_alloc_arg *args, int flags);
......
...@@ -60,8 +60,8 @@ xfs_allocbt_alloc_block( ...@@ -60,8 +60,8 @@ xfs_allocbt_alloc_block(
xfs_agblock_t bno; xfs_agblock_t bno;
/* Allocate the new block from the freelist. If we can't, give up. */ /* Allocate the new block from the freelist. If we can't, give up. */
error = xfs_alloc_get_freelist(cur->bc_tp, cur->bc_ag.agbp, error = xfs_alloc_get_freelist(cur->bc_ag.pag, cur->bc_tp,
&bno, 1); cur->bc_ag.agbp, &bno, 1);
if (error) if (error)
return error; return error;
...@@ -71,7 +71,7 @@ xfs_allocbt_alloc_block( ...@@ -71,7 +71,7 @@ xfs_allocbt_alloc_block(
} }
atomic64_inc(&cur->bc_mp->m_allocbt_blks); atomic64_inc(&cur->bc_mp->m_allocbt_blks);
xfs_extent_busy_reuse(cur->bc_mp, cur->bc_ag.agbp->b_pag, bno, 1, false); xfs_extent_busy_reuse(cur->bc_mp, cur->bc_ag.pag, bno, 1, false);
new->s = cpu_to_be32(bno); new->s = cpu_to_be32(bno);
...@@ -89,7 +89,8 @@ xfs_allocbt_free_block( ...@@ -89,7 +89,8 @@ xfs_allocbt_free_block(
int error; int error;
bno = xfs_daddr_to_agbno(cur->bc_mp, xfs_buf_daddr(bp)); bno = xfs_daddr_to_agbno(cur->bc_mp, xfs_buf_daddr(bp));
error = xfs_alloc_put_freelist(cur->bc_tp, agbp, NULL, bno, 1); error = xfs_alloc_put_freelist(cur->bc_ag.pag, cur->bc_tp, agbp, NULL,
bno, 1);
if (error) if (error)
return error; return error;
......
...@@ -3185,7 +3185,8 @@ xfs_bmap_longest_free_extent( ...@@ -3185,7 +3185,8 @@ xfs_bmap_longest_free_extent(
pag = xfs_perag_get(mp, ag); pag = xfs_perag_get(mp, ag);
if (!pag->pagf_init) { if (!pag->pagf_init) {
error = xfs_alloc_pagf_init(mp, tp, ag, XFS_ALLOC_FLAG_TRYLOCK); error = xfs_alloc_read_agf(pag, tp, XFS_ALLOC_FLAG_TRYLOCK,
NULL);
if (error) { if (error) {
/* Couldn't lock the AGF, so skip this AG. */ /* Couldn't lock the AGF, so skip this AG. */
if (error == -EAGAIN) { if (error == -EAGAIN) {
......
...@@ -91,10 +91,9 @@ xfs_btree_check_lblock_siblings( ...@@ -91,10 +91,9 @@ xfs_btree_check_lblock_siblings(
static inline xfs_failaddr_t static inline xfs_failaddr_t
xfs_btree_check_sblock_siblings( xfs_btree_check_sblock_siblings(
struct xfs_mount *mp, struct xfs_perag *pag,
struct xfs_btree_cur *cur, struct xfs_btree_cur *cur,
int level, int level,
xfs_agnumber_t agno,
xfs_agblock_t agbno, xfs_agblock_t agbno,
__be32 dsibling) __be32 dsibling)
{ {
...@@ -110,7 +109,7 @@ xfs_btree_check_sblock_siblings( ...@@ -110,7 +109,7 @@ xfs_btree_check_sblock_siblings(
if (!xfs_btree_check_sptr(cur, sibling, level + 1)) if (!xfs_btree_check_sptr(cur, sibling, level + 1))
return __this_address; return __this_address;
} else { } else {
if (!xfs_verify_agbno(mp, agno, sibling)) if (!xfs_verify_agbno(pag, sibling))
return __this_address; return __this_address;
} }
return NULL; return NULL;
...@@ -195,11 +194,11 @@ __xfs_btree_check_sblock( ...@@ -195,11 +194,11 @@ __xfs_btree_check_sblock(
struct xfs_buf *bp) struct xfs_buf *bp)
{ {
struct xfs_mount *mp = cur->bc_mp; struct xfs_mount *mp = cur->bc_mp;
struct xfs_perag *pag = cur->bc_ag.pag;
xfs_btnum_t btnum = cur->bc_btnum; xfs_btnum_t btnum = cur->bc_btnum;
int crc = xfs_has_crc(mp); int crc = xfs_has_crc(mp);
xfs_failaddr_t fa; xfs_failaddr_t fa;
xfs_agblock_t agbno = NULLAGBLOCK; xfs_agblock_t agbno = NULLAGBLOCK;
xfs_agnumber_t agno = NULLAGNUMBER;
if (crc) { if (crc) {
if (!uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_meta_uuid)) if (!uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_meta_uuid))
...@@ -217,16 +216,14 @@ __xfs_btree_check_sblock( ...@@ -217,16 +216,14 @@ __xfs_btree_check_sblock(
cur->bc_ops->get_maxrecs(cur, level)) cur->bc_ops->get_maxrecs(cur, level))
return __this_address; return __this_address;
if (bp) { if (bp)
agbno = xfs_daddr_to_agbno(mp, xfs_buf_daddr(bp)); agbno = xfs_daddr_to_agbno(mp, xfs_buf_daddr(bp));
agno = xfs_daddr_to_agno(mp, xfs_buf_daddr(bp));
}
fa = xfs_btree_check_sblock_siblings(mp, cur, level, agno, agbno, fa = xfs_btree_check_sblock_siblings(pag, cur, level, agbno,
block->bb_u.s.bb_leftsib); block->bb_u.s.bb_leftsib);
if (!fa) if (!fa)
fa = xfs_btree_check_sblock_siblings(mp, cur, level, agno, fa = xfs_btree_check_sblock_siblings(pag, cur, level, agbno,
agbno, block->bb_u.s.bb_rightsib); block->bb_u.s.bb_rightsib);
return fa; return fa;
} }
...@@ -288,7 +285,7 @@ xfs_btree_check_sptr( ...@@ -288,7 +285,7 @@ xfs_btree_check_sptr(
{ {
if (level <= 0) if (level <= 0)
return false; return false;
return xfs_verify_agbno(cur->bc_mp, cur->bc_ag.pag->pag_agno, agbno); return xfs_verify_agbno(cur->bc_ag.pag, agbno);
} }
/* /*
...@@ -4595,7 +4592,6 @@ xfs_btree_sblock_verify( ...@@ -4595,7 +4592,6 @@ xfs_btree_sblock_verify(
{ {
struct xfs_mount *mp = bp->b_mount; struct xfs_mount *mp = bp->b_mount;
struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp);
xfs_agnumber_t agno;
xfs_agblock_t agbno; xfs_agblock_t agbno;
xfs_failaddr_t fa; xfs_failaddr_t fa;
...@@ -4604,12 +4600,11 @@ xfs_btree_sblock_verify( ...@@ -4604,12 +4600,11 @@ xfs_btree_sblock_verify(
return __this_address; return __this_address;
/* sibling pointer verification */ /* sibling pointer verification */
agno = xfs_daddr_to_agno(mp, xfs_buf_daddr(bp));
agbno = xfs_daddr_to_agbno(mp, xfs_buf_daddr(bp)); agbno = xfs_daddr_to_agbno(mp, xfs_buf_daddr(bp));
fa = xfs_btree_check_sblock_siblings(mp, NULL, -1, agno, agbno, fa = xfs_btree_check_sblock_siblings(bp->b_pag, NULL, -1, agbno,
block->bb_u.s.bb_leftsib); block->bb_u.s.bb_leftsib);
if (!fa) if (!fa)
fa = xfs_btree_check_sblock_siblings(mp, NULL, -1, agno, agbno, fa = xfs_btree_check_sblock_siblings(bp->b_pag, NULL, -1, agbno,
block->bb_u.s.bb_rightsib); block->bb_u.s.bb_rightsib);
return fa; return fa;
} }
......
...@@ -105,7 +105,6 @@ xfs_inobt_get_rec( ...@@ -105,7 +105,6 @@ xfs_inobt_get_rec(
int *stat) int *stat)
{ {
struct xfs_mount *mp = cur->bc_mp; struct xfs_mount *mp = cur->bc_mp;
xfs_agnumber_t agno = cur->bc_ag.pag->pag_agno;
union xfs_btree_rec *rec; union xfs_btree_rec *rec;
int error; int error;
uint64_t realfree; uint64_t realfree;
...@@ -116,7 +115,7 @@ xfs_inobt_get_rec( ...@@ -116,7 +115,7 @@ xfs_inobt_get_rec(
xfs_inobt_btrec_to_irec(mp, rec, irec); xfs_inobt_btrec_to_irec(mp, rec, irec);
if (!xfs_verify_agino(mp, agno, irec->ir_startino)) if (!xfs_verify_agino(cur->bc_ag.pag, irec->ir_startino))
goto out_bad_rec; goto out_bad_rec;
if (irec->ir_count < XFS_INODES_PER_HOLEMASK_BIT || if (irec->ir_count < XFS_INODES_PER_HOLEMASK_BIT ||
irec->ir_count > XFS_INODES_PER_CHUNK) irec->ir_count > XFS_INODES_PER_CHUNK)
...@@ -137,7 +136,8 @@ xfs_inobt_get_rec( ...@@ -137,7 +136,8 @@ xfs_inobt_get_rec(
out_bad_rec: out_bad_rec:
xfs_warn(mp, xfs_warn(mp,
"%s Inode BTree record corruption in AG %d detected!", "%s Inode BTree record corruption in AG %d detected!",
cur->bc_btnum == XFS_BTNUM_INO ? "Used" : "Free", agno); cur->bc_btnum == XFS_BTNUM_INO ? "Used" : "Free",
cur->bc_ag.pag->pag_agno);
xfs_warn(mp, xfs_warn(mp,
"start inode 0x%x, count 0x%x, free 0x%x freemask 0x%llx, holemask 0x%x", "start inode 0x%x, count 0x%x, free 0x%x freemask 0x%llx, holemask 0x%x",
irec->ir_startino, irec->ir_count, irec->ir_freecount, irec->ir_startino, irec->ir_count, irec->ir_freecount,
...@@ -1610,7 +1610,7 @@ xfs_dialloc_good_ag( ...@@ -1610,7 +1610,7 @@ xfs_dialloc_good_ag(
return false; return false;
if (!pag->pagi_init) { if (!pag->pagi_init) {
error = xfs_ialloc_pagi_init(mp, tp, pag->pag_agno); error = xfs_ialloc_read_agi(pag, tp, NULL);
if (error) if (error)
return false; return false;
} }
...@@ -1621,7 +1621,7 @@ xfs_dialloc_good_ag( ...@@ -1621,7 +1621,7 @@ xfs_dialloc_good_ag(
return false; return false;
if (!pag->pagf_init) { if (!pag->pagf_init) {
error = xfs_alloc_pagf_init(mp, tp, pag->pag_agno, flags); error = xfs_alloc_read_agf(pag, tp, flags, NULL);
if (error) if (error)
return false; return false;
} }
...@@ -1679,7 +1679,7 @@ xfs_dialloc_try_ag( ...@@ -1679,7 +1679,7 @@ xfs_dialloc_try_ag(
* Then read in the AGI buffer and recheck with the AGI buffer * Then read in the AGI buffer and recheck with the AGI buffer
* lock held. * lock held.
*/ */
error = xfs_ialloc_read_agi(pag->pag_mount, *tpp, pag->pag_agno, &agbp); error = xfs_ialloc_read_agi(pag, *tpp, &agbp);
if (error) if (error)
return error; return error;
...@@ -2169,7 +2169,7 @@ xfs_difree( ...@@ -2169,7 +2169,7 @@ xfs_difree(
/* /*
* Get the allocation group header. * Get the allocation group header.
*/ */
error = xfs_ialloc_read_agi(mp, tp, pag->pag_agno, &agbp); error = xfs_ialloc_read_agi(pag, tp, &agbp);
if (error) { if (error) {
xfs_warn(mp, "%s: xfs_ialloc_read_agi() returned error %d.", xfs_warn(mp, "%s: xfs_ialloc_read_agi() returned error %d.",
__func__, error); __func__, error);
...@@ -2215,7 +2215,7 @@ xfs_imap_lookup( ...@@ -2215,7 +2215,7 @@ xfs_imap_lookup(
int error; int error;
int i; int i;
error = xfs_ialloc_read_agi(mp, tp, pag->pag_agno, &agbp); error = xfs_ialloc_read_agi(pag, tp, &agbp);
if (error) { if (error) {
xfs_alert(mp, xfs_alert(mp,
"%s: xfs_ialloc_read_agi() returned error %d, agno %d", "%s: xfs_ialloc_read_agi() returned error %d, agno %d",
...@@ -2571,47 +2571,48 @@ const struct xfs_buf_ops xfs_agi_buf_ops = { ...@@ -2571,47 +2571,48 @@ const struct xfs_buf_ops xfs_agi_buf_ops = {
*/ */
int int
xfs_read_agi( xfs_read_agi(
struct xfs_mount *mp, /* file system mount structure */ struct xfs_perag *pag,
struct xfs_trans *tp, /* transaction pointer */ struct xfs_trans *tp,
xfs_agnumber_t agno, /* allocation group number */ struct xfs_buf **agibpp)
struct xfs_buf **bpp) /* allocation group hdr buf */
{ {
struct xfs_mount *mp = pag->pag_mount;
int error; int error;
trace_xfs_read_agi(mp, agno); trace_xfs_read_agi(pag->pag_mount, pag->pag_agno);
ASSERT(agno != NULLAGNUMBER);
error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), XFS_AG_DADDR(mp, pag->pag_agno, XFS_AGI_DADDR(mp)),
XFS_FSS_TO_BB(mp, 1), 0, bpp, &xfs_agi_buf_ops); XFS_FSS_TO_BB(mp, 1), 0, agibpp, &xfs_agi_buf_ops);
if (error) if (error)
return error; return error;
if (tp) if (tp)
xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_AGI_BUF); xfs_trans_buf_set_type(tp, *agibpp, XFS_BLFT_AGI_BUF);
xfs_buf_set_ref(*bpp, XFS_AGI_REF); xfs_buf_set_ref(*agibpp, XFS_AGI_REF);
return 0; return 0;
} }
/*
* Read in the agi and initialise the per-ag data. If the caller supplies a
* @agibpp, return the locked AGI buffer to them, otherwise release it.
*/
int int
xfs_ialloc_read_agi( xfs_ialloc_read_agi(
struct xfs_mount *mp, /* file system mount structure */ struct xfs_perag *pag,
struct xfs_trans *tp, /* transaction pointer */ struct xfs_trans *tp,
xfs_agnumber_t agno, /* allocation group number */ struct xfs_buf **agibpp)
struct xfs_buf **bpp) /* allocation group hdr buf */
{ {
struct xfs_agi *agi; /* allocation group header */ struct xfs_buf *agibp;
struct xfs_perag *pag; /* per allocation group data */ struct xfs_agi *agi;
int error; int error;
trace_xfs_ialloc_read_agi(mp, agno); trace_xfs_ialloc_read_agi(pag->pag_mount, pag->pag_agno);
error = xfs_read_agi(mp, tp, agno, bpp); error = xfs_read_agi(pag, tp, &agibp);
if (error) if (error)
return error; return error;
agi = (*bpp)->b_addr; agi = agibp->b_addr;
pag = (*bpp)->b_pag;
if (!pag->pagi_init) { if (!pag->pagi_init) {
pag->pagi_freecount = be32_to_cpu(agi->agi_freecount); pag->pagi_freecount = be32_to_cpu(agi->agi_freecount);
pag->pagi_count = be32_to_cpu(agi->agi_count); pag->pagi_count = be32_to_cpu(agi->agi_count);
...@@ -2623,27 +2624,11 @@ xfs_ialloc_read_agi( ...@@ -2623,27 +2624,11 @@ xfs_ialloc_read_agi(
* we are in the middle of a forced shutdown. * we are in the middle of a forced shutdown.
*/ */
ASSERT(pag->pagi_freecount == be32_to_cpu(agi->agi_freecount) || ASSERT(pag->pagi_freecount == be32_to_cpu(agi->agi_freecount) ||
xfs_is_shutdown(mp)); xfs_is_shutdown(pag->pag_mount));
return 0; if (agibpp)
} *agibpp = agibp;
else
/* xfs_trans_brelse(tp, agibp);
* Read in the agi to initialise the per-ag data in the mount structure
*/
int
xfs_ialloc_pagi_init(
xfs_mount_t *mp, /* file system mount structure */
xfs_trans_t *tp, /* transaction pointer */
xfs_agnumber_t agno) /* allocation group number */
{
struct xfs_buf *bp = NULL;
int error;
error = xfs_ialloc_read_agi(mp, tp, agno, &bp);
if (error)
return error;
if (bp)
xfs_trans_brelse(tp, bp);
return 0; return 0;
} }
...@@ -2912,8 +2897,7 @@ xfs_ialloc_calc_rootino( ...@@ -2912,8 +2897,7 @@ xfs_ialloc_calc_rootino(
* allocation group, or very odd geometries created by old mkfs * allocation group, or very odd geometries created by old mkfs
* versions on very small filesystems. * versions on very small filesystems.
*/ */
if (mp->m_sb.sb_logstart && if (xfs_ag_contains_log(mp, 0))
XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart) == 0)
first_bno += mp->m_sb.sb_logblocks; first_bno += mp->m_sb.sb_logblocks;
/* /*
......
...@@ -62,25 +62,10 @@ xfs_ialloc_log_agi( ...@@ -62,25 +62,10 @@ xfs_ialloc_log_agi(
struct xfs_buf *bp, /* allocation group header buffer */ struct xfs_buf *bp, /* allocation group header buffer */
uint32_t fields); /* bitmask of fields to log */ uint32_t fields); /* bitmask of fields to log */
/* int xfs_read_agi(struct xfs_perag *pag, struct xfs_trans *tp,
* Read in the allocation group header (inode allocation section) struct xfs_buf **agibpp);
*/ int xfs_ialloc_read_agi(struct xfs_perag *pag, struct xfs_trans *tp,
int /* error */ struct xfs_buf **agibpp);
xfs_ialloc_read_agi(
struct xfs_mount *mp, /* file system mount structure */
struct xfs_trans *tp, /* transaction pointer */
xfs_agnumber_t agno, /* allocation group number */
struct xfs_buf **bpp); /* allocation group hdr buf */
/*
* Read in the allocation group header to initialise the per-ag data
* in the mount structure
*/
int
xfs_ialloc_pagi_init(
struct xfs_mount *mp, /* file system mount structure */
struct xfs_trans *tp, /* transaction pointer */
xfs_agnumber_t agno); /* allocation group number */
/* /*
* Lookup a record by ino in the btree given by cur. * Lookup a record by ino in the btree given by cur.
...@@ -102,8 +87,6 @@ int xfs_ialloc_inode_init(struct xfs_mount *mp, struct xfs_trans *tp, ...@@ -102,8 +87,6 @@ int xfs_ialloc_inode_init(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_agnumber_t agno, xfs_agblock_t agbno,
xfs_agblock_t length, unsigned int gen); xfs_agblock_t length, unsigned int gen);
int xfs_read_agi(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_agnumber_t agno, struct xfs_buf **bpp);
union xfs_btree_rec; union xfs_btree_rec;
void xfs_inobt_btrec_to_irec(struct xfs_mount *mp, void xfs_inobt_btrec_to_irec(struct xfs_mount *mp,
......
...@@ -683,10 +683,10 @@ xfs_inobt_rec_check_count( ...@@ -683,10 +683,10 @@ xfs_inobt_rec_check_count(
static xfs_extlen_t static xfs_extlen_t
xfs_inobt_max_size( xfs_inobt_max_size(
struct xfs_mount *mp, struct xfs_perag *pag)
xfs_agnumber_t agno)
{ {
xfs_agblock_t agblocks = xfs_ag_block_count(mp, agno); struct xfs_mount *mp = pag->pag_mount;
xfs_agblock_t agblocks = pag->block_count;
/* Bail out if we're uninitialized, which can happen in mkfs. */ /* Bail out if we're uninitialized, which can happen in mkfs. */
if (M_IGEO(mp)->inobt_mxr[0] == 0) if (M_IGEO(mp)->inobt_mxr[0] == 0)
...@@ -697,8 +697,7 @@ xfs_inobt_max_size( ...@@ -697,8 +697,7 @@ xfs_inobt_max_size(
* never be available for the kinds of things that would require btree * never be available for the kinds of things that would require btree
* expansion. We therefore can pretend the space isn't there. * expansion. We therefore can pretend the space isn't there.
*/ */
if (mp->m_sb.sb_logstart && if (xfs_ag_contains_log(mp, pag->pag_agno))
XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart) == agno)
agblocks -= mp->m_sb.sb_logblocks; agblocks -= mp->m_sb.sb_logblocks;
return xfs_btree_calc_size(M_IGEO(mp)->inobt_mnr, return xfs_btree_calc_size(M_IGEO(mp)->inobt_mnr,
...@@ -722,7 +721,7 @@ xfs_inobt_cur( ...@@ -722,7 +721,7 @@ xfs_inobt_cur(
ASSERT(*agi_bpp == NULL); ASSERT(*agi_bpp == NULL);
ASSERT(*curpp == NULL); ASSERT(*curpp == NULL);
error = xfs_ialloc_read_agi(mp, tp, pag->pag_agno, agi_bpp); error = xfs_ialloc_read_agi(pag, tp, agi_bpp);
if (error) if (error)
return error; return error;
...@@ -757,16 +756,15 @@ xfs_inobt_count_blocks( ...@@ -757,16 +756,15 @@ xfs_inobt_count_blocks(
/* Read finobt block count from AGI header. */ /* Read finobt block count from AGI header. */
static int static int
xfs_finobt_read_blocks( xfs_finobt_read_blocks(
struct xfs_mount *mp,
struct xfs_trans *tp,
struct xfs_perag *pag, struct xfs_perag *pag,
struct xfs_trans *tp,
xfs_extlen_t *tree_blocks) xfs_extlen_t *tree_blocks)
{ {
struct xfs_buf *agbp; struct xfs_buf *agbp;
struct xfs_agi *agi; struct xfs_agi *agi;
int error; int error;
error = xfs_ialloc_read_agi(mp, tp, pag->pag_agno, &agbp); error = xfs_ialloc_read_agi(pag, tp, &agbp);
if (error) if (error)
return error; return error;
...@@ -794,14 +792,14 @@ xfs_finobt_calc_reserves( ...@@ -794,14 +792,14 @@ xfs_finobt_calc_reserves(
return 0; return 0;
if (xfs_has_inobtcounts(mp)) if (xfs_has_inobtcounts(mp))
error = xfs_finobt_read_blocks(mp, tp, pag, &tree_len); error = xfs_finobt_read_blocks(pag, tp, &tree_len);
else else
error = xfs_inobt_count_blocks(mp, tp, pag, XFS_BTNUM_FINO, error = xfs_inobt_count_blocks(mp, tp, pag, XFS_BTNUM_FINO,
&tree_len); &tree_len);
if (error) if (error)
return error; return error;
*ask += xfs_inobt_max_size(mp, pag->pag_agno); *ask += xfs_inobt_max_size(pag);
*used += tree_len; *used += tree_len;
return 0; return 0;
} }
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "xfs_log_format.h" #include "xfs_log_format.h"
#include "xfs_trans_resv.h" #include "xfs_trans_resv.h"
#include "xfs_mount.h" #include "xfs_mount.h"
#include "xfs_ag.h"
#include "xfs_inode.h" #include "xfs_inode.h"
#include "xfs_errortag.h" #include "xfs_errortag.h"
#include "xfs_error.h" #include "xfs_error.h"
...@@ -41,14 +42,12 @@ xfs_inode_buf_verify( ...@@ -41,14 +42,12 @@ xfs_inode_buf_verify(
bool readahead) bool readahead)
{ {
struct xfs_mount *mp = bp->b_mount; struct xfs_mount *mp = bp->b_mount;
xfs_agnumber_t agno;
int i; int i;
int ni; int ni;
/* /*
* Validate the magic number and version of every inode in the buffer * Validate the magic number and version of every inode in the buffer
*/ */
agno = xfs_daddr_to_agno(mp, xfs_buf_daddr(bp));
ni = XFS_BB_TO_FSB(mp, bp->b_length) * mp->m_sb.sb_inopblock; ni = XFS_BB_TO_FSB(mp, bp->b_length) * mp->m_sb.sb_inopblock;
for (i = 0; i < ni; i++) { for (i = 0; i < ni; i++) {
struct xfs_dinode *dip; struct xfs_dinode *dip;
...@@ -59,7 +58,7 @@ xfs_inode_buf_verify( ...@@ -59,7 +58,7 @@ xfs_inode_buf_verify(
unlinked_ino = be32_to_cpu(dip->di_next_unlinked); unlinked_ino = be32_to_cpu(dip->di_next_unlinked);
di_ok = xfs_verify_magic16(bp, dip->di_magic) && di_ok = xfs_verify_magic16(bp, dip->di_magic) &&
xfs_dinode_good_version(mp, dip->di_version) && xfs_dinode_good_version(mp, dip->di_version) &&
xfs_verify_agino_or_null(mp, agno, unlinked_ino); xfs_verify_agino_or_null(bp->b_pag, unlinked_ino);
if (unlikely(XFS_TEST_ERROR(!di_ok, mp, if (unlikely(XFS_TEST_ERROR(!di_ok, mp,
XFS_ERRTAG_ITOBP_INOTOBP))) { XFS_ERRTAG_ITOBP_INOTOBP))) {
if (readahead) { if (readahead) {
......
...@@ -111,7 +111,7 @@ xfs_refcount_get_rec( ...@@ -111,7 +111,7 @@ xfs_refcount_get_rec(
int *stat) int *stat)
{ {
struct xfs_mount *mp = cur->bc_mp; struct xfs_mount *mp = cur->bc_mp;
xfs_agnumber_t agno = cur->bc_ag.pag->pag_agno; struct xfs_perag *pag = cur->bc_ag.pag;
union xfs_btree_rec *rec; union xfs_btree_rec *rec;
int error; int error;
xfs_agblock_t realstart; xfs_agblock_t realstart;
...@@ -121,8 +121,6 @@ xfs_refcount_get_rec( ...@@ -121,8 +121,6 @@ xfs_refcount_get_rec(
return error; return error;
xfs_refcount_btrec_to_irec(rec, irec); xfs_refcount_btrec_to_irec(rec, irec);
agno = cur->bc_ag.pag->pag_agno;
if (irec->rc_blockcount == 0 || irec->rc_blockcount > MAXREFCEXTLEN) if (irec->rc_blockcount == 0 || irec->rc_blockcount > MAXREFCEXTLEN)
goto out_bad_rec; goto out_bad_rec;
...@@ -137,22 +135,23 @@ xfs_refcount_get_rec( ...@@ -137,22 +135,23 @@ xfs_refcount_get_rec(
} }
/* check for valid extent range, including overflow */ /* check for valid extent range, including overflow */
if (!xfs_verify_agbno(mp, agno, realstart)) if (!xfs_verify_agbno(pag, realstart))
goto out_bad_rec; goto out_bad_rec;
if (realstart > realstart + irec->rc_blockcount) if (realstart > realstart + irec->rc_blockcount)
goto out_bad_rec; goto out_bad_rec;
if (!xfs_verify_agbno(mp, agno, realstart + irec->rc_blockcount - 1)) if (!xfs_verify_agbno(pag, realstart + irec->rc_blockcount - 1))
goto out_bad_rec; goto out_bad_rec;
if (irec->rc_refcount == 0 || irec->rc_refcount > MAXREFCOUNT) if (irec->rc_refcount == 0 || irec->rc_refcount > MAXREFCOUNT)
goto out_bad_rec; goto out_bad_rec;
trace_xfs_refcount_get(cur->bc_mp, cur->bc_ag.pag->pag_agno, irec); trace_xfs_refcount_get(cur->bc_mp, pag->pag_agno, irec);
return 0; return 0;
out_bad_rec: out_bad_rec:
xfs_warn(mp, xfs_warn(mp,
"Refcount BTree record corruption in AG %d detected!", agno); "Refcount BTree record corruption in AG %d detected!",
pag->pag_agno);
xfs_warn(mp, xfs_warn(mp,
"Start block 0x%x, block count 0x%x, references 0x%x", "Start block 0x%x, block count 0x%x, references 0x%x",
irec->rc_startblock, irec->rc_blockcount, irec->rc_refcount); irec->rc_startblock, irec->rc_blockcount, irec->rc_refcount);
...@@ -1177,8 +1176,8 @@ xfs_refcount_finish_one( ...@@ -1177,8 +1176,8 @@ xfs_refcount_finish_one(
*pcur = NULL; *pcur = NULL;
} }
if (rcur == NULL) { if (rcur == NULL) {
error = xfs_alloc_read_agf(tp->t_mountp, tp, pag->pag_agno, error = xfs_alloc_read_agf(pag, tp, XFS_ALLOC_FLAG_FREEING,
XFS_ALLOC_FLAG_FREEING, &agbp); &agbp);
if (error) if (error)
goto out_drop; goto out_drop;
...@@ -1710,7 +1709,7 @@ xfs_refcount_recover_cow_leftovers( ...@@ -1710,7 +1709,7 @@ xfs_refcount_recover_cow_leftovers(
if (error) if (error)
return error; return error;
error = xfs_alloc_read_agf(mp, tp, pag->pag_agno, 0, &agbp); error = xfs_alloc_read_agf(pag, tp, 0, &agbp);
if (error) if (error)
goto out_trans; goto out_trans;
cur = xfs_refcountbt_init_cursor(mp, tp, agbp, pag); cur = xfs_refcountbt_init_cursor(mp, tp, agbp, pag);
......
...@@ -493,7 +493,7 @@ xfs_refcountbt_calc_reserves( ...@@ -493,7 +493,7 @@ xfs_refcountbt_calc_reserves(
if (!xfs_has_reflink(mp)) if (!xfs_has_reflink(mp))
return 0; return 0;
error = xfs_alloc_read_agf(mp, tp, pag->pag_agno, 0, &agbp); error = xfs_alloc_read_agf(pag, tp, 0, &agbp);
if (error) if (error)
return error; return error;
...@@ -507,8 +507,7 @@ xfs_refcountbt_calc_reserves( ...@@ -507,8 +507,7 @@ xfs_refcountbt_calc_reserves(
* never be available for the kinds of things that would require btree * never be available for the kinds of things that would require btree
* expansion. We therefore can pretend the space isn't there. * expansion. We therefore can pretend the space isn't there.
*/ */
if (mp->m_sb.sb_logstart && if (xfs_ag_contains_log(mp, pag->pag_agno))
XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart) == pag->pag_agno)
agblocks -= mp->m_sb.sb_logblocks; agblocks -= mp->m_sb.sb_logblocks;
*ask += xfs_refcountbt_max_size(mp, agblocks); *ask += xfs_refcountbt_max_size(mp, agblocks);
......
...@@ -215,7 +215,7 @@ xfs_rmap_get_rec( ...@@ -215,7 +215,7 @@ xfs_rmap_get_rec(
int *stat) int *stat)
{ {
struct xfs_mount *mp = cur->bc_mp; struct xfs_mount *mp = cur->bc_mp;
xfs_agnumber_t agno = cur->bc_ag.pag->pag_agno; struct xfs_perag *pag = cur->bc_ag.pag;
union xfs_btree_rec *rec; union xfs_btree_rec *rec;
int error; int error;
...@@ -235,12 +235,12 @@ xfs_rmap_get_rec( ...@@ -235,12 +235,12 @@ xfs_rmap_get_rec(
goto out_bad_rec; goto out_bad_rec;
} else { } else {
/* check for valid extent range, including overflow */ /* check for valid extent range, including overflow */
if (!xfs_verify_agbno(mp, agno, irec->rm_startblock)) if (!xfs_verify_agbno(pag, irec->rm_startblock))
goto out_bad_rec; goto out_bad_rec;
if (irec->rm_startblock > if (irec->rm_startblock >
irec->rm_startblock + irec->rm_blockcount) irec->rm_startblock + irec->rm_blockcount)
goto out_bad_rec; goto out_bad_rec;
if (!xfs_verify_agbno(mp, agno, if (!xfs_verify_agbno(pag,
irec->rm_startblock + irec->rm_blockcount - 1)) irec->rm_startblock + irec->rm_blockcount - 1))
goto out_bad_rec; goto out_bad_rec;
} }
...@@ -254,7 +254,7 @@ xfs_rmap_get_rec( ...@@ -254,7 +254,7 @@ xfs_rmap_get_rec(
out_bad_rec: out_bad_rec:
xfs_warn(mp, xfs_warn(mp,
"Reverse Mapping BTree record corruption in AG %d detected!", "Reverse Mapping BTree record corruption in AG %d detected!",
agno); pag->pag_agno);
xfs_warn(mp, xfs_warn(mp,
"Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x", "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
irec->rm_owner, irec->rm_flags, irec->rm_startblock, irec->rm_owner, irec->rm_flags, irec->rm_startblock,
......
...@@ -90,7 +90,7 @@ xfs_rmapbt_alloc_block( ...@@ -90,7 +90,7 @@ xfs_rmapbt_alloc_block(
xfs_agblock_t bno; xfs_agblock_t bno;
/* Allocate the new block from the freelist. If we can't, give up. */ /* Allocate the new block from the freelist. If we can't, give up. */
error = xfs_alloc_get_freelist(cur->bc_tp, cur->bc_ag.agbp, error = xfs_alloc_get_freelist(pag, cur->bc_tp, cur->bc_ag.agbp,
&bno, 1); &bno, 1);
if (error) if (error)
return error; return error;
...@@ -129,7 +129,7 @@ xfs_rmapbt_free_block( ...@@ -129,7 +129,7 @@ xfs_rmapbt_free_block(
bno, 1); bno, 1);
be32_add_cpu(&agf->agf_rmap_blocks, -1); be32_add_cpu(&agf->agf_rmap_blocks, -1);
xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_RMAP_BLOCKS); xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_RMAP_BLOCKS);
error = xfs_alloc_put_freelist(cur->bc_tp, agbp, NULL, bno, 1); error = xfs_alloc_put_freelist(pag, cur->bc_tp, agbp, NULL, bno, 1);
if (error) if (error)
return error; return error;
...@@ -652,7 +652,7 @@ xfs_rmapbt_calc_reserves( ...@@ -652,7 +652,7 @@ xfs_rmapbt_calc_reserves(
if (!xfs_has_rmapbt(mp)) if (!xfs_has_rmapbt(mp))
return 0; return 0;
error = xfs_alloc_read_agf(mp, tp, pag->pag_agno, 0, &agbp); error = xfs_alloc_read_agf(pag, tp, 0, &agbp);
if (error) if (error)
return error; return error;
...@@ -666,8 +666,7 @@ xfs_rmapbt_calc_reserves( ...@@ -666,8 +666,7 @@ xfs_rmapbt_calc_reserves(
* never be available for the kinds of things that would require btree * never be available for the kinds of things that would require btree
* expansion. We therefore can pretend the space isn't there. * expansion. We therefore can pretend the space isn't there.
*/ */
if (mp->m_sb.sb_logstart && if (xfs_ag_contains_log(mp, pag->pag_agno))
XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart) == pag->pag_agno)
agblocks -= mp->m_sb.sb_logblocks; agblocks -= mp->m_sb.sb_logblocks;
/* Reserve 1% of the AG or enough for 1 block per record. */ /* Reserve 1% of the AG or enough for 1 block per record. */
......
...@@ -13,25 +13,13 @@ ...@@ -13,25 +13,13 @@
#include "xfs_mount.h" #include "xfs_mount.h"
#include "xfs_ag.h" #include "xfs_ag.h"
/* Find the size of the AG, in blocks. */
inline xfs_agblock_t
xfs_ag_block_count(
struct xfs_mount *mp,
xfs_agnumber_t agno)
{
ASSERT(agno < mp->m_sb.sb_agcount);
if (agno < mp->m_sb.sb_agcount - 1)
return mp->m_sb.sb_agblocks;
return mp->m_sb.sb_dblocks - (agno * mp->m_sb.sb_agblocks);
}
/* /*
* Verify that an AG block number pointer neither points outside the AG * Verify that an AG block number pointer neither points outside the AG
* nor points at static metadata. * nor points at static metadata.
*/ */
inline bool static inline bool
xfs_verify_agbno( xfs_verify_agno_agbno(
struct xfs_mount *mp, struct xfs_mount *mp,
xfs_agnumber_t agno, xfs_agnumber_t agno,
xfs_agblock_t agbno) xfs_agblock_t agbno)
...@@ -59,7 +47,7 @@ xfs_verify_fsbno( ...@@ -59,7 +47,7 @@ xfs_verify_fsbno(
if (agno >= mp->m_sb.sb_agcount) if (agno >= mp->m_sb.sb_agcount)
return false; return false;
return xfs_verify_agbno(mp, agno, XFS_FSB_TO_AGBNO(mp, fsbno)); return xfs_verify_agno_agbno(mp, agno, XFS_FSB_TO_AGBNO(mp, fsbno));
} }
/* /*
...@@ -85,40 +73,12 @@ xfs_verify_fsbext( ...@@ -85,40 +73,12 @@ xfs_verify_fsbext(
XFS_FSB_TO_AGNO(mp, fsbno + len - 1); XFS_FSB_TO_AGNO(mp, fsbno + len - 1);
} }
/* Calculate the first and last possible inode number in an AG. */
inline void
xfs_agino_range(
struct xfs_mount *mp,
xfs_agnumber_t agno,
xfs_agino_t *first,
xfs_agino_t *last)
{
xfs_agblock_t bno;
xfs_agblock_t eoag;
eoag = xfs_ag_block_count(mp, agno);
/*
* Calculate the first inode, which will be in the first
* cluster-aligned block after the AGFL.
*/
bno = round_up(XFS_AGFL_BLOCK(mp) + 1, M_IGEO(mp)->cluster_align);
*first = XFS_AGB_TO_AGINO(mp, bno);
/*
* Calculate the last inode, which will be at the end of the
* last (aligned) cluster that can be allocated in the AG.
*/
bno = round_down(eoag, M_IGEO(mp)->cluster_align);
*last = XFS_AGB_TO_AGINO(mp, bno) - 1;
}
/* /*
* Verify that an AG inode number pointer neither points outside the AG * Verify that an AG inode number pointer neither points outside the AG
* nor points at static metadata. * nor points at static metadata.
*/ */
inline bool static inline bool
xfs_verify_agino( xfs_verify_agno_agino(
struct xfs_mount *mp, struct xfs_mount *mp,
xfs_agnumber_t agno, xfs_agnumber_t agno,
xfs_agino_t agino) xfs_agino_t agino)
...@@ -130,19 +90,6 @@ xfs_verify_agino( ...@@ -130,19 +90,6 @@ xfs_verify_agino(
return agino >= first && agino <= last; return agino >= first && agino <= last;
} }
/*
* Verify that an AG inode number pointer neither points outside the AG
* nor points at static metadata, or is NULLAGINO.
*/
bool
xfs_verify_agino_or_null(
struct xfs_mount *mp,
xfs_agnumber_t agno,
xfs_agino_t agino)
{
return agino == NULLAGINO || xfs_verify_agino(mp, agno, agino);
}
/* /*
* Verify that an FS inode number pointer neither points outside the * Verify that an FS inode number pointer neither points outside the
* filesystem nor points at static AG metadata. * filesystem nor points at static AG metadata.
...@@ -159,7 +106,7 @@ xfs_verify_ino( ...@@ -159,7 +106,7 @@ xfs_verify_ino(
return false; return false;
if (XFS_AGINO_TO_INO(mp, agno, agino) != ino) if (XFS_AGINO_TO_INO(mp, agno, agino) != ino)
return false; return false;
return xfs_verify_agino(mp, agno, agino); return xfs_verify_agno_agino(mp, agno, agino);
} }
/* Is this an internal inode number? */ /* Is this an internal inode number? */
...@@ -229,12 +176,8 @@ xfs_icount_range( ...@@ -229,12 +176,8 @@ xfs_icount_range(
/* root, rtbitmap, rtsum all live in the first chunk */ /* root, rtbitmap, rtsum all live in the first chunk */
*min = XFS_INODES_PER_CHUNK; *min = XFS_INODES_PER_CHUNK;
for_each_perag(mp, agno, pag) { for_each_perag(mp, agno, pag)
xfs_agino_t first, last; nr_inos += pag->agino_max - pag->agino_min + 1;
xfs_agino_range(mp, agno, &first, &last);
nr_inos += last - first + 1;
}
*max = nr_inos; *max = nr_inos;
} }
......
...@@ -179,19 +179,10 @@ enum xfs_ag_resv_type { ...@@ -179,19 +179,10 @@ enum xfs_ag_resv_type {
*/ */
struct xfs_mount; struct xfs_mount;
xfs_agblock_t xfs_ag_block_count(struct xfs_mount *mp, xfs_agnumber_t agno);
bool xfs_verify_agbno(struct xfs_mount *mp, xfs_agnumber_t agno,
xfs_agblock_t agbno);
bool xfs_verify_fsbno(struct xfs_mount *mp, xfs_fsblock_t fsbno); bool xfs_verify_fsbno(struct xfs_mount *mp, xfs_fsblock_t fsbno);
bool xfs_verify_fsbext(struct xfs_mount *mp, xfs_fsblock_t fsbno, bool xfs_verify_fsbext(struct xfs_mount *mp, xfs_fsblock_t fsbno,
xfs_fsblock_t len); xfs_fsblock_t len);
void xfs_agino_range(struct xfs_mount *mp, xfs_agnumber_t agno,
xfs_agino_t *first, xfs_agino_t *last);
bool xfs_verify_agino(struct xfs_mount *mp, xfs_agnumber_t agno,
xfs_agino_t agino);
bool xfs_verify_agino_or_null(struct xfs_mount *mp, xfs_agnumber_t agno,
xfs_agino_t agino);
bool xfs_verify_ino(struct xfs_mount *mp, xfs_ino_t ino); bool xfs_verify_ino(struct xfs_mount *mp, xfs_ino_t ino);
bool xfs_internal_inum(struct xfs_mount *mp, xfs_ino_t ino); bool xfs_internal_inum(struct xfs_mount *mp, xfs_ino_t ino);
bool xfs_verify_dir_ino(struct xfs_mount *mp, xfs_ino_t ino); bool xfs_verify_dir_ino(struct xfs_mount *mp, xfs_ino_t ino);
......
...@@ -541,16 +541,16 @@ xchk_agf( ...@@ -541,16 +541,16 @@ xchk_agf(
/* Check the AG length */ /* Check the AG length */
eoag = be32_to_cpu(agf->agf_length); eoag = be32_to_cpu(agf->agf_length);
if (eoag != xfs_ag_block_count(mp, agno)) if (eoag != pag->block_count)
xchk_block_set_corrupt(sc, sc->sa.agf_bp); xchk_block_set_corrupt(sc, sc->sa.agf_bp);
/* Check the AGF btree roots and levels */ /* Check the AGF btree roots and levels */
agbno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNO]); agbno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNO]);
if (!xfs_verify_agbno(mp, agno, agbno)) if (!xfs_verify_agbno(pag, agbno))
xchk_block_set_corrupt(sc, sc->sa.agf_bp); xchk_block_set_corrupt(sc, sc->sa.agf_bp);
agbno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNT]); agbno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNT]);
if (!xfs_verify_agbno(mp, agno, agbno)) if (!xfs_verify_agbno(pag, agbno))
xchk_block_set_corrupt(sc, sc->sa.agf_bp); xchk_block_set_corrupt(sc, sc->sa.agf_bp);
level = be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]); level = be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]);
...@@ -563,7 +563,7 @@ xchk_agf( ...@@ -563,7 +563,7 @@ xchk_agf(
if (xfs_has_rmapbt(mp)) { if (xfs_has_rmapbt(mp)) {
agbno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_RMAP]); agbno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_RMAP]);
if (!xfs_verify_agbno(mp, agno, agbno)) if (!xfs_verify_agbno(pag, agbno))
xchk_block_set_corrupt(sc, sc->sa.agf_bp); xchk_block_set_corrupt(sc, sc->sa.agf_bp);
level = be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]); level = be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]);
...@@ -573,7 +573,7 @@ xchk_agf( ...@@ -573,7 +573,7 @@ xchk_agf(
if (xfs_has_reflink(mp)) { if (xfs_has_reflink(mp)) {
agbno = be32_to_cpu(agf->agf_refcount_root); agbno = be32_to_cpu(agf->agf_refcount_root);
if (!xfs_verify_agbno(mp, agno, agbno)) if (!xfs_verify_agbno(pag, agbno))
xchk_block_set_corrupt(sc, sc->sa.agf_bp); xchk_block_set_corrupt(sc, sc->sa.agf_bp);
level = be32_to_cpu(agf->agf_refcount_level); level = be32_to_cpu(agf->agf_refcount_level);
...@@ -639,9 +639,8 @@ xchk_agfl_block( ...@@ -639,9 +639,8 @@ xchk_agfl_block(
{ {
struct xchk_agfl_info *sai = priv; struct xchk_agfl_info *sai = priv;
struct xfs_scrub *sc = sai->sc; struct xfs_scrub *sc = sai->sc;
xfs_agnumber_t agno = sc->sa.pag->pag_agno;
if (xfs_verify_agbno(mp, agno, agbno) && if (xfs_verify_agbno(sc->sa.pag, agbno) &&
sai->nr_entries < sai->sz_entries) sai->nr_entries < sai->sz_entries)
sai->entries[sai->nr_entries++] = agbno; sai->entries[sai->nr_entries++] = agbno;
else else
...@@ -871,12 +870,12 @@ xchk_agi( ...@@ -871,12 +870,12 @@ xchk_agi(
/* Check the AG length */ /* Check the AG length */
eoag = be32_to_cpu(agi->agi_length); eoag = be32_to_cpu(agi->agi_length);
if (eoag != xfs_ag_block_count(mp, agno)) if (eoag != pag->block_count)
xchk_block_set_corrupt(sc, sc->sa.agi_bp); xchk_block_set_corrupt(sc, sc->sa.agi_bp);
/* Check btree roots and levels */ /* Check btree roots and levels */
agbno = be32_to_cpu(agi->agi_root); agbno = be32_to_cpu(agi->agi_root);
if (!xfs_verify_agbno(mp, agno, agbno)) if (!xfs_verify_agbno(pag, agbno))
xchk_block_set_corrupt(sc, sc->sa.agi_bp); xchk_block_set_corrupt(sc, sc->sa.agi_bp);
level = be32_to_cpu(agi->agi_level); level = be32_to_cpu(agi->agi_level);
...@@ -885,7 +884,7 @@ xchk_agi( ...@@ -885,7 +884,7 @@ xchk_agi(
if (xfs_has_finobt(mp)) { if (xfs_has_finobt(mp)) {
agbno = be32_to_cpu(agi->agi_free_root); agbno = be32_to_cpu(agi->agi_free_root);
if (!xfs_verify_agbno(mp, agno, agbno)) if (!xfs_verify_agbno(pag, agbno))
xchk_block_set_corrupt(sc, sc->sa.agi_bp); xchk_block_set_corrupt(sc, sc->sa.agi_bp);
level = be32_to_cpu(agi->agi_free_level); level = be32_to_cpu(agi->agi_free_level);
...@@ -902,17 +901,17 @@ xchk_agi( ...@@ -902,17 +901,17 @@ xchk_agi(
/* Check inode pointers */ /* Check inode pointers */
agino = be32_to_cpu(agi->agi_newino); agino = be32_to_cpu(agi->agi_newino);
if (!xfs_verify_agino_or_null(mp, agno, agino)) if (!xfs_verify_agino_or_null(pag, agino))
xchk_block_set_corrupt(sc, sc->sa.agi_bp); xchk_block_set_corrupt(sc, sc->sa.agi_bp);
agino = be32_to_cpu(agi->agi_dirino); agino = be32_to_cpu(agi->agi_dirino);
if (!xfs_verify_agino_or_null(mp, agno, agino)) if (!xfs_verify_agino_or_null(pag, agino))
xchk_block_set_corrupt(sc, sc->sa.agi_bp); xchk_block_set_corrupt(sc, sc->sa.agi_bp);
/* Check unlinked inode buckets */ /* Check unlinked inode buckets */
for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++) { for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++) {
agino = be32_to_cpu(agi->agi_unlinked[i]); agino = be32_to_cpu(agi->agi_unlinked[i]);
if (!xfs_verify_agino_or_null(mp, agno, agino)) if (!xfs_verify_agino_or_null(pag, agino))
xchk_block_set_corrupt(sc, sc->sa.agi_bp); xchk_block_set_corrupt(sc, sc->sa.agi_bp);
} }
......
...@@ -106,7 +106,7 @@ xrep_agf_check_agfl_block( ...@@ -106,7 +106,7 @@ xrep_agf_check_agfl_block(
{ {
struct xfs_scrub *sc = priv; struct xfs_scrub *sc = priv;
if (!xfs_verify_agbno(mp, sc->sa.pag->pag_agno, agbno)) if (!xfs_verify_agbno(sc->sa.pag, agbno))
return -EFSCORRUPTED; return -EFSCORRUPTED;
return 0; return 0;
} }
...@@ -130,10 +130,7 @@ xrep_check_btree_root( ...@@ -130,10 +130,7 @@ xrep_check_btree_root(
struct xfs_scrub *sc, struct xfs_scrub *sc,
struct xrep_find_ag_btree *fab) struct xrep_find_ag_btree *fab)
{ {
struct xfs_mount *mp = sc->mp; return xfs_verify_agbno(sc->sa.pag, fab->root) &&
xfs_agnumber_t agno = sc->sm->sm_agno;
return xfs_verify_agbno(mp, agno, fab->root) &&
fab->height <= fab->maxlevels; fab->height <= fab->maxlevels;
} }
...@@ -201,8 +198,7 @@ xrep_agf_init_header( ...@@ -201,8 +198,7 @@ xrep_agf_init_header(
agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC); agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC);
agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION); agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION);
agf->agf_seqno = cpu_to_be32(sc->sa.pag->pag_agno); agf->agf_seqno = cpu_to_be32(sc->sa.pag->pag_agno);
agf->agf_length = cpu_to_be32(xfs_ag_block_count(mp, agf->agf_length = cpu_to_be32(sc->sa.pag->block_count);
sc->sa.pag->pag_agno));
agf->agf_flfirst = old_agf->agf_flfirst; agf->agf_flfirst = old_agf->agf_flfirst;
agf->agf_fllast = old_agf->agf_fllast; agf->agf_fllast = old_agf->agf_fllast;
agf->agf_flcount = old_agf->agf_flcount; agf->agf_flcount = old_agf->agf_flcount;
...@@ -405,7 +401,7 @@ xrep_agf( ...@@ -405,7 +401,7 @@ xrep_agf(
* btrees rooted in the AGF. If the AGFL contents are obviously bad * btrees rooted in the AGF. If the AGFL contents are obviously bad
* then we'll bail out. * then we'll bail out.
*/ */
error = xfs_alloc_read_agfl(mp, sc->tp, sc->sa.pag->pag_agno, &agfl_bp); error = xfs_alloc_read_agfl(sc->sa.pag, sc->tp, &agfl_bp);
if (error) if (error)
return error; return error;
...@@ -666,8 +662,7 @@ xrep_agfl( ...@@ -666,8 +662,7 @@ xrep_agfl(
* nothing wrong with the AGF, but all the AG header repair functions * nothing wrong with the AGF, but all the AG header repair functions
* have this chicken-and-egg problem. * have this chicken-and-egg problem.
*/ */
error = xfs_alloc_read_agf(mp, sc->tp, sc->sa.pag->pag_agno, 0, error = xfs_alloc_read_agf(sc->sa.pag, sc->tp, 0, &agf_bp);
&agf_bp);
if (error) if (error)
return error; return error;
...@@ -742,8 +737,7 @@ xrep_agi_find_btrees( ...@@ -742,8 +737,7 @@ xrep_agi_find_btrees(
int error; int error;
/* Read the AGF. */ /* Read the AGF. */
error = xfs_alloc_read_agf(mp, sc->tp, sc->sa.pag->pag_agno, 0, error = xfs_alloc_read_agf(sc->sa.pag, sc->tp, 0, &agf_bp);
&agf_bp);
if (error) if (error)
return error; return error;
...@@ -782,8 +776,7 @@ xrep_agi_init_header( ...@@ -782,8 +776,7 @@ xrep_agi_init_header(
agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC); agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC);
agi->agi_versionnum = cpu_to_be32(XFS_AGI_VERSION); agi->agi_versionnum = cpu_to_be32(XFS_AGI_VERSION);
agi->agi_seqno = cpu_to_be32(sc->sa.pag->pag_agno); agi->agi_seqno = cpu_to_be32(sc->sa.pag->pag_agno);
agi->agi_length = cpu_to_be32(xfs_ag_block_count(mp, agi->agi_length = cpu_to_be32(sc->sa.pag->block_count);
sc->sa.pag->pag_agno));
agi->agi_newino = cpu_to_be32(NULLAGINO); agi->agi_newino = cpu_to_be32(NULLAGINO);
agi->agi_dirino = cpu_to_be32(NULLAGINO); agi->agi_dirino = cpu_to_be32(NULLAGINO);
if (xfs_has_crc(mp)) if (xfs_has_crc(mp))
......
...@@ -93,8 +93,7 @@ xchk_allocbt_rec( ...@@ -93,8 +93,7 @@ xchk_allocbt_rec(
struct xchk_btree *bs, struct xchk_btree *bs,
const union xfs_btree_rec *rec) const union xfs_btree_rec *rec)
{ {
struct xfs_mount *mp = bs->cur->bc_mp; struct xfs_perag *pag = bs->cur->bc_ag.pag;
xfs_agnumber_t agno = bs->cur->bc_ag.pag->pag_agno;
xfs_agblock_t bno; xfs_agblock_t bno;
xfs_extlen_t len; xfs_extlen_t len;
...@@ -102,8 +101,8 @@ xchk_allocbt_rec( ...@@ -102,8 +101,8 @@ xchk_allocbt_rec(
len = be32_to_cpu(rec->alloc.ar_blockcount); len = be32_to_cpu(rec->alloc.ar_blockcount);
if (bno + len <= bno || if (bno + len <= bno ||
!xfs_verify_agbno(mp, agno, bno) || !xfs_verify_agbno(pag, bno) ||
!xfs_verify_agbno(mp, agno, bno + len - 1)) !xfs_verify_agbno(pag, bno + len - 1))
xchk_btree_set_corrupt(bs->sc, bs->cur, 0); xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
xchk_allocbt_xref(bs->sc, bno, len); xchk_allocbt_xref(bs->sc, bno, len);
......
...@@ -540,7 +540,7 @@ xchk_bmap_check_ag_rmaps( ...@@ -540,7 +540,7 @@ xchk_bmap_check_ag_rmaps(
struct xfs_buf *agf; struct xfs_buf *agf;
int error; int error;
error = xfs_alloc_read_agf(sc->mp, sc->tp, pag->pag_agno, 0, &agf); error = xfs_alloc_read_agf(pag, sc->tp, 0, &agf);
if (error) if (error)
return error; return error;
......
...@@ -416,15 +416,15 @@ xchk_ag_read_headers( ...@@ -416,15 +416,15 @@ xchk_ag_read_headers(
if (!sa->pag) if (!sa->pag)
return -ENOENT; return -ENOENT;
error = xfs_ialloc_read_agi(mp, sc->tp, agno, &sa->agi_bp); error = xfs_ialloc_read_agi(sa->pag, sc->tp, &sa->agi_bp);
if (error && want_ag_read_header_failure(sc, XFS_SCRUB_TYPE_AGI)) if (error && want_ag_read_header_failure(sc, XFS_SCRUB_TYPE_AGI))
return error; return error;
error = xfs_alloc_read_agf(mp, sc->tp, agno, 0, &sa->agf_bp); error = xfs_alloc_read_agf(sa->pag, sc->tp, 0, &sa->agf_bp);
if (error && want_ag_read_header_failure(sc, XFS_SCRUB_TYPE_AGF)) if (error && want_ag_read_header_failure(sc, XFS_SCRUB_TYPE_AGF))
return error; return error;
error = xfs_alloc_read_agfl(mp, sc->tp, agno, &sa->agfl_bp); error = xfs_alloc_read_agfl(sa->pag, sc->tp, &sa->agfl_bp);
if (error && want_ag_read_header_failure(sc, XFS_SCRUB_TYPE_AGFL)) if (error && want_ag_read_header_failure(sc, XFS_SCRUB_TYPE_AGFL))
return error; return error;
......
...@@ -78,10 +78,10 @@ xchk_fscount_warmup( ...@@ -78,10 +78,10 @@ xchk_fscount_warmup(
continue; continue;
/* Lock both AG headers. */ /* Lock both AG headers. */
error = xfs_ialloc_read_agi(mp, sc->tp, agno, &agi_bp); error = xfs_ialloc_read_agi(pag, sc->tp, &agi_bp);
if (error) if (error)
break; break;
error = xfs_alloc_read_agf(mp, sc->tp, agno, 0, &agf_bp); error = xfs_alloc_read_agf(pag, sc->tp, 0, &agf_bp);
if (error) if (error)
break; break;
......
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#include "xfs_shared.h" #include "xfs_shared.h"
#include "xfs_format.h" #include "xfs_format.h"
#include "xfs_btree.h" #include "xfs_btree.h"
#include "xfs_trans_resv.h"
#include "xfs_mount.h"
#include "xfs_ag.h" #include "xfs_ag.h"
#include "xfs_health.h" #include "xfs_health.h"
#include "scrub/scrub.h" #include "scrub/scrub.h"
......
...@@ -104,13 +104,13 @@ xchk_iallocbt_chunk( ...@@ -104,13 +104,13 @@ xchk_iallocbt_chunk(
xfs_extlen_t len) xfs_extlen_t len)
{ {
struct xfs_mount *mp = bs->cur->bc_mp; struct xfs_mount *mp = bs->cur->bc_mp;
xfs_agnumber_t agno = bs->cur->bc_ag.pag->pag_agno; struct xfs_perag *pag = bs->cur->bc_ag.pag;
xfs_agblock_t bno; xfs_agblock_t bno;
bno = XFS_AGINO_TO_AGBNO(mp, agino); bno = XFS_AGINO_TO_AGBNO(mp, agino);
if (bno + len <= bno || if (bno + len <= bno ||
!xfs_verify_agbno(mp, agno, bno) || !xfs_verify_agbno(pag, bno) ||
!xfs_verify_agbno(mp, agno, bno + len - 1)) !xfs_verify_agbno(pag, bno + len - 1))
xchk_btree_set_corrupt(bs->sc, bs->cur, 0); xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
xchk_iallocbt_chunk_xref(bs->sc, irec, agino, bno, len); xchk_iallocbt_chunk_xref(bs->sc, irec, agino, bno, len);
...@@ -421,10 +421,10 @@ xchk_iallocbt_rec( ...@@ -421,10 +421,10 @@ xchk_iallocbt_rec(
const union xfs_btree_rec *rec) const union xfs_btree_rec *rec)
{ {
struct xfs_mount *mp = bs->cur->bc_mp; struct xfs_mount *mp = bs->cur->bc_mp;
struct xfs_perag *pag = bs->cur->bc_ag.pag;
struct xchk_iallocbt *iabt = bs->private; struct xchk_iallocbt *iabt = bs->private;
struct xfs_inobt_rec_incore irec; struct xfs_inobt_rec_incore irec;
uint64_t holes; uint64_t holes;
xfs_agnumber_t agno = bs->cur->bc_ag.pag->pag_agno;
xfs_agino_t agino; xfs_agino_t agino;
xfs_extlen_t len; xfs_extlen_t len;
int holecount; int holecount;
...@@ -446,8 +446,8 @@ xchk_iallocbt_rec( ...@@ -446,8 +446,8 @@ xchk_iallocbt_rec(
agino = irec.ir_startino; agino = irec.ir_startino;
/* Record has to be properly aligned within the AG. */ /* Record has to be properly aligned within the AG. */
if (!xfs_verify_agino(mp, agno, agino) || if (!xfs_verify_agino(pag, agino) ||
!xfs_verify_agino(mp, agno, agino + XFS_INODES_PER_CHUNK - 1)) { !xfs_verify_agino(pag, agino + XFS_INODES_PER_CHUNK - 1)) {
xchk_btree_set_corrupt(bs->sc, bs->cur, 0); xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
goto out; goto out;
} }
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
#include "scrub/scrub.h" #include "scrub/scrub.h"
#include "scrub/common.h" #include "scrub/common.h"
#include "scrub/btree.h" #include "scrub/btree.h"
#include "xfs_trans_resv.h"
#include "xfs_mount.h"
#include "xfs_ag.h" #include "xfs_ag.h"
/* /*
...@@ -332,9 +334,8 @@ xchk_refcountbt_rec( ...@@ -332,9 +334,8 @@ xchk_refcountbt_rec(
struct xchk_btree *bs, struct xchk_btree *bs,
const union xfs_btree_rec *rec) const union xfs_btree_rec *rec)
{ {
struct xfs_mount *mp = bs->cur->bc_mp;
xfs_agblock_t *cow_blocks = bs->private; xfs_agblock_t *cow_blocks = bs->private;
xfs_agnumber_t agno = bs->cur->bc_ag.pag->pag_agno; struct xfs_perag *pag = bs->cur->bc_ag.pag;
xfs_agblock_t bno; xfs_agblock_t bno;
xfs_extlen_t len; xfs_extlen_t len;
xfs_nlink_t refcount; xfs_nlink_t refcount;
...@@ -354,8 +355,8 @@ xchk_refcountbt_rec( ...@@ -354,8 +355,8 @@ xchk_refcountbt_rec(
/* Check the extent. */ /* Check the extent. */
bno &= ~XFS_REFC_COW_START; bno &= ~XFS_REFC_COW_START;
if (bno + len <= bno || if (bno + len <= bno ||
!xfs_verify_agbno(mp, agno, bno) || !xfs_verify_agbno(pag, bno) ||
!xfs_verify_agbno(mp, agno, bno + len - 1)) !xfs_verify_agbno(pag, bno + len - 1))
xchk_btree_set_corrupt(bs->sc, bs->cur, 0); xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
if (refcount == 0) if (refcount == 0)
......
...@@ -199,7 +199,7 @@ xrep_calc_ag_resblks( ...@@ -199,7 +199,7 @@ xrep_calc_ag_resblks(
icount = pag->pagi_count; icount = pag->pagi_count;
} else { } else {
/* Try to get the actual counters from disk. */ /* Try to get the actual counters from disk. */
error = xfs_ialloc_read_agi(mp, NULL, sm->sm_agno, &bp); error = xfs_ialloc_read_agi(pag, NULL, &bp);
if (!error) { if (!error) {
icount = pag->pagi_count; icount = pag->pagi_count;
xfs_buf_relse(bp); xfs_buf_relse(bp);
...@@ -207,9 +207,9 @@ xrep_calc_ag_resblks( ...@@ -207,9 +207,9 @@ xrep_calc_ag_resblks(
} }
/* Now grab the block counters from the AGF. */ /* Now grab the block counters from the AGF. */
error = xfs_alloc_read_agf(mp, NULL, sm->sm_agno, 0, &bp); error = xfs_alloc_read_agf(pag, NULL, 0, &bp);
if (error) { if (error) {
aglen = xfs_ag_block_count(mp, sm->sm_agno); aglen = pag->block_count;
freelen = aglen; freelen = aglen;
usedlen = aglen; usedlen = aglen;
} else { } else {
...@@ -220,25 +220,22 @@ xrep_calc_ag_resblks( ...@@ -220,25 +220,22 @@ xrep_calc_ag_resblks(
usedlen = aglen - freelen; usedlen = aglen - freelen;
xfs_buf_relse(bp); xfs_buf_relse(bp);
} }
xfs_perag_put(pag);
/* If the icount is impossible, make some worst-case assumptions. */ /* If the icount is impossible, make some worst-case assumptions. */
if (icount == NULLAGINO || if (icount == NULLAGINO ||
!xfs_verify_agino(mp, sm->sm_agno, icount)) { !xfs_verify_agino(pag, icount)) {
xfs_agino_t first, last; icount = pag->agino_max - pag->agino_min + 1;
xfs_agino_range(mp, sm->sm_agno, &first, &last);
icount = last - first + 1;
} }
/* If the block counts are impossible, make worst-case assumptions. */ /* If the block counts are impossible, make worst-case assumptions. */
if (aglen == NULLAGBLOCK || if (aglen == NULLAGBLOCK ||
aglen != xfs_ag_block_count(mp, sm->sm_agno) || aglen != pag->block_count ||
freelen >= aglen) { freelen >= aglen) {
aglen = xfs_ag_block_count(mp, sm->sm_agno); aglen = pag->block_count;
freelen = aglen; freelen = aglen;
usedlen = aglen; usedlen = aglen;
} }
xfs_perag_put(pag);
trace_xrep_calc_ag_resblks(mp, sm->sm_agno, icount, aglen, trace_xrep_calc_ag_resblks(mp, sm->sm_agno, icount, aglen,
freelen, usedlen); freelen, usedlen);
...@@ -300,13 +297,13 @@ xrep_alloc_ag_block( ...@@ -300,13 +297,13 @@ xrep_alloc_ag_block(
switch (resv) { switch (resv) {
case XFS_AG_RESV_AGFL: case XFS_AG_RESV_AGFL:
case XFS_AG_RESV_RMAPBT: case XFS_AG_RESV_RMAPBT:
error = xfs_alloc_get_freelist(sc->tp, sc->sa.agf_bp, &bno, 1); error = xfs_alloc_get_freelist(sc->sa.pag, sc->tp,
sc->sa.agf_bp, &bno, 1);
if (error) if (error)
return error; return error;
if (bno == NULLAGBLOCK) if (bno == NULLAGBLOCK)
return -ENOSPC; return -ENOSPC;
xfs_extent_busy_reuse(sc->mp, sc->sa.pag, bno, xfs_extent_busy_reuse(sc->mp, sc->sa.pag, bno, 1, false);
1, false);
*fsbno = XFS_AGB_TO_FSB(sc->mp, sc->sa.pag->pag_agno, bno); *fsbno = XFS_AGB_TO_FSB(sc->mp, sc->sa.pag->pag_agno, bno);
if (resv == XFS_AG_RESV_RMAPBT) if (resv == XFS_AG_RESV_RMAPBT)
xfs_ag_resv_rmapbt_alloc(sc->mp, sc->sa.pag->pag_agno); xfs_ag_resv_rmapbt_alloc(sc->mp, sc->sa.pag->pag_agno);
...@@ -516,8 +513,8 @@ xrep_put_freelist( ...@@ -516,8 +513,8 @@ xrep_put_freelist(
return error; return error;
/* Put the block on the AGFL. */ /* Put the block on the AGFL. */
error = xfs_alloc_put_freelist(sc->tp, sc->sa.agf_bp, sc->sa.agfl_bp, error = xfs_alloc_put_freelist(sc->sa.pag, sc->tp, sc->sa.agf_bp,
agbno, 0); sc->sa.agfl_bp, agbno, 0);
if (error) if (error)
return error; return error;
xfs_extent_busy_insert(sc->tp, sc->sa.pag, agbno, 1, xfs_extent_busy_insert(sc->tp, sc->sa.pag, agbno, 1,
...@@ -543,6 +540,7 @@ xrep_reap_block( ...@@ -543,6 +540,7 @@ xrep_reap_block(
agno = XFS_FSB_TO_AGNO(sc->mp, fsbno); agno = XFS_FSB_TO_AGNO(sc->mp, fsbno);
agbno = XFS_FSB_TO_AGBNO(sc->mp, fsbno); agbno = XFS_FSB_TO_AGBNO(sc->mp, fsbno);
ASSERT(agno == sc->sa.pag->pag_agno);
/* /*
* If we are repairing per-inode metadata, we need to read in the AGF * If we are repairing per-inode metadata, we need to read in the AGF
...@@ -550,7 +548,7 @@ xrep_reap_block( ...@@ -550,7 +548,7 @@ xrep_reap_block(
* the AGF buffer that the setup functions already grabbed. * the AGF buffer that the setup functions already grabbed.
*/ */
if (sc->ip) { if (sc->ip) {
error = xfs_alloc_read_agf(sc->mp, sc->tp, agno, 0, &agf_bp); error = xfs_alloc_read_agf(sc->sa.pag, sc->tp, 0, &agf_bp);
if (error) if (error)
return error; return error;
} else { } else {
......
...@@ -92,7 +92,7 @@ xchk_rmapbt_rec( ...@@ -92,7 +92,7 @@ xchk_rmapbt_rec(
{ {
struct xfs_mount *mp = bs->cur->bc_mp; struct xfs_mount *mp = bs->cur->bc_mp;
struct xfs_rmap_irec irec; struct xfs_rmap_irec irec;
xfs_agnumber_t agno = bs->cur->bc_ag.pag->pag_agno; struct xfs_perag *pag = bs->cur->bc_ag.pag;
bool non_inode; bool non_inode;
bool is_unwritten; bool is_unwritten;
bool is_bmbt; bool is_bmbt;
...@@ -121,8 +121,8 @@ xchk_rmapbt_rec( ...@@ -121,8 +121,8 @@ xchk_rmapbt_rec(
* Otherwise we must point somewhere past the static metadata * Otherwise we must point somewhere past the static metadata
* but before the end of the FS. Run the regular check. * but before the end of the FS. Run the regular check.
*/ */
if (!xfs_verify_agbno(mp, agno, irec.rm_startblock) || if (!xfs_verify_agbno(pag, irec.rm_startblock) ||
!xfs_verify_agbno(mp, agno, irec.rm_startblock + !xfs_verify_agbno(pag, irec.rm_startblock +
irec.rm_blockcount - 1)) irec.rm_blockcount - 1))
xchk_btree_set_corrupt(bs->sc, bs->cur, 0); xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
} }
......
...@@ -45,7 +45,7 @@ xfs_trim_extents( ...@@ -45,7 +45,7 @@ xfs_trim_extents(
*/ */
xfs_log_force(mp, XFS_LOG_SYNC); xfs_log_force(mp, XFS_LOG_SYNC);
error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); error = xfs_alloc_read_agf(pag, NULL, 0, &agbp);
if (error) if (error)
goto out_put_perag; goto out_put_perag;
agf = agbp->b_addr; agf = agbp->b_addr;
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "xfs_bit.h" #include "xfs_bit.h"
#include "xfs_shared.h" #include "xfs_shared.h"
#include "xfs_mount.h" #include "xfs_mount.h"
#include "xfs_ag.h"
#include "xfs_defer.h" #include "xfs_defer.h"
#include "xfs_trans.h" #include "xfs_trans.h"
#include "xfs_trans_priv.h" #include "xfs_trans_priv.h"
...@@ -551,6 +552,7 @@ xfs_agfl_free_finish_item( ...@@ -551,6 +552,7 @@ xfs_agfl_free_finish_item(
xfs_agnumber_t agno; xfs_agnumber_t agno;
xfs_agblock_t agbno; xfs_agblock_t agbno;
uint next_extent; uint next_extent;
struct xfs_perag *pag;
free = container_of(item, struct xfs_extent_free_item, xefi_list); free = container_of(item, struct xfs_extent_free_item, xefi_list);
ASSERT(free->xefi_blockcount == 1); ASSERT(free->xefi_blockcount == 1);
...@@ -560,9 +562,11 @@ xfs_agfl_free_finish_item( ...@@ -560,9 +562,11 @@ xfs_agfl_free_finish_item(
trace_xfs_agfl_free_deferred(mp, agno, 0, agbno, free->xefi_blockcount); trace_xfs_agfl_free_deferred(mp, agno, 0, agbno, free->xefi_blockcount);
error = xfs_alloc_read_agf(mp, tp, agno, 0, &agbp); pag = xfs_perag_get(mp, agno);
error = xfs_alloc_read_agf(pag, tp, 0, &agbp);
if (!error) if (!error)
error = xfs_free_agfl_block(tp, agno, agbno, agbp, &oinfo); error = xfs_free_agfl_block(tp, agno, agbno, agbp, &oinfo);
xfs_perag_put(pag);
/* /*
* Mark the transaction dirty, even on error. This ensures the * Mark the transaction dirty, even on error. This ensures the
......
...@@ -126,7 +126,7 @@ xfs_filestream_pick_ag( ...@@ -126,7 +126,7 @@ xfs_filestream_pick_ag(
pag = xfs_perag_get(mp, ag); pag = xfs_perag_get(mp, ag);
if (!pag->pagf_init) { if (!pag->pagf_init) {
err = xfs_alloc_pagf_init(mp, NULL, ag, trylock); err = xfs_alloc_read_agf(pag, NULL, trylock, NULL);
if (err) { if (err) {
if (err != -EAGAIN) { if (err != -EAGAIN) {
xfs_perag_put(pag); xfs_perag_put(pag);
...@@ -181,7 +181,7 @@ xfs_filestream_pick_ag( ...@@ -181,7 +181,7 @@ xfs_filestream_pick_ag(
if (ag != startag) if (ag != startag)
continue; continue;
/* Allow sleeping in xfs_alloc_pagf_init() on the 2nd pass. */ /* Allow sleeping in xfs_alloc_read_agf() on the 2nd pass. */
if (trylock != 0) { if (trylock != 0) {
trylock = 0; trylock = 0;
continue; continue;
......
...@@ -642,8 +642,7 @@ __xfs_getfsmap_datadev( ...@@ -642,8 +642,7 @@ __xfs_getfsmap_datadev(
info->agf_bp = NULL; info->agf_bp = NULL;
} }
error = xfs_alloc_read_agf(mp, tp, pag->pag_agno, 0, error = xfs_alloc_read_agf(pag, tp, 0, &info->agf_bp);
&info->agf_bp);
if (error) if (error)
break; break;
......
...@@ -41,6 +41,7 @@ xfs_resizefs_init_new_ags( ...@@ -41,6 +41,7 @@ xfs_resizefs_init_new_ags(
xfs_agnumber_t oagcount, xfs_agnumber_t oagcount,
xfs_agnumber_t nagcount, xfs_agnumber_t nagcount,
xfs_rfsblock_t delta, xfs_rfsblock_t delta,
struct xfs_perag *last_pag,
bool *lastag_extended) bool *lastag_extended)
{ {
struct xfs_mount *mp = tp->t_mountp; struct xfs_mount *mp = tp->t_mountp;
...@@ -73,7 +74,7 @@ xfs_resizefs_init_new_ags( ...@@ -73,7 +74,7 @@ xfs_resizefs_init_new_ags(
if (delta) { if (delta) {
*lastag_extended = true; *lastag_extended = true;
error = xfs_ag_extend_space(mp, tp, id, delta); error = xfs_ag_extend_space(last_pag, tp, delta);
} }
return error; return error;
} }
...@@ -96,6 +97,7 @@ xfs_growfs_data_private( ...@@ -96,6 +97,7 @@ xfs_growfs_data_private(
xfs_agnumber_t oagcount; xfs_agnumber_t oagcount;
struct xfs_trans *tp; struct xfs_trans *tp;
struct aghdr_init_data id = {}; struct aghdr_init_data id = {};
struct xfs_perag *last_pag;
nb = in->newblocks; nb = in->newblocks;
error = xfs_sb_validate_fsb_count(&mp->m_sb, nb); error = xfs_sb_validate_fsb_count(&mp->m_sb, nb);
...@@ -128,10 +130,9 @@ xfs_growfs_data_private( ...@@ -128,10 +130,9 @@ xfs_growfs_data_private(
return -EINVAL; return -EINVAL;
oagcount = mp->m_sb.sb_agcount; oagcount = mp->m_sb.sb_agcount;
/* allocate the new per-ag structures */ /* allocate the new per-ag structures */
if (nagcount > oagcount) { if (nagcount > oagcount) {
error = xfs_initialize_perag(mp, nagcount, &nagimax); error = xfs_initialize_perag(mp, nagcount, nb, &nagimax);
if (error) if (error)
return error; return error;
} else if (nagcount < oagcount) { } else if (nagcount < oagcount) {
...@@ -145,15 +146,17 @@ xfs_growfs_data_private( ...@@ -145,15 +146,17 @@ xfs_growfs_data_private(
if (error) if (error)
return error; return error;
last_pag = xfs_perag_get(mp, oagcount - 1);
if (delta > 0) { if (delta > 0) {
error = xfs_resizefs_init_new_ags(tp, &id, oagcount, nagcount, error = xfs_resizefs_init_new_ags(tp, &id, oagcount, nagcount,
delta, &lastag_extended); delta, last_pag, &lastag_extended);
} else { } else {
xfs_warn_mount(mp, XFS_OPSTATE_WARNED_SHRINK, xfs_warn_mount(mp, XFS_OPSTATE_WARNED_SHRINK,
"EXPERIMENTAL online shrink feature in use. Use at your own risk!"); "EXPERIMENTAL online shrink feature in use. Use at your own risk!");
error = xfs_ag_shrink_space(mp, &tp, nagcount - 1, -delta); error = xfs_ag_shrink_space(last_pag, &tp, -delta);
} }
xfs_perag_put(last_pag);
if (error) if (error)
goto out_trans_cancel; goto out_trans_cancel;
......
...@@ -2008,7 +2008,7 @@ xfs_iunlink_update_bucket( ...@@ -2008,7 +2008,7 @@ xfs_iunlink_update_bucket(
xfs_agino_t old_value; xfs_agino_t old_value;
int offset; int offset;
ASSERT(xfs_verify_agino_or_null(tp->t_mountp, pag->pag_agno, new_agino)); ASSERT(xfs_verify_agino_or_null(pag, new_agino));
old_value = be32_to_cpu(agi->agi_unlinked[bucket_index]); old_value = be32_to_cpu(agi->agi_unlinked[bucket_index]);
trace_xfs_iunlink_update_bucket(tp->t_mountp, pag->pag_agno, bucket_index, trace_xfs_iunlink_update_bucket(tp->t_mountp, pag->pag_agno, bucket_index,
...@@ -2045,7 +2045,7 @@ xfs_iunlink_update_dinode( ...@@ -2045,7 +2045,7 @@ xfs_iunlink_update_dinode(
struct xfs_mount *mp = tp->t_mountp; struct xfs_mount *mp = tp->t_mountp;
int offset; int offset;
ASSERT(xfs_verify_agino_or_null(mp, pag->pag_agno, next_agino)); ASSERT(xfs_verify_agino_or_null(pag, next_agino));
trace_xfs_iunlink_update_dinode(mp, pag->pag_agno, agino, trace_xfs_iunlink_update_dinode(mp, pag->pag_agno, agino,
be32_to_cpu(dip->di_next_unlinked), next_agino); be32_to_cpu(dip->di_next_unlinked), next_agino);
...@@ -2075,7 +2075,7 @@ xfs_iunlink_update_inode( ...@@ -2075,7 +2075,7 @@ xfs_iunlink_update_inode(
xfs_agino_t old_value; xfs_agino_t old_value;
int error; int error;
ASSERT(xfs_verify_agino_or_null(mp, pag->pag_agno, next_agino)); ASSERT(xfs_verify_agino_or_null(pag, next_agino));
error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &ibp); error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &ibp);
if (error) if (error)
...@@ -2084,7 +2084,7 @@ xfs_iunlink_update_inode( ...@@ -2084,7 +2084,7 @@ xfs_iunlink_update_inode(
/* Make sure the old pointer isn't garbage. */ /* Make sure the old pointer isn't garbage. */
old_value = be32_to_cpu(dip->di_next_unlinked); old_value = be32_to_cpu(dip->di_next_unlinked);
if (!xfs_verify_agino_or_null(mp, pag->pag_agno, old_value)) { if (!xfs_verify_agino_or_null(pag, old_value)) {
xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, dip, xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, dip,
sizeof(*dip), __this_address); sizeof(*dip), __this_address);
error = -EFSCORRUPTED; error = -EFSCORRUPTED;
...@@ -2143,7 +2143,7 @@ xfs_iunlink( ...@@ -2143,7 +2143,7 @@ xfs_iunlink(
pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino)); pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
/* Get the agi buffer first. It ensures lock ordering on the list. */ /* Get the agi buffer first. It ensures lock ordering on the list. */
error = xfs_read_agi(mp, tp, pag->pag_agno, &agibp); error = xfs_read_agi(pag, tp, &agibp);
if (error) if (error)
goto out; goto out;
agi = agibp->b_addr; agi = agibp->b_addr;
...@@ -2155,7 +2155,7 @@ xfs_iunlink( ...@@ -2155,7 +2155,7 @@ xfs_iunlink(
*/ */
next_agino = be32_to_cpu(agi->agi_unlinked[bucket_index]); next_agino = be32_to_cpu(agi->agi_unlinked[bucket_index]);
if (next_agino == agino || if (next_agino == agino ||
!xfs_verify_agino_or_null(mp, pag->pag_agno, next_agino)) { !xfs_verify_agino_or_null(pag, next_agino)) {
xfs_buf_mark_corrupt(agibp); xfs_buf_mark_corrupt(agibp);
error = -EFSCORRUPTED; error = -EFSCORRUPTED;
goto out; goto out;
...@@ -2291,7 +2291,7 @@ xfs_iunlink_map_prev( ...@@ -2291,7 +2291,7 @@ xfs_iunlink_map_prev(
* Make sure this pointer is valid and isn't an obvious * Make sure this pointer is valid and isn't an obvious
* infinite loop. * infinite loop.
*/ */
if (!xfs_verify_agino(mp, pag->pag_agno, unlinked_agino) || if (!xfs_verify_agino(pag, unlinked_agino) ||
next_agino == unlinked_agino) { next_agino == unlinked_agino) {
XFS_CORRUPTION_ERROR(__func__, XFS_CORRUPTION_ERROR(__func__,
XFS_ERRLEVEL_LOW, mp, XFS_ERRLEVEL_LOW, mp,
...@@ -2328,7 +2328,7 @@ xfs_iunlink_remove( ...@@ -2328,7 +2328,7 @@ xfs_iunlink_remove(
trace_xfs_iunlink_remove(ip); trace_xfs_iunlink_remove(ip);
/* Get the agi buffer first. It ensures lock ordering on the list. */ /* Get the agi buffer first. It ensures lock ordering on the list. */
error = xfs_read_agi(mp, tp, pag->pag_agno, &agibp); error = xfs_read_agi(pag, tp, &agibp);
if (error) if (error)
return error; return error;
agi = agibp->b_addr; agi = agibp->b_addr;
...@@ -2338,7 +2338,7 @@ xfs_iunlink_remove( ...@@ -2338,7 +2338,7 @@ xfs_iunlink_remove(
* go on. Make sure the head pointer isn't garbage. * go on. Make sure the head pointer isn't garbage.
*/ */
head_agino = be32_to_cpu(agi->agi_unlinked[bucket_index]); head_agino = be32_to_cpu(agi->agi_unlinked[bucket_index]);
if (!xfs_verify_agino(mp, pag->pag_agno, head_agino)) { if (!xfs_verify_agino(pag, head_agino)) {
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
agi, sizeof(*agi)); agi, sizeof(*agi));
return -EFSCORRUPTED; return -EFSCORRUPTED;
...@@ -3229,11 +3229,13 @@ xfs_rename( ...@@ -3229,11 +3229,13 @@ xfs_rename(
if (inodes[i] == wip || if (inodes[i] == wip ||
(inodes[i] == target_ip && (inodes[i] == target_ip &&
(VFS_I(target_ip)->i_nlink == 1 || src_is_directory))) { (VFS_I(target_ip)->i_nlink == 1 || src_is_directory))) {
struct xfs_perag *pag;
struct xfs_buf *bp; struct xfs_buf *bp;
xfs_agnumber_t agno;
agno = XFS_INO_TO_AGNO(mp, inodes[i]->i_ino); pag = xfs_perag_get(mp,
error = xfs_read_agi(mp, tp, agno, &bp); XFS_INO_TO_AGNO(mp, inodes[i]->i_ino));
error = xfs_read_agi(pag, tp, &bp);
xfs_perag_put(pag);
if (error) if (error)
goto out_trans_cancel; goto out_trans_cancel;
} }
......
...@@ -955,6 +955,7 @@ xfs_ioc_ag_geometry( ...@@ -955,6 +955,7 @@ xfs_ioc_ag_geometry(
struct xfs_mount *mp, struct xfs_mount *mp,
void __user *arg) void __user *arg)
{ {
struct xfs_perag *pag;
struct xfs_ag_geometry ageo; struct xfs_ag_geometry ageo;
int error; int error;
...@@ -965,7 +966,12 @@ xfs_ioc_ag_geometry( ...@@ -965,7 +966,12 @@ xfs_ioc_ag_geometry(
if (memchr_inv(&ageo.ag_reserved, 0, sizeof(ageo.ag_reserved))) if (memchr_inv(&ageo.ag_reserved, 0, sizeof(ageo.ag_reserved)))
return -EINVAL; return -EINVAL;
error = xfs_ag_get_geometry(mp, ageo.ag_number, &ageo); pag = xfs_perag_get(mp, ageo.ag_number);
if (!pag)
return -EINVAL;
error = xfs_ag_get_geometry(pag, &ageo);
xfs_perag_put(pag);
if (error) if (error)
return error; return error;
......
...@@ -2629,12 +2629,12 @@ xlog_recover_cancel_intents( ...@@ -2629,12 +2629,12 @@ xlog_recover_cancel_intents(
*/ */
STATIC void STATIC void
xlog_recover_clear_agi_bucket( xlog_recover_clear_agi_bucket(
xfs_mount_t *mp, struct xfs_perag *pag,
xfs_agnumber_t agno,
int bucket) int bucket)
{ {
xfs_trans_t *tp; struct xfs_mount *mp = pag->pag_mount;
xfs_agi_t *agi; struct xfs_trans *tp;
struct xfs_agi *agi;
struct xfs_buf *agibp; struct xfs_buf *agibp;
int offset; int offset;
int error; int error;
...@@ -2643,7 +2643,7 @@ xlog_recover_clear_agi_bucket( ...@@ -2643,7 +2643,7 @@ xlog_recover_clear_agi_bucket(
if (error) if (error)
goto out_error; goto out_error;
error = xfs_read_agi(mp, tp, agno, &agibp); error = xfs_read_agi(pag, tp, &agibp);
if (error) if (error)
goto out_abort; goto out_abort;
...@@ -2662,14 +2662,14 @@ xlog_recover_clear_agi_bucket( ...@@ -2662,14 +2662,14 @@ xlog_recover_clear_agi_bucket(
out_abort: out_abort:
xfs_trans_cancel(tp); xfs_trans_cancel(tp);
out_error: out_error:
xfs_warn(mp, "%s: failed to clear agi %d. Continuing.", __func__, agno); xfs_warn(mp, "%s: failed to clear agi %d. Continuing.", __func__,
pag->pag_agno);
return; return;
} }
STATIC xfs_agino_t STATIC xfs_agino_t
xlog_recover_process_one_iunlink( xlog_recover_process_one_iunlink(
struct xfs_mount *mp, struct xfs_perag *pag,
xfs_agnumber_t agno,
xfs_agino_t agino, xfs_agino_t agino,
int bucket) int bucket)
{ {
...@@ -2679,15 +2679,15 @@ xlog_recover_process_one_iunlink( ...@@ -2679,15 +2679,15 @@ xlog_recover_process_one_iunlink(
xfs_ino_t ino; xfs_ino_t ino;
int error; int error;
ino = XFS_AGINO_TO_INO(mp, agno, agino); ino = XFS_AGINO_TO_INO(pag->pag_mount, pag->pag_agno, agino);
error = xfs_iget(mp, NULL, ino, 0, 0, &ip); error = xfs_iget(pag->pag_mount, NULL, ino, 0, 0, &ip);
if (error) if (error)
goto fail; goto fail;
/* /*
* Get the on disk inode to find the next inode in the bucket. * Get the on disk inode to find the next inode in the bucket.
*/ */
error = xfs_imap_to_bp(mp, NULL, &ip->i_imap, &ibp); error = xfs_imap_to_bp(pag->pag_mount, NULL, &ip->i_imap, &ibp);
if (error) if (error)
goto fail_iput; goto fail_iput;
dip = xfs_buf_offset(ibp, ip->i_imap.im_boffset); dip = xfs_buf_offset(ibp, ip->i_imap.im_boffset);
...@@ -2714,7 +2714,7 @@ xlog_recover_process_one_iunlink( ...@@ -2714,7 +2714,7 @@ xlog_recover_process_one_iunlink(
* Call xlog_recover_clear_agi_bucket() to perform a transaction to * Call xlog_recover_clear_agi_bucket() to perform a transaction to
* clear the inode pointer in the bucket. * clear the inode pointer in the bucket.
*/ */
xlog_recover_clear_agi_bucket(mp, agno, bucket); xlog_recover_clear_agi_bucket(pag, bucket);
return NULLAGINO; return NULLAGINO;
} }
...@@ -2755,7 +2755,7 @@ xlog_recover_process_iunlinks( ...@@ -2755,7 +2755,7 @@ xlog_recover_process_iunlinks(
int error; int error;
for_each_perag(mp, agno, pag) { for_each_perag(mp, agno, pag) {
error = xfs_read_agi(mp, NULL, pag->pag_agno, &agibp); error = xfs_read_agi(pag, NULL, &agibp);
if (error) { if (error) {
/* /*
* AGI is b0rked. Don't process it. * AGI is b0rked. Don't process it.
...@@ -2780,8 +2780,8 @@ xlog_recover_process_iunlinks( ...@@ -2780,8 +2780,8 @@ xlog_recover_process_iunlinks(
for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++) { for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++) {
agino = be32_to_cpu(agi->agi_unlinked[bucket]); agino = be32_to_cpu(agi->agi_unlinked[bucket]);
while (agino != NULLAGINO) { while (agino != NULLAGINO) {
agino = xlog_recover_process_one_iunlink(mp, agino = xlog_recover_process_one_iunlink(pag,
pag->pag_agno, agino, bucket); agino, bucket);
cond_resched(); cond_resched();
} }
} }
...@@ -3313,7 +3313,8 @@ xlog_do_recover( ...@@ -3313,7 +3313,8 @@ xlog_do_recover(
/* re-initialise in-core superblock and geometry structures */ /* re-initialise in-core superblock and geometry structures */
mp->m_features |= xfs_sb_version_to_features(sbp); mp->m_features |= xfs_sb_version_to_features(sbp);
xfs_reinit_percpu_counters(mp); xfs_reinit_percpu_counters(mp);
error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi); error = xfs_initialize_perag(mp, sbp->sb_agcount, sbp->sb_dblocks,
&mp->m_maxagi);
if (error) { if (error) {
xfs_warn(mp, "Failed post-recovery per-ag init: %d", error); xfs_warn(mp, "Failed post-recovery per-ag init: %d", error);
return error; return error;
......
...@@ -778,7 +778,8 @@ xfs_mountfs( ...@@ -778,7 +778,8 @@ xfs_mountfs(
/* /*
* Allocate and initialize the per-ag data. * Allocate and initialize the per-ag data.
*/ */
error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi); error = xfs_initialize_perag(mp, sbp->sb_agcount, mp->m_sb.sb_dblocks,
&mp->m_maxagi);
if (error) { if (error) {
xfs_warn(mp, "Failed per-ag init: %d", error); xfs_warn(mp, "Failed per-ag init: %d", error);
goto out_free_dir; goto out_free_dir;
......
...@@ -125,11 +125,10 @@ ...@@ -125,11 +125,10 @@
* shared blocks. If there are no shared extents, fbno and flen will * shared blocks. If there are no shared extents, fbno and flen will
* be set to NULLAGBLOCK and 0, respectively. * be set to NULLAGBLOCK and 0, respectively.
*/ */
int static int
xfs_reflink_find_shared( xfs_reflink_find_shared(
struct xfs_mount *mp, struct xfs_perag *pag,
struct xfs_trans *tp, struct xfs_trans *tp,
xfs_agnumber_t agno,
xfs_agblock_t agbno, xfs_agblock_t agbno,
xfs_extlen_t aglen, xfs_extlen_t aglen,
xfs_agblock_t *fbno, xfs_agblock_t *fbno,
...@@ -140,11 +139,11 @@ xfs_reflink_find_shared( ...@@ -140,11 +139,11 @@ xfs_reflink_find_shared(
struct xfs_btree_cur *cur; struct xfs_btree_cur *cur;
int error; int error;
error = xfs_alloc_read_agf(mp, tp, agno, 0, &agbp); error = xfs_alloc_read_agf(pag, tp, 0, &agbp);
if (error) if (error)
return error; return error;
cur = xfs_refcountbt_init_cursor(mp, tp, agbp, agbp->b_pag); cur = xfs_refcountbt_init_cursor(pag->pag_mount, tp, agbp, pag);
error = xfs_refcount_find_shared(cur, agbno, aglen, fbno, flen, error = xfs_refcount_find_shared(cur, agbno, aglen, fbno, flen,
find_end_of_shared); find_end_of_shared);
...@@ -171,7 +170,8 @@ xfs_reflink_trim_around_shared( ...@@ -171,7 +170,8 @@ xfs_reflink_trim_around_shared(
struct xfs_bmbt_irec *irec, struct xfs_bmbt_irec *irec,
bool *shared) bool *shared)
{ {
xfs_agnumber_t agno; struct xfs_mount *mp = ip->i_mount;
struct xfs_perag *pag;
xfs_agblock_t agbno; xfs_agblock_t agbno;
xfs_extlen_t aglen; xfs_extlen_t aglen;
xfs_agblock_t fbno; xfs_agblock_t fbno;
...@@ -186,12 +186,13 @@ xfs_reflink_trim_around_shared( ...@@ -186,12 +186,13 @@ xfs_reflink_trim_around_shared(
trace_xfs_reflink_trim_around_shared(ip, irec); trace_xfs_reflink_trim_around_shared(ip, irec);
agno = XFS_FSB_TO_AGNO(ip->i_mount, irec->br_startblock); pag = xfs_perag_get(mp, XFS_FSB_TO_AGNO(mp, irec->br_startblock));
agbno = XFS_FSB_TO_AGBNO(ip->i_mount, irec->br_startblock); agbno = XFS_FSB_TO_AGBNO(mp, irec->br_startblock);
aglen = irec->br_blockcount; aglen = irec->br_blockcount;
error = xfs_reflink_find_shared(ip->i_mount, NULL, agno, agbno, error = xfs_reflink_find_shared(pag, NULL, agbno, aglen, &fbno, &flen,
aglen, &fbno, &flen, true); true);
xfs_perag_put(pag);
if (error) if (error)
return error; return error;
...@@ -1420,11 +1421,6 @@ xfs_reflink_inode_has_shared_extents( ...@@ -1420,11 +1421,6 @@ xfs_reflink_inode_has_shared_extents(
struct xfs_bmbt_irec got; struct xfs_bmbt_irec got;
struct xfs_mount *mp = ip->i_mount; struct xfs_mount *mp = ip->i_mount;
struct xfs_ifork *ifp; struct xfs_ifork *ifp;
xfs_agnumber_t agno;
xfs_agblock_t agbno;
xfs_extlen_t aglen;
xfs_agblock_t rbno;
xfs_extlen_t rlen;
struct xfs_iext_cursor icur; struct xfs_iext_cursor icur;
bool found; bool found;
int error; int error;
...@@ -1437,17 +1433,25 @@ xfs_reflink_inode_has_shared_extents( ...@@ -1437,17 +1433,25 @@ xfs_reflink_inode_has_shared_extents(
*has_shared = false; *has_shared = false;
found = xfs_iext_lookup_extent(ip, ifp, 0, &icur, &got); found = xfs_iext_lookup_extent(ip, ifp, 0, &icur, &got);
while (found) { while (found) {
struct xfs_perag *pag;
xfs_agblock_t agbno;
xfs_extlen_t aglen;
xfs_agblock_t rbno;
xfs_extlen_t rlen;
if (isnullstartblock(got.br_startblock) || if (isnullstartblock(got.br_startblock) ||
got.br_state != XFS_EXT_NORM) got.br_state != XFS_EXT_NORM)
goto next; goto next;
agno = XFS_FSB_TO_AGNO(mp, got.br_startblock);
pag = xfs_perag_get(mp, XFS_FSB_TO_AGNO(mp, got.br_startblock));
agbno = XFS_FSB_TO_AGBNO(mp, got.br_startblock); agbno = XFS_FSB_TO_AGBNO(mp, got.br_startblock);
aglen = got.br_blockcount; aglen = got.br_blockcount;
error = xfs_reflink_find_shared(pag, tp, agbno, aglen,
error = xfs_reflink_find_shared(mp, tp, agno, agbno, aglen,
&rbno, &rlen, false); &rbno, &rlen, false);
xfs_perag_put(pag);
if (error) if (error)
return error; return error;
/* Is there still a shared block here? */ /* Is there still a shared block here? */
if (rbno != NULLAGBLOCK) { if (rbno != NULLAGBLOCK) {
*has_shared = true; *has_shared = true;
......
...@@ -16,9 +16,6 @@ static inline bool xfs_is_cow_inode(struct xfs_inode *ip) ...@@ -16,9 +16,6 @@ static inline bool xfs_is_cow_inode(struct xfs_inode *ip)
return xfs_is_reflink_inode(ip) || xfs_is_always_cow_inode(ip); return xfs_is_reflink_inode(ip) || xfs_is_always_cow_inode(ip);
} }
extern int xfs_reflink_find_shared(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t aglen,
xfs_agblock_t *fbno, xfs_extlen_t *flen, bool find_maximal);
extern int xfs_reflink_trim_around_shared(struct xfs_inode *ip, extern int xfs_reflink_trim_around_shared(struct xfs_inode *ip,
struct xfs_bmbt_irec *irec, bool *shared); struct xfs_bmbt_irec *irec, bool *shared);
int xfs_bmap_trim_cow(struct xfs_inode *ip, struct xfs_bmbt_irec *imap, int xfs_bmap_trim_cow(struct xfs_inode *ip, struct xfs_bmbt_irec *imap,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册