Re: [PATCH 15/22] xfs: use perag for ialloc btree cursors

Darrick J. Wong
2021-05-13T03:55:58Z

On Thu, May 06, 2021 at 05:20:47PM +1000, Dave Chinner wrote:
> From: Dave Chinner <dchinner@redhat.com>
>
> Signed-off-by: Dave Chinner <dchinner@redhat.com>

Looks good...
Reviewed-by: Darrick J. Wong <djwong@kernel.org>

--D

> ---
> fs/xfs/libxfs/xfs_ialloc.c | 177 ++++++++++++++++---------------
> fs/xfs/libxfs/xfs_ialloc_btree.c | 27 ++---
> fs/xfs/libxfs/xfs_ialloc_btree.h | 6 +-
> fs/xfs/scrub/agheader_repair.c | 4 +-
> fs/xfs/scrub/common.c | 5 +-
> fs/xfs/xfs_iwalk.c | 6 +-
> 6 files changed, 109 insertions(+), 116 deletions(-)
>
> diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
> index 905872bab426..e6f64d41e208 100644
> --- a/fs/xfs/libxfs/xfs_ialloc.c
> +++ b/fs/xfs/libxfs/xfs_ialloc.c
> @@ -172,18 +172,17 @@ xfs_inobt_insert(
> struct xfs_mount *mp,
> struct xfs_trans *tp,
> struct xfs_buf *agbp,
> + struct xfs_perag *pag,
> xfs_agino_t newino,
> xfs_agino_t newlen,
> xfs_btnum_t btnum)
> {
> struct xfs_btree_cur *cur;
> - struct xfs_agi *agi = agbp->b_addr;
> - xfs_agnumber_t agno = be32_to_cpu(agi->agi_seqno);
> xfs_agino_t thisino;
> int i;
> int error;
>
> - cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, NULL, btnum);
> + cur = xfs_inobt_init_cursor(mp, tp, agbp, pag, btnum);
>
> for (thisino = newino;
> thisino < newino + newlen;
> @@ -520,18 +519,17 @@ xfs_inobt_insert_sprec(
> struct xfs_mount *mp,
> struct xfs_trans *tp,
> struct xfs_buf *agbp,
> + struct xfs_perag *pag,
> int btnum,
> struct xfs_inobt_rec_incore *nrec, /* in/out: new/merged rec. */
> bool merge) /* merge or replace */
> {
> struct xfs_btree_cur *cur;
> - struct xfs_agi *agi = agbp->b_addr;
> - xfs_agnumber_t agno = be32_to_cpu(agi->agi_seqno);
> int error;
> int i;
> struct xfs_inobt_rec_incore rec;
>
> - cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, NULL, btnum);
> + cur = xfs_inobt_init_cursor(mp, tp, agbp, pag, btnum);
>
> /* the new record is pre-aligned so we know where to look */
> error = xfs_inobt_lookup(cur, nrec->ir_startino, XFS_LOOKUP_EQ, &i);
> @@ -578,14 +576,14 @@ xfs_inobt_insert_sprec(
> goto error;
> }
>
> - trace_xfs_irec_merge_pre(mp, agno, rec.ir_startino,
> + trace_xfs_irec_merge_pre(mp, pag->pag_agno, rec.ir_startino,
> rec.ir_holemask, nrec->ir_startino,
> nrec->ir_holemask);
>
> /* merge to nrec to output the updated record */
> __xfs_inobt_rec_merge(nrec, &rec);
>
> - trace_xfs_irec_merge_post(mp, agno, nrec->ir_startino,
> + trace_xfs_irec_merge_post(mp, pag->pag_agno, nrec->ir_startino,
> nrec->ir_holemask);
>
> error = xfs_inobt_rec_check_count(mp, nrec);
> @@ -613,21 +611,20 @@ xfs_inobt_insert_sprec(
> STATIC int
> xfs_ialloc_ag_alloc(
> struct xfs_trans *tp,
> - struct xfs_buf *agbp)
> + struct xfs_buf *agbp,
> + struct xfs_perag *pag)
> {
> struct xfs_agi *agi;
> struct xfs_alloc_arg args;
> - xfs_agnumber_t agno;
> int error;
> xfs_agino_t newino; /* new first inode's number */
> xfs_agino_t newlen; /* new number of inodes */
> int isaligned = 0; /* inode allocation at stripe */
> /* unit boundary */
> /* init. to full chunk */
> - uint16_t allocmask = (uint16_t) -1;
> struct xfs_inobt_rec_incore rec;
> - struct xfs_perag *pag;
> struct xfs_ino_geometry *igeo = M_IGEO(tp->t_mountp);
> + uint16_t allocmask = (uint16_t) -1;
> int do_sparse = 0;
>
> memset(&args, 0, sizeof(args));
> @@ -660,14 +657,13 @@ xfs_ialloc_ag_alloc(
> */
> agi = agbp->b_addr;
> newino = be32_to_cpu(agi->agi_newino);
> - agno = be32_to_cpu(agi->agi_seqno);
> args.agbno = XFS_AGINO_TO_AGBNO(args.mp, newino) +
> igeo->ialloc_blks;
> if (do_sparse)
> goto sparse_alloc;
> if (likely(newino != NULLAGINO &&
> (args.agbno < be32_to_cpu(agi->agi_length)))) {
> - args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno);
> + args.fsbno = XFS_AGB_TO_FSB(args.mp, pag->pag_agno, args.agbno);
> args.type = XFS_ALLOCTYPE_THIS_BNO;
> args.prod = 1;
>
> @@ -727,7 +723,7 @@ xfs_ialloc_ag_alloc(
> * For now, just allocate blocks up front.
> */
> args.agbno = be32_to_cpu(agi->agi_root);
> - args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno);
> + args.fsbno = XFS_AGB_TO_FSB(args.mp, pag->pag_agno, args.agbno);
> /*
> * Allocate a fixed-size extent of inodes.
> */
> @@ -748,7 +744,7 @@ xfs_ialloc_ag_alloc(
> if (isaligned && args.fsbno == NULLFSBLOCK) {
> args.type = XFS_ALLOCTYPE_NEAR_BNO;
> args.agbno = be32_to_cpu(agi->agi_root);
> - args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno);
> + args.fsbno = XFS_AGB_TO_FSB(args.mp, pag->pag_agno, args.agbno);
> args.alignment = igeo->cluster_align;
> if ((error = xfs_alloc_vextent(&args)))
> return error;
> @@ -764,7 +760,7 @@ xfs_ialloc_ag_alloc(
> sparse_alloc:
> args.type = XFS_ALLOCTYPE_NEAR_BNO;
> args.agbno = be32_to_cpu(agi->agi_root);
> - args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno);
> + args.fsbno = XFS_AGB_TO_FSB(args.mp, pag->pag_agno, args.agbno);
> args.alignment = args.mp->m_sb.sb_spino_align;
> args.prod = 1;
>
> @@ -809,7 +805,7 @@ xfs_ialloc_ag_alloc(
> * rather than a linear progression to prevent the next generation
> * number from being easily guessable.
> */
> - error = xfs_ialloc_inode_init(args.mp, tp, NULL, newlen, agno,
> + error = xfs_ialloc_inode_init(args.mp, tp, NULL, newlen, pag->pag_agno,
> args.agbno, args.len, prandom_u32());
>
> if (error)
> @@ -836,12 +832,12 @@ xfs_ialloc_ag_alloc(
> * if necessary. If a merge does occur, rec is updated to the
> * merged record.
> */
> - error = xfs_inobt_insert_sprec(args.mp, tp, agbp, XFS_BTNUM_INO,
> - &rec, true);
> + error = xfs_inobt_insert_sprec(args.mp, tp, agbp, pag,
> + XFS_BTNUM_INO, &rec, true);
> if (error == -EFSCORRUPTED) {
> xfs_alert(args.mp,
> "invalid sparse inode record: ino 0x%llx holemask 0x%x count %u",
> - XFS_AGINO_TO_INO(args.mp, agno,
> + XFS_AGINO_TO_INO(args.mp, pag->pag_agno,
> rec.ir_startino),
> rec.ir_holemask, rec.ir_count);
> xfs_force_shutdown(args.mp, SHUTDOWN_CORRUPT_INCORE);
> @@ -861,21 +857,20 @@ xfs_ialloc_ag_alloc(
> * existing record with this one.
> */
> if (xfs_sb_version_hasfinobt(&args.mp->m_sb)) {
> - error = xfs_inobt_insert_sprec(args.mp, tp, agbp,
> - XFS_BTNUM_FINO, &rec,
> - false);
> + error = xfs_inobt_insert_sprec(args.mp, tp, agbp, pag,
> + XFS_BTNUM_FINO, &rec, false);
> if (error)
> return error;
> }
> } else {
> /* full chunk - insert new records to both btrees */
> - error = xfs_inobt_insert(args.mp, tp, agbp, newino, newlen,
> + error = xfs_inobt_insert(args.mp, tp, agbp, pag, newino, newlen,
> XFS_BTNUM_INO);
> if (error)
> return error;
>
> if (xfs_sb_version_hasfinobt(&args.mp->m_sb)) {
> - error = xfs_inobt_insert(args.mp, tp, agbp, newino,
> + error = xfs_inobt_insert(args.mp, tp, agbp, pag, newino,
> newlen, XFS_BTNUM_FINO);
> if (error)
> return error;
> @@ -887,7 +882,6 @@ xfs_ialloc_ag_alloc(
> */
> be32_add_cpu(&agi->agi_count, newlen);
> be32_add_cpu(&agi->agi_freecount, newlen);
> - pag = agbp->b_pag;
> pag->pagi_freecount += newlen;
> pag->pagi_count += newlen;
> agi->agi_newino = cpu_to_be32(newino);
> @@ -1123,15 +1117,14 @@ STATIC int
> xfs_dialloc_ag_inobt(
> struct xfs_trans *tp,
> struct xfs_buf *agbp,
> + struct xfs_perag *pag,
> xfs_ino_t parent,
> xfs_ino_t *inop)
> {
> struct xfs_mount *mp = tp->t_mountp;
> struct xfs_agi *agi = agbp->b_addr;
> - xfs_agnumber_t agno = be32_to_cpu(agi->agi_seqno);
> xfs_agnumber_t pagno = XFS_INO_TO_AGNO(mp, parent);
> xfs_agino_t pagino = XFS_INO_TO_AGINO(mp, parent);
> - struct xfs_perag *pag = agbp->b_pag;
> struct xfs_btree_cur *cur, *tcur;
> struct xfs_inobt_rec_incore rec, trec;
> xfs_ino_t ino;
> @@ -1145,7 +1138,7 @@ xfs_dialloc_ag_inobt(
> ASSERT(pag->pagi_freecount > 0);
>
> restart_pagno:
> - cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, NULL, XFS_BTNUM_INO);
> + cur = xfs_inobt_init_cursor(mp, tp, agbp, pag, XFS_BTNUM_INO);
> /*
> * If pagino is 0 (this is the root inode allocation) use newino.
> * This must work because we've just allocated some.
> @@ -1160,7 +1153,7 @@ xfs_dialloc_ag_inobt(
> /*
> * If in the same AG as the parent, try to get near the parent.
> */
> - if (pagno == agno) {
> + if (pagno == pag->pag_agno) {
> int doneleft; /* done, to the left */
> int doneright; /* done, to the right */
>
> @@ -1363,7 +1356,7 @@ xfs_dialloc_ag_inobt(
> ASSERT(offset < XFS_INODES_PER_CHUNK);
> ASSERT((XFS_AGINO_TO_OFFSET(mp, rec.ir_startino) %
> XFS_INODES_PER_CHUNK) == 0);
> - ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino + offset);
> + ino = XFS_AGINO_TO_INO(mp, pag->pag_agno, rec.ir_startino + offset);
> rec.ir_free &= ~XFS_INOBT_MASK(offset);
> rec.ir_freecount--;
> error = xfs_inobt_update(cur, &rec);
> @@ -1577,7 +1570,6 @@ xfs_dialloc_ag(
> {
> struct xfs_mount *mp = tp->t_mountp;
> struct xfs_agi *agi = agbp->b_addr;
> - xfs_agnumber_t agno = be32_to_cpu(agi->agi_seqno);
> xfs_agnumber_t pagno = XFS_INO_TO_AGNO(mp, parent);
> xfs_agino_t pagino = XFS_INO_TO_AGINO(mp, parent);
> struct xfs_btree_cur *cur; /* finobt cursor */
> @@ -1587,9 +1579,10 @@ xfs_dialloc_ag(
> int error;
> int offset;
> int i;
> + struct xfs_perag *pag = agbp->b_pag;
>
> if (!xfs_sb_version_hasfinobt(&mp->m_sb))
> - return xfs_dialloc_ag_inobt(tp, agbp, parent, inop);
> + return xfs_dialloc_ag_inobt(tp, agbp, pag, parent, inop);
>
> /*
> * If pagino is 0 (this is the root inode allocation) use newino.
> @@ -1598,7 +1591,7 @@ xfs_dialloc_ag(
> if (!pagino)
> pagino = be32_to_cpu(agi->agi_newino);
>
> - cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, NULL, XFS_BTNUM_FINO);
> + cur = xfs_inobt_init_cursor(mp, tp, agbp, pag, XFS_BTNUM_FINO);
>
> error = xfs_check_agi_freecount(cur, agi);
> if (error)
> @@ -1609,7 +1602,7 @@ xfs_dialloc_ag(
> * parent. If so, find the closest available inode to the parent. If
> * not, consider the agi hint or find the first free inode in the AG.
> */
> - if (agno == pagno)
> + if (pag->pag_agno == pagno)
> error = xfs_dialloc_ag_finobt_near(pagino, &cur, &rec);
> else
> error = xfs_dialloc_ag_finobt_newino(agi, cur, &rec);
> @@ -1621,7 +1614,7 @@ xfs_dialloc_ag(
> ASSERT(offset < XFS_INODES_PER_CHUNK);
> ASSERT((XFS_AGINO_TO_OFFSET(mp, rec.ir_startino) %
> XFS_INODES_PER_CHUNK) == 0);
> - ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino + offset);
> + ino = XFS_AGINO_TO_INO(mp, pag->pag_agno, rec.ir_startino + offset);
>
> /*
> * Modify or remove the finobt record.
> @@ -1641,7 +1634,7 @@ xfs_dialloc_ag(
> * the original freecount. If all is well, make the equivalent update to
> * the inobt using the finobt record and offset information.
> */
> - icur = xfs_inobt_init_cursor(mp, tp, agbp, agno, NULL, XFS_BTNUM_INO);
> + icur = xfs_inobt_init_cursor(mp, tp, agbp, pag, XFS_BTNUM_INO);
>
> error = xfs_check_agi_freecount(icur, agi);
> if (error)
> @@ -1657,7 +1650,7 @@ xfs_dialloc_ag(
> */
> be32_add_cpu(&agi->agi_freecount, -1);
> xfs_ialloc_log_agi(tp, agbp, XFS_AGI_FREECOUNT);
> - agbp->b_pag->pagi_freecount--;
> + pag->pagi_freecount--;
>
> xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, -1);
>
> @@ -1809,7 +1802,7 @@ xfs_dialloc_select_ag(
> if (!okalloc)
> goto nextag_relse_buffer;
>
> - error = xfs_ialloc_ag_alloc(*tpp, agbp);
> + error = xfs_ialloc_ag_alloc(*tpp, agbp, pag);
> if (error < 0) {
> xfs_trans_brelse(*tpp, agbp);
>
> @@ -1935,12 +1928,12 @@ xfs_difree_inobt(
> struct xfs_mount *mp,
> struct xfs_trans *tp,
> struct xfs_buf *agbp,
> + struct xfs_perag *pag,
> xfs_agino_t agino,
> struct xfs_icluster *xic,
> struct xfs_inobt_rec_incore *orec)
> {
> struct xfs_agi *agi = agbp->b_addr;
> - xfs_agnumber_t agno = be32_to_cpu(agi->agi_seqno);
> struct xfs_btree_cur *cur;
> struct xfs_inobt_rec_incore rec;
> int ilen;
> @@ -1954,7 +1947,7 @@ xfs_difree_inobt(
> /*
> * Initialize the cursor.
> */
> - cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, NULL, XFS_BTNUM_INO);
> + cur = xfs_inobt_init_cursor(mp, tp, agbp, pag, XFS_BTNUM_INO);
>
> error = xfs_check_agi_freecount(cur, agi);
> if (error)
> @@ -2005,7 +1998,8 @@ xfs_difree_inobt(
> struct xfs_perag *pag = agbp->b_pag;
>
> xic->deleted = true;
> - xic->first_ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino);
> + xic->first_ino = XFS_AGINO_TO_INO(mp, pag->pag_agno,
> + rec.ir_startino);
> xic->alloc = xfs_inobt_irec_to_allocmask(&rec);
>
> /*
> @@ -2028,7 +2022,7 @@ xfs_difree_inobt(
> goto error0;
> }
>
> - xfs_difree_inode_chunk(tp, agno, &rec);
> + xfs_difree_inode_chunk(tp, pag->pag_agno, &rec);
> } else {
> xic->deleted = false;
>
> @@ -2044,7 +2038,7 @@ xfs_difree_inobt(
> */
> be32_add_cpu(&agi->agi_freecount, 1);
> xfs_ialloc_log_agi(tp, agbp, XFS_AGI_FREECOUNT);
> - agbp->b_pag->pagi_freecount++;
> + pag->pagi_freecount++;
> xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, 1);
> }
>
> @@ -2069,18 +2063,18 @@ xfs_difree_finobt(
> struct xfs_mount *mp,
> struct xfs_trans *tp,
> struct xfs_buf *agbp,
> + struct xfs_perag *pag,
> xfs_agino_t agino,
> struct xfs_inobt_rec_incore *ibtrec) /* inobt record */
> {
> struct xfs_agi *agi = agbp->b_addr;
> - xfs_agnumber_t agno = be32_to_cpu(agi->agi_seqno);
> struct xfs_btree_cur *cur;
> struct xfs_inobt_rec_incore rec;
> int offset = agino - ibtrec->ir_startino;
> int error;
> int i;
>
> - cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, NULL, XFS_BTNUM_FINO);
> + cur = xfs_inobt_init_cursor(mp, tp, agbp, pag, XFS_BTNUM_FINO);
>
> error = xfs_inobt_lookup(cur, ibtrec->ir_startino, XFS_LOOKUP_EQ, &i);
> if (error)
> @@ -2188,16 +2182,15 @@ xfs_difree(
> xfs_agino_t agino; /* allocation group inode number */
> xfs_agnumber_t agno; /* allocation group number */
> int error; /* error return value */
> - struct xfs_mount *mp; /* mount structure for filesystem */
> + struct xfs_mount *mp = tp->t_mountp;
> struct xfs_inobt_rec_incore rec;/* btree record */
> -
> - mp = tp->t_mountp;
> + struct xfs_perag *pag;
>
> /*
> * Break up inode number into its components.
> */
> agno = XFS_INO_TO_AGNO(mp, inode);
> - if (agno >= mp->m_sb.sb_agcount) {
> + if (agno >= mp->m_sb.sb_agcount) {
> xfs_warn(mp, "%s: agno >= mp->m_sb.sb_agcount (%d >= %d).",
> __func__, agno, mp->m_sb.sb_agcount);
> ASSERT(0);
> @@ -2231,7 +2224,8 @@ xfs_difree(
> /*
> * Fix up the inode allocation btree.
> */
> - error = xfs_difree_inobt(mp, tp, agbp, agino, xic, &rec);
> + pag = agbp->b_pag;
> + error = xfs_difree_inobt(mp, tp, agbp, pag, agino, xic, &rec);
> if (error)
> goto error0;
>
> @@ -2239,7 +2233,7 @@ xfs_difree(
> * Fix up the free inode btree.
> */
> if (xfs_sb_version_hasfinobt(&mp->m_sb)) {
> - error = xfs_difree_finobt(mp, tp, agbp, agino, &rec);
> + error = xfs_difree_finobt(mp, tp, agbp, pag, agino, &rec);
> if (error)
> goto error0;
> }
> @@ -2254,7 +2248,7 @@ STATIC int
> xfs_imap_lookup(
> struct xfs_mount *mp,
> struct xfs_trans *tp,
> - xfs_agnumber_t agno,
> + struct xfs_perag *pag,
> xfs_agino_t agino,
> xfs_agblock_t agbno,
> xfs_agblock_t *chunk_agbno,
> @@ -2267,11 +2261,11 @@ xfs_imap_lookup(
> int error;
> int i;
>
> - error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
> + error = xfs_ialloc_read_agi(mp, tp, pag->pag_agno, &agbp);
> if (error) {
> xfs_alert(mp,
> "%s: xfs_ialloc_read_agi() returned error %d, agno %d",
> - __func__, error, agno);
> + __func__, error, pag->pag_agno);
> return error;
> }
>
> @@ -2281,7 +2275,7 @@ xfs_imap_lookup(
> * we have a record, we need to ensure it contains the inode number
> * we are looking up.
> */
> - cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, NULL, XFS_BTNUM_INO);
> + cur = xfs_inobt_init_cursor(mp, tp, agbp, pag, XFS_BTNUM_INO);
> error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &i);
> if (!error) {
> if (i)
> @@ -2315,42 +2309,44 @@ xfs_imap_lookup(
> */
> int
> xfs_imap(
> - xfs_mount_t *mp, /* file system mount structure */
> - xfs_trans_t *tp, /* transaction pointer */
> - xfs_ino_t ino, /* inode to locate */
> - struct xfs_imap *imap, /* location map structure */
> - uint flags) /* flags for inode btree lookup */
> + struct xfs_mount *mp, /* file system mount structure */
> + struct xfs_trans *tp, /* transaction pointer */
> + xfs_ino_t ino, /* inode to locate */
> + struct xfs_imap *imap, /* location map structure */
> + uint flags) /* flags for inode btree lookup */
> {
> - xfs_agblock_t agbno; /* block number of inode in the alloc group */
> - xfs_agino_t agino; /* inode number within alloc group */
> - xfs_agnumber_t agno; /* allocation group number */
> - xfs_agblock_t chunk_agbno; /* first block in inode chunk */
> - xfs_agblock_t cluster_agbno; /* first block in inode cluster */
> - int error; /* error code */
> - int offset; /* index of inode in its buffer */
> - xfs_agblock_t offset_agbno; /* blks from chunk start to inode */
> + xfs_agblock_t agbno; /* block number of inode in the alloc group */
> + xfs_agino_t agino; /* inode number within alloc group */
> + xfs_agblock_t chunk_agbno; /* first block in inode chunk */
> + xfs_agblock_t cluster_agbno; /* first block in inode cluster */
> + int error; /* error code */
> + int offset; /* index of inode in its buffer */
> + xfs_agblock_t offset_agbno; /* blks from chunk start to inode */
> + struct xfs_perag *pag;
>
> ASSERT(ino != NULLFSINO);
>
> /*
> * Split up the inode number into its parts.
> */
> - agno = XFS_INO_TO_AGNO(mp, ino);
> + pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ino));
> agino = XFS_INO_TO_AGINO(mp, ino);
> agbno = XFS_AGINO_TO_AGBNO(mp, agino);
> - if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks ||
> - ino != XFS_AGINO_TO_INO(mp, agno, agino)) {
> + if (!pag || agbno >= mp->m_sb.sb_agblocks ||
> + ino != XFS_AGINO_TO_INO(mp, pag->pag_agno, agino)) {
> + error = -EINVAL;
> #ifdef DEBUG
> /*
> * Don't output diagnostic information for untrusted inodes
> * as they can be invalid without implying corruption.
> */
> if (flags & XFS_IGET_UNTRUSTED)
> - return -EINVAL;
> - if (agno >= mp->m_sb.sb_agcount) {
> + goto out_drop;
> + if (!pag) {
> xfs_alert(mp,
> "%s: agno (%d) >= mp->m_sb.sb_agcount (%d)",
> - __func__, agno, mp->m_sb.sb_agcount);
> + __func__, XFS_INO_TO_AGNO(mp, ino),
> + mp->m_sb.sb_agcount);
> }
> if (agbno >= mp->m_sb.sb_agblocks) {
> xfs_alert(mp,
> @@ -2358,15 +2354,15 @@ xfs_imap(
> __func__, (unsigned long long)agbno,
> (unsigned long)mp->m_sb.sb_agblocks);
> }
> - if (ino != XFS_AGINO_TO_INO(mp, agno, agino)) {
> + if (pag && ino != XFS_AGINO_TO_INO(mp, pag->pag_agno, agino)) {
> xfs_alert(mp,
> "%s: ino (0x%llx) != XFS_AGINO_TO_INO() (0x%llx)",
> __func__, ino,
> - XFS_AGINO_TO_INO(mp, agno, agino));
> + XFS_AGINO_TO_INO(mp, pag->pag_agno, agino));
> }
> xfs_stack_trace();
> #endif /* DEBUG */
> - return -EINVAL;
> + goto out_drop;
> }
>
> /*
> @@ -2377,10 +2373,10 @@ xfs_imap(
> * in all cases where an untrusted inode number is passed.
> */
> if (flags & XFS_IGET_UNTRUSTED) {
> - error = xfs_imap_lookup(mp, tp, agno, agino, agbno,
> + error = xfs_imap_lookup(mp, tp, pag, agino, agbno,
> &chunk_agbno, &offset_agbno, flags);
> if (error)
> - return error;
> + goto out_drop;
> goto out_map;
> }
>
> @@ -2392,11 +2388,12 @@ xfs_imap(
> offset = XFS_INO_TO_OFFSET(mp, ino);
> ASSERT(offset < mp->m_sb.sb_inopblock);
>
> - imap->im_blkno = XFS_AGB_TO_DADDR(mp, agno, agbno);
> + imap->im_blkno = XFS_AGB_TO_DADDR(mp, pag->pag_agno, agbno);
> imap->im_len = XFS_FSB_TO_BB(mp, 1);
> imap->im_boffset = (unsigned short)(offset <<
> mp->m_sb.sb_inodelog);
> - return 0;
> + error = 0;
> + goto out_drop;
> }
>
> /*
> @@ -2408,10 +2405,10 @@ xfs_imap(
> offset_agbno = agbno & M_IGEO(mp)->inoalign_mask;
> chunk_agbno = agbno - offset_agbno;
> } else {
> - error = xfs_imap_lookup(mp, tp, agno, agino, agbno,
> + error = xfs_imap_lookup(mp, tp, pag, agino, agbno,
> &chunk_agbno, &offset_agbno, flags);
> if (error)
> - return error;
> + goto out_drop;
> }
>
> out_map:
> @@ -2422,7 +2419,7 @@ xfs_imap(
> offset = ((agbno - cluster_agbno) * mp->m_sb.sb_inopblock) +
> XFS_INO_TO_OFFSET(mp, ino);
>
> - imap->im_blkno = XFS_AGB_TO_DADDR(mp, agno, cluster_agbno);
> + imap->im_blkno = XFS_AGB_TO_DADDR(mp, pag->pag_agno, cluster_agbno);
> imap->im_len = XFS_FSB_TO_BB(mp, M_IGEO(mp)->blocks_per_cluster);
> imap->im_boffset = (unsigned short)(offset << mp->m_sb.sb_inodelog);
>
> @@ -2439,9 +2436,13 @@ xfs_imap(
> __func__, (unsigned long long) imap->im_blkno,
> (unsigned long long) imap->im_len,
> XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks));
> - return -EINVAL;
> + error = -EINVAL;
> + goto out_drop;
> }
> - return 0;
> + error = 0;
> +out_drop:
> + xfs_perag_put(pag);
> + return error;
> }
>
> /*
> diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.c b/fs/xfs/libxfs/xfs_ialloc_btree.c
> index 6c4efdf01674..450161b53648 100644
> --- a/fs/xfs/libxfs/xfs_ialloc_btree.c
> +++ b/fs/xfs/libxfs/xfs_ialloc_btree.c
> @@ -35,8 +35,7 @@ xfs_inobt_dup_cursor(
> struct xfs_btree_cur *cur)
> {
> return xfs_inobt_init_cursor(cur->bc_mp, cur->bc_tp,
> - cur->bc_ag.agbp, cur->bc_ag.agno,
> - cur->bc_ag.pag, cur->bc_btnum);
> + cur->bc_ag.agbp, cur->bc_ag.pag, cur->bc_btnum);
> }
>
> STATIC void
> @@ -428,7 +427,6 @@ static struct xfs_btree_cur *
> xfs_inobt_init_common(
> struct xfs_mount *mp, /* file system mount point */
> struct xfs_trans *tp, /* transaction pointer */
> - xfs_agnumber_t agno, /* allocation group number */
> struct xfs_perag *pag,
> xfs_btnum_t btnum) /* ialloc or free ino btree */
> {
> @@ -451,12 +449,10 @@ xfs_inobt_init_common(
> if (xfs_sb_version_hascrc(&mp->m_sb))
> cur->bc_flags |= XFS_BTREE_CRC_BLOCKS;
>
> - cur->bc_ag.agno = agno;
> - if (pag) {
> - /* take a reference for the cursor */
> - atomic_inc(&pag->pag_ref);
> - }
> + /* take a reference for the cursor */
> + atomic_inc(&pag->pag_ref);
> cur->bc_ag.pag = pag;
> + cur->bc_ag.agno = pag->pag_agno;
> return cur;
> }
>
> @@ -466,14 +462,13 @@ xfs_inobt_init_cursor(
> struct xfs_mount *mp,
> struct xfs_trans *tp,
> struct xfs_buf *agbp,
> - xfs_agnumber_t agno,
> struct xfs_perag *pag,
> xfs_btnum_t btnum)
> {
> struct xfs_btree_cur *cur;
> struct xfs_agi *agi = agbp->b_addr;
>
> - cur = xfs_inobt_init_common(mp, tp, agno, pag, btnum);
> + cur = xfs_inobt_init_common(mp, tp, pag, btnum);
> if (btnum == XFS_BTNUM_INO)
> cur->bc_nlevels = be32_to_cpu(agi->agi_level);
> else
> @@ -487,12 +482,12 @@ struct xfs_btree_cur *
> xfs_inobt_stage_cursor(
> struct xfs_mount *mp,
> struct xbtree_afakeroot *afake,
> - xfs_agnumber_t agno,
> + struct xfs_perag *pag,
> xfs_btnum_t btnum)
> {
> struct xfs_btree_cur *cur;
>
> - cur = xfs_inobt_init_common(mp, NULL, agno, NULL, btnum);
> + cur = xfs_inobt_init_common(mp, NULL, pag, btnum);
> xfs_btree_stage_afakeroot(cur, afake);
> return cur;
> }
> @@ -664,7 +659,7 @@ int
> xfs_inobt_cur(
> struct xfs_mount *mp,
> struct xfs_trans *tp,
> - xfs_agnumber_t agno,
> + struct xfs_perag *pag,
> xfs_btnum_t which,
> struct xfs_btree_cur **curpp,
> struct xfs_buf **agi_bpp)
> @@ -675,11 +670,11 @@ xfs_inobt_cur(
> ASSERT(*agi_bpp == NULL);
> ASSERT(*curpp == NULL);
>
> - error = xfs_ialloc_read_agi(mp, tp, agno, agi_bpp);
> + error = xfs_ialloc_read_agi(mp, tp, pag->pag_agno, agi_bpp);
> if (error)
> return error;
>
> - cur = xfs_inobt_init_cursor(mp, tp, *agi_bpp, agno, NULL, which);
> + cur = xfs_inobt_init_cursor(mp, tp, *agi_bpp, pag, which);
> *curpp = cur;
> return 0;
> }
> @@ -696,7 +691,7 @@ xfs_inobt_count_blocks(
> struct xfs_btree_cur *cur = NULL;
> int error;
>
> - error = xfs_inobt_cur(mp, tp, pag->pag_agno, btnum, &cur, &agbp);
> + error = xfs_inobt_cur(mp, tp, pag, btnum, &cur, &agbp);
> if (error)
> return error;
>
> diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.h b/fs/xfs/libxfs/xfs_ialloc_btree.h
> index 04dfa7eee81f..e530c82b2217 100644
> --- a/fs/xfs/libxfs/xfs_ialloc_btree.h
> +++ b/fs/xfs/libxfs/xfs_ialloc_btree.h
> @@ -47,10 +47,10 @@ struct xfs_perag;
> ((index) - 1) * sizeof(xfs_inobt_ptr_t)))
>
> extern struct xfs_btree_cur *xfs_inobt_init_cursor(struct xfs_mount *mp,
> - struct xfs_trans *tp, struct xfs_buf *agbp, xfs_agnumber_t agno,
> + struct xfs_trans *tp, struct xfs_buf *agbp,
> struct xfs_perag *pag, xfs_btnum_t btnum);
> struct xfs_btree_cur *xfs_inobt_stage_cursor(struct xfs_mount *mp,
> - struct xbtree_afakeroot *afake, xfs_agnumber_t agno,
> + struct xbtree_afakeroot *afake, struct xfs_perag *pag,
> xfs_btnum_t btnum);
> extern int xfs_inobt_maxrecs(struct xfs_mount *, int, int);
>
> @@ -69,7 +69,7 @@ int xfs_finobt_calc_reserves(struct xfs_mount *mp, struct xfs_trans *tp,
> extern xfs_extlen_t xfs_iallocbt_calc_size(struct xfs_mount *mp,
> unsigned long long len);
> int xfs_inobt_cur(struct xfs_mount *mp, struct xfs_trans *tp,
> - xfs_agnumber_t agno, xfs_btnum_t btnum,
> + struct xfs_perag *pag, xfs_btnum_t btnum,
> struct xfs_btree_cur **curpp, struct xfs_buf **agi_bpp);
>
> void xfs_inobt_commit_staged_btree(struct xfs_btree_cur *cur,
> diff --git a/fs/xfs/scrub/agheader_repair.c b/fs/xfs/scrub/agheader_repair.c
> index ee2d85e3fd4a..ecc9146647ba 100644
> --- a/fs/xfs/scrub/agheader_repair.c
> +++ b/fs/xfs/scrub/agheader_repair.c
> @@ -806,7 +806,7 @@ xrep_agi_calc_from_btrees(
> xfs_agino_t freecount;
> int error;
>
> - cur = xfs_inobt_init_cursor(mp, sc->tp, agi_bp, sc->sa.agno,
> + cur = xfs_inobt_init_cursor(mp, sc->tp, agi_bp,
> sc->sa.pag, XFS_BTNUM_INO);
> error = xfs_ialloc_count_inodes(cur, &count, &freecount);
> if (error)
> @@ -828,7 +828,7 @@ xrep_agi_calc_from_btrees(
> xfs_sb_version_hasinobtcounts(&mp->m_sb)) {
> xfs_agblock_t blocks;
>
> - cur = xfs_inobt_init_cursor(mp, sc->tp, agi_bp, sc->sa.agno,
> + cur = xfs_inobt_init_cursor(mp, sc->tp, agi_bp,
> sc->sa.pag, XFS_BTNUM_FINO);
> error = xfs_btree_count_blocks(cur, &blocks);
> if (error)
> diff --git a/fs/xfs/scrub/common.c b/fs/xfs/scrub/common.c
> index 3035f8cee6f6..64c3b9b78d0d 100644
> --- a/fs/xfs/scrub/common.c
> +++ b/fs/xfs/scrub/common.c
> @@ -458,7 +458,6 @@ xchk_ag_btcur_init(
> struct xchk_ag *sa)
> {
> struct xfs_mount *mp = sc->mp;
> - xfs_agnumber_t agno = sa->agno;
>
> xchk_perag_get(sc->mp, sa);
> if (sa->agf_bp &&
> @@ -479,14 +478,14 @@ xchk_ag_btcur_init(
> if (sa->agi_bp &&
> xchk_ag_btree_healthy_enough(sc, sa->pag, XFS_BTNUM_INO)) {
> sa->ino_cur = xfs_inobt_init_cursor(mp, sc->tp, sa->agi_bp,
> - agno, sa->pag, XFS_BTNUM_INO);
> + sa->pag, XFS_BTNUM_INO);
> }
>
> /* Set up a finobt cursor for cross-referencing. */
> if (sa->agi_bp && xfs_sb_version_hasfinobt(&mp->m_sb) &&
> xchk_ag_btree_healthy_enough(sc, sa->pag, XFS_BTNUM_FINO)) {
> sa->fino_cur = xfs_inobt_init_cursor(mp, sc->tp, sa->agi_bp,
> - agno, sa->pag, XFS_BTNUM_FINO);
> + sa->pag, XFS_BTNUM_FINO);
> }
>
> /* Set up a rmapbt cursor for cross-referencing. */
> diff --git a/fs/xfs/xfs_iwalk.c b/fs/xfs/xfs_iwalk.c
> index c7e8f48a3ec4..917d51eefee3 100644
> --- a/fs/xfs/xfs_iwalk.c
> +++ b/fs/xfs/xfs_iwalk.c
> @@ -272,8 +272,7 @@ xfs_iwalk_ag_start(
>
> /* Set up a fresh cursor and empty the inobt cache. */
> iwag->nr_recs = 0;
> - error = xfs_inobt_cur(mp, tp, pag->pag_agno, XFS_BTNUM_INO,
> - curpp, agi_bpp);
> + error = xfs_inobt_cur(mp, tp, pag, XFS_BTNUM_INO, curpp, agi_bpp);
> if (error)
> return error;
>
> @@ -378,8 +377,7 @@ xfs_iwalk_run_callbacks(
> return 0;
>
> /* ...and recreate the cursor just past where we left off. */
> - error = xfs_inobt_cur(mp, tp, iwag->pag->pag_agno, XFS_BTNUM_INO,
> - curpp, agi_bpp);
> + error = xfs_inobt_cur(mp, tp, iwag->pag, XFS_BTNUM_INO, curpp, agi_bpp);
> if (error)
> return error;
>
> --
> 2.31.1
>