10b61f8a4SDave Chinner // SPDX-License-Identifier: GPL-2.0 230f712c9SDave Chinner /* 330f712c9SDave Chinner * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. 430f712c9SDave Chinner * All Rights Reserved. 530f712c9SDave Chinner */ 630f712c9SDave Chinner #include "xfs.h" 730f712c9SDave Chinner #include "xfs_fs.h" 830f712c9SDave Chinner #include "xfs_shared.h" 930f712c9SDave Chinner #include "xfs_format.h" 1030f712c9SDave Chinner #include "xfs_log_format.h" 1130f712c9SDave Chinner #include "xfs_trans_resv.h" 1230f712c9SDave Chinner #include "xfs_bit.h" 1330f712c9SDave Chinner #include "xfs_mount.h" 1430f712c9SDave Chinner #include "xfs_btree.h" 15c29ce8f4SDarrick J. Wong #include "xfs_btree_staging.h" 1630f712c9SDave Chinner #include "xfs_ialloc.h" 1730f712c9SDave Chinner #include "xfs_ialloc_btree.h" 1830f712c9SDave Chinner #include "xfs_alloc.h" 1930f712c9SDave Chinner #include "xfs_error.h" 2030f712c9SDave Chinner #include "xfs_trace.h" 2130f712c9SDave Chinner #include "xfs_trans.h" 22340785ccSDarrick J. Wong #include "xfs_rmap.h" 2330933120SDave Chinner #include "xfs_ag.h" 2430f712c9SDave Chinner 2530f712c9SDave Chinner STATIC int 2630f712c9SDave Chinner xfs_inobt_get_minrecs( 2730f712c9SDave Chinner struct xfs_btree_cur *cur, 2830f712c9SDave Chinner int level) 2930f712c9SDave Chinner { 30ef325959SDarrick J. Wong return M_IGEO(cur->bc_mp)->inobt_mnr[level != 0]; 3130f712c9SDave Chinner } 3230f712c9SDave Chinner 3330f712c9SDave Chinner STATIC struct xfs_btree_cur * 3430f712c9SDave Chinner xfs_inobt_dup_cursor( 3530f712c9SDave Chinner struct xfs_btree_cur *cur) 3630f712c9SDave Chinner { 3730f712c9SDave Chinner return xfs_inobt_init_cursor(cur->bc_mp, cur->bc_tp, 38576af732SDave Chinner cur->bc_ag.agbp, cur->bc_ag.agno, 39*be9fb17dSDave Chinner cur->bc_ag.pag, cur->bc_btnum); 4030f712c9SDave Chinner } 4130f712c9SDave Chinner 4230f712c9SDave Chinner STATIC void 4330f712c9SDave Chinner xfs_inobt_set_root( 4430f712c9SDave Chinner struct xfs_btree_cur *cur, 4530f712c9SDave Chinner union xfs_btree_ptr *nptr, 4630f712c9SDave Chinner int inc) /* level change */ 4730f712c9SDave Chinner { 48576af732SDave Chinner struct xfs_buf *agbp = cur->bc_ag.agbp; 49370c782bSChristoph Hellwig struct xfs_agi *agi = agbp->b_addr; 5030f712c9SDave Chinner 5130f712c9SDave Chinner agi->agi_root = nptr->s; 5230f712c9SDave Chinner be32_add_cpu(&agi->agi_level, inc); 5330f712c9SDave Chinner xfs_ialloc_log_agi(cur->bc_tp, agbp, XFS_AGI_ROOT | XFS_AGI_LEVEL); 5430f712c9SDave Chinner } 5530f712c9SDave Chinner 5630f712c9SDave Chinner STATIC void 5730f712c9SDave Chinner xfs_finobt_set_root( 5830f712c9SDave Chinner struct xfs_btree_cur *cur, 5930f712c9SDave Chinner union xfs_btree_ptr *nptr, 6030f712c9SDave Chinner int inc) /* level change */ 6130f712c9SDave Chinner { 62576af732SDave Chinner struct xfs_buf *agbp = cur->bc_ag.agbp; 63370c782bSChristoph Hellwig struct xfs_agi *agi = agbp->b_addr; 6430f712c9SDave Chinner 6530f712c9SDave Chinner agi->agi_free_root = nptr->s; 6630f712c9SDave Chinner be32_add_cpu(&agi->agi_free_level, inc); 6730f712c9SDave Chinner xfs_ialloc_log_agi(cur->bc_tp, agbp, 6830f712c9SDave Chinner XFS_AGI_FREE_ROOT | XFS_AGI_FREE_LEVEL); 6930f712c9SDave Chinner } 7030f712c9SDave Chinner 712a39946cSDarrick J. Wong /* Update the inode btree block counter for this btree. */ 722a39946cSDarrick J. Wong static inline void 732a39946cSDarrick J. Wong xfs_inobt_mod_blockcount( 742a39946cSDarrick J. Wong struct xfs_btree_cur *cur, 752a39946cSDarrick J. Wong int howmuch) 762a39946cSDarrick J. Wong { 772a39946cSDarrick J. Wong struct xfs_buf *agbp = cur->bc_ag.agbp; 782a39946cSDarrick J. Wong struct xfs_agi *agi = agbp->b_addr; 792a39946cSDarrick J. Wong 802a39946cSDarrick J. Wong if (!xfs_sb_version_hasinobtcounts(&cur->bc_mp->m_sb)) 812a39946cSDarrick J. Wong return; 822a39946cSDarrick J. Wong 832a39946cSDarrick J. Wong if (cur->bc_btnum == XFS_BTNUM_FINO) 842a39946cSDarrick J. Wong be32_add_cpu(&agi->agi_fblocks, howmuch); 852a39946cSDarrick J. Wong else if (cur->bc_btnum == XFS_BTNUM_INO) 862a39946cSDarrick J. Wong be32_add_cpu(&agi->agi_iblocks, howmuch); 872a39946cSDarrick J. Wong xfs_ialloc_log_agi(cur->bc_tp, agbp, XFS_AGI_IBLOCKS); 882a39946cSDarrick J. Wong } 892a39946cSDarrick J. Wong 9030f712c9SDave Chinner STATIC int 9176d771b4SChristoph Hellwig __xfs_inobt_alloc_block( 9230f712c9SDave Chinner struct xfs_btree_cur *cur, 9330f712c9SDave Chinner union xfs_btree_ptr *start, 9430f712c9SDave Chinner union xfs_btree_ptr *new, 9576d771b4SChristoph Hellwig int *stat, 9676d771b4SChristoph Hellwig enum xfs_ag_resv_type resv) 9730f712c9SDave Chinner { 9830f712c9SDave Chinner xfs_alloc_arg_t args; /* block allocation args */ 9930f712c9SDave Chinner int error; /* error return value */ 10030f712c9SDave Chinner xfs_agblock_t sbno = be32_to_cpu(start->s); 10130f712c9SDave Chinner 10230f712c9SDave Chinner memset(&args, 0, sizeof(args)); 10330f712c9SDave Chinner args.tp = cur->bc_tp; 10430f712c9SDave Chinner args.mp = cur->bc_mp; 1057280fedaSDarrick J. Wong args.oinfo = XFS_RMAP_OINFO_INOBT; 106576af732SDave Chinner args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_ag.agno, sbno); 10730f712c9SDave Chinner args.minlen = 1; 10830f712c9SDave Chinner args.maxlen = 1; 10930f712c9SDave Chinner args.prod = 1; 11030f712c9SDave Chinner args.type = XFS_ALLOCTYPE_NEAR_BNO; 11176d771b4SChristoph Hellwig args.resv = resv; 11230f712c9SDave Chinner 11330f712c9SDave Chinner error = xfs_alloc_vextent(&args); 114e157ebdcSCarlos Maiolino if (error) 11530f712c9SDave Chinner return error; 116e157ebdcSCarlos Maiolino 11730f712c9SDave Chinner if (args.fsbno == NULLFSBLOCK) { 11830f712c9SDave Chinner *stat = 0; 11930f712c9SDave Chinner return 0; 12030f712c9SDave Chinner } 12130f712c9SDave Chinner ASSERT(args.len == 1); 12230f712c9SDave Chinner 12330f712c9SDave Chinner new->s = cpu_to_be32(XFS_FSB_TO_AGBNO(args.mp, args.fsbno)); 12430f712c9SDave Chinner *stat = 1; 1252a39946cSDarrick J. Wong xfs_inobt_mod_blockcount(cur, 1); 12630f712c9SDave Chinner return 0; 12730f712c9SDave Chinner } 12830f712c9SDave Chinner 12930f712c9SDave Chinner STATIC int 13076d771b4SChristoph Hellwig xfs_inobt_alloc_block( 13176d771b4SChristoph Hellwig struct xfs_btree_cur *cur, 13276d771b4SChristoph Hellwig union xfs_btree_ptr *start, 13376d771b4SChristoph Hellwig union xfs_btree_ptr *new, 13476d771b4SChristoph Hellwig int *stat) 13576d771b4SChristoph Hellwig { 13676d771b4SChristoph Hellwig return __xfs_inobt_alloc_block(cur, start, new, stat, XFS_AG_RESV_NONE); 13776d771b4SChristoph Hellwig } 13876d771b4SChristoph Hellwig 13976d771b4SChristoph Hellwig STATIC int 14076d771b4SChristoph Hellwig xfs_finobt_alloc_block( 14176d771b4SChristoph Hellwig struct xfs_btree_cur *cur, 14276d771b4SChristoph Hellwig union xfs_btree_ptr *start, 14376d771b4SChristoph Hellwig union xfs_btree_ptr *new, 14476d771b4SChristoph Hellwig int *stat) 14576d771b4SChristoph Hellwig { 146e1f6ca11SDarrick J. Wong if (cur->bc_mp->m_finobt_nores) 147ad90bb58SBrian Foster return xfs_inobt_alloc_block(cur, start, new, stat); 14876d771b4SChristoph Hellwig return __xfs_inobt_alloc_block(cur, start, new, stat, 14976d771b4SChristoph Hellwig XFS_AG_RESV_METADATA); 15076d771b4SChristoph Hellwig } 15176d771b4SChristoph Hellwig 15276d771b4SChristoph Hellwig STATIC int 153ad90bb58SBrian Foster __xfs_inobt_free_block( 154ad90bb58SBrian Foster struct xfs_btree_cur *cur, 155ad90bb58SBrian Foster struct xfs_buf *bp, 156ad90bb58SBrian Foster enum xfs_ag_resv_type resv) 157ad90bb58SBrian Foster { 1582a39946cSDarrick J. Wong xfs_inobt_mod_blockcount(cur, -1); 159ad90bb58SBrian Foster return xfs_free_extent(cur->bc_tp, 160ad90bb58SBrian Foster XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(bp)), 1, 1617280fedaSDarrick J. Wong &XFS_RMAP_OINFO_INOBT, resv); 162ad90bb58SBrian Foster } 163ad90bb58SBrian Foster 164ad90bb58SBrian Foster STATIC int 16530f712c9SDave Chinner xfs_inobt_free_block( 16630f712c9SDave Chinner struct xfs_btree_cur *cur, 16730f712c9SDave Chinner struct xfs_buf *bp) 16830f712c9SDave Chinner { 169ad90bb58SBrian Foster return __xfs_inobt_free_block(cur, bp, XFS_AG_RESV_NONE); 170ad90bb58SBrian Foster } 171340785ccSDarrick J. Wong 172ad90bb58SBrian Foster STATIC int 173ad90bb58SBrian Foster xfs_finobt_free_block( 174ad90bb58SBrian Foster struct xfs_btree_cur *cur, 175ad90bb58SBrian Foster struct xfs_buf *bp) 176ad90bb58SBrian Foster { 177e1f6ca11SDarrick J. Wong if (cur->bc_mp->m_finobt_nores) 178ad90bb58SBrian Foster return xfs_inobt_free_block(cur, bp); 179ad90bb58SBrian Foster return __xfs_inobt_free_block(cur, bp, XFS_AG_RESV_METADATA); 18030f712c9SDave Chinner } 18130f712c9SDave Chinner 18230f712c9SDave Chinner STATIC int 18330f712c9SDave Chinner xfs_inobt_get_maxrecs( 18430f712c9SDave Chinner struct xfs_btree_cur *cur, 18530f712c9SDave Chinner int level) 18630f712c9SDave Chinner { 187ef325959SDarrick J. Wong return M_IGEO(cur->bc_mp)->inobt_mxr[level != 0]; 18830f712c9SDave Chinner } 18930f712c9SDave Chinner 19030f712c9SDave Chinner STATIC void 19130f712c9SDave Chinner xfs_inobt_init_key_from_rec( 19230f712c9SDave Chinner union xfs_btree_key *key, 19330f712c9SDave Chinner union xfs_btree_rec *rec) 19430f712c9SDave Chinner { 19530f712c9SDave Chinner key->inobt.ir_startino = rec->inobt.ir_startino; 19630f712c9SDave Chinner } 19730f712c9SDave Chinner 19830f712c9SDave Chinner STATIC void 199118bb47eSDarrick J. Wong xfs_inobt_init_high_key_from_rec( 200118bb47eSDarrick J. Wong union xfs_btree_key *key, 201118bb47eSDarrick J. Wong union xfs_btree_rec *rec) 202118bb47eSDarrick J. Wong { 203118bb47eSDarrick J. Wong __u32 x; 204118bb47eSDarrick J. Wong 205118bb47eSDarrick J. Wong x = be32_to_cpu(rec->inobt.ir_startino); 206118bb47eSDarrick J. Wong x += XFS_INODES_PER_CHUNK - 1; 207118bb47eSDarrick J. Wong key->inobt.ir_startino = cpu_to_be32(x); 208118bb47eSDarrick J. Wong } 209118bb47eSDarrick J. Wong 210118bb47eSDarrick J. Wong STATIC void 21130f712c9SDave Chinner xfs_inobt_init_rec_from_cur( 21230f712c9SDave Chinner struct xfs_btree_cur *cur, 21330f712c9SDave Chinner union xfs_btree_rec *rec) 21430f712c9SDave Chinner { 21530f712c9SDave Chinner rec->inobt.ir_startino = cpu_to_be32(cur->bc_rec.i.ir_startino); 2165419040fSBrian Foster if (xfs_sb_version_hassparseinodes(&cur->bc_mp->m_sb)) { 2175419040fSBrian Foster rec->inobt.ir_u.sp.ir_holemask = 2185419040fSBrian Foster cpu_to_be16(cur->bc_rec.i.ir_holemask); 2195419040fSBrian Foster rec->inobt.ir_u.sp.ir_count = cur->bc_rec.i.ir_count; 2205419040fSBrian Foster rec->inobt.ir_u.sp.ir_freecount = cur->bc_rec.i.ir_freecount; 2215419040fSBrian Foster } else { 2225419040fSBrian Foster /* ir_holemask/ir_count not supported on-disk */ 2235419040fSBrian Foster rec->inobt.ir_u.f.ir_freecount = 2245419040fSBrian Foster cpu_to_be32(cur->bc_rec.i.ir_freecount); 2255419040fSBrian Foster } 22630f712c9SDave Chinner rec->inobt.ir_free = cpu_to_be64(cur->bc_rec.i.ir_free); 22730f712c9SDave Chinner } 22830f712c9SDave Chinner 22930f712c9SDave Chinner /* 23030f712c9SDave Chinner * initial value of ptr for lookup 23130f712c9SDave Chinner */ 23230f712c9SDave Chinner STATIC void 23330f712c9SDave Chinner xfs_inobt_init_ptr_from_cur( 23430f712c9SDave Chinner struct xfs_btree_cur *cur, 23530f712c9SDave Chinner union xfs_btree_ptr *ptr) 23630f712c9SDave Chinner { 237576af732SDave Chinner struct xfs_agi *agi = cur->bc_ag.agbp->b_addr; 23830f712c9SDave Chinner 239576af732SDave Chinner ASSERT(cur->bc_ag.agno == be32_to_cpu(agi->agi_seqno)); 24030f712c9SDave Chinner 24130f712c9SDave Chinner ptr->s = agi->agi_root; 24230f712c9SDave Chinner } 24330f712c9SDave Chinner 24430f712c9SDave Chinner STATIC void 24530f712c9SDave Chinner xfs_finobt_init_ptr_from_cur( 24630f712c9SDave Chinner struct xfs_btree_cur *cur, 24730f712c9SDave Chinner union xfs_btree_ptr *ptr) 24830f712c9SDave Chinner { 249576af732SDave Chinner struct xfs_agi *agi = cur->bc_ag.agbp->b_addr; 25030f712c9SDave Chinner 251576af732SDave Chinner ASSERT(cur->bc_ag.agno == be32_to_cpu(agi->agi_seqno)); 25230f712c9SDave Chinner ptr->s = agi->agi_free_root; 25330f712c9SDave Chinner } 25430f712c9SDave Chinner 255c8ce540dSDarrick J. Wong STATIC int64_t 25630f712c9SDave Chinner xfs_inobt_key_diff( 25730f712c9SDave Chinner struct xfs_btree_cur *cur, 25830f712c9SDave Chinner union xfs_btree_key *key) 25930f712c9SDave Chinner { 260c8ce540dSDarrick J. Wong return (int64_t)be32_to_cpu(key->inobt.ir_startino) - 26130f712c9SDave Chinner cur->bc_rec.i.ir_startino; 26230f712c9SDave Chinner } 26330f712c9SDave Chinner 264118bb47eSDarrick J. Wong STATIC int64_t 265118bb47eSDarrick J. Wong xfs_inobt_diff_two_keys( 266118bb47eSDarrick J. Wong struct xfs_btree_cur *cur, 267118bb47eSDarrick J. Wong union xfs_btree_key *k1, 268118bb47eSDarrick J. Wong union xfs_btree_key *k2) 269118bb47eSDarrick J. Wong { 270118bb47eSDarrick J. Wong return (int64_t)be32_to_cpu(k1->inobt.ir_startino) - 271118bb47eSDarrick J. Wong be32_to_cpu(k2->inobt.ir_startino); 272118bb47eSDarrick J. Wong } 273118bb47eSDarrick J. Wong 274a6a781a5SDarrick J. Wong static xfs_failaddr_t 27530f712c9SDave Chinner xfs_inobt_verify( 27630f712c9SDave Chinner struct xfs_buf *bp) 27730f712c9SDave Chinner { 278dbd329f1SChristoph Hellwig struct xfs_mount *mp = bp->b_mount; 27930f712c9SDave Chinner struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); 280a6a781a5SDarrick J. Wong xfs_failaddr_t fa; 28130f712c9SDave Chinner unsigned int level; 28230f712c9SDave Chinner 2838473fee3SBrian Foster if (!xfs_verify_magic(bp, block->bb_magic)) 2848473fee3SBrian Foster return __this_address; 2858473fee3SBrian Foster 28630f712c9SDave Chinner /* 28730f712c9SDave Chinner * During growfs operations, we can't verify the exact owner as the 28830f712c9SDave Chinner * perag is not fully initialised and hence not attached to the buffer. 28930f712c9SDave Chinner * 29030f712c9SDave Chinner * Similarly, during log recovery we will have a perag structure 29130f712c9SDave Chinner * attached, but the agi information will not yet have been initialised 29230f712c9SDave Chinner * from the on disk AGI. We don't currently use any of this information, 29330f712c9SDave Chinner * but beware of the landmine (i.e. need to check pag->pagi_init) if we 29430f712c9SDave Chinner * ever do. 29530f712c9SDave Chinner */ 2968473fee3SBrian Foster if (xfs_sb_version_hascrc(&mp->m_sb)) { 297a6a781a5SDarrick J. Wong fa = xfs_btree_sblock_v5hdr_verify(bp); 298a6a781a5SDarrick J. Wong if (fa) 299a6a781a5SDarrick J. Wong return fa; 30030f712c9SDave Chinner } 30130f712c9SDave Chinner 302c5ab131bSDarrick J. Wong /* level verification */ 30330f712c9SDave Chinner level = be16_to_cpu(block->bb_level); 304ef325959SDarrick J. Wong if (level >= M_IGEO(mp)->inobt_maxlevels) 305a6a781a5SDarrick J. Wong return __this_address; 30630f712c9SDave Chinner 307ef325959SDarrick J. Wong return xfs_btree_sblock_verify(bp, 308ef325959SDarrick J. Wong M_IGEO(mp)->inobt_mxr[level != 0]); 30930f712c9SDave Chinner } 31030f712c9SDave Chinner 31130f712c9SDave Chinner static void 31230f712c9SDave Chinner xfs_inobt_read_verify( 31330f712c9SDave Chinner struct xfs_buf *bp) 31430f712c9SDave Chinner { 315bc1a09b8SDarrick J. Wong xfs_failaddr_t fa; 316bc1a09b8SDarrick J. Wong 31730f712c9SDave Chinner if (!xfs_btree_sblock_verify_crc(bp)) 318bc1a09b8SDarrick J. Wong xfs_verifier_error(bp, -EFSBADCRC, __this_address); 319bc1a09b8SDarrick J. Wong else { 320bc1a09b8SDarrick J. Wong fa = xfs_inobt_verify(bp); 321bc1a09b8SDarrick J. Wong if (fa) 322bc1a09b8SDarrick J. Wong xfs_verifier_error(bp, -EFSCORRUPTED, fa); 323bc1a09b8SDarrick J. Wong } 32430f712c9SDave Chinner 32531ca03c9SDarrick J. Wong if (bp->b_error) 32630f712c9SDave Chinner trace_xfs_btree_corrupt(bp, _RET_IP_); 32730f712c9SDave Chinner } 32830f712c9SDave Chinner 32930f712c9SDave Chinner static void 33030f712c9SDave Chinner xfs_inobt_write_verify( 33130f712c9SDave Chinner struct xfs_buf *bp) 33230f712c9SDave Chinner { 333bc1a09b8SDarrick J. Wong xfs_failaddr_t fa; 334bc1a09b8SDarrick J. Wong 335bc1a09b8SDarrick J. Wong fa = xfs_inobt_verify(bp); 336bc1a09b8SDarrick J. Wong if (fa) { 33730f712c9SDave Chinner trace_xfs_btree_corrupt(bp, _RET_IP_); 338bc1a09b8SDarrick J. Wong xfs_verifier_error(bp, -EFSCORRUPTED, fa); 33930f712c9SDave Chinner return; 34030f712c9SDave Chinner } 34130f712c9SDave Chinner xfs_btree_sblock_calc_crc(bp); 34230f712c9SDave Chinner 34330f712c9SDave Chinner } 34430f712c9SDave Chinner 34530f712c9SDave Chinner const struct xfs_buf_ops xfs_inobt_buf_ops = { 346233135b7SEric Sandeen .name = "xfs_inobt", 3478473fee3SBrian Foster .magic = { cpu_to_be32(XFS_IBT_MAGIC), cpu_to_be32(XFS_IBT_CRC_MAGIC) }, 34830f712c9SDave Chinner .verify_read = xfs_inobt_read_verify, 34930f712c9SDave Chinner .verify_write = xfs_inobt_write_verify, 350b5572597SDarrick J. Wong .verify_struct = xfs_inobt_verify, 35130f712c9SDave Chinner }; 35230f712c9SDave Chinner 35301e68f40SBrian Foster const struct xfs_buf_ops xfs_finobt_buf_ops = { 35401e68f40SBrian Foster .name = "xfs_finobt", 3558473fee3SBrian Foster .magic = { cpu_to_be32(XFS_FIBT_MAGIC), 3568473fee3SBrian Foster cpu_to_be32(XFS_FIBT_CRC_MAGIC) }, 35701e68f40SBrian Foster .verify_read = xfs_inobt_read_verify, 35801e68f40SBrian Foster .verify_write = xfs_inobt_write_verify, 35901e68f40SBrian Foster .verify_struct = xfs_inobt_verify, 36001e68f40SBrian Foster }; 36101e68f40SBrian Foster 36230f712c9SDave Chinner STATIC int 36330f712c9SDave Chinner xfs_inobt_keys_inorder( 36430f712c9SDave Chinner struct xfs_btree_cur *cur, 36530f712c9SDave Chinner union xfs_btree_key *k1, 36630f712c9SDave Chinner union xfs_btree_key *k2) 36730f712c9SDave Chinner { 36830f712c9SDave Chinner return be32_to_cpu(k1->inobt.ir_startino) < 36930f712c9SDave Chinner be32_to_cpu(k2->inobt.ir_startino); 37030f712c9SDave Chinner } 37130f712c9SDave Chinner 37230f712c9SDave Chinner STATIC int 37330f712c9SDave Chinner xfs_inobt_recs_inorder( 37430f712c9SDave Chinner struct xfs_btree_cur *cur, 37530f712c9SDave Chinner union xfs_btree_rec *r1, 37630f712c9SDave Chinner union xfs_btree_rec *r2) 37730f712c9SDave Chinner { 37830f712c9SDave Chinner return be32_to_cpu(r1->inobt.ir_startino) + XFS_INODES_PER_CHUNK <= 37930f712c9SDave Chinner be32_to_cpu(r2->inobt.ir_startino); 38030f712c9SDave Chinner } 38130f712c9SDave Chinner 38230f712c9SDave Chinner static const struct xfs_btree_ops xfs_inobt_ops = { 38330f712c9SDave Chinner .rec_len = sizeof(xfs_inobt_rec_t), 38430f712c9SDave Chinner .key_len = sizeof(xfs_inobt_key_t), 38530f712c9SDave Chinner 38630f712c9SDave Chinner .dup_cursor = xfs_inobt_dup_cursor, 38730f712c9SDave Chinner .set_root = xfs_inobt_set_root, 38830f712c9SDave Chinner .alloc_block = xfs_inobt_alloc_block, 38930f712c9SDave Chinner .free_block = xfs_inobt_free_block, 39030f712c9SDave Chinner .get_minrecs = xfs_inobt_get_minrecs, 39130f712c9SDave Chinner .get_maxrecs = xfs_inobt_get_maxrecs, 39230f712c9SDave Chinner .init_key_from_rec = xfs_inobt_init_key_from_rec, 393118bb47eSDarrick J. Wong .init_high_key_from_rec = xfs_inobt_init_high_key_from_rec, 39430f712c9SDave Chinner .init_rec_from_cur = xfs_inobt_init_rec_from_cur, 39530f712c9SDave Chinner .init_ptr_from_cur = xfs_inobt_init_ptr_from_cur, 39630f712c9SDave Chinner .key_diff = xfs_inobt_key_diff, 39730f712c9SDave Chinner .buf_ops = &xfs_inobt_buf_ops, 398118bb47eSDarrick J. Wong .diff_two_keys = xfs_inobt_diff_two_keys, 39930f712c9SDave Chinner .keys_inorder = xfs_inobt_keys_inorder, 40030f712c9SDave Chinner .recs_inorder = xfs_inobt_recs_inorder, 40130f712c9SDave Chinner }; 40230f712c9SDave Chinner 40330f712c9SDave Chinner static const struct xfs_btree_ops xfs_finobt_ops = { 40430f712c9SDave Chinner .rec_len = sizeof(xfs_inobt_rec_t), 40530f712c9SDave Chinner .key_len = sizeof(xfs_inobt_key_t), 40630f712c9SDave Chinner 40730f712c9SDave Chinner .dup_cursor = xfs_inobt_dup_cursor, 40830f712c9SDave Chinner .set_root = xfs_finobt_set_root, 40976d771b4SChristoph Hellwig .alloc_block = xfs_finobt_alloc_block, 410ad90bb58SBrian Foster .free_block = xfs_finobt_free_block, 41130f712c9SDave Chinner .get_minrecs = xfs_inobt_get_minrecs, 41230f712c9SDave Chinner .get_maxrecs = xfs_inobt_get_maxrecs, 41330f712c9SDave Chinner .init_key_from_rec = xfs_inobt_init_key_from_rec, 414118bb47eSDarrick J. Wong .init_high_key_from_rec = xfs_inobt_init_high_key_from_rec, 41530f712c9SDave Chinner .init_rec_from_cur = xfs_inobt_init_rec_from_cur, 41630f712c9SDave Chinner .init_ptr_from_cur = xfs_finobt_init_ptr_from_cur, 41730f712c9SDave Chinner .key_diff = xfs_inobt_key_diff, 41801e68f40SBrian Foster .buf_ops = &xfs_finobt_buf_ops, 419118bb47eSDarrick J. Wong .diff_two_keys = xfs_inobt_diff_two_keys, 42030f712c9SDave Chinner .keys_inorder = xfs_inobt_keys_inorder, 42130f712c9SDave Chinner .recs_inorder = xfs_inobt_recs_inorder, 42230f712c9SDave Chinner }; 42330f712c9SDave Chinner 42430f712c9SDave Chinner /* 425c29ce8f4SDarrick J. Wong * Initialize a new inode btree cursor. 42630f712c9SDave Chinner */ 427c29ce8f4SDarrick J. Wong static struct xfs_btree_cur * 428c29ce8f4SDarrick J. Wong xfs_inobt_init_common( 42930f712c9SDave Chinner struct xfs_mount *mp, /* file system mount point */ 43030f712c9SDave Chinner struct xfs_trans *tp, /* transaction pointer */ 43130f712c9SDave Chinner xfs_agnumber_t agno, /* allocation group number */ 432*be9fb17dSDave Chinner struct xfs_perag *pag, 43330f712c9SDave Chinner xfs_btnum_t btnum) /* ialloc or free ino btree */ 43430f712c9SDave Chinner { 43530f712c9SDave Chinner struct xfs_btree_cur *cur; 43630f712c9SDave Chinner 43732a2b11fSCarlos Maiolino cur = kmem_cache_zalloc(xfs_btree_cur_zone, GFP_NOFS | __GFP_NOFAIL); 43830f712c9SDave Chinner cur->bc_tp = tp; 43930f712c9SDave Chinner cur->bc_mp = mp; 44030f712c9SDave Chinner cur->bc_btnum = btnum; 44130f712c9SDave Chinner if (btnum == XFS_BTNUM_INO) { 44211ef38afSDave Chinner cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_ibt_2); 443c29ce8f4SDarrick J. Wong cur->bc_ops = &xfs_inobt_ops; 44430f712c9SDave Chinner } else { 44511ef38afSDave Chinner cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_fibt_2); 446c29ce8f4SDarrick J. Wong cur->bc_ops = &xfs_finobt_ops; 44730f712c9SDave Chinner } 44830f712c9SDave Chinner 44930f712c9SDave Chinner cur->bc_blocklog = mp->m_sb.sb_blocklog; 45030f712c9SDave Chinner 45130f712c9SDave Chinner if (xfs_sb_version_hascrc(&mp->m_sb)) 45230f712c9SDave Chinner cur->bc_flags |= XFS_BTREE_CRC_BLOCKS; 45330f712c9SDave Chinner 454576af732SDave Chinner cur->bc_ag.agno = agno; 455*be9fb17dSDave Chinner if (pag) { 456*be9fb17dSDave Chinner /* take a reference for the cursor */ 457*be9fb17dSDave Chinner atomic_inc(&pag->pag_ref); 458*be9fb17dSDave Chinner } 459*be9fb17dSDave Chinner cur->bc_ag.pag = pag; 46030f712c9SDave Chinner return cur; 46130f712c9SDave Chinner } 46230f712c9SDave Chinner 463c29ce8f4SDarrick J. Wong /* Create an inode btree cursor. */ 464c29ce8f4SDarrick J. Wong struct xfs_btree_cur * 465c29ce8f4SDarrick J. Wong xfs_inobt_init_cursor( 466c29ce8f4SDarrick J. Wong struct xfs_mount *mp, 467c29ce8f4SDarrick J. Wong struct xfs_trans *tp, 468c29ce8f4SDarrick J. Wong struct xfs_buf *agbp, 469c29ce8f4SDarrick J. Wong xfs_agnumber_t agno, 470*be9fb17dSDave Chinner struct xfs_perag *pag, 471c29ce8f4SDarrick J. Wong xfs_btnum_t btnum) 472c29ce8f4SDarrick J. Wong { 473c29ce8f4SDarrick J. Wong struct xfs_btree_cur *cur; 474c29ce8f4SDarrick J. Wong struct xfs_agi *agi = agbp->b_addr; 475c29ce8f4SDarrick J. Wong 476*be9fb17dSDave Chinner cur = xfs_inobt_init_common(mp, tp, agno, pag, btnum); 477c29ce8f4SDarrick J. Wong if (btnum == XFS_BTNUM_INO) 478c29ce8f4SDarrick J. Wong cur->bc_nlevels = be32_to_cpu(agi->agi_level); 479c29ce8f4SDarrick J. Wong else 480c29ce8f4SDarrick J. Wong cur->bc_nlevels = be32_to_cpu(agi->agi_free_level); 481c29ce8f4SDarrick J. Wong cur->bc_ag.agbp = agbp; 482c29ce8f4SDarrick J. Wong return cur; 483c29ce8f4SDarrick J. Wong } 484c29ce8f4SDarrick J. Wong 485c29ce8f4SDarrick J. Wong /* Create an inode btree cursor with a fake root for staging. */ 486c29ce8f4SDarrick J. Wong struct xfs_btree_cur * 487c29ce8f4SDarrick J. Wong xfs_inobt_stage_cursor( 488c29ce8f4SDarrick J. Wong struct xfs_mount *mp, 489c29ce8f4SDarrick J. Wong struct xbtree_afakeroot *afake, 490c29ce8f4SDarrick J. Wong xfs_agnumber_t agno, 491c29ce8f4SDarrick J. Wong xfs_btnum_t btnum) 492c29ce8f4SDarrick J. Wong { 493c29ce8f4SDarrick J. Wong struct xfs_btree_cur *cur; 494c29ce8f4SDarrick J. Wong 495*be9fb17dSDave Chinner cur = xfs_inobt_init_common(mp, NULL, agno, NULL, btnum); 496c29ce8f4SDarrick J. Wong xfs_btree_stage_afakeroot(cur, afake); 497c29ce8f4SDarrick J. Wong return cur; 498c29ce8f4SDarrick J. Wong } 499c29ce8f4SDarrick J. Wong 500c29ce8f4SDarrick J. Wong /* 501c29ce8f4SDarrick J. Wong * Install a new inobt btree root. Caller is responsible for invalidating 502c29ce8f4SDarrick J. Wong * and freeing the old btree blocks. 503c29ce8f4SDarrick J. Wong */ 504c29ce8f4SDarrick J. Wong void 505c29ce8f4SDarrick J. Wong xfs_inobt_commit_staged_btree( 506c29ce8f4SDarrick J. Wong struct xfs_btree_cur *cur, 507c29ce8f4SDarrick J. Wong struct xfs_trans *tp, 508c29ce8f4SDarrick J. Wong struct xfs_buf *agbp) 509c29ce8f4SDarrick J. Wong { 510c29ce8f4SDarrick J. Wong struct xfs_agi *agi = agbp->b_addr; 511c29ce8f4SDarrick J. Wong struct xbtree_afakeroot *afake = cur->bc_ag.afake; 51211f74423SDarrick J. Wong int fields; 513c29ce8f4SDarrick J. Wong 514c29ce8f4SDarrick J. Wong ASSERT(cur->bc_flags & XFS_BTREE_STAGING); 515c29ce8f4SDarrick J. Wong 516c29ce8f4SDarrick J. Wong if (cur->bc_btnum == XFS_BTNUM_INO) { 51711f74423SDarrick J. Wong fields = XFS_AGI_ROOT | XFS_AGI_LEVEL; 518c29ce8f4SDarrick J. Wong agi->agi_root = cpu_to_be32(afake->af_root); 519c29ce8f4SDarrick J. Wong agi->agi_level = cpu_to_be32(afake->af_levels); 52011f74423SDarrick J. Wong if (xfs_sb_version_hasinobtcounts(&cur->bc_mp->m_sb)) { 52111f74423SDarrick J. Wong agi->agi_iblocks = cpu_to_be32(afake->af_blocks); 52211f74423SDarrick J. Wong fields |= XFS_AGI_IBLOCKS; 52311f74423SDarrick J. Wong } 52411f74423SDarrick J. Wong xfs_ialloc_log_agi(tp, agbp, fields); 525c29ce8f4SDarrick J. Wong xfs_btree_commit_afakeroot(cur, tp, agbp, &xfs_inobt_ops); 526c29ce8f4SDarrick J. Wong } else { 52711f74423SDarrick J. Wong fields = XFS_AGI_FREE_ROOT | XFS_AGI_FREE_LEVEL; 528c29ce8f4SDarrick J. Wong agi->agi_free_root = cpu_to_be32(afake->af_root); 529c29ce8f4SDarrick J. Wong agi->agi_free_level = cpu_to_be32(afake->af_levels); 53011f74423SDarrick J. Wong if (xfs_sb_version_hasinobtcounts(&cur->bc_mp->m_sb)) { 53111f74423SDarrick J. Wong agi->agi_fblocks = cpu_to_be32(afake->af_blocks); 53211f74423SDarrick J. Wong fields |= XFS_AGI_IBLOCKS; 53311f74423SDarrick J. Wong } 53411f74423SDarrick J. Wong xfs_ialloc_log_agi(tp, agbp, fields); 535c29ce8f4SDarrick J. Wong xfs_btree_commit_afakeroot(cur, tp, agbp, &xfs_finobt_ops); 536c29ce8f4SDarrick J. Wong } 537c29ce8f4SDarrick J. Wong } 538c29ce8f4SDarrick J. Wong 53930f712c9SDave Chinner /* 54030f712c9SDave Chinner * Calculate number of records in an inobt btree block. 54130f712c9SDave Chinner */ 54230f712c9SDave Chinner int 54330f712c9SDave Chinner xfs_inobt_maxrecs( 54430f712c9SDave Chinner struct xfs_mount *mp, 54530f712c9SDave Chinner int blocklen, 54630f712c9SDave Chinner int leaf) 54730f712c9SDave Chinner { 54830f712c9SDave Chinner blocklen -= XFS_INOBT_BLOCK_LEN(mp); 54930f712c9SDave Chinner 55030f712c9SDave Chinner if (leaf) 55130f712c9SDave Chinner return blocklen / sizeof(xfs_inobt_rec_t); 55230f712c9SDave Chinner return blocklen / (sizeof(xfs_inobt_key_t) + sizeof(xfs_inobt_ptr_t)); 55330f712c9SDave Chinner } 5544148c347SBrian Foster 5554148c347SBrian Foster /* 5564148c347SBrian Foster * Convert the inode record holemask to an inode allocation bitmap. The inode 5574148c347SBrian Foster * allocation bitmap is inode granularity and specifies whether an inode is 5584148c347SBrian Foster * physically allocated on disk (not whether the inode is considered allocated 5594148c347SBrian Foster * or free by the fs). 5604148c347SBrian Foster * 5614148c347SBrian Foster * A bit value of 1 means the inode is allocated, a value of 0 means it is free. 5624148c347SBrian Foster */ 5634148c347SBrian Foster uint64_t 5644148c347SBrian Foster xfs_inobt_irec_to_allocmask( 5654148c347SBrian Foster struct xfs_inobt_rec_incore *rec) 5664148c347SBrian Foster { 5674148c347SBrian Foster uint64_t bitmap = 0; 5684148c347SBrian Foster uint64_t inodespbit; 5694148c347SBrian Foster int nextbit; 5704148c347SBrian Foster uint allocbitmap; 5714148c347SBrian Foster 5724148c347SBrian Foster /* 5734148c347SBrian Foster * The holemask has 16-bits for a 64 inode record. Therefore each 5744148c347SBrian Foster * holemask bit represents multiple inodes. Create a mask of bits to set 5754148c347SBrian Foster * in the allocmask for each holemask bit. 5764148c347SBrian Foster */ 5774148c347SBrian Foster inodespbit = (1 << XFS_INODES_PER_HOLEMASK_BIT) - 1; 5784148c347SBrian Foster 5794148c347SBrian Foster /* 5804148c347SBrian Foster * Allocated inodes are represented by 0 bits in holemask. Invert the 0 5814148c347SBrian Foster * bits to 1 and convert to a uint so we can use xfs_next_bit(). Mask 5824148c347SBrian Foster * anything beyond the 16 holemask bits since this casts to a larger 5834148c347SBrian Foster * type. 5844148c347SBrian Foster */ 5854148c347SBrian Foster allocbitmap = ~rec->ir_holemask & ((1 << XFS_INOBT_HOLEMASK_BITS) - 1); 5864148c347SBrian Foster 5874148c347SBrian Foster /* 5884148c347SBrian Foster * allocbitmap is the inverted holemask so every set bit represents 5894148c347SBrian Foster * allocated inodes. To expand from 16-bit holemask granularity to 5904148c347SBrian Foster * 64-bit (e.g., bit-per-inode), set inodespbit bits in the target 5914148c347SBrian Foster * bitmap for every holemask bit. 5924148c347SBrian Foster */ 5934148c347SBrian Foster nextbit = xfs_next_bit(&allocbitmap, 1, 0); 5944148c347SBrian Foster while (nextbit != -1) { 5954148c347SBrian Foster ASSERT(nextbit < (sizeof(rec->ir_holemask) * NBBY)); 5964148c347SBrian Foster 5974148c347SBrian Foster bitmap |= (inodespbit << 5984148c347SBrian Foster (nextbit * XFS_INODES_PER_HOLEMASK_BIT)); 5994148c347SBrian Foster 6004148c347SBrian Foster nextbit = xfs_next_bit(&allocbitmap, 1, nextbit + 1); 6014148c347SBrian Foster } 6024148c347SBrian Foster 6034148c347SBrian Foster return bitmap; 6044148c347SBrian Foster } 60556d1115cSBrian Foster 60656d1115cSBrian Foster #if defined(DEBUG) || defined(XFS_WARN) 60756d1115cSBrian Foster /* 60856d1115cSBrian Foster * Verify that an in-core inode record has a valid inode count. 60956d1115cSBrian Foster */ 61056d1115cSBrian Foster int 61156d1115cSBrian Foster xfs_inobt_rec_check_count( 61256d1115cSBrian Foster struct xfs_mount *mp, 61356d1115cSBrian Foster struct xfs_inobt_rec_incore *rec) 61456d1115cSBrian Foster { 61556d1115cSBrian Foster int inocount = 0; 61656d1115cSBrian Foster int nextbit = 0; 61756d1115cSBrian Foster uint64_t allocbmap; 61856d1115cSBrian Foster int wordsz; 61956d1115cSBrian Foster 62056d1115cSBrian Foster wordsz = sizeof(allocbmap) / sizeof(unsigned int); 62156d1115cSBrian Foster allocbmap = xfs_inobt_irec_to_allocmask(rec); 62256d1115cSBrian Foster 62356d1115cSBrian Foster nextbit = xfs_next_bit((uint *) &allocbmap, wordsz, nextbit); 62456d1115cSBrian Foster while (nextbit != -1) { 62556d1115cSBrian Foster inocount++; 62656d1115cSBrian Foster nextbit = xfs_next_bit((uint *) &allocbmap, wordsz, 62756d1115cSBrian Foster nextbit + 1); 62856d1115cSBrian Foster } 62956d1115cSBrian Foster 63056d1115cSBrian Foster if (inocount != rec->ir_count) 63156d1115cSBrian Foster return -EFSCORRUPTED; 63256d1115cSBrian Foster 63356d1115cSBrian Foster return 0; 63456d1115cSBrian Foster } 63556d1115cSBrian Foster #endif /* DEBUG */ 63676d771b4SChristoph Hellwig 63776d771b4SChristoph Hellwig static xfs_extlen_t 63876d771b4SChristoph Hellwig xfs_inobt_max_size( 639c0876897SDave Chinner struct xfs_mount *mp, 640c0876897SDave Chinner xfs_agnumber_t agno) 64176d771b4SChristoph Hellwig { 642c0876897SDave Chinner xfs_agblock_t agblocks = xfs_ag_block_count(mp, agno); 643c0876897SDave Chinner 64476d771b4SChristoph Hellwig /* Bail out if we're uninitialized, which can happen in mkfs. */ 645ef325959SDarrick J. Wong if (M_IGEO(mp)->inobt_mxr[0] == 0) 64676d771b4SChristoph Hellwig return 0; 64776d771b4SChristoph Hellwig 6485cd213b0SDarrick J. Wong /* 6495cd213b0SDarrick J. Wong * The log is permanently allocated, so the space it occupies will 6505cd213b0SDarrick J. Wong * never be available for the kinds of things that would require btree 6515cd213b0SDarrick J. Wong * expansion. We therefore can pretend the space isn't there. 6525cd213b0SDarrick J. Wong */ 6535cd213b0SDarrick J. Wong if (mp->m_sb.sb_logstart && 6545cd213b0SDarrick J. Wong XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart) == agno) 6555cd213b0SDarrick J. Wong agblocks -= mp->m_sb.sb_logblocks; 6565cd213b0SDarrick J. Wong 657ef325959SDarrick J. Wong return xfs_btree_calc_size(M_IGEO(mp)->inobt_mnr, 658c0876897SDave Chinner (uint64_t)agblocks * mp->m_sb.sb_inopblock / 65976d771b4SChristoph Hellwig XFS_INODES_PER_CHUNK); 66076d771b4SChristoph Hellwig } 66176d771b4SChristoph Hellwig 662a211432cSDarrick J. Wong /* Read AGI and create inobt cursor. */ 663a211432cSDarrick J. Wong int 664a211432cSDarrick J. Wong xfs_inobt_cur( 665a211432cSDarrick J. Wong struct xfs_mount *mp, 666a211432cSDarrick J. Wong struct xfs_trans *tp, 667a211432cSDarrick J. Wong xfs_agnumber_t agno, 668a211432cSDarrick J. Wong xfs_btnum_t which, 669a211432cSDarrick J. Wong struct xfs_btree_cur **curpp, 670a211432cSDarrick J. Wong struct xfs_buf **agi_bpp) 671a211432cSDarrick J. Wong { 672a211432cSDarrick J. Wong struct xfs_btree_cur *cur; 673a211432cSDarrick J. Wong int error; 674a211432cSDarrick J. Wong 675a211432cSDarrick J. Wong ASSERT(*agi_bpp == NULL); 676a211432cSDarrick J. Wong ASSERT(*curpp == NULL); 677a211432cSDarrick J. Wong 678a211432cSDarrick J. Wong error = xfs_ialloc_read_agi(mp, tp, agno, agi_bpp); 679a211432cSDarrick J. Wong if (error) 680a211432cSDarrick J. Wong return error; 681a211432cSDarrick J. Wong 682*be9fb17dSDave Chinner cur = xfs_inobt_init_cursor(mp, tp, *agi_bpp, agno, NULL, which); 683a211432cSDarrick J. Wong *curpp = cur; 684a211432cSDarrick J. Wong return 0; 685a211432cSDarrick J. Wong } 686a211432cSDarrick J. Wong 68776d771b4SChristoph Hellwig static int 68876d771b4SChristoph Hellwig xfs_inobt_count_blocks( 68976d771b4SChristoph Hellwig struct xfs_mount *mp, 690ebcbef3aSDarrick J. Wong struct xfs_trans *tp, 69130933120SDave Chinner struct xfs_perag *pag, 69276d771b4SChristoph Hellwig xfs_btnum_t btnum, 69376d771b4SChristoph Hellwig xfs_extlen_t *tree_blocks) 69476d771b4SChristoph Hellwig { 695a211432cSDarrick J. Wong struct xfs_buf *agbp = NULL; 696a211432cSDarrick J. Wong struct xfs_btree_cur *cur = NULL; 69776d771b4SChristoph Hellwig int error; 69876d771b4SChristoph Hellwig 69930933120SDave Chinner error = xfs_inobt_cur(mp, tp, pag->pag_agno, btnum, &cur, &agbp); 70076d771b4SChristoph Hellwig if (error) 70176d771b4SChristoph Hellwig return error; 70276d771b4SChristoph Hellwig 70376d771b4SChristoph Hellwig error = xfs_btree_count_blocks(cur, tree_blocks); 7040b04b6b8SDarrick J. Wong xfs_btree_del_cursor(cur, error); 705ebcbef3aSDarrick J. Wong xfs_trans_brelse(tp, agbp); 70676d771b4SChristoph Hellwig 70776d771b4SChristoph Hellwig return error; 70876d771b4SChristoph Hellwig } 70976d771b4SChristoph Hellwig 7101ac35f06SDarrick J. Wong /* Read finobt block count from AGI header. */ 7111ac35f06SDarrick J. Wong static int 7121ac35f06SDarrick J. Wong xfs_finobt_read_blocks( 7131ac35f06SDarrick J. Wong struct xfs_mount *mp, 7141ac35f06SDarrick J. Wong struct xfs_trans *tp, 71530933120SDave Chinner struct xfs_perag *pag, 7161ac35f06SDarrick J. Wong xfs_extlen_t *tree_blocks) 7171ac35f06SDarrick J. Wong { 7181ac35f06SDarrick J. Wong struct xfs_buf *agbp; 7191ac35f06SDarrick J. Wong struct xfs_agi *agi; 7201ac35f06SDarrick J. Wong int error; 7211ac35f06SDarrick J. Wong 72230933120SDave Chinner error = xfs_ialloc_read_agi(mp, tp, pag->pag_agno, &agbp); 7231ac35f06SDarrick J. Wong if (error) 7241ac35f06SDarrick J. Wong return error; 7251ac35f06SDarrick J. Wong 7261ac35f06SDarrick J. Wong agi = agbp->b_addr; 7271ac35f06SDarrick J. Wong *tree_blocks = be32_to_cpu(agi->agi_fblocks); 7281ac35f06SDarrick J. Wong xfs_trans_brelse(tp, agbp); 7291ac35f06SDarrick J. Wong return 0; 7301ac35f06SDarrick J. Wong } 7311ac35f06SDarrick J. Wong 73276d771b4SChristoph Hellwig /* 73376d771b4SChristoph Hellwig * Figure out how many blocks to reserve and how many are used by this btree. 73476d771b4SChristoph Hellwig */ 73576d771b4SChristoph Hellwig int 73676d771b4SChristoph Hellwig xfs_finobt_calc_reserves( 73776d771b4SChristoph Hellwig struct xfs_mount *mp, 738ebcbef3aSDarrick J. Wong struct xfs_trans *tp, 73930933120SDave Chinner struct xfs_perag *pag, 74076d771b4SChristoph Hellwig xfs_extlen_t *ask, 74176d771b4SChristoph Hellwig xfs_extlen_t *used) 74276d771b4SChristoph Hellwig { 74376d771b4SChristoph Hellwig xfs_extlen_t tree_len = 0; 74476d771b4SChristoph Hellwig int error; 74576d771b4SChristoph Hellwig 74676d771b4SChristoph Hellwig if (!xfs_sb_version_hasfinobt(&mp->m_sb)) 74776d771b4SChristoph Hellwig return 0; 74876d771b4SChristoph Hellwig 7491ac35f06SDarrick J. Wong if (xfs_sb_version_hasinobtcounts(&mp->m_sb)) 75030933120SDave Chinner error = xfs_finobt_read_blocks(mp, tp, pag, &tree_len); 7511ac35f06SDarrick J. Wong else 75230933120SDave Chinner error = xfs_inobt_count_blocks(mp, tp, pag, XFS_BTNUM_FINO, 7531ac35f06SDarrick J. Wong &tree_len); 75476d771b4SChristoph Hellwig if (error) 75576d771b4SChristoph Hellwig return error; 75676d771b4SChristoph Hellwig 75730933120SDave Chinner *ask += xfs_inobt_max_size(mp, pag->pag_agno); 75876d771b4SChristoph Hellwig *used += tree_len; 75976d771b4SChristoph Hellwig return 0; 76076d771b4SChristoph Hellwig } 76114861c47SDarrick J. Wong 76214861c47SDarrick J. Wong /* Calculate the inobt btree size for some records. */ 76314861c47SDarrick J. Wong xfs_extlen_t 76414861c47SDarrick J. Wong xfs_iallocbt_calc_size( 76514861c47SDarrick J. Wong struct xfs_mount *mp, 76614861c47SDarrick J. Wong unsigned long long len) 76714861c47SDarrick J. Wong { 768ef325959SDarrick J. Wong return xfs_btree_calc_size(M_IGEO(mp)->inobt_mnr, len); 76914861c47SDarrick J. Wong } 770