10b61f8a4SDave Chinner // SPDX-License-Identifier: GPL-2.0+ 21946b91cSDarrick J. Wong /* 31946b91cSDarrick J. Wong * Copyright (C) 2016 Oracle. All Rights Reserved. 41946b91cSDarrick J. Wong * Author: Darrick J. Wong <darrick.wong@oracle.com> 51946b91cSDarrick J. Wong */ 61946b91cSDarrick J. Wong #include "xfs.h" 71946b91cSDarrick J. Wong #include "xfs_fs.h" 81946b91cSDarrick J. Wong #include "xfs_shared.h" 91946b91cSDarrick J. Wong #include "xfs_format.h" 101946b91cSDarrick J. Wong #include "xfs_log_format.h" 111946b91cSDarrick J. Wong #include "xfs_trans_resv.h" 121946b91cSDarrick J. Wong #include "xfs_sb.h" 131946b91cSDarrick J. Wong #include "xfs_mount.h" 141946b91cSDarrick J. Wong #include "xfs_btree.h" 151946b91cSDarrick J. Wong #include "xfs_refcount_btree.h" 161946b91cSDarrick J. Wong #include "xfs_alloc.h" 171946b91cSDarrick J. Wong #include "xfs_error.h" 181946b91cSDarrick J. Wong #include "xfs_trace.h" 191946b91cSDarrick J. Wong #include "xfs_trans.h" 201946b91cSDarrick J. Wong #include "xfs_bit.h" 21bdf28630SDarrick J. Wong #include "xfs_rmap.h" 221946b91cSDarrick J. Wong 231946b91cSDarrick J. Wong static struct xfs_btree_cur * 241946b91cSDarrick J. Wong xfs_refcountbt_dup_cursor( 251946b91cSDarrick J. Wong struct xfs_btree_cur *cur) 261946b91cSDarrick J. Wong { 271946b91cSDarrick J. Wong return xfs_refcountbt_init_cursor(cur->bc_mp, cur->bc_tp, 28576af732SDave Chinner cur->bc_ag.agbp, cur->bc_ag.agno); 291946b91cSDarrick J. Wong } 301946b91cSDarrick J. Wong 31bdf28630SDarrick J. Wong STATIC void 32bdf28630SDarrick J. Wong xfs_refcountbt_set_root( 33bdf28630SDarrick J. Wong struct xfs_btree_cur *cur, 34bdf28630SDarrick J. Wong union xfs_btree_ptr *ptr, 35bdf28630SDarrick J. Wong int inc) 36bdf28630SDarrick J. Wong { 37576af732SDave Chinner struct xfs_buf *agbp = cur->bc_ag.agbp; 389798f615SChristoph Hellwig struct xfs_agf *agf = agbp->b_addr; 39bdf28630SDarrick J. Wong xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); 40bdf28630SDarrick J. Wong struct xfs_perag *pag = xfs_perag_get(cur->bc_mp, seqno); 41bdf28630SDarrick J. Wong 42bdf28630SDarrick J. Wong ASSERT(ptr->s != 0); 43bdf28630SDarrick J. Wong 44bdf28630SDarrick J. Wong agf->agf_refcount_root = ptr->s; 45bdf28630SDarrick J. Wong be32_add_cpu(&agf->agf_refcount_level, inc); 46bdf28630SDarrick J. Wong pag->pagf_refcount_level += inc; 47bdf28630SDarrick J. Wong xfs_perag_put(pag); 48bdf28630SDarrick J. Wong 49bdf28630SDarrick J. Wong xfs_alloc_log_agf(cur->bc_tp, agbp, 50bdf28630SDarrick J. Wong XFS_AGF_REFCOUNT_ROOT | XFS_AGF_REFCOUNT_LEVEL); 51bdf28630SDarrick J. Wong } 52bdf28630SDarrick J. Wong 53bdf28630SDarrick J. Wong STATIC int 54bdf28630SDarrick J. Wong xfs_refcountbt_alloc_block( 55bdf28630SDarrick J. Wong struct xfs_btree_cur *cur, 56bdf28630SDarrick J. Wong union xfs_btree_ptr *start, 57bdf28630SDarrick J. Wong union xfs_btree_ptr *new, 58bdf28630SDarrick J. Wong int *stat) 59bdf28630SDarrick J. Wong { 60576af732SDave Chinner struct xfs_buf *agbp = cur->bc_ag.agbp; 619798f615SChristoph Hellwig struct xfs_agf *agf = agbp->b_addr; 62bdf28630SDarrick J. Wong struct xfs_alloc_arg args; /* block allocation args */ 63bdf28630SDarrick J. Wong int error; /* error return value */ 64bdf28630SDarrick J. Wong 65bdf28630SDarrick J. Wong memset(&args, 0, sizeof(args)); 66bdf28630SDarrick J. Wong args.tp = cur->bc_tp; 67bdf28630SDarrick J. Wong args.mp = cur->bc_mp; 68bdf28630SDarrick J. Wong args.type = XFS_ALLOCTYPE_NEAR_BNO; 69576af732SDave Chinner args.fsbno = XFS_AGB_TO_FSB(cur->bc_mp, cur->bc_ag.agno, 70bdf28630SDarrick J. Wong xfs_refc_block(args.mp)); 717280fedaSDarrick J. Wong args.oinfo = XFS_RMAP_OINFO_REFC; 72bdf28630SDarrick J. Wong args.minlen = args.maxlen = args.prod = 1; 7384d69619SDarrick J. Wong args.resv = XFS_AG_RESV_METADATA; 74bdf28630SDarrick J. Wong 75bdf28630SDarrick J. Wong error = xfs_alloc_vextent(&args); 76bdf28630SDarrick J. Wong if (error) 77bdf28630SDarrick J. Wong goto out_error; 78576af732SDave Chinner trace_xfs_refcountbt_alloc_block(cur->bc_mp, cur->bc_ag.agno, 79bdf28630SDarrick J. Wong args.agbno, 1); 80bdf28630SDarrick J. Wong if (args.fsbno == NULLFSBLOCK) { 81bdf28630SDarrick J. Wong *stat = 0; 82bdf28630SDarrick J. Wong return 0; 83bdf28630SDarrick J. Wong } 84576af732SDave Chinner ASSERT(args.agno == cur->bc_ag.agno); 85bdf28630SDarrick J. Wong ASSERT(args.len == 1); 86bdf28630SDarrick J. Wong 87bdf28630SDarrick J. Wong new->s = cpu_to_be32(args.agbno); 88bdf28630SDarrick J. Wong be32_add_cpu(&agf->agf_refcount_blocks, 1); 89bdf28630SDarrick J. Wong xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_REFCOUNT_BLOCKS); 90bdf28630SDarrick J. Wong 91bdf28630SDarrick J. Wong *stat = 1; 92bdf28630SDarrick J. Wong return 0; 93bdf28630SDarrick J. Wong 94bdf28630SDarrick J. Wong out_error: 95bdf28630SDarrick J. Wong return error; 96bdf28630SDarrick J. Wong } 97bdf28630SDarrick J. Wong 98bdf28630SDarrick J. Wong STATIC int 99bdf28630SDarrick J. Wong xfs_refcountbt_free_block( 100bdf28630SDarrick J. Wong struct xfs_btree_cur *cur, 101bdf28630SDarrick J. Wong struct xfs_buf *bp) 102bdf28630SDarrick J. Wong { 103bdf28630SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 104576af732SDave Chinner struct xfs_buf *agbp = cur->bc_ag.agbp; 1059798f615SChristoph Hellwig struct xfs_agf *agf = agbp->b_addr; 106bdf28630SDarrick J. Wong xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp)); 10784d69619SDarrick J. Wong int error; 108bdf28630SDarrick J. Wong 109576af732SDave Chinner trace_xfs_refcountbt_free_block(cur->bc_mp, cur->bc_ag.agno, 110bdf28630SDarrick J. Wong XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno), 1); 111bdf28630SDarrick J. Wong be32_add_cpu(&agf->agf_refcount_blocks, -1); 112bdf28630SDarrick J. Wong xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_REFCOUNT_BLOCKS); 1137280fedaSDarrick J. Wong error = xfs_free_extent(cur->bc_tp, fsbno, 1, &XFS_RMAP_OINFO_REFC, 11484d69619SDarrick J. Wong XFS_AG_RESV_METADATA); 11584d69619SDarrick J. Wong if (error) 11684d69619SDarrick J. Wong return error; 117bdf28630SDarrick J. Wong 11884d69619SDarrick J. Wong return error; 119bdf28630SDarrick J. Wong } 120bdf28630SDarrick J. Wong 121bdf28630SDarrick J. Wong STATIC int 122bdf28630SDarrick J. Wong xfs_refcountbt_get_minrecs( 123bdf28630SDarrick J. Wong struct xfs_btree_cur *cur, 124bdf28630SDarrick J. Wong int level) 125bdf28630SDarrick J. Wong { 126bdf28630SDarrick J. Wong return cur->bc_mp->m_refc_mnr[level != 0]; 127bdf28630SDarrick J. Wong } 128bdf28630SDarrick J. Wong 129bdf28630SDarrick J. Wong STATIC int 130bdf28630SDarrick J. Wong xfs_refcountbt_get_maxrecs( 131bdf28630SDarrick J. Wong struct xfs_btree_cur *cur, 132bdf28630SDarrick J. Wong int level) 133bdf28630SDarrick J. Wong { 134bdf28630SDarrick J. Wong return cur->bc_mp->m_refc_mxr[level != 0]; 135bdf28630SDarrick J. Wong } 136bdf28630SDarrick J. Wong 137bdf28630SDarrick J. Wong STATIC void 138bdf28630SDarrick J. Wong xfs_refcountbt_init_key_from_rec( 139bdf28630SDarrick J. Wong union xfs_btree_key *key, 140bdf28630SDarrick J. Wong union xfs_btree_rec *rec) 141bdf28630SDarrick J. Wong { 142bdf28630SDarrick J. Wong key->refc.rc_startblock = rec->refc.rc_startblock; 143bdf28630SDarrick J. Wong } 144bdf28630SDarrick J. Wong 145bdf28630SDarrick J. Wong STATIC void 146bdf28630SDarrick J. Wong xfs_refcountbt_init_high_key_from_rec( 147bdf28630SDarrick J. Wong union xfs_btree_key *key, 148bdf28630SDarrick J. Wong union xfs_btree_rec *rec) 149bdf28630SDarrick J. Wong { 150bdf28630SDarrick J. Wong __u32 x; 151bdf28630SDarrick J. Wong 152bdf28630SDarrick J. Wong x = be32_to_cpu(rec->refc.rc_startblock); 153bdf28630SDarrick J. Wong x += be32_to_cpu(rec->refc.rc_blockcount) - 1; 154bdf28630SDarrick J. Wong key->refc.rc_startblock = cpu_to_be32(x); 155bdf28630SDarrick J. Wong } 156bdf28630SDarrick J. Wong 157bdf28630SDarrick J. Wong STATIC void 158bdf28630SDarrick J. Wong xfs_refcountbt_init_rec_from_cur( 159bdf28630SDarrick J. Wong struct xfs_btree_cur *cur, 160bdf28630SDarrick J. Wong union xfs_btree_rec *rec) 161bdf28630SDarrick J. Wong { 162bdf28630SDarrick J. Wong rec->refc.rc_startblock = cpu_to_be32(cur->bc_rec.rc.rc_startblock); 163bdf28630SDarrick J. Wong rec->refc.rc_blockcount = cpu_to_be32(cur->bc_rec.rc.rc_blockcount); 164bdf28630SDarrick J. Wong rec->refc.rc_refcount = cpu_to_be32(cur->bc_rec.rc.rc_refcount); 165bdf28630SDarrick J. Wong } 166bdf28630SDarrick J. Wong 167bdf28630SDarrick J. Wong STATIC void 168bdf28630SDarrick J. Wong xfs_refcountbt_init_ptr_from_cur( 169bdf28630SDarrick J. Wong struct xfs_btree_cur *cur, 170bdf28630SDarrick J. Wong union xfs_btree_ptr *ptr) 171bdf28630SDarrick J. Wong { 172576af732SDave Chinner struct xfs_agf *agf = cur->bc_ag.agbp->b_addr; 173bdf28630SDarrick J. Wong 174576af732SDave Chinner ASSERT(cur->bc_ag.agno == be32_to_cpu(agf->agf_seqno)); 175bdf28630SDarrick J. Wong 176bdf28630SDarrick J. Wong ptr->s = agf->agf_refcount_root; 177bdf28630SDarrick J. Wong } 178bdf28630SDarrick J. Wong 179c8ce540dSDarrick J. Wong STATIC int64_t 180bdf28630SDarrick J. Wong xfs_refcountbt_key_diff( 181bdf28630SDarrick J. Wong struct xfs_btree_cur *cur, 182bdf28630SDarrick J. Wong union xfs_btree_key *key) 183bdf28630SDarrick J. Wong { 184bdf28630SDarrick J. Wong struct xfs_refcount_irec *rec = &cur->bc_rec.rc; 185bdf28630SDarrick J. Wong struct xfs_refcount_key *kp = &key->refc; 186bdf28630SDarrick J. Wong 187c8ce540dSDarrick J. Wong return (int64_t)be32_to_cpu(kp->rc_startblock) - rec->rc_startblock; 188bdf28630SDarrick J. Wong } 189bdf28630SDarrick J. Wong 190c8ce540dSDarrick J. Wong STATIC int64_t 191bdf28630SDarrick J. Wong xfs_refcountbt_diff_two_keys( 192bdf28630SDarrick J. Wong struct xfs_btree_cur *cur, 193bdf28630SDarrick J. Wong union xfs_btree_key *k1, 194bdf28630SDarrick J. Wong union xfs_btree_key *k2) 195bdf28630SDarrick J. Wong { 196c8ce540dSDarrick J. Wong return (int64_t)be32_to_cpu(k1->refc.rc_startblock) - 197bdf28630SDarrick J. Wong be32_to_cpu(k2->refc.rc_startblock); 198bdf28630SDarrick J. Wong } 199bdf28630SDarrick J. Wong 200a6a781a5SDarrick J. Wong STATIC xfs_failaddr_t 2011946b91cSDarrick J. Wong xfs_refcountbt_verify( 2021946b91cSDarrick J. Wong struct xfs_buf *bp) 2031946b91cSDarrick J. Wong { 204dbd329f1SChristoph Hellwig struct xfs_mount *mp = bp->b_mount; 2051946b91cSDarrick J. Wong struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); 2061946b91cSDarrick J. Wong struct xfs_perag *pag = bp->b_pag; 207a6a781a5SDarrick J. Wong xfs_failaddr_t fa; 2081946b91cSDarrick J. Wong unsigned int level; 2091946b91cSDarrick J. Wong 21039708c20SBrian Foster if (!xfs_verify_magic(bp, block->bb_magic)) 211a6a781a5SDarrick J. Wong return __this_address; 2121946b91cSDarrick J. Wong 2131946b91cSDarrick J. Wong if (!xfs_sb_version_hasreflink(&mp->m_sb)) 214a6a781a5SDarrick J. Wong return __this_address; 215a6a781a5SDarrick J. Wong fa = xfs_btree_sblock_v5hdr_verify(bp); 216a6a781a5SDarrick J. Wong if (fa) 217a6a781a5SDarrick J. Wong return fa; 2181946b91cSDarrick J. Wong 2191946b91cSDarrick J. Wong level = be16_to_cpu(block->bb_level); 2201946b91cSDarrick J. Wong if (pag && pag->pagf_init) { 2211946b91cSDarrick J. Wong if (level >= pag->pagf_refcount_level) 222a6a781a5SDarrick J. Wong return __this_address; 2231946b91cSDarrick J. Wong } else if (level >= mp->m_refc_maxlevels) 224a6a781a5SDarrick J. Wong return __this_address; 2251946b91cSDarrick J. Wong 2261946b91cSDarrick J. Wong return xfs_btree_sblock_verify(bp, mp->m_refc_mxr[level != 0]); 2271946b91cSDarrick J. Wong } 2281946b91cSDarrick J. Wong 2291946b91cSDarrick J. Wong STATIC void 2301946b91cSDarrick J. Wong xfs_refcountbt_read_verify( 2311946b91cSDarrick J. Wong struct xfs_buf *bp) 2321946b91cSDarrick J. Wong { 233bc1a09b8SDarrick J. Wong xfs_failaddr_t fa; 234bc1a09b8SDarrick J. Wong 2351946b91cSDarrick J. Wong if (!xfs_btree_sblock_verify_crc(bp)) 236bc1a09b8SDarrick J. Wong xfs_verifier_error(bp, -EFSBADCRC, __this_address); 237bc1a09b8SDarrick J. Wong else { 238bc1a09b8SDarrick J. Wong fa = xfs_refcountbt_verify(bp); 239bc1a09b8SDarrick J. Wong if (fa) 240bc1a09b8SDarrick J. Wong xfs_verifier_error(bp, -EFSCORRUPTED, fa); 241bc1a09b8SDarrick J. Wong } 2421946b91cSDarrick J. Wong 24331ca03c9SDarrick J. Wong if (bp->b_error) 2441946b91cSDarrick J. Wong trace_xfs_btree_corrupt(bp, _RET_IP_); 2451946b91cSDarrick J. Wong } 2461946b91cSDarrick J. Wong 2471946b91cSDarrick J. Wong STATIC void 2481946b91cSDarrick J. Wong xfs_refcountbt_write_verify( 2491946b91cSDarrick J. Wong struct xfs_buf *bp) 2501946b91cSDarrick J. Wong { 251bc1a09b8SDarrick J. Wong xfs_failaddr_t fa; 252bc1a09b8SDarrick J. Wong 253bc1a09b8SDarrick J. Wong fa = xfs_refcountbt_verify(bp); 254bc1a09b8SDarrick J. Wong if (fa) { 2551946b91cSDarrick J. Wong trace_xfs_btree_corrupt(bp, _RET_IP_); 256bc1a09b8SDarrick J. Wong xfs_verifier_error(bp, -EFSCORRUPTED, fa); 2571946b91cSDarrick J. Wong return; 2581946b91cSDarrick J. Wong } 2591946b91cSDarrick J. Wong xfs_btree_sblock_calc_crc(bp); 2601946b91cSDarrick J. Wong 2611946b91cSDarrick J. Wong } 2621946b91cSDarrick J. Wong 2631946b91cSDarrick J. Wong const struct xfs_buf_ops xfs_refcountbt_buf_ops = { 2641946b91cSDarrick J. Wong .name = "xfs_refcountbt", 26539708c20SBrian Foster .magic = { 0, cpu_to_be32(XFS_REFC_CRC_MAGIC) }, 2661946b91cSDarrick J. Wong .verify_read = xfs_refcountbt_read_verify, 2671946b91cSDarrick J. Wong .verify_write = xfs_refcountbt_write_verify, 268b5572597SDarrick J. Wong .verify_struct = xfs_refcountbt_verify, 2691946b91cSDarrick J. Wong }; 2701946b91cSDarrick J. Wong 271bdf28630SDarrick J. Wong STATIC int 272bdf28630SDarrick J. Wong xfs_refcountbt_keys_inorder( 273bdf28630SDarrick J. Wong struct xfs_btree_cur *cur, 274bdf28630SDarrick J. Wong union xfs_btree_key *k1, 275bdf28630SDarrick J. Wong union xfs_btree_key *k2) 276bdf28630SDarrick J. Wong { 277bdf28630SDarrick J. Wong return be32_to_cpu(k1->refc.rc_startblock) < 278bdf28630SDarrick J. Wong be32_to_cpu(k2->refc.rc_startblock); 279bdf28630SDarrick J. Wong } 280bdf28630SDarrick J. Wong 281bdf28630SDarrick J. Wong STATIC int 282bdf28630SDarrick J. Wong xfs_refcountbt_recs_inorder( 283bdf28630SDarrick J. Wong struct xfs_btree_cur *cur, 284bdf28630SDarrick J. Wong union xfs_btree_rec *r1, 285bdf28630SDarrick J. Wong union xfs_btree_rec *r2) 286bdf28630SDarrick J. Wong { 287bdf28630SDarrick J. Wong return be32_to_cpu(r1->refc.rc_startblock) + 288bdf28630SDarrick J. Wong be32_to_cpu(r1->refc.rc_blockcount) <= 289bdf28630SDarrick J. Wong be32_to_cpu(r2->refc.rc_startblock); 290bdf28630SDarrick J. Wong } 291bdf28630SDarrick J. Wong 2921946b91cSDarrick J. Wong static const struct xfs_btree_ops xfs_refcountbt_ops = { 2931946b91cSDarrick J. Wong .rec_len = sizeof(struct xfs_refcount_rec), 2941946b91cSDarrick J. Wong .key_len = sizeof(struct xfs_refcount_key), 2951946b91cSDarrick J. Wong 2961946b91cSDarrick J. Wong .dup_cursor = xfs_refcountbt_dup_cursor, 297bdf28630SDarrick J. Wong .set_root = xfs_refcountbt_set_root, 298bdf28630SDarrick J. Wong .alloc_block = xfs_refcountbt_alloc_block, 299bdf28630SDarrick J. Wong .free_block = xfs_refcountbt_free_block, 300bdf28630SDarrick J. Wong .get_minrecs = xfs_refcountbt_get_minrecs, 301bdf28630SDarrick J. Wong .get_maxrecs = xfs_refcountbt_get_maxrecs, 302bdf28630SDarrick J. Wong .init_key_from_rec = xfs_refcountbt_init_key_from_rec, 303bdf28630SDarrick J. Wong .init_high_key_from_rec = xfs_refcountbt_init_high_key_from_rec, 304bdf28630SDarrick J. Wong .init_rec_from_cur = xfs_refcountbt_init_rec_from_cur, 305bdf28630SDarrick J. Wong .init_ptr_from_cur = xfs_refcountbt_init_ptr_from_cur, 306bdf28630SDarrick J. Wong .key_diff = xfs_refcountbt_key_diff, 3071946b91cSDarrick J. Wong .buf_ops = &xfs_refcountbt_buf_ops, 308bdf28630SDarrick J. Wong .diff_two_keys = xfs_refcountbt_diff_two_keys, 309bdf28630SDarrick J. Wong .keys_inorder = xfs_refcountbt_keys_inorder, 310bdf28630SDarrick J. Wong .recs_inorder = xfs_refcountbt_recs_inorder, 3111946b91cSDarrick J. Wong }; 3121946b91cSDarrick J. Wong 3131946b91cSDarrick J. Wong /* 3141946b91cSDarrick J. Wong * Allocate a new refcount btree cursor. 3151946b91cSDarrick J. Wong */ 3161946b91cSDarrick J. Wong struct xfs_btree_cur * 3171946b91cSDarrick J. Wong xfs_refcountbt_init_cursor( 3181946b91cSDarrick J. Wong struct xfs_mount *mp, 3191946b91cSDarrick J. Wong struct xfs_trans *tp, 3201946b91cSDarrick J. Wong struct xfs_buf *agbp, 321ed7ef8e5SBrian Foster xfs_agnumber_t agno) 3221946b91cSDarrick J. Wong { 3239798f615SChristoph Hellwig struct xfs_agf *agf = agbp->b_addr; 3241946b91cSDarrick J. Wong struct xfs_btree_cur *cur; 3251946b91cSDarrick J. Wong 3261946b91cSDarrick J. Wong ASSERT(agno != NULLAGNUMBER); 3271946b91cSDarrick J. Wong ASSERT(agno < mp->m_sb.sb_agcount); 3281946b91cSDarrick J. Wong cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_NOFS); 3291946b91cSDarrick J. Wong 3301946b91cSDarrick J. Wong cur->bc_tp = tp; 3311946b91cSDarrick J. Wong cur->bc_mp = mp; 3321946b91cSDarrick J. Wong cur->bc_btnum = XFS_BTNUM_REFC; 3331946b91cSDarrick J. Wong cur->bc_blocklog = mp->m_sb.sb_blocklog; 3341946b91cSDarrick J. Wong cur->bc_ops = &xfs_refcountbt_ops; 33511ef38afSDave Chinner cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_refcbt_2); 3361946b91cSDarrick J. Wong 3371946b91cSDarrick J. Wong cur->bc_nlevels = be32_to_cpu(agf->agf_refcount_level); 3381946b91cSDarrick J. Wong 339576af732SDave Chinner cur->bc_ag.agbp = agbp; 340576af732SDave Chinner cur->bc_ag.agno = agno; 3411946b91cSDarrick J. Wong cur->bc_flags |= XFS_BTREE_CRC_BLOCKS; 3421946b91cSDarrick J. Wong 343576af732SDave Chinner cur->bc_ag.priv.refc.nr_ops = 0; 344576af732SDave Chinner cur->bc_ag.priv.refc.shape_changes = 0; 3451946b91cSDarrick J. Wong 3461946b91cSDarrick J. Wong return cur; 3471946b91cSDarrick J. Wong } 3481946b91cSDarrick J. Wong 3491946b91cSDarrick J. Wong /* 3501946b91cSDarrick J. Wong * Calculate the number of records in a refcount btree block. 3511946b91cSDarrick J. Wong */ 3521946b91cSDarrick J. Wong int 3531946b91cSDarrick J. Wong xfs_refcountbt_maxrecs( 3541946b91cSDarrick J. Wong int blocklen, 3551946b91cSDarrick J. Wong bool leaf) 3561946b91cSDarrick J. Wong { 3571946b91cSDarrick J. Wong blocklen -= XFS_REFCOUNT_BLOCK_LEN; 3581946b91cSDarrick J. Wong 3591946b91cSDarrick J. Wong if (leaf) 3601946b91cSDarrick J. Wong return blocklen / sizeof(struct xfs_refcount_rec); 3611946b91cSDarrick J. Wong return blocklen / (sizeof(struct xfs_refcount_key) + 3621946b91cSDarrick J. Wong sizeof(xfs_refcount_ptr_t)); 3631946b91cSDarrick J. Wong } 3641946b91cSDarrick J. Wong 3651946b91cSDarrick J. Wong /* Compute the maximum height of a refcount btree. */ 3661946b91cSDarrick J. Wong void 3671946b91cSDarrick J. Wong xfs_refcountbt_compute_maxlevels( 3681946b91cSDarrick J. Wong struct xfs_mount *mp) 3691946b91cSDarrick J. Wong { 370a1f69417SEric Sandeen mp->m_refc_maxlevels = xfs_btree_compute_maxlevels( 3711946b91cSDarrick J. Wong mp->m_refc_mnr, mp->m_sb.sb_agblocks); 3721946b91cSDarrick J. Wong } 37384d69619SDarrick J. Wong 37484d69619SDarrick J. Wong /* Calculate the refcount btree size for some records. */ 37584d69619SDarrick J. Wong xfs_extlen_t 37684d69619SDarrick J. Wong xfs_refcountbt_calc_size( 37784d69619SDarrick J. Wong struct xfs_mount *mp, 37884d69619SDarrick J. Wong unsigned long long len) 37984d69619SDarrick J. Wong { 380a1f69417SEric Sandeen return xfs_btree_calc_size(mp->m_refc_mnr, len); 38184d69619SDarrick J. Wong } 38284d69619SDarrick J. Wong 38384d69619SDarrick J. Wong /* 38484d69619SDarrick J. Wong * Calculate the maximum refcount btree size. 38584d69619SDarrick J. Wong */ 38684d69619SDarrick J. Wong xfs_extlen_t 38784d69619SDarrick J. Wong xfs_refcountbt_max_size( 38820e73b00SDarrick J. Wong struct xfs_mount *mp, 38920e73b00SDarrick J. Wong xfs_agblock_t agblocks) 39084d69619SDarrick J. Wong { 39184d69619SDarrick J. Wong /* Bail out if we're uninitialized, which can happen in mkfs. */ 39284d69619SDarrick J. Wong if (mp->m_refc_mxr[0] == 0) 39384d69619SDarrick J. Wong return 0; 39484d69619SDarrick J. Wong 39520e73b00SDarrick J. Wong return xfs_refcountbt_calc_size(mp, agblocks); 39684d69619SDarrick J. Wong } 39784d69619SDarrick J. Wong 39884d69619SDarrick J. Wong /* 39984d69619SDarrick J. Wong * Figure out how many blocks to reserve and how many are used by this btree. 40084d69619SDarrick J. Wong */ 40184d69619SDarrick J. Wong int 40284d69619SDarrick J. Wong xfs_refcountbt_calc_reserves( 40384d69619SDarrick J. Wong struct xfs_mount *mp, 404ebcbef3aSDarrick J. Wong struct xfs_trans *tp, 40584d69619SDarrick J. Wong xfs_agnumber_t agno, 40684d69619SDarrick J. Wong xfs_extlen_t *ask, 40784d69619SDarrick J. Wong xfs_extlen_t *used) 40884d69619SDarrick J. Wong { 40984d69619SDarrick J. Wong struct xfs_buf *agbp; 41084d69619SDarrick J. Wong struct xfs_agf *agf; 41120e73b00SDarrick J. Wong xfs_agblock_t agblocks; 41284d69619SDarrick J. Wong xfs_extlen_t tree_len; 41384d69619SDarrick J. Wong int error; 41484d69619SDarrick J. Wong 41584d69619SDarrick J. Wong if (!xfs_sb_version_hasreflink(&mp->m_sb)) 41684d69619SDarrick J. Wong return 0; 41784d69619SDarrick J. Wong 41884d69619SDarrick J. Wong 419ebcbef3aSDarrick J. Wong error = xfs_alloc_read_agf(mp, tp, agno, 0, &agbp); 42084d69619SDarrick J. Wong if (error) 42184d69619SDarrick J. Wong return error; 42284d69619SDarrick J. Wong 4239798f615SChristoph Hellwig agf = agbp->b_addr; 42420e73b00SDarrick J. Wong agblocks = be32_to_cpu(agf->agf_length); 42584d69619SDarrick J. Wong tree_len = be32_to_cpu(agf->agf_refcount_blocks); 426ebcbef3aSDarrick J. Wong xfs_trans_brelse(tp, agbp); 42784d69619SDarrick J. Wong 4285cd213b0SDarrick J. Wong /* 4295cd213b0SDarrick J. Wong * The log is permanently allocated, so the space it occupies will 4305cd213b0SDarrick J. Wong * never be available for the kinds of things that would require btree 4315cd213b0SDarrick J. Wong * expansion. We therefore can pretend the space isn't there. 4325cd213b0SDarrick J. Wong */ 4335cd213b0SDarrick J. Wong if (mp->m_sb.sb_logstart && 4345cd213b0SDarrick J. Wong XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart) == agno) 4355cd213b0SDarrick J. Wong agblocks -= mp->m_sb.sb_logblocks; 4365cd213b0SDarrick J. Wong 43720e73b00SDarrick J. Wong *ask += xfs_refcountbt_max_size(mp, agblocks); 43884d69619SDarrick J. Wong *used += tree_len; 43984d69619SDarrick J. Wong 44084d69619SDarrick J. Wong return error; 44184d69619SDarrick J. Wong } 442