atomic_t        pag_ref;        /* passive reference count */
        atomic_t        pag_active_ref; /* active reference count */
        wait_queue_head_t pag_active_wq;/* woken active_ref falls to zero */
-       char            pagf_init;      /* this agf's entry is initialized */
-       char            pagi_init;      /* this agi's entry is initialized */
-       char            pagf_metadata;  /* the agf is preferred to be metadata */
-       char            pagi_inodeok;   /* The agi is ok for inodes */
+       unsigned long   pag_opstate;
        uint8_t         pagf_levels[XFS_BTNUM_AGF];
                                        /* # of levels in bno & cnt btree */
-       bool            pagf_agflreset; /* agfl requires reset before use */
        uint32_t        pagf_flcount;   /* count of blocks in freelist */
        xfs_extlen_t    pagf_freeblks;  /* total free blocks */
        xfs_extlen_t    pagf_longest;   /* longest free space */
 #endif /* __KERNEL__ */
 };
 
+/*
+ * Per-AG operational state. These are atomic flag bits.
+ */
+#define XFS_AGSTATE_AGF_INIT           0
+#define XFS_AGSTATE_AGI_INIT           1
+#define XFS_AGSTATE_PREFERS_METADATA   2
+#define XFS_AGSTATE_ALLOWS_INODES      3
+#define XFS_AGSTATE_AGFL_NEEDS_RESET   4
+
+#define __XFS_AG_OPSTATE(name, NAME) \
+static inline bool xfs_perag_ ## name (struct xfs_perag *pag) \
+{ \
+       return test_bit(XFS_AGSTATE_ ## NAME, &pag->pag_opstate); \
+}
+
+__XFS_AG_OPSTATE(initialised_agf, AGF_INIT)
+__XFS_AG_OPSTATE(initialised_agi, AGI_INIT)
+__XFS_AG_OPSTATE(prefers_metadata, PREFERS_METADATA)
+__XFS_AG_OPSTATE(allows_inodes, ALLOWS_INODES)
+__XFS_AG_OPSTATE(agfl_needs_reset, AGFL_NEEDS_RESET)
+
 int xfs_initialize_perag(struct xfs_mount *mp, xfs_agnumber_t agcount,
                        xfs_rfsblock_t dcount, xfs_agnumber_t *maxagi);
 int xfs_initialize_perag_data(struct xfs_mount *mp, xfs_agnumber_t agno);
 
        struct xfs_mount        *mp = tp->t_mountp;
        struct xfs_agf          *agf = agbp->b_addr;
 
-       ASSERT(pag->pagf_agflreset);
+       ASSERT(xfs_perag_agfl_needs_reset(pag));
        trace_xfs_agfl_reset(mp, agf, 0, _RET_IP_);
 
        xfs_warn(mp,
                                    XFS_AGF_FLCOUNT);
 
        pag->pagf_flcount = 0;
-       pag->pagf_agflreset = false;
+       clear_bit(XFS_AGSTATE_AGFL_NEEDS_RESET, &pag->pag_opstate);
 }
 
 /*
        /* deferred ops (AGFL block frees) require permanent transactions */
        ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
 
-       if (!pag->pagf_init) {
+       if (!xfs_perag_initialised_agf(pag)) {
                error = xfs_alloc_read_agf(pag, tp, flags, &agbp);
                if (error) {
                        /* Couldn't lock the AGF so skip this AG. */
         * somewhere else if we are not being asked to try harder at this
         * point
         */
-       if (pag->pagf_metadata && (args->datatype & XFS_ALLOC_USERDATA) &&
+       if (xfs_perag_prefers_metadata(pag) &&
+           (args->datatype & XFS_ALLOC_USERDATA) &&
            (flags & XFS_ALLOC_FLAG_TRYLOCK)) {
                ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING));
                goto out_agbp_relse;
        }
 
        /* reset a padding mismatched agfl before final free space check */
-       if (pag->pagf_agflreset)
+       if (xfs_perag_agfl_needs_reset(pag))
                xfs_agfl_reset(tp, agbp, pag);
 
        /* If there isn't enough total space or single-extent, reject it. */
        if (be32_to_cpu(agf->agf_flfirst) == xfs_agfl_size(mp))
                agf->agf_flfirst = 0;
 
-       ASSERT(!pag->pagf_agflreset);
+       ASSERT(!xfs_perag_agfl_needs_reset(pag));
        be32_add_cpu(&agf->agf_flcount, -1);
        pag->pagf_flcount--;
 
        if (be32_to_cpu(agf->agf_fllast) == xfs_agfl_size(mp))
                agf->agf_fllast = 0;
 
-       ASSERT(!pag->pagf_agflreset);
+       ASSERT(!xfs_perag_agfl_needs_reset(pag));
        be32_add_cpu(&agf->agf_flcount, 1);
        pag->pagf_flcount++;
 
                return error;
 
        agf = agfbp->b_addr;
-       if (!pag->pagf_init) {
+       if (!xfs_perag_initialised_agf(pag)) {
                pag->pagf_freeblks = be32_to_cpu(agf->agf_freeblks);
                pag->pagf_btreeblks = be32_to_cpu(agf->agf_btreeblks);
                pag->pagf_flcount = be32_to_cpu(agf->agf_flcount);
                pag->pagf_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_init = 1;
-               pag->pagf_agflreset = xfs_agfl_needs_reset(pag->pag_mount, agf);
+               if (xfs_agfl_needs_reset(pag->pag_mount, agf))
+                       set_bit(XFS_AGSTATE_AGFL_NEEDS_RESET, &pag->pag_opstate);
 
                /*
                 * Update the in-core allocbt counter. Filter out the rmapbt
                if (allocbt_blks > 0)
                        atomic64_add(allocbt_blks,
                                        &pag->pag_mount->m_allocbt_blks);
+
+               set_bit(XFS_AGSTATE_AGF_INIT, &pag->pag_opstate);
        }
 #ifdef DEBUG
        else if (!xfs_is_shutdown(pag->pag_mount)) {
 
        level = be16_to_cpu(block->bb_level);
        if (bp->b_ops->magic[0] == cpu_to_be32(XFS_ABTC_MAGIC))
                btnum = XFS_BTNUM_CNTi;
-       if (pag && pag->pagf_init) {
+       if (pag && xfs_perag_initialised_agf(pag)) {
                if (level >= pag->pagf_levels[btnum])
                        return __this_address;
        } else if (level >= mp->m_alloc_maxlevels)
 
        int                     error = 0;
 
        pag = xfs_perag_get(mp, ag);
-       if (!pag->pagf_init) {
+       if (!xfs_perag_initialised_agf(pag)) {
                error = xfs_alloc_read_agf(pag, tp, XFS_ALLOC_FLAG_TRYLOCK,
                                NULL);
                if (error) {
 
        int                     i, j;
        int                     searchdistance = 10;
 
-       ASSERT(pag->pagi_init);
-       ASSERT(pag->pagi_inodeok);
+       ASSERT(xfs_perag_initialised_agi(pag));
+       ASSERT(xfs_perag_allows_inodes(pag));
        ASSERT(pag->pagi_freecount > 0);
 
  restart_pagno:
 
        if (!pag)
                return false;
-       if (!pag->pagi_inodeok)
+       if (!xfs_perag_allows_inodes(pag))
                return false;
 
-       if (!pag->pagi_init) {
+       if (!xfs_perag_initialised_agi(pag)) {
                error = xfs_ialloc_read_agi(pag, tp, NULL);
                if (error)
                        return false;
        if (!ok_alloc)
                return false;
 
-       if (!pag->pagf_init) {
+       if (!xfs_perag_initialised_agf(pag)) {
                error = xfs_alloc_read_agf(pag, tp, flags, NULL);
                if (error)
                        return false;
                return error;
 
        agi = agibp->b_addr;
-       if (!pag->pagi_init) {
+       if (!xfs_perag_initialised_agi(pag)) {
                pag->pagi_freecount = be32_to_cpu(agi->agi_freecount);
                pag->pagi_count = be32_to_cpu(agi->agi_count);
-               pag->pagi_init = 1;
+               set_bit(XFS_AGSTATE_AGI_INIT, &pag->pag_opstate);
        }
 
        /*
 
         * Similarly, during log recovery we will have a perag structure
         * attached, but the agi information will not yet have been initialised
         * from the on disk AGI. We don't currently use any of this information,
-        * but beware of the landmine (i.e. need to check pag->pagi_init) if we
-        * ever do.
+        * but beware of the landmine (i.e. need to check
+        * xfs_perag_initialised_agi(pag)) if we ever do.
         */
        if (xfs_has_crc(mp)) {
                fa = xfs_btree_sblock_v5hdr_verify(bp);
 
                return fa;
 
        level = be16_to_cpu(block->bb_level);
-       if (pag && pag->pagf_init) {
+       if (pag && xfs_perag_initialised_agf(pag)) {
                if (level >= pag->pagf_refcount_level)
                        return __this_address;
        } else if (level >= mp->m_refc_maxlevels)
 
                return fa;
 
        level = be16_to_cpu(block->bb_level);
-       if (pag && pag->pagf_init) {
+       if (pag && xfs_perag_initialised_agf(pag)) {
                if (level >= pag->pagf_levels[XFS_BTNUM_RMAPi])
                        return __this_address;
        } else if (level >= mp->m_rmap_maxlevels)
 
        struct xfs_agf          *old_agf)
 {
        struct xfs_mount        *mp = sc->mp;
+       struct xfs_perag        *pag = sc->sa.pag;
        struct xfs_agf          *agf = agf_bp->b_addr;
 
        memcpy(old_agf, agf, sizeof(*old_agf));
        memset(agf, 0, BBTOB(agf_bp->b_length));
        agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC);
        agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION);
-       agf->agf_seqno = cpu_to_be32(sc->sa.pag->pag_agno);
-       agf->agf_length = cpu_to_be32(sc->sa.pag->block_count);
+       agf->agf_seqno = cpu_to_be32(pag->pag_agno);
+       agf->agf_length = cpu_to_be32(pag->block_count);
        agf->agf_flfirst = old_agf->agf_flfirst;
        agf->agf_fllast = old_agf->agf_fllast;
        agf->agf_flcount = old_agf->agf_flcount;
                uuid_copy(&agf->agf_uuid, &mp->m_sb.sb_meta_uuid);
 
        /* Mark the incore AGF data stale until we're done fixing things. */
-       ASSERT(sc->sa.pag->pagf_init);
-       sc->sa.pag->pagf_init = 0;
+       ASSERT(xfs_perag_initialised_agf(pag));
+       clear_bit(XFS_AGSTATE_AGF_INIT, &pag->pag_opstate);
 }
 
 /* Set btree root information in an AGF. */
        pag->pagf_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_init = 1;
+       set_bit(XFS_AGSTATE_AGF_INIT, &pag->pag_opstate);
 
        return 0;
 }
 
 out_revert:
        /* Mark the incore AGF state stale and revert the AGF. */
-       sc->sa.pag->pagf_init = 0;
+       clear_bit(XFS_AGSTATE_AGF_INIT, &sc->sa.pag->pag_opstate);
        memcpy(agf, &old_agf, sizeof(old_agf));
        return error;
 }
        xfs_force_summary_recalc(sc->mp);
 
        /* Update the AGF counters. */
-       if (sc->sa.pag->pagf_init)
+       if (xfs_perag_initialised_agf(sc->sa.pag))
                sc->sa.pag->pagf_flcount = flcount;
        agf->agf_flfirst = cpu_to_be32(0);
        agf->agf_flcount = cpu_to_be32(flcount);
        struct xfs_agi          *old_agi)
 {
        struct xfs_agi          *agi = agi_bp->b_addr;
+       struct xfs_perag        *pag = sc->sa.pag;
        struct xfs_mount        *mp = sc->mp;
 
        memcpy(old_agi, agi, sizeof(*old_agi));
        memset(agi, 0, BBTOB(agi_bp->b_length));
        agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC);
        agi->agi_versionnum = cpu_to_be32(XFS_AGI_VERSION);
-       agi->agi_seqno = cpu_to_be32(sc->sa.pag->pag_agno);
-       agi->agi_length = cpu_to_be32(sc->sa.pag->block_count);
+       agi->agi_seqno = cpu_to_be32(pag->pag_agno);
+       agi->agi_length = cpu_to_be32(pag->block_count);
        agi->agi_newino = cpu_to_be32(NULLAGINO);
        agi->agi_dirino = cpu_to_be32(NULLAGINO);
        if (xfs_has_crc(mp))
                        sizeof(agi->agi_unlinked));
 
        /* Mark the incore AGF data stale until we're done fixing things. */
-       ASSERT(sc->sa.pag->pagi_init);
-       sc->sa.pag->pagi_init = 0;
+       ASSERT(xfs_perag_initialised_agi(pag));
+       clear_bit(XFS_AGSTATE_AGI_INIT, &pag->pag_opstate);
 }
 
 /* Set btree root information in an AGI. */
        pag = sc->sa.pag;
        pag->pagi_count = be32_to_cpu(agi->agi_count);
        pag->pagi_freecount = be32_to_cpu(agi->agi_freecount);
-       pag->pagi_init = 1;
+       set_bit(XFS_AGSTATE_AGI_INIT, &pag->pag_opstate);
 
        return 0;
 }
 
 out_revert:
        /* Mark the incore AGI state stale and revert the AGI. */
-       sc->sa.pag->pagi_init = 0;
+       clear_bit(XFS_AGSTATE_AGI_INIT, &sc->sa.pag->pag_opstate);
        memcpy(agi, &old_agi, sizeof(old_agi));
        return error;
 }
 
        for_each_perag(mp, agno, pag) {
                if (xchk_should_terminate(sc, &error))
                        break;
-               if (pag->pagi_init && pag->pagf_init)
+               if (xfs_perag_initialised_agi(pag) &&
+                   xfs_perag_initialised_agf(pag))
                        continue;
 
                /* Lock both AG headers. */
                 * These are supposed to be initialized by the header read
                 * function.
                 */
-               if (!pag->pagi_init || !pag->pagf_init) {
+               if (!xfs_perag_initialised_agi(pag) ||
+                   !xfs_perag_initialised_agf(pag)) {
                        error = -EFSCORRUPTED;
                        break;
                }
                        break;
 
                /* This somehow got unset since the warmup? */
-               if (!pag->pagi_init || !pag->pagf_init) {
+               if (!xfs_perag_initialised_agi(pag) ||
+                   !xfs_perag_initialised_agf(pag)) {
                        error = -EFSCORRUPTED;
                        break;
                }
 
                return 0;
 
        pag = xfs_perag_get(mp, sm->sm_agno);
-       if (pag->pagi_init) {
+       if (xfs_perag_initialised_agi(pag)) {
                /* Use in-core icount if possible. */
                icount = pag->pagi_count;
        } else {
 
 
                pag = xfs_perag_get(mp, ag);
 
-               if (!pag->pagf_init) {
+               if (!xfs_perag_initialised_agf(pag)) {
                        err = xfs_alloc_read_agf(pag, NULL, trylock, NULL);
                        if (err) {
                                if (err != -EAGAIN) {
                                xfs_ag_resv_needed(pag, XFS_AG_RESV_NONE));
                if (((minlen && longest >= minlen) ||
                     (!minlen && pag->pagf_freeblks >= minfree)) &&
-                   (!pag->pagf_metadata || !(flags & XFS_PICK_USERDATA) ||
+                   (!xfs_perag_prefers_metadata(pag) ||
+                    !(flags & XFS_PICK_USERDATA) ||
                     (flags & XFS_PICK_LOWSPACE))) {
 
                        /* Break out, retaining the reference on the AG. */
 
        return 0;
 }
 
+static bool
+xfs_set_inode_alloc_perag(
+       struct xfs_perag        *pag,
+       xfs_ino_t               ino,
+       xfs_agnumber_t          max_metadata)
+{
+       if (!xfs_is_inode32(pag->pag_mount)) {
+               set_bit(XFS_AGSTATE_ALLOWS_INODES, &pag->pag_opstate);
+               clear_bit(XFS_AGSTATE_PREFERS_METADATA, &pag->pag_opstate);
+               return false;
+       }
+
+       if (ino > XFS_MAXINUMBER_32) {
+               clear_bit(XFS_AGSTATE_ALLOWS_INODES, &pag->pag_opstate);
+               clear_bit(XFS_AGSTATE_PREFERS_METADATA, &pag->pag_opstate);
+               return false;
+       }
+
+       set_bit(XFS_AGSTATE_ALLOWS_INODES, &pag->pag_opstate);
+       if (pag->pag_agno < max_metadata)
+               set_bit(XFS_AGSTATE_PREFERS_METADATA, &pag->pag_opstate);
+       else
+               clear_bit(XFS_AGSTATE_PREFERS_METADATA, &pag->pag_opstate);
+       return true;
+}
+
 /*
  * Set parameters for inode allocation heuristics, taking into account
  * filesystem size and inode32/inode64 mount options; i.e. specifically
                ino = XFS_AGINO_TO_INO(mp, index, agino);
 
                pag = xfs_perag_get(mp, index);
-
-               if (xfs_is_inode32(mp)) {
-                       if (ino > XFS_MAXINUMBER_32) {
-                               pag->pagi_inodeok = 0;
-                               pag->pagf_metadata = 0;
-                       } else {
-                               pag->pagi_inodeok = 1;
-                               maxagi++;
-                               if (index < max_metadata)
-                                       pag->pagf_metadata = 1;
-                               else
-                                       pag->pagf_metadata = 0;
-                       }
-               } else {
-                       pag->pagi_inodeok = 1;
-                       pag->pagf_metadata = 0;
-               }
-
+               if (xfs_set_inode_alloc_perag(pag, ino, max_metadata))
+                       maxagi++;
                xfs_perag_put(pag);
        }