11946b91cSDarrick J. Wong /* 21946b91cSDarrick J. Wong * Copyright (C) 2016 Oracle. All Rights Reserved. 31946b91cSDarrick J. Wong * 41946b91cSDarrick J. Wong * Author: Darrick J. Wong <darrick.wong@oracle.com> 51946b91cSDarrick J. Wong * 61946b91cSDarrick J. Wong * This program is free software; you can redistribute it and/or 71946b91cSDarrick J. Wong * modify it under the terms of the GNU General Public License 81946b91cSDarrick J. Wong * as published by the Free Software Foundation; either version 2 91946b91cSDarrick J. Wong * of the License, or (at your option) any later version. 101946b91cSDarrick J. Wong * 111946b91cSDarrick J. Wong * This program is distributed in the hope that it would be useful, 121946b91cSDarrick J. Wong * but WITHOUT ANY WARRANTY; without even the implied warranty of 131946b91cSDarrick J. Wong * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 141946b91cSDarrick J. Wong * GNU General Public License for more details. 151946b91cSDarrick J. Wong * 161946b91cSDarrick J. Wong * You should have received a copy of the GNU General Public License 171946b91cSDarrick J. Wong * along with this program; if not, write the Free Software Foundation, 181946b91cSDarrick J. Wong * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. 191946b91cSDarrick J. Wong */ 201946b91cSDarrick J. Wong #include "xfs.h" 211946b91cSDarrick J. Wong #include "xfs_fs.h" 221946b91cSDarrick J. Wong #include "xfs_shared.h" 231946b91cSDarrick J. Wong #include "xfs_format.h" 241946b91cSDarrick J. Wong #include "xfs_log_format.h" 251946b91cSDarrick J. Wong #include "xfs_trans_resv.h" 261946b91cSDarrick J. Wong #include "xfs_sb.h" 271946b91cSDarrick J. Wong #include "xfs_mount.h" 281946b91cSDarrick J. Wong #include "xfs_btree.h" 291946b91cSDarrick J. Wong #include "xfs_bmap.h" 301946b91cSDarrick J. Wong #include "xfs_refcount_btree.h" 311946b91cSDarrick J. Wong #include "xfs_alloc.h" 321946b91cSDarrick J. Wong #include "xfs_error.h" 331946b91cSDarrick J. Wong #include "xfs_trace.h" 341946b91cSDarrick J. Wong #include "xfs_cksum.h" 351946b91cSDarrick J. Wong #include "xfs_trans.h" 361946b91cSDarrick J. Wong #include "xfs_bit.h" 37bdf28630SDarrick J. Wong #include "xfs_rmap.h" 381946b91cSDarrick J. Wong 391946b91cSDarrick J. Wong static struct xfs_btree_cur * 401946b91cSDarrick J. Wong xfs_refcountbt_dup_cursor( 411946b91cSDarrick J. Wong struct xfs_btree_cur *cur) 421946b91cSDarrick J. Wong { 431946b91cSDarrick J. Wong return xfs_refcountbt_init_cursor(cur->bc_mp, cur->bc_tp, 441946b91cSDarrick J. Wong cur->bc_private.a.agbp, cur->bc_private.a.agno, 451946b91cSDarrick J. Wong cur->bc_private.a.dfops); 461946b91cSDarrick J. Wong } 471946b91cSDarrick J. Wong 48bdf28630SDarrick J. Wong STATIC void 49bdf28630SDarrick J. Wong xfs_refcountbt_set_root( 50bdf28630SDarrick J. Wong struct xfs_btree_cur *cur, 51bdf28630SDarrick J. Wong union xfs_btree_ptr *ptr, 52bdf28630SDarrick J. Wong int inc) 53bdf28630SDarrick J. Wong { 54bdf28630SDarrick J. Wong struct xfs_buf *agbp = cur->bc_private.a.agbp; 55bdf28630SDarrick J. Wong struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); 56bdf28630SDarrick J. Wong xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); 57bdf28630SDarrick J. Wong struct xfs_perag *pag = xfs_perag_get(cur->bc_mp, seqno); 58bdf28630SDarrick J. Wong 59bdf28630SDarrick J. Wong ASSERT(ptr->s != 0); 60bdf28630SDarrick J. Wong 61bdf28630SDarrick J. Wong agf->agf_refcount_root = ptr->s; 62bdf28630SDarrick J. Wong be32_add_cpu(&agf->agf_refcount_level, inc); 63bdf28630SDarrick J. Wong pag->pagf_refcount_level += inc; 64bdf28630SDarrick J. Wong xfs_perag_put(pag); 65bdf28630SDarrick J. Wong 66bdf28630SDarrick J. Wong xfs_alloc_log_agf(cur->bc_tp, agbp, 67bdf28630SDarrick J. Wong XFS_AGF_REFCOUNT_ROOT | XFS_AGF_REFCOUNT_LEVEL); 68bdf28630SDarrick J. Wong } 69bdf28630SDarrick J. Wong 70bdf28630SDarrick J. Wong STATIC int 71bdf28630SDarrick J. Wong xfs_refcountbt_alloc_block( 72bdf28630SDarrick J. Wong struct xfs_btree_cur *cur, 73bdf28630SDarrick J. Wong union xfs_btree_ptr *start, 74bdf28630SDarrick J. Wong union xfs_btree_ptr *new, 75bdf28630SDarrick J. Wong int *stat) 76bdf28630SDarrick J. Wong { 77bdf28630SDarrick J. Wong struct xfs_buf *agbp = cur->bc_private.a.agbp; 78bdf28630SDarrick J. Wong struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); 79bdf28630SDarrick J. Wong struct xfs_alloc_arg args; /* block allocation args */ 80bdf28630SDarrick J. Wong int error; /* error return value */ 81bdf28630SDarrick J. Wong 8284d69619SDarrick J. Wong XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); 8384d69619SDarrick J. Wong 84bdf28630SDarrick J. Wong memset(&args, 0, sizeof(args)); 85bdf28630SDarrick J. Wong args.tp = cur->bc_tp; 86bdf28630SDarrick J. Wong args.mp = cur->bc_mp; 87bdf28630SDarrick J. Wong args.type = XFS_ALLOCTYPE_NEAR_BNO; 88bdf28630SDarrick J. Wong args.fsbno = XFS_AGB_TO_FSB(cur->bc_mp, cur->bc_private.a.agno, 89bdf28630SDarrick J. Wong xfs_refc_block(args.mp)); 90bdf28630SDarrick J. Wong args.firstblock = args.fsbno; 91bdf28630SDarrick J. Wong xfs_rmap_ag_owner(&args.oinfo, XFS_RMAP_OWN_REFC); 92bdf28630SDarrick J. Wong args.minlen = args.maxlen = args.prod = 1; 9384d69619SDarrick J. Wong args.resv = XFS_AG_RESV_METADATA; 94bdf28630SDarrick J. Wong 95bdf28630SDarrick J. Wong error = xfs_alloc_vextent(&args); 96bdf28630SDarrick J. Wong if (error) 97bdf28630SDarrick J. Wong goto out_error; 98bdf28630SDarrick J. Wong trace_xfs_refcountbt_alloc_block(cur->bc_mp, cur->bc_private.a.agno, 99bdf28630SDarrick J. Wong args.agbno, 1); 100bdf28630SDarrick J. Wong if (args.fsbno == NULLFSBLOCK) { 101bdf28630SDarrick J. Wong XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); 102bdf28630SDarrick J. Wong *stat = 0; 103bdf28630SDarrick J. Wong return 0; 104bdf28630SDarrick J. Wong } 105bdf28630SDarrick J. Wong ASSERT(args.agno == cur->bc_private.a.agno); 106bdf28630SDarrick J. Wong ASSERT(args.len == 1); 107bdf28630SDarrick J. Wong 108bdf28630SDarrick J. Wong new->s = cpu_to_be32(args.agbno); 109bdf28630SDarrick J. Wong be32_add_cpu(&agf->agf_refcount_blocks, 1); 110bdf28630SDarrick J. Wong xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_REFCOUNT_BLOCKS); 111bdf28630SDarrick J. Wong 112bdf28630SDarrick J. Wong XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); 113bdf28630SDarrick J. Wong *stat = 1; 114bdf28630SDarrick J. Wong return 0; 115bdf28630SDarrick J. Wong 116bdf28630SDarrick J. Wong out_error: 117bdf28630SDarrick J. Wong XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); 118bdf28630SDarrick J. Wong return error; 119bdf28630SDarrick J. Wong } 120bdf28630SDarrick J. Wong 121bdf28630SDarrick J. Wong STATIC int 122bdf28630SDarrick J. Wong xfs_refcountbt_free_block( 123bdf28630SDarrick J. Wong struct xfs_btree_cur *cur, 124bdf28630SDarrick J. Wong struct xfs_buf *bp) 125bdf28630SDarrick J. Wong { 126bdf28630SDarrick J. Wong struct xfs_mount *mp = cur->bc_mp; 127bdf28630SDarrick J. Wong struct xfs_buf *agbp = cur->bc_private.a.agbp; 128bdf28630SDarrick J. Wong struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); 129bdf28630SDarrick J. Wong xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp)); 130bdf28630SDarrick J. Wong struct xfs_owner_info oinfo; 13184d69619SDarrick J. Wong int error; 132bdf28630SDarrick J. Wong 133bdf28630SDarrick J. Wong trace_xfs_refcountbt_free_block(cur->bc_mp, cur->bc_private.a.agno, 134bdf28630SDarrick J. Wong XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno), 1); 135bdf28630SDarrick J. Wong xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_REFC); 136bdf28630SDarrick J. Wong be32_add_cpu(&agf->agf_refcount_blocks, -1); 137bdf28630SDarrick J. Wong xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_REFCOUNT_BLOCKS); 13884d69619SDarrick J. Wong error = xfs_free_extent(cur->bc_tp, fsbno, 1, &oinfo, 13984d69619SDarrick J. Wong XFS_AG_RESV_METADATA); 14084d69619SDarrick J. Wong if (error) 14184d69619SDarrick J. Wong return error; 142bdf28630SDarrick J. Wong 14384d69619SDarrick J. Wong return error; 144bdf28630SDarrick J. Wong } 145bdf28630SDarrick J. Wong 146bdf28630SDarrick J. Wong STATIC int 147bdf28630SDarrick J. Wong xfs_refcountbt_get_minrecs( 148bdf28630SDarrick J. Wong struct xfs_btree_cur *cur, 149bdf28630SDarrick J. Wong int level) 150bdf28630SDarrick J. Wong { 151bdf28630SDarrick J. Wong return cur->bc_mp->m_refc_mnr[level != 0]; 152bdf28630SDarrick J. Wong } 153bdf28630SDarrick J. Wong 154bdf28630SDarrick J. Wong STATIC int 155bdf28630SDarrick J. Wong xfs_refcountbt_get_maxrecs( 156bdf28630SDarrick J. Wong struct xfs_btree_cur *cur, 157bdf28630SDarrick J. Wong int level) 158bdf28630SDarrick J. Wong { 159bdf28630SDarrick J. Wong return cur->bc_mp->m_refc_mxr[level != 0]; 160bdf28630SDarrick J. Wong } 161bdf28630SDarrick J. Wong 162bdf28630SDarrick J. Wong STATIC void 163bdf28630SDarrick J. Wong xfs_refcountbt_init_key_from_rec( 164bdf28630SDarrick J. Wong union xfs_btree_key *key, 165bdf28630SDarrick J. Wong union xfs_btree_rec *rec) 166bdf28630SDarrick J. Wong { 167bdf28630SDarrick J. Wong key->refc.rc_startblock = rec->refc.rc_startblock; 168bdf28630SDarrick J. Wong } 169bdf28630SDarrick J. Wong 170bdf28630SDarrick J. Wong STATIC void 171bdf28630SDarrick J. Wong xfs_refcountbt_init_high_key_from_rec( 172bdf28630SDarrick J. Wong union xfs_btree_key *key, 173bdf28630SDarrick J. Wong union xfs_btree_rec *rec) 174bdf28630SDarrick J. Wong { 175bdf28630SDarrick J. Wong __u32 x; 176bdf28630SDarrick J. Wong 177bdf28630SDarrick J. Wong x = be32_to_cpu(rec->refc.rc_startblock); 178bdf28630SDarrick J. Wong x += be32_to_cpu(rec->refc.rc_blockcount) - 1; 179bdf28630SDarrick J. Wong key->refc.rc_startblock = cpu_to_be32(x); 180bdf28630SDarrick J. Wong } 181bdf28630SDarrick J. Wong 182bdf28630SDarrick J. Wong STATIC void 183bdf28630SDarrick J. Wong xfs_refcountbt_init_rec_from_cur( 184bdf28630SDarrick J. Wong struct xfs_btree_cur *cur, 185bdf28630SDarrick J. Wong union xfs_btree_rec *rec) 186bdf28630SDarrick J. Wong { 187bdf28630SDarrick J. Wong rec->refc.rc_startblock = cpu_to_be32(cur->bc_rec.rc.rc_startblock); 188bdf28630SDarrick J. Wong rec->refc.rc_blockcount = cpu_to_be32(cur->bc_rec.rc.rc_blockcount); 189bdf28630SDarrick J. Wong rec->refc.rc_refcount = cpu_to_be32(cur->bc_rec.rc.rc_refcount); 190bdf28630SDarrick J. Wong } 191bdf28630SDarrick J. Wong 192bdf28630SDarrick J. Wong STATIC void 193bdf28630SDarrick J. Wong xfs_refcountbt_init_ptr_from_cur( 194bdf28630SDarrick J. Wong struct xfs_btree_cur *cur, 195bdf28630SDarrick J. Wong union xfs_btree_ptr *ptr) 196bdf28630SDarrick J. Wong { 197bdf28630SDarrick J. Wong struct xfs_agf *agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); 198bdf28630SDarrick J. Wong 199bdf28630SDarrick J. Wong ASSERT(cur->bc_private.a.agno == be32_to_cpu(agf->agf_seqno)); 200bdf28630SDarrick J. Wong ASSERT(agf->agf_refcount_root != 0); 201bdf28630SDarrick J. Wong 202bdf28630SDarrick J. Wong ptr->s = agf->agf_refcount_root; 203bdf28630SDarrick J. Wong } 204bdf28630SDarrick J. Wong 205bdf28630SDarrick J. Wong STATIC __int64_t 206bdf28630SDarrick J. Wong xfs_refcountbt_key_diff( 207bdf28630SDarrick J. Wong struct xfs_btree_cur *cur, 208bdf28630SDarrick J. Wong union xfs_btree_key *key) 209bdf28630SDarrick J. Wong { 210bdf28630SDarrick J. Wong struct xfs_refcount_irec *rec = &cur->bc_rec.rc; 211bdf28630SDarrick J. Wong struct xfs_refcount_key *kp = &key->refc; 212bdf28630SDarrick J. Wong 213bdf28630SDarrick J. Wong return (__int64_t)be32_to_cpu(kp->rc_startblock) - rec->rc_startblock; 214bdf28630SDarrick J. Wong } 215bdf28630SDarrick J. Wong 216bdf28630SDarrick J. Wong STATIC __int64_t 217bdf28630SDarrick J. Wong xfs_refcountbt_diff_two_keys( 218bdf28630SDarrick J. Wong struct xfs_btree_cur *cur, 219bdf28630SDarrick J. Wong union xfs_btree_key *k1, 220bdf28630SDarrick J. Wong union xfs_btree_key *k2) 221bdf28630SDarrick J. Wong { 222bdf28630SDarrick J. Wong return (__int64_t)be32_to_cpu(k1->refc.rc_startblock) - 223bdf28630SDarrick J. Wong be32_to_cpu(k2->refc.rc_startblock); 224bdf28630SDarrick J. Wong } 225bdf28630SDarrick J. Wong 2261946b91cSDarrick J. Wong STATIC bool 2271946b91cSDarrick J. Wong xfs_refcountbt_verify( 2281946b91cSDarrick J. Wong struct xfs_buf *bp) 2291946b91cSDarrick J. Wong { 2301946b91cSDarrick J. Wong struct xfs_mount *mp = bp->b_target->bt_mount; 2311946b91cSDarrick J. Wong struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); 2321946b91cSDarrick J. Wong struct xfs_perag *pag = bp->b_pag; 2331946b91cSDarrick J. Wong unsigned int level; 2341946b91cSDarrick J. Wong 2351946b91cSDarrick J. Wong if (block->bb_magic != cpu_to_be32(XFS_REFC_CRC_MAGIC)) 2361946b91cSDarrick J. Wong return false; 2371946b91cSDarrick J. Wong 2381946b91cSDarrick J. Wong if (!xfs_sb_version_hasreflink(&mp->m_sb)) 2391946b91cSDarrick J. Wong return false; 2401946b91cSDarrick J. Wong if (!xfs_btree_sblock_v5hdr_verify(bp)) 2411946b91cSDarrick J. Wong return false; 2421946b91cSDarrick J. Wong 2431946b91cSDarrick J. Wong level = be16_to_cpu(block->bb_level); 2441946b91cSDarrick J. Wong if (pag && pag->pagf_init) { 2451946b91cSDarrick J. Wong if (level >= pag->pagf_refcount_level) 2461946b91cSDarrick J. Wong return false; 2471946b91cSDarrick J. Wong } else if (level >= mp->m_refc_maxlevels) 2481946b91cSDarrick J. Wong return false; 2491946b91cSDarrick J. Wong 2501946b91cSDarrick J. Wong return xfs_btree_sblock_verify(bp, mp->m_refc_mxr[level != 0]); 2511946b91cSDarrick J. Wong } 2521946b91cSDarrick J. Wong 2531946b91cSDarrick J. Wong STATIC void 2541946b91cSDarrick J. Wong xfs_refcountbt_read_verify( 2551946b91cSDarrick J. Wong struct xfs_buf *bp) 2561946b91cSDarrick J. Wong { 2571946b91cSDarrick J. Wong if (!xfs_btree_sblock_verify_crc(bp)) 2581946b91cSDarrick J. Wong xfs_buf_ioerror(bp, -EFSBADCRC); 2591946b91cSDarrick J. Wong else if (!xfs_refcountbt_verify(bp)) 2601946b91cSDarrick J. Wong xfs_buf_ioerror(bp, -EFSCORRUPTED); 2611946b91cSDarrick J. Wong 2621946b91cSDarrick J. Wong if (bp->b_error) { 2631946b91cSDarrick J. Wong trace_xfs_btree_corrupt(bp, _RET_IP_); 2641946b91cSDarrick J. Wong xfs_verifier_error(bp); 2651946b91cSDarrick J. Wong } 2661946b91cSDarrick J. Wong } 2671946b91cSDarrick J. Wong 2681946b91cSDarrick J. Wong STATIC void 2691946b91cSDarrick J. Wong xfs_refcountbt_write_verify( 2701946b91cSDarrick J. Wong struct xfs_buf *bp) 2711946b91cSDarrick J. Wong { 2721946b91cSDarrick J. Wong if (!xfs_refcountbt_verify(bp)) { 2731946b91cSDarrick J. Wong trace_xfs_btree_corrupt(bp, _RET_IP_); 2741946b91cSDarrick J. Wong xfs_buf_ioerror(bp, -EFSCORRUPTED); 2751946b91cSDarrick J. Wong xfs_verifier_error(bp); 2761946b91cSDarrick J. Wong return; 2771946b91cSDarrick J. Wong } 2781946b91cSDarrick J. Wong xfs_btree_sblock_calc_crc(bp); 2791946b91cSDarrick J. Wong 2801946b91cSDarrick J. Wong } 2811946b91cSDarrick J. Wong 2821946b91cSDarrick J. Wong const struct xfs_buf_ops xfs_refcountbt_buf_ops = { 2831946b91cSDarrick J. Wong .name = "xfs_refcountbt", 2841946b91cSDarrick J. Wong .verify_read = xfs_refcountbt_read_verify, 2851946b91cSDarrick J. Wong .verify_write = xfs_refcountbt_write_verify, 2861946b91cSDarrick J. Wong }; 2871946b91cSDarrick J. Wong 288bdf28630SDarrick J. Wong #if defined(DEBUG) || defined(XFS_WARN) 289bdf28630SDarrick J. Wong STATIC int 290bdf28630SDarrick J. Wong xfs_refcountbt_keys_inorder( 291bdf28630SDarrick J. Wong struct xfs_btree_cur *cur, 292bdf28630SDarrick J. Wong union xfs_btree_key *k1, 293bdf28630SDarrick J. Wong union xfs_btree_key *k2) 294bdf28630SDarrick J. Wong { 295bdf28630SDarrick J. Wong return be32_to_cpu(k1->refc.rc_startblock) < 296bdf28630SDarrick J. Wong be32_to_cpu(k2->refc.rc_startblock); 297bdf28630SDarrick J. Wong } 298bdf28630SDarrick J. Wong 299bdf28630SDarrick J. Wong STATIC int 300bdf28630SDarrick J. Wong xfs_refcountbt_recs_inorder( 301bdf28630SDarrick J. Wong struct xfs_btree_cur *cur, 302bdf28630SDarrick J. Wong union xfs_btree_rec *r1, 303bdf28630SDarrick J. Wong union xfs_btree_rec *r2) 304bdf28630SDarrick J. Wong { 305bdf28630SDarrick J. Wong return be32_to_cpu(r1->refc.rc_startblock) + 306bdf28630SDarrick J. Wong be32_to_cpu(r1->refc.rc_blockcount) <= 307bdf28630SDarrick J. Wong be32_to_cpu(r2->refc.rc_startblock); 308bdf28630SDarrick J. Wong } 309bdf28630SDarrick J. Wong #endif 310bdf28630SDarrick J. Wong 3111946b91cSDarrick J. Wong static const struct xfs_btree_ops xfs_refcountbt_ops = { 3121946b91cSDarrick J. Wong .rec_len = sizeof(struct xfs_refcount_rec), 3131946b91cSDarrick J. Wong .key_len = sizeof(struct xfs_refcount_key), 3141946b91cSDarrick J. Wong 3151946b91cSDarrick J. Wong .dup_cursor = xfs_refcountbt_dup_cursor, 316bdf28630SDarrick J. Wong .set_root = xfs_refcountbt_set_root, 317bdf28630SDarrick J. Wong .alloc_block = xfs_refcountbt_alloc_block, 318bdf28630SDarrick J. Wong .free_block = xfs_refcountbt_free_block, 319bdf28630SDarrick J. Wong .get_minrecs = xfs_refcountbt_get_minrecs, 320bdf28630SDarrick J. Wong .get_maxrecs = xfs_refcountbt_get_maxrecs, 321bdf28630SDarrick J. Wong .init_key_from_rec = xfs_refcountbt_init_key_from_rec, 322bdf28630SDarrick J. Wong .init_high_key_from_rec = xfs_refcountbt_init_high_key_from_rec, 323bdf28630SDarrick J. Wong .init_rec_from_cur = xfs_refcountbt_init_rec_from_cur, 324bdf28630SDarrick J. Wong .init_ptr_from_cur = xfs_refcountbt_init_ptr_from_cur, 325bdf28630SDarrick J. Wong .key_diff = xfs_refcountbt_key_diff, 3261946b91cSDarrick J. Wong .buf_ops = &xfs_refcountbt_buf_ops, 327bdf28630SDarrick J. Wong .diff_two_keys = xfs_refcountbt_diff_two_keys, 328bdf28630SDarrick J. Wong #if defined(DEBUG) || defined(XFS_WARN) 329bdf28630SDarrick J. Wong .keys_inorder = xfs_refcountbt_keys_inorder, 330bdf28630SDarrick J. Wong .recs_inorder = xfs_refcountbt_recs_inorder, 331bdf28630SDarrick J. Wong #endif 3321946b91cSDarrick J. Wong }; 3331946b91cSDarrick J. Wong 3341946b91cSDarrick J. Wong /* 3351946b91cSDarrick J. Wong * Allocate a new refcount btree cursor. 3361946b91cSDarrick J. Wong */ 3371946b91cSDarrick J. Wong struct xfs_btree_cur * 3381946b91cSDarrick J. Wong xfs_refcountbt_init_cursor( 3391946b91cSDarrick J. Wong struct xfs_mount *mp, 3401946b91cSDarrick J. Wong struct xfs_trans *tp, 3411946b91cSDarrick J. Wong struct xfs_buf *agbp, 3421946b91cSDarrick J. Wong xfs_agnumber_t agno, 3431946b91cSDarrick J. Wong struct xfs_defer_ops *dfops) 3441946b91cSDarrick J. Wong { 3451946b91cSDarrick J. Wong struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); 3461946b91cSDarrick J. Wong struct xfs_btree_cur *cur; 3471946b91cSDarrick J. Wong 3481946b91cSDarrick J. Wong ASSERT(agno != NULLAGNUMBER); 3491946b91cSDarrick J. Wong ASSERT(agno < mp->m_sb.sb_agcount); 3501946b91cSDarrick J. Wong cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_NOFS); 3511946b91cSDarrick J. Wong 3521946b91cSDarrick J. Wong cur->bc_tp = tp; 3531946b91cSDarrick J. Wong cur->bc_mp = mp; 3541946b91cSDarrick J. Wong cur->bc_btnum = XFS_BTNUM_REFC; 3551946b91cSDarrick J. Wong cur->bc_blocklog = mp->m_sb.sb_blocklog; 3561946b91cSDarrick J. Wong cur->bc_ops = &xfs_refcountbt_ops; 3571946b91cSDarrick J. Wong 3581946b91cSDarrick J. Wong cur->bc_nlevels = be32_to_cpu(agf->agf_refcount_level); 3591946b91cSDarrick J. Wong 3601946b91cSDarrick J. Wong cur->bc_private.a.agbp = agbp; 3611946b91cSDarrick J. Wong cur->bc_private.a.agno = agno; 3621946b91cSDarrick J. Wong cur->bc_private.a.dfops = dfops; 3631946b91cSDarrick J. Wong cur->bc_flags |= XFS_BTREE_CRC_BLOCKS; 3641946b91cSDarrick J. Wong 3651946b91cSDarrick J. Wong cur->bc_private.a.priv.refc.nr_ops = 0; 3661946b91cSDarrick J. Wong cur->bc_private.a.priv.refc.shape_changes = 0; 3671946b91cSDarrick J. Wong 3681946b91cSDarrick J. Wong return cur; 3691946b91cSDarrick J. Wong } 3701946b91cSDarrick J. Wong 3711946b91cSDarrick J. Wong /* 3721946b91cSDarrick J. Wong * Calculate the number of records in a refcount btree block. 3731946b91cSDarrick J. Wong */ 3741946b91cSDarrick J. Wong int 3751946b91cSDarrick J. Wong xfs_refcountbt_maxrecs( 3761946b91cSDarrick J. Wong struct xfs_mount *mp, 3771946b91cSDarrick J. Wong int blocklen, 3781946b91cSDarrick J. Wong bool leaf) 3791946b91cSDarrick J. Wong { 3801946b91cSDarrick J. Wong blocklen -= XFS_REFCOUNT_BLOCK_LEN; 3811946b91cSDarrick J. Wong 3821946b91cSDarrick J. Wong if (leaf) 3831946b91cSDarrick J. Wong return blocklen / sizeof(struct xfs_refcount_rec); 3841946b91cSDarrick J. Wong return blocklen / (sizeof(struct xfs_refcount_key) + 3851946b91cSDarrick J. Wong sizeof(xfs_refcount_ptr_t)); 3861946b91cSDarrick J. Wong } 3871946b91cSDarrick J. Wong 3881946b91cSDarrick J. Wong /* Compute the maximum height of a refcount btree. */ 3891946b91cSDarrick J. Wong void 3901946b91cSDarrick J. Wong xfs_refcountbt_compute_maxlevels( 3911946b91cSDarrick J. Wong struct xfs_mount *mp) 3921946b91cSDarrick J. Wong { 3931946b91cSDarrick J. Wong mp->m_refc_maxlevels = xfs_btree_compute_maxlevels(mp, 3941946b91cSDarrick J. Wong mp->m_refc_mnr, mp->m_sb.sb_agblocks); 3951946b91cSDarrick J. Wong } 39684d69619SDarrick J. Wong 39784d69619SDarrick J. Wong /* Calculate the refcount btree size for some records. */ 39884d69619SDarrick J. Wong xfs_extlen_t 39984d69619SDarrick J. Wong xfs_refcountbt_calc_size( 40084d69619SDarrick J. Wong struct xfs_mount *mp, 40184d69619SDarrick J. Wong unsigned long long len) 40284d69619SDarrick J. Wong { 40384d69619SDarrick J. Wong return xfs_btree_calc_size(mp, mp->m_refc_mnr, len); 40484d69619SDarrick J. Wong } 40584d69619SDarrick J. Wong 40684d69619SDarrick J. Wong /* 40784d69619SDarrick J. Wong * Calculate the maximum refcount btree size. 40884d69619SDarrick J. Wong */ 40984d69619SDarrick J. Wong xfs_extlen_t 41084d69619SDarrick J. Wong xfs_refcountbt_max_size( 41184d69619SDarrick J. Wong struct xfs_mount *mp) 41284d69619SDarrick J. Wong { 41384d69619SDarrick J. Wong /* Bail out if we're uninitialized, which can happen in mkfs. */ 41484d69619SDarrick J. Wong if (mp->m_refc_mxr[0] == 0) 41584d69619SDarrick J. Wong return 0; 41684d69619SDarrick J. Wong 41784d69619SDarrick J. Wong return xfs_refcountbt_calc_size(mp, mp->m_sb.sb_agblocks); 41884d69619SDarrick J. Wong } 41984d69619SDarrick J. Wong 42084d69619SDarrick J. Wong /* 42184d69619SDarrick J. Wong * Figure out how many blocks to reserve and how many are used by this btree. 42284d69619SDarrick J. Wong */ 42384d69619SDarrick J. Wong int 42484d69619SDarrick J. Wong xfs_refcountbt_calc_reserves( 42584d69619SDarrick J. Wong struct xfs_mount *mp, 42684d69619SDarrick J. Wong xfs_agnumber_t agno, 42784d69619SDarrick J. Wong xfs_extlen_t *ask, 42884d69619SDarrick J. Wong xfs_extlen_t *used) 42984d69619SDarrick J. Wong { 43084d69619SDarrick J. Wong struct xfs_buf *agbp; 43184d69619SDarrick J. Wong struct xfs_agf *agf; 43284d69619SDarrick J. Wong xfs_extlen_t tree_len; 43384d69619SDarrick J. Wong int error; 43484d69619SDarrick J. Wong 43584d69619SDarrick J. Wong if (!xfs_sb_version_hasreflink(&mp->m_sb)) 43684d69619SDarrick J. Wong return 0; 43784d69619SDarrick J. Wong 43884d69619SDarrick J. Wong *ask += xfs_refcountbt_max_size(mp); 43984d69619SDarrick J. Wong 44084d69619SDarrick J. Wong error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); 44184d69619SDarrick J. Wong if (error) 44284d69619SDarrick J. Wong return error; 44384d69619SDarrick J. Wong 44484d69619SDarrick J. Wong agf = XFS_BUF_TO_AGF(agbp); 44584d69619SDarrick J. Wong tree_len = be32_to_cpu(agf->agf_refcount_blocks); 44684d69619SDarrick J. Wong xfs_buf_relse(agbp); 44784d69619SDarrick J. Wong 44884d69619SDarrick J. Wong *used += tree_len; 44984d69619SDarrick J. Wong 45084d69619SDarrick J. Wong return error; 45184d69619SDarrick J. Wong } 452