]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: add a perag to the btree cursor
authorDave Chinner <dchinner@redhat.com>
Fri, 15 Oct 2021 20:28:26 +0000 (16:28 -0400)
committerEric Sandeen <sandeen@sandeen.net>
Fri, 15 Oct 2021 20:28:26 +0000 (16:28 -0400)
Source kernel commit: be9fb17d88f08af648a89784d30dbac83d893154

Which will eventually completely replace the agno in it.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
17 files changed:
db/fsmap.c
db/info.c
libxfs/xfs_alloc.c
libxfs/xfs_alloc_btree.c
libxfs/xfs_alloc_btree.h
libxfs/xfs_btree.c
libxfs/xfs_btree.h
libxfs/xfs_ialloc.c
libxfs/xfs_ialloc_btree.c
libxfs/xfs_ialloc_btree.h
libxfs/xfs_refcount.c
libxfs/xfs_refcount_btree.c
libxfs/xfs_refcount_btree.h
libxfs/xfs_rmap.c
libxfs/xfs_rmap_btree.c
libxfs/xfs_rmap_btree.h
repair/rmap.c

index a6e61962df5f18a0519ab0a67a4b2cf3c5e59184..5973f0d611df77decc66175e44511dc63b55c29f 100644 (file)
@@ -41,12 +41,12 @@ fsmap(
        struct fsmap_info       info;
        xfs_agnumber_t          start_ag;
        xfs_agnumber_t          end_ag;
-       xfs_agnumber_t          agno;
        xfs_daddr_t             eofs;
        struct xfs_rmap_irec    low = {0};
        struct xfs_rmap_irec    high = {0};
        struct xfs_btree_cur    *bt_cur;
        struct xfs_buf          *agbp;
+       struct xfs_perag        *pag;
        int                     error;
 
        eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
@@ -63,29 +63,33 @@ fsmap(
        end_ag = XFS_FSB_TO_AGNO(mp, end_fsb);
 
        info.nr = 0;
-       for (agno = start_ag; agno <= end_ag; agno++) {
-               if (agno == end_ag)
+       for_each_perag_range(mp, start_ag, end_ag, pag) {
+               if (pag->pag_agno == end_ag)
                        high.rm_startblock = XFS_FSB_TO_AGBNO(mp, end_fsb);
 
-               error = -libxfs_alloc_read_agf(mp, NULL, agno, 0, &agbp);
+               error = -libxfs_alloc_read_agf(mp, NULL, pag->pag_agno, 0, &agbp);
                if (error) {
+                       libxfs_perag_put(pag);
                        dbprintf(_("Error %d while reading AGF.\n"), error);
                        return;
                }
 
-               bt_cur = libxfs_rmapbt_init_cursor(mp, NULL, agbp, agno);
+               bt_cur = libxfs_rmapbt_init_cursor(mp, NULL, agbp,
+                               pag->pag_agno, pag);
                if (!bt_cur) {
                        libxfs_buf_relse(agbp);
+                       libxfs_perag_put(pag);
                        dbprintf(_("Not enough memory.\n"));
                        return;
                }
 
-               info.agno = agno;
+               info.agno = pag->pag_agno;
                error = -libxfs_rmap_query_range(bt_cur, &low, &high,
                                fsmap_fn, &info);
                if (error) {
                        libxfs_btree_del_cursor(bt_cur, XFS_BTREE_ERROR);
                        libxfs_buf_relse(agbp);
+                       libxfs_perag_put(pag);
                        dbprintf(_("Error %d while querying fsmap btree.\n"),
                                error);
                        return;
@@ -94,7 +98,7 @@ fsmap(
                libxfs_btree_del_cursor(bt_cur, XFS_BTREE_NOERROR);
                libxfs_buf_relse(agbp);
 
-               if (agno == start_ag)
+               if (pag->pag_agno == start_ag)
                        low.rm_startblock = 0;
        }
 }
index 6c5c3e5b52fc55bf8b6c8a9afa6deb37b37d33e8..2ecaea647fd977fc8bfed5095c218799102ccfa3 100644 (file)
--- a/db/info.c
+++ b/db/info.c
@@ -66,7 +66,7 @@ print_agresv_info(
 {
        struct xfs_buf  *bp;
        struct xfs_agf  *agf;
-       struct xfs_perag *pag = xfs_perag_get(mp, agno);
+       struct xfs_perag *pag = libxfs_perag_get(mp, agno);
        xfs_extlen_t    ask = 0;
        xfs_extlen_t    used = 0;
        xfs_extlen_t    free = 0;
@@ -97,7 +97,7 @@ print_agresv_info(
        if (ask - used > free)
                printf(" <not enough space>");
        printf("\n");
-       xfs_perag_put(pag);
+       libxfs_perag_put(pag);
 }
 
 static int
index c69761eba684d6f4bb0945995c698ed5a26ce5e9..dfe0a9ce3f4a3c9ee7ede1362247e0ccc822331d 100644 (file)
@@ -772,7 +772,8 @@ xfs_alloc_cur_setup(
         */
        if (!acur->cnt)
                acur->cnt = xfs_allocbt_init_cursor(args->mp, args->tp,
-                                       args->agbp, args->agno, XFS_BTNUM_CNT);
+                                               args->agbp, args->agno,
+                                               args->pag, XFS_BTNUM_CNT);
        error = xfs_alloc_lookup_ge(acur->cnt, 0, args->maxlen, &i);
        if (error)
                return error;
@@ -782,10 +783,12 @@ xfs_alloc_cur_setup(
         */
        if (!acur->bnolt)
                acur->bnolt = xfs_allocbt_init_cursor(args->mp, args->tp,
-                                       args->agbp, args->agno, XFS_BTNUM_BNO);
+                                               args->agbp, args->agno,
+                                               args->pag, XFS_BTNUM_BNO);
        if (!acur->bnogt)
                acur->bnogt = xfs_allocbt_init_cursor(args->mp, args->tp,
-                                       args->agbp, args->agno, XFS_BTNUM_BNO);
+                                               args->agbp, args->agno,
+                                               args->pag, XFS_BTNUM_BNO);
        return i == 1 ? 0 : -ENOSPC;
 }
 
@@ -1213,7 +1216,7 @@ xfs_alloc_ag_vextent_exact(
         * Allocate/initialize a cursor for the by-number freespace btree.
         */
        bno_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp,
-                                         args->agno, XFS_BTNUM_BNO);
+                                         args->agno, args->pag, XFS_BTNUM_BNO);
 
        /*
         * Lookup bno and minlen in the btree (minlen is irrelevant, really).
@@ -1273,7 +1276,7 @@ xfs_alloc_ag_vextent_exact(
         * Allocate/initialize a cursor for the by-size btree.
         */
        cnt_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp,
-               args->agno, XFS_BTNUM_CNT);
+                                       args->agno, args->pag, XFS_BTNUM_CNT);
        ASSERT(args->agbno + args->len <= be32_to_cpu(agf->agf_length));
        error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen, args->agbno,
                                      args->len, XFSA_FIXUP_BNO_OK);
@@ -1670,7 +1673,7 @@ restart:
         * Allocate and initialize a cursor for the by-size btree.
         */
        cnt_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp,
-               args->agno, XFS_BTNUM_CNT);
+                                       args->agno, args->pag, XFS_BTNUM_CNT);
        bno_cur = NULL;
        busy = false;
 
@@ -1833,7 +1836,7 @@ restart:
         * Allocate and initialize a cursor for the by-block tree.
         */
        bno_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp,
-               args->agno, XFS_BTNUM_BNO);
+                                       args->agno, args->pag, XFS_BTNUM_BNO);
        if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen,
                        rbno, rlen, XFSA_FIXUP_CNT_OK)))
                goto error0;
@@ -1905,7 +1908,8 @@ xfs_free_ag_extent(
        /*
         * Allocate and initialize a cursor for the by-block btree.
         */
-       bno_cur = xfs_allocbt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_BNO);
+       bno_cur = xfs_allocbt_init_cursor(mp, tp, agbp, agno,
+                                       NULL, XFS_BTNUM_BNO);
        /*
         * Look for a neighboring block on the left (lower block numbers)
         * that is contiguous with this space.
@@ -1975,7 +1979,8 @@ xfs_free_ag_extent(
        /*
         * Now allocate and initialize a cursor for the by-size tree.
         */
-       cnt_cur = xfs_allocbt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_CNT);
+       cnt_cur = xfs_allocbt_init_cursor(mp, tp, agbp, agno,
+                                       NULL, XFS_BTNUM_CNT);
        /*
         * Have both left and right contiguous neighbors.
         * Merge all three into a single free block.
@@ -2486,7 +2491,7 @@ xfs_exact_minlen_extent_available(
        int                     error = 0;
 
        cnt_cur = xfs_allocbt_init_cursor(args->mp, args->tp, agbp,
-                       args->agno, XFS_BTNUM_CNT);
+                                       args->agno, args->pag, XFS_BTNUM_CNT);
        error = xfs_alloc_lookup_ge(cnt_cur, 0, args->minlen, stat);
        if (error)
                goto out;
index 00a17bb0ac084643e1f0aeaf0c9375bac691986d..d2f2a82e83928ce807b974f03aefc21750c57737 100644 (file)
@@ -25,7 +25,7 @@ xfs_allocbt_dup_cursor(
 {
        return xfs_allocbt_init_cursor(cur->bc_mp, cur->bc_tp,
                        cur->bc_ag.agbp, cur->bc_ag.agno,
-                       cur->bc_btnum);
+                       cur->bc_ag.pag, cur->bc_btnum);
 }
 
 STATIC void
@@ -471,6 +471,7 @@ xfs_allocbt_init_common(
        struct xfs_mount        *mp,
        struct xfs_trans        *tp,
        xfs_agnumber_t          agno,
+       struct xfs_perag        *pag,
        xfs_btnum_t             btnum)
 {
        struct xfs_btree_cur    *cur;
@@ -495,6 +496,11 @@ xfs_allocbt_init_common(
 
        cur->bc_ag.agno = agno;
        cur->bc_ag.abt.active = false;
+       if (pag) {
+               /* take a reference for the cursor */
+               atomic_inc(&pag->pag_ref);
+       }
+       cur->bc_ag.pag = pag;
 
        if (xfs_sb_version_hascrc(&mp->m_sb))
                cur->bc_flags |= XFS_BTREE_CRC_BLOCKS;
@@ -511,12 +517,13 @@ xfs_allocbt_init_cursor(
        struct xfs_trans        *tp,            /* transaction pointer */
        struct xfs_buf          *agbp,          /* buffer for agf structure */
        xfs_agnumber_t          agno,           /* allocation group number */
+       struct xfs_perag        *pag,
        xfs_btnum_t             btnum)          /* btree identifier */
 {
        struct xfs_agf          *agf = agbp->b_addr;
        struct xfs_btree_cur    *cur;
 
-       cur = xfs_allocbt_init_common(mp, tp, agno, btnum);
+       cur = xfs_allocbt_init_common(mp, tp, agno, pag, btnum);
        if (btnum == XFS_BTNUM_CNT)
                cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]);
        else
@@ -537,7 +544,7 @@ xfs_allocbt_stage_cursor(
 {
        struct xfs_btree_cur    *cur;
 
-       cur = xfs_allocbt_init_common(mp, NULL, agno, btnum);
+       cur = xfs_allocbt_init_common(mp, NULL, agno, NULL, btnum);
        xfs_btree_stage_afakeroot(cur, afake);
        return cur;
 }
index a5b998e950fe50f7af27bce8368d39dca1721744..a10cedba18d8934148a39b43a032936ea83c95e0 100644 (file)
@@ -13,6 +13,7 @@
 struct xfs_buf;
 struct xfs_btree_cur;
 struct xfs_mount;
+struct xfs_perag;
 struct xbtree_afakeroot;
 
 /*
@@ -48,7 +49,7 @@ struct xbtree_afakeroot;
 
 extern struct xfs_btree_cur *xfs_allocbt_init_cursor(struct xfs_mount *,
                struct xfs_trans *, struct xfs_buf *,
-               xfs_agnumber_t, xfs_btnum_t);
+               xfs_agnumber_t, struct xfs_perag *pag, xfs_btnum_t);
 struct xfs_btree_cur *xfs_allocbt_stage_cursor(struct xfs_mount *mp,
                struct xbtree_afakeroot *afake, xfs_agnumber_t agno,
                xfs_btnum_t btnum);
index 4faf4a67c38d2dae0b7cff21a0f4c22fb1649082..d9c5e8a320076c96c78fb741724d9b60cf6b6f66 100644 (file)
@@ -374,6 +374,8 @@ xfs_btree_del_cursor(
               XFS_FORCED_SHUTDOWN(cur->bc_mp));
        if (unlikely(cur->bc_flags & XFS_BTREE_STAGING))
                kmem_free(cur->bc_ops);
+       if (!(cur->bc_flags & XFS_BTREE_LONG_PTRS) && cur->bc_ag.pag)
+               xfs_perag_put(cur->bc_ag.pag);
        kmem_cache_free(xfs_btree_cur_zone, cur);
 }
 
index 10e50cbacacf5ddf5af7ceb2ad8429ac5028b8ae..e71f33f1f111855895e3d30cb06862d8472794ce 100644 (file)
@@ -11,6 +11,7 @@ struct xfs_inode;
 struct xfs_mount;
 struct xfs_trans;
 struct xfs_ifork;
+struct xfs_perag;
 
 extern kmem_zone_t     *xfs_btree_cur_zone;
 
@@ -180,11 +181,12 @@ union xfs_btree_irec {
 
 /* Per-AG btree information. */
 struct xfs_btree_cur_ag {
+       xfs_agnumber_t          agno;
+       struct xfs_perag        *pag;
        union {
                struct xfs_buf          *agbp;
                struct xbtree_afakeroot *afake; /* for staging cursor */
        };
-       xfs_agnumber_t          agno;
        union {
                struct {
                        unsigned long nr_ops;   /* # record updates */
@@ -231,6 +233,13 @@ typedef struct xfs_btree_cur
        uint8_t         bc_blocklog;    /* log2(blocksize) of btree blocks */
        xfs_btnum_t     bc_btnum;       /* identifies which btree type */
        int             bc_statoff;     /* offset of btre stats array */
+
+       /*
+        * Short btree pointers need an agno to be able to turn the pointers
+        * into physical addresses for IO, so the btree cursor switches between
+        * bc_ino and bc_ag based on whether XFS_BTREE_LONG_PTRS is set for the
+        * cursor.
+        */
        union {
                struct xfs_btree_cur_ag bc_ag;
                struct xfs_btree_cur_ino bc_ino;
index 745daafbce7065d39300cb14c5754498a464b30f..5d61be05a3c7738f6b6cb6e424c620db2a426447 100644 (file)
@@ -178,7 +178,7 @@ xfs_inobt_insert(
        int                     i;
        int                     error;
 
-       cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, btnum);
+       cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, NULL, btnum);
 
        for (thisino = newino;
             thisino < newino + newlen;
@@ -526,7 +526,7 @@ xfs_inobt_insert_sprec(
        int                             i;
        struct xfs_inobt_rec_incore     rec;
 
-       cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, btnum);
+       cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, NULL, 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);
@@ -1140,7 +1140,7 @@ xfs_dialloc_ag_inobt(
        ASSERT(pag->pagi_freecount > 0);
 
  restart_pagno:
-       cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_INO);
+       cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, NULL, XFS_BTNUM_INO);
        /*
         * If pagino is 0 (this is the root inode allocation) use newino.
         * This must work because we've just allocated some.
@@ -1593,7 +1593,7 @@ xfs_dialloc_ag(
        if (!pagino)
                pagino = be32_to_cpu(agi->agi_newino);
 
-       cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_FINO);
+       cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, NULL, XFS_BTNUM_FINO);
 
        error = xfs_check_agi_freecount(cur, agi);
        if (error)
@@ -1636,7 +1636,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, XFS_BTNUM_INO);
+       icur = xfs_inobt_init_cursor(mp, tp, agbp, agno, NULL, XFS_BTNUM_INO);
 
        error = xfs_check_agi_freecount(icur, agi);
        if (error)
@@ -1949,7 +1949,7 @@ xfs_difree_inobt(
        /*
         * Initialize the cursor.
         */
-       cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_INO);
+       cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, NULL, XFS_BTNUM_INO);
 
        error = xfs_check_agi_freecount(cur, agi);
        if (error)
@@ -2075,7 +2075,7 @@ xfs_difree_finobt(
        int                             error;
        int                             i;
 
-       cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_FINO);
+       cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, NULL, XFS_BTNUM_FINO);
 
        error = xfs_inobt_lookup(cur, ibtrec->ir_startino, XFS_LOOKUP_EQ, &i);
        if (error)
@@ -2276,7 +2276,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, XFS_BTNUM_INO);
+       cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, NULL, XFS_BTNUM_INO);
        error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &i);
        if (!error) {
                if (i)
index e93843e25a18b6dac6bd0a8990bff86deda35363..9b97145394dc05e6fb7b2621e40bce06fb9ae788 100644 (file)
@@ -35,7 +35,7 @@ xfs_inobt_dup_cursor(
 {
        return xfs_inobt_init_cursor(cur->bc_mp, cur->bc_tp,
                        cur->bc_ag.agbp, cur->bc_ag.agno,
-                       cur->bc_btnum);
+                       cur->bc_ag.pag, cur->bc_btnum);
 }
 
 STATIC void
@@ -428,6 +428,7 @@ 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 */
 {
        struct xfs_btree_cur    *cur;
@@ -450,6 +451,11 @@ xfs_inobt_init_common(
                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);
+       }
+       cur->bc_ag.pag = pag;
        return cur;
 }
 
@@ -460,12 +466,13 @@ xfs_inobt_init_cursor(
        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, btnum);
+       cur = xfs_inobt_init_common(mp, tp, agno, pag, btnum);
        if (btnum == XFS_BTNUM_INO)
                cur->bc_nlevels = be32_to_cpu(agi->agi_level);
        else
@@ -484,7 +491,7 @@ xfs_inobt_stage_cursor(
 {
        struct xfs_btree_cur    *cur;
 
-       cur = xfs_inobt_init_common(mp, NULL, agno, btnum);
+       cur = xfs_inobt_init_common(mp, NULL, agno, NULL, btnum);
        xfs_btree_stage_afakeroot(cur, afake);
        return cur;
 }
@@ -671,7 +678,7 @@ xfs_inobt_cur(
        if (error)
                return error;
 
-       cur = xfs_inobt_init_cursor(mp, tp, *agi_bpp, agno, which);
+       cur = xfs_inobt_init_cursor(mp, tp, *agi_bpp, agno, NULL, which);
        *curpp = cur;
        return 0;
 }
index d5afe01fb2deb5985b0f48bf69f21566b2507761..04dfa7eee81ff3000a4a143de681aa31600ddf93 100644 (file)
@@ -13,6 +13,7 @@
 struct xfs_buf;
 struct xfs_btree_cur;
 struct xfs_mount;
+struct xfs_perag;
 
 /*
  * Btree block header size depends on a superblock flag.
@@ -45,9 +46,9 @@ struct xfs_mount;
                 (maxrecs) * sizeof(xfs_inobt_key_t) + \
                 ((index) - 1) * sizeof(xfs_inobt_ptr_t)))
 
-extern struct xfs_btree_cur *xfs_inobt_init_cursor(struct xfs_mount *,
-               struct xfs_trans *, struct xfs_buf *, xfs_agnumber_t,
-               xfs_btnum_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_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,
                xfs_btnum_t btnum);
index 2097e0eae954f9366f127bfddf4b0a7f9dc30333..0516ae6dbad84efd42cf60c98deacef40a86c88a 100644 (file)
@@ -1177,7 +1177,7 @@ xfs_refcount_finish_one(
                if (error)
                        return error;
 
-               rcur = xfs_refcountbt_init_cursor(mp, tp, agbp, agno);
+               rcur = xfs_refcountbt_init_cursor(mp, tp, agbp, agno, NULL);
                rcur->bc_ag.refc.nr_ops = nr_ops;
                rcur->bc_ag.refc.shape_changes = shape_changes;
        }
@@ -1706,7 +1706,7 @@ xfs_refcount_recover_cow_leftovers(
        error = xfs_alloc_read_agf(mp, tp, agno, 0, &agbp);
        if (error)
                goto out_trans;
-       cur = xfs_refcountbt_init_cursor(mp, tp, agbp, agno);
+       cur = xfs_refcountbt_init_cursor(mp, tp, agbp, agno, NULL);
 
        /* Find all the leftover CoW staging extents. */
        memset(&low, 0, sizeof(low));
index e23ea313b5b118ecfcdd018555ae635a1c40a5f7..0851d357e0090a1ad0705e46a845113a697f8fb5 100644 (file)
@@ -25,7 +25,7 @@ xfs_refcountbt_dup_cursor(
        struct xfs_btree_cur    *cur)
 {
        return xfs_refcountbt_init_cursor(cur->bc_mp, cur->bc_tp,
-                       cur->bc_ag.agbp, cur->bc_ag.agno);
+                       cur->bc_ag.agbp, cur->bc_ag.agno, cur->bc_ag.pag);
 }
 
 STATIC void
@@ -315,7 +315,8 @@ static struct xfs_btree_cur *
 xfs_refcountbt_init_common(
        struct xfs_mount        *mp,
        struct xfs_trans        *tp,
-       xfs_agnumber_t          agno)
+       xfs_agnumber_t          agno,
+       struct xfs_perag        *pag)
 {
        struct xfs_btree_cur    *cur;
 
@@ -331,6 +332,11 @@ xfs_refcountbt_init_common(
 
        cur->bc_ag.agno = agno;
        cur->bc_flags |= XFS_BTREE_CRC_BLOCKS;
+       if (pag) {
+               /* take a reference for the cursor */
+               atomic_inc(&pag->pag_ref);
+       }
+       cur->bc_ag.pag = pag;
 
        cur->bc_ag.refc.nr_ops = 0;
        cur->bc_ag.refc.shape_changes = 0;
@@ -344,12 +350,13 @@ xfs_refcountbt_init_cursor(
        struct xfs_mount        *mp,
        struct xfs_trans        *tp,
        struct xfs_buf          *agbp,
-       xfs_agnumber_t          agno)
+       xfs_agnumber_t          agno,
+       struct xfs_perag        *pag)
 {
        struct xfs_agf          *agf = agbp->b_addr;
        struct xfs_btree_cur    *cur;
 
-       cur = xfs_refcountbt_init_common(mp, tp, agno);
+       cur = xfs_refcountbt_init_common(mp, tp, agno, pag);
        cur->bc_nlevels = be32_to_cpu(agf->agf_refcount_level);
        cur->bc_ag.agbp = agbp;
        return cur;
@@ -364,7 +371,7 @@ xfs_refcountbt_stage_cursor(
 {
        struct xfs_btree_cur    *cur;
 
-       cur = xfs_refcountbt_init_common(mp, NULL, agno);
+       cur = xfs_refcountbt_init_common(mp, NULL, agno, NULL);
        xfs_btree_stage_afakeroot(cur, afake);
        return cur;
 }
index eab1b0c672c00333a0f9f411bdb32701a6334b2a..8b82a39f104aa5104e983522f8246512798c72e8 100644 (file)
@@ -47,7 +47,7 @@ struct xbtree_afakeroot;
 
 extern struct xfs_btree_cur *xfs_refcountbt_init_cursor(struct xfs_mount *mp,
                struct xfs_trans *tp, struct xfs_buf *agbp,
-               xfs_agnumber_t agno);
+               xfs_agnumber_t agno, struct xfs_perag *pag);
 struct xfs_btree_cur *xfs_refcountbt_stage_cursor(struct xfs_mount *mp,
                struct xbtree_afakeroot *afake, xfs_agnumber_t agno);
 extern int xfs_refcountbt_maxrecs(int blocklen, bool leaf);
index 6323ccdc21f220cc247cfccf5ad5ca9f7c93c15d..e61de3b2ad803441d8c97ef83f841e802b71af97 100644 (file)
@@ -707,7 +707,7 @@ xfs_rmap_free(
        if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
                return 0;
 
-       cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
+       cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno, NULL);
 
        error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
 
@@ -961,7 +961,7 @@ xfs_rmap_alloc(
        if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
                return 0;
 
-       cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
+       cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno, NULL);
        error = xfs_rmap_map(cur, bno, len, false, oinfo);
 
        xfs_btree_del_cursor(cur, error);
@@ -2407,7 +2407,7 @@ xfs_rmap_finish_one(
                        goto out_drop;
                }
 
-               rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag->pag_agno);
+               rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag->pag_agno, pag);
        }
        *pcur = rcur;
 
index c8cac84f6b82b38af097b275527ada95fc890c9d..bed2f38159b700f99c1152f6abf7531ec164e88f 100644 (file)
@@ -50,7 +50,7 @@ xfs_rmapbt_dup_cursor(
        struct xfs_btree_cur    *cur)
 {
        return xfs_rmapbt_init_cursor(cur->bc_mp, cur->bc_tp,
-                       cur->bc_ag.agbp, cur->bc_ag.agno);
+                       cur->bc_ag.agbp, cur->bc_ag.agno, cur->bc_ag.pag);
 }
 
 STATIC void
@@ -447,7 +447,8 @@ static struct xfs_btree_cur *
 xfs_rmapbt_init_common(
        struct xfs_mount        *mp,
        struct xfs_trans        *tp,
-       xfs_agnumber_t          agno)
+       xfs_agnumber_t          agno,
+       struct xfs_perag        *pag)
 {
        struct xfs_btree_cur    *cur;
 
@@ -461,6 +462,11 @@ xfs_rmapbt_init_common(
        cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_rmap_2);
        cur->bc_ag.agno = agno;
        cur->bc_ops = &xfs_rmapbt_ops;
+       if (pag) {
+               /* take a reference for the cursor */
+               atomic_inc(&pag->pag_ref);
+       }
+       cur->bc_ag.pag = pag;
 
        return cur;
 }
@@ -471,12 +477,13 @@ xfs_rmapbt_init_cursor(
        struct xfs_mount        *mp,
        struct xfs_trans        *tp,
        struct xfs_buf          *agbp,
-       xfs_agnumber_t          agno)
+       xfs_agnumber_t          agno,
+       struct xfs_perag        *pag)
 {
        struct xfs_agf          *agf = agbp->b_addr;
        struct xfs_btree_cur    *cur;
 
-       cur = xfs_rmapbt_init_common(mp, tp, agno);
+       cur = xfs_rmapbt_init_common(mp, tp, agno, pag);
        cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]);
        cur->bc_ag.agbp = agbp;
        return cur;
@@ -491,7 +498,7 @@ xfs_rmapbt_stage_cursor(
 {
        struct xfs_btree_cur    *cur;
 
-       cur = xfs_rmapbt_init_common(mp, NULL, agno);
+       cur = xfs_rmapbt_init_common(mp, NULL, agno, NULL);
        xfs_btree_stage_afakeroot(cur, afake);
        return cur;
 }
index cef361a10aaf116072badad66a0f867824ce2e99..b036470a5446f0e79d3439c6d40e0bd6ba66f500 100644 (file)
@@ -43,7 +43,7 @@ struct xbtree_afakeroot;
 
 struct xfs_btree_cur *xfs_rmapbt_init_cursor(struct xfs_mount *mp,
                                struct xfs_trans *tp, struct xfs_buf *bp,
-                               xfs_agnumber_t agno);
+                               xfs_agnumber_t agno, struct xfs_perag *pag);
 struct xfs_btree_cur *xfs_rmapbt_stage_cursor(struct xfs_mount *mp,
                struct xbtree_afakeroot *afake, xfs_agnumber_t agno);
 void xfs_rmapbt_commit_staged_btree(struct xfs_btree_cur *cur,
index 54451a7e262d08bc5bbf08b543568b2d0292f1f7..2ffa27c8b09dfc6a9d93c72ce8e3cc0e039c8718 100644 (file)
@@ -976,14 +976,14 @@ rmaps_verify_btree(
        struct xfs_mount        *mp,
        xfs_agnumber_t          agno)
 {
+       struct xfs_rmap_irec    tmp;
        struct xfs_slab_cursor  *rm_cur;
        struct xfs_btree_cur    *bt_cur = NULL;
-       int                     error;
-       int                     have;
        struct xfs_buf          *agbp = NULL;
        struct xfs_rmap_irec    *rm_rec;
-       struct xfs_rmap_irec    tmp;
-       struct xfs_perag        *pag;           /* per allocation group data */
+       struct xfs_perag        *pag = NULL;
+       int                     have;
+       int                     error;
 
        if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
                return 0;
@@ -1005,9 +1005,8 @@ rmaps_verify_btree(
        /* Leave the per-ag data "uninitialized" since we rewrite it later */
        pag = libxfs_perag_get(mp, agno);
        pag->pagf_init = 0;
-       libxfs_perag_put(pag);
 
-       bt_cur = libxfs_rmapbt_init_cursor(mp, NULL, agbp, agno);
+       bt_cur = libxfs_rmapbt_init_cursor(mp, NULL, agbp, agno, pag);
        if (!bt_cur) {
                error = -ENOMEM;
                goto err;
@@ -1081,6 +1080,8 @@ next_loop:
 err:
        if (bt_cur)
                libxfs_btree_del_cursor(bt_cur, XFS_BTREE_NOERROR);
+       if (pag)
+               libxfs_perag_put(pag);
        if (agbp)
                libxfs_buf_relse(agbp);
        free_slab_cursor(&rm_cur);
@@ -1333,18 +1334,18 @@ refcount_avoid_check(void)
  */
 int
 check_refcounts(
-       struct xfs_mount        *mp,
-       xfs_agnumber_t          agno)
+       struct xfs_mount                *mp,
+       xfs_agnumber_t                  agno)
 {
-       struct xfs_slab_cursor  *rl_cur;
-       struct xfs_btree_cur    *bt_cur = NULL;
-       int                     error;
-       int                     have;
-       int                     i;
-       struct xfs_buf          *agbp = NULL;
-       struct xfs_refcount_irec        *rl_rec;
        struct xfs_refcount_irec        tmp;
-       struct xfs_perag        *pag;           /* per allocation group data */
+       struct xfs_slab_cursor          *rl_cur;
+       struct xfs_btree_cur            *bt_cur = NULL;
+       struct xfs_buf                  *agbp = NULL;
+       struct xfs_perag                *pag = NULL;
+       struct xfs_refcount_irec        *rl_rec;
+       int                             have;
+       int                             i;
+       int                             error;
 
        if (!xfs_sb_version_hasreflink(&mp->m_sb))
                return 0;
@@ -1366,9 +1367,8 @@ check_refcounts(
        /* Leave the per-ag data "uninitialized" since we rewrite it later */
        pag = libxfs_perag_get(mp, agno);
        pag->pagf_init = 0;
-       libxfs_perag_put(pag);
 
-       bt_cur = libxfs_refcountbt_init_cursor(mp, NULL, agbp, agno);
+       bt_cur = libxfs_refcountbt_init_cursor(mp, NULL, agbp, agno, pag);
        if (!bt_cur) {
                error = -ENOMEM;
                goto err;
@@ -1417,6 +1417,8 @@ err:
        if (bt_cur)
                libxfs_btree_del_cursor(bt_cur, error ? XFS_BTREE_ERROR :
                                                        XFS_BTREE_NOERROR);
+       if (pag)
+               libxfs_perag_put(pag);
        if (agbp)
                libxfs_buf_relse(agbp);
        free_slab_cursor(&rl_cur);