int
 xfs_refcount_lookup_le(
        struct xfs_btree_cur    *cur,
+       enum xfs_refc_domain    domain,
        xfs_agblock_t           bno,
        int                     *stat)
 {
-       trace_xfs_refcount_lookup(cur->bc_mp, cur->bc_ag.pag->pag_agno, bno,
+       trace_xfs_refcount_lookup(cur->bc_mp, cur->bc_ag.pag->pag_agno,
+                       xfs_refcount_encode_startblock(bno, domain),
                        XFS_LOOKUP_LE);
        cur->bc_rec.rc.rc_startblock = bno;
        cur->bc_rec.rc.rc_blockcount = 0;
+       cur->bc_rec.rc.rc_domain = domain;
        return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat);
 }
 
 int
 xfs_refcount_lookup_ge(
        struct xfs_btree_cur    *cur,
+       enum xfs_refc_domain    domain,
        xfs_agblock_t           bno,
        int                     *stat)
 {
-       trace_xfs_refcount_lookup(cur->bc_mp, cur->bc_ag.pag->pag_agno, bno,
+       trace_xfs_refcount_lookup(cur->bc_mp, cur->bc_ag.pag->pag_agno,
+                       xfs_refcount_encode_startblock(bno, domain),
                        XFS_LOOKUP_GE);
        cur->bc_rec.rc.rc_startblock = bno;
        cur->bc_rec.rc.rc_blockcount = 0;
+       cur->bc_rec.rc.rc_domain = domain;
        return xfs_btree_lookup(cur, XFS_LOOKUP_GE, stat);
 }
 
 int
 xfs_refcount_lookup_eq(
        struct xfs_btree_cur    *cur,
+       enum xfs_refc_domain    domain,
        xfs_agblock_t           bno,
        int                     *stat)
 {
-       trace_xfs_refcount_lookup(cur->bc_mp, cur->bc_ag.pag->pag_agno, bno,
+       trace_xfs_refcount_lookup(cur->bc_mp, cur->bc_ag.pag->pag_agno,
+                       xfs_refcount_encode_startblock(bno, domain),
                        XFS_LOOKUP_LE);
        cur->bc_rec.rc.rc_startblock = bno;
        cur->bc_rec.rc.rc_blockcount = 0;
+       cur->bc_rec.rc.rc_domain = domain;
        return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat);
 }
 
        const union xfs_btree_rec       *rec,
        struct xfs_refcount_irec        *irec)
 {
-       irec->rc_startblock = be32_to_cpu(rec->refc.rc_startblock);
+       uint32_t                        start;
+
+       start = be32_to_cpu(rec->refc.rc_startblock);
+       if (start & XFS_REFC_COW_START) {
+               start &= ~XFS_REFC_COW_START;
+               irec->rc_domain = XFS_REFC_DOMAIN_COW;
+       } else {
+               irec->rc_domain = XFS_REFC_DOMAIN_SHARED;
+       }
+
+       irec->rc_startblock = start;
        irec->rc_blockcount = be32_to_cpu(rec->refc.rc_blockcount);
        irec->rc_refcount = be32_to_cpu(rec->refc.rc_refcount);
 }
        struct xfs_perag                *pag = cur->bc_ag.pag;
        union xfs_btree_rec             *rec;
        int                             error;
-       xfs_agblock_t                   realstart;
 
        error = xfs_btree_get_rec(cur, &rec, stat);
        if (error || !*stat)
        if (irec->rc_blockcount == 0 || irec->rc_blockcount > MAXREFCEXTLEN)
                goto out_bad_rec;
 
-       /* handle special COW-staging state */
-       realstart = irec->rc_startblock;
-       if (realstart & XFS_REFC_COW_START) {
-               if (irec->rc_refcount != 1)
-                       goto out_bad_rec;
-               realstart &= ~XFS_REFC_COW_START;
-       } else if (irec->rc_refcount < 2) {
+       /* handle special COW-staging domain */
+       if (irec->rc_domain == XFS_REFC_DOMAIN_COW && irec->rc_refcount != 1)
+               goto out_bad_rec;
+       if (irec->rc_domain == XFS_REFC_DOMAIN_SHARED && irec->rc_refcount < 2)
                goto out_bad_rec;
-       }
 
        /* check for valid extent range, including overflow */
-       if (!xfs_verify_agbext(pag, realstart, irec->rc_blockcount))
+       if (!xfs_verify_agbext(pag, irec->rc_startblock, irec->rc_blockcount))
                goto out_bad_rec;
 
        if (irec->rc_refcount == 0 || irec->rc_refcount > MAXREFCOUNT)
        struct xfs_refcount_irec        *irec)
 {
        union xfs_btree_rec     rec;
+       uint32_t                start;
        int                     error;
 
        trace_xfs_refcount_update(cur->bc_mp, cur->bc_ag.pag->pag_agno, irec);
-       rec.refc.rc_startblock = cpu_to_be32(irec->rc_startblock);
+
+       start = xfs_refcount_encode_startblock(irec->rc_startblock,
+                       irec->rc_domain);
+       rec.refc.rc_startblock = cpu_to_be32(start);
        rec.refc.rc_blockcount = cpu_to_be32(irec->rc_blockcount);
        rec.refc.rc_refcount = cpu_to_be32(irec->rc_refcount);
+
        error = xfs_btree_update(cur, &rec);
        if (error)
                trace_xfs_refcount_update_error(cur->bc_mp,
        int                             error;
 
        trace_xfs_refcount_insert(cur->bc_mp, cur->bc_ag.pag->pag_agno, irec);
+
        cur->bc_rec.rc.rc_startblock = irec->rc_startblock;
        cur->bc_rec.rc.rc_blockcount = irec->rc_blockcount;
        cur->bc_rec.rc.rc_refcount = irec->rc_refcount;
+       cur->bc_rec.rc.rc_domain = irec->rc_domain;
+
        error = xfs_btree_insert(cur, i);
        if (error)
                goto out_error;
        }
        if (error)
                goto out_error;
-       error = xfs_refcount_lookup_ge(cur, irec.rc_startblock, &found_rec);
+       error = xfs_refcount_lookup_ge(cur, irec.rc_domain, irec.rc_startblock,
+                       &found_rec);
 out_error:
        if (error)
                trace_xfs_refcount_delete_error(cur->bc_mp,
 STATIC int
 xfs_refcount_split_extent(
        struct xfs_btree_cur            *cur,
+       enum xfs_refc_domain            domain,
        xfs_agblock_t                   agbno,
        bool                            *shape_changed)
 {
        int                             error;
 
        *shape_changed = false;
-       error = xfs_refcount_lookup_le(cur, agbno, &found_rec);
+       error = xfs_refcount_lookup_le(cur, domain, agbno, &found_rec);
        if (error)
                goto out_error;
        if (!found_rec)
         * call removes the center and the second one removes the right
         * extent.
         */
-       error = xfs_refcount_lookup_ge(cur, center->rc_startblock,
-                       &found_rec);
+       error = xfs_refcount_lookup_ge(cur, center->rc_domain,
+                       center->rc_startblock, &found_rec);
        if (error)
                goto out_error;
        if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
        }
 
        /* Enlarge the left extent. */
-       error = xfs_refcount_lookup_le(cur, left->rc_startblock,
-                       &found_rec);
+       error = xfs_refcount_lookup_le(cur, left->rc_domain,
+                       left->rc_startblock, &found_rec);
        if (error)
                goto out_error;
        if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
 
        /* If the extent at agbno (cleft) wasn't synthesized, remove it. */
        if (cleft->rc_refcount > 1) {
-               error = xfs_refcount_lookup_le(cur, cleft->rc_startblock,
-                               &found_rec);
+               error = xfs_refcount_lookup_le(cur, cleft->rc_domain,
+                               cleft->rc_startblock, &found_rec);
                if (error)
                        goto out_error;
                if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
        }
 
        /* Enlarge the left extent. */
-       error = xfs_refcount_lookup_le(cur, left->rc_startblock,
-                       &found_rec);
+       error = xfs_refcount_lookup_le(cur, left->rc_domain,
+                       left->rc_startblock, &found_rec);
        if (error)
                goto out_error;
        if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
         * remove it.
         */
        if (cright->rc_refcount > 1) {
-               error = xfs_refcount_lookup_le(cur, cright->rc_startblock,
-                       &found_rec);
+               error = xfs_refcount_lookup_le(cur, cright->rc_domain,
+                               cright->rc_startblock, &found_rec);
                if (error)
                        goto out_error;
                if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
        }
 
        /* Enlarge the right extent. */
-       error = xfs_refcount_lookup_le(cur, right->rc_startblock,
-                       &found_rec);
+       error = xfs_refcount_lookup_le(cur, right->rc_domain,
+                       right->rc_startblock, &found_rec);
        if (error)
                goto out_error;
        if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
        int                             flags)
 {
        struct xfs_refcount_irec        tmp;
+       enum xfs_refc_domain            domain;
        int                             error;
        int                             found_rec;
 
+       if (flags & XFS_FIND_RCEXT_SHARED)
+               domain = XFS_REFC_DOMAIN_SHARED;
+       else
+               domain = XFS_REFC_DOMAIN_COW;
+
        left->rc_startblock = cleft->rc_startblock = NULLAGBLOCK;
-       error = xfs_refcount_lookup_le(cur, agbno - 1, &found_rec);
+       error = xfs_refcount_lookup_le(cur, domain, agbno - 1, &found_rec);
        if (error)
                goto out_error;
        if (!found_rec)
                        cleft->rc_blockcount = min(aglen,
                                        tmp.rc_startblock - agbno);
                        cleft->rc_refcount = 1;
+                       cleft->rc_domain = domain;
                }
        } else {
                /*
                cleft->rc_startblock = agbno;
                cleft->rc_blockcount = aglen;
                cleft->rc_refcount = 1;
+               cleft->rc_domain = domain;
        }
        trace_xfs_refcount_find_left_extent(cur->bc_mp, cur->bc_ag.pag->pag_agno,
                        left, cleft, agbno);
        int                             flags)
 {
        struct xfs_refcount_irec        tmp;
+       enum xfs_refc_domain            domain;
        int                             error;
        int                             found_rec;
 
+       if (flags & XFS_FIND_RCEXT_SHARED)
+               domain = XFS_REFC_DOMAIN_SHARED;
+       else
+               domain = XFS_REFC_DOMAIN_COW;
+
        right->rc_startblock = cright->rc_startblock = NULLAGBLOCK;
-       error = xfs_refcount_lookup_ge(cur, agbno + aglen, &found_rec);
+       error = xfs_refcount_lookup_ge(cur, domain, agbno + aglen, &found_rec);
        if (error)
                goto out_error;
        if (!found_rec)
                        cright->rc_blockcount = right->rc_startblock -
                                        cright->rc_startblock;
                        cright->rc_refcount = 1;
+                       cright->rc_domain = domain;
                }
        } else {
                /*
                cright->rc_startblock = agbno;
                cright->rc_blockcount = aglen;
                cright->rc_refcount = 1;
+               cright->rc_domain = domain;
        }
        trace_xfs_refcount_find_right_extent(cur->bc_mp, cur->bc_ag.pag->pag_agno,
                        cright, right, agbno + aglen);
        if (*aglen == 0)
                return 0;
 
-       error = xfs_refcount_lookup_ge(cur, *agbno, &found_rec);
+       error = xfs_refcount_lookup_ge(cur, XFS_REFC_DOMAIN_SHARED, *agbno,
+                       &found_rec);
        if (error)
                goto out_error;
 
                        ext.rc_startblock = cur->bc_mp->m_sb.sb_agblocks;
                        ext.rc_blockcount = 0;
                        ext.rc_refcount = 0;
+                       ext.rc_domain = XFS_REFC_DOMAIN_SHARED;
                }
 
                /*
                        tmp.rc_blockcount = min(*aglen,
                                        ext.rc_startblock - *agbno);
                        tmp.rc_refcount = 1 + adj;
+                       tmp.rc_domain = XFS_REFC_DOMAIN_SHARED;
+
                        trace_xfs_refcount_modify_extent(cur->bc_mp,
                                        cur->bc_ag.pag->pag_agno, &tmp);
 
                                break;
 
                        /* Move the cursor to the start of ext. */
-                       error = xfs_refcount_lookup_ge(cur, *agbno,
+                       error = xfs_refcount_lookup_ge(cur,
+                                       XFS_REFC_DOMAIN_SHARED, *agbno,
                                        &found_rec);
                        if (error)
                                goto out_error;
        /*
         * Ensure that no rcextents cross the boundary of the adjustment range.
         */
-       error = xfs_refcount_split_extent(cur, agbno, &shape_changed);
+       error = xfs_refcount_split_extent(cur, XFS_REFC_DOMAIN_SHARED,
+                       agbno, &shape_changed);
        if (error)
                goto out_error;
        if (shape_changed)
                shape_changes++;
 
-       error = xfs_refcount_split_extent(cur, agbno + aglen, &shape_changed);
+       error = xfs_refcount_split_extent(cur, XFS_REFC_DOMAIN_SHARED,
+                       agbno + aglen, &shape_changed);
        if (error)
                goto out_error;
        if (shape_changed)
        *flen = 0;
 
        /* Try to find a refcount extent that crosses the start */
-       error = xfs_refcount_lookup_le(cur, agbno, &have);
+       error = xfs_refcount_lookup_le(cur, XFS_REFC_DOMAIN_SHARED, agbno,
+                       &have);
        if (error)
                goto out_error;
        if (!have) {
                return 0;
 
        /* Find any overlapping refcount records */
-       error = xfs_refcount_lookup_ge(cur, agbno, &found_rec);
+       error = xfs_refcount_lookup_ge(cur, XFS_REFC_DOMAIN_COW, agbno,
+                       &found_rec);
        if (error)
                goto out_error;
        error = xfs_refcount_get_rec(cur, &ext, &found_rec);
        if (error)
                goto out_error;
        if (!found_rec) {
-               ext.rc_startblock = cur->bc_mp->m_sb.sb_agblocks +
-                               XFS_REFC_COW_START;
+               ext.rc_startblock = cur->bc_mp->m_sb.sb_agblocks;
                ext.rc_blockcount = 0;
                ext.rc_refcount = 0;
+               ext.rc_domain = XFS_REFC_DOMAIN_COW;
        }
 
        switch (adj) {
                tmp.rc_startblock = agbno;
                tmp.rc_blockcount = aglen;
                tmp.rc_refcount = 1;
+               tmp.rc_domain = XFS_REFC_DOMAIN_COW;
+
                trace_xfs_refcount_modify_extent(cur->bc_mp,
                                cur->bc_ag.pag->pag_agno, &tmp);
 
        bool                    shape_changed;
        int                     error;
 
-       agbno += XFS_REFC_COW_START;
-
        /*
         * Ensure that no rcextents cross the boundary of the adjustment range.
         */
-       error = xfs_refcount_split_extent(cur, agbno, &shape_changed);
+       error = xfs_refcount_split_extent(cur, XFS_REFC_DOMAIN_COW,
+                       agbno, &shape_changed);
        if (error)
                goto out_error;
 
-       error = xfs_refcount_split_extent(cur, agbno + aglen, &shape_changed);
+       error = xfs_refcount_split_extent(cur, XFS_REFC_DOMAIN_COW,
+                       agbno + aglen, &shape_changed);
        if (error)
                goto out_error;
 
        union xfs_btree_irec            low;
        union xfs_btree_irec            high;
        xfs_fsblock_t                   fsb;
-       xfs_agblock_t                   agbno;
        int                             error;
 
        if (mp->m_sb.sb_agblocks >= XFS_REFC_COW_START)
        /* Find all the leftover CoW staging extents. */
        memset(&low, 0, sizeof(low));
        memset(&high, 0, sizeof(high));
-       low.rc.rc_startblock = XFS_REFC_COW_START;
+       low.rc.rc_domain = high.rc.rc_domain = XFS_REFC_DOMAIN_COW;
        high.rc.rc_startblock = -1U;
        error = xfs_btree_query_range(cur, &low, &high,
                        xfs_refcount_recover_extent, &debris);
                                &rr->rr_rrec);
 
                /* Free the orphan record */
-               agbno = rr->rr_rrec.rc_startblock - XFS_REFC_COW_START;
-               fsb = XFS_AGB_TO_FSB(mp, pag->pag_agno, agbno);
+               fsb = XFS_AGB_TO_FSB(mp, pag->pag_agno,
+                               rr->rr_rrec.rc_startblock);
                xfs_refcount_free_cow_extent(tp, fsb,
                                rr->rr_rrec.rc_blockcount);
 
 int
 xfs_refcount_has_record(
        struct xfs_btree_cur    *cur,
+       enum xfs_refc_domain    domain,
        xfs_agblock_t           bno,
        xfs_extlen_t            len,
        bool                    *exists)
        low.rc.rc_startblock = bno;
        memset(&high, 0xFF, sizeof(high));
        high.rc.rc_startblock = bno + len - 1;
+       low.rc.rc_domain = high.rc.rc_domain = domain;
 
        return xfs_btree_has_record(cur, &low, &high, exists);
 }