130f712c9SDave Chinner /* 230f712c9SDave Chinner * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. 330f712c9SDave Chinner * All Rights Reserved. 430f712c9SDave Chinner * 530f712c9SDave Chinner * This program is free software; you can redistribute it and/or 630f712c9SDave Chinner * modify it under the terms of the GNU General Public License as 730f712c9SDave Chinner * published by the Free Software Foundation. 830f712c9SDave Chinner * 930f712c9SDave Chinner * This program is distributed in the hope that it would be useful, 1030f712c9SDave Chinner * but WITHOUT ANY WARRANTY; without even the implied warranty of 1130f712c9SDave Chinner * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1230f712c9SDave Chinner * GNU General Public License for more details. 1330f712c9SDave Chinner * 1430f712c9SDave Chinner * You should have received a copy of the GNU General Public License 1530f712c9SDave Chinner * along with this program; if not, write the Free Software Foundation, 1630f712c9SDave Chinner * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 1730f712c9SDave Chinner */ 1830f712c9SDave Chinner #include "xfs.h" 1930f712c9SDave Chinner #include "xfs_fs.h" 2030f712c9SDave Chinner #include "xfs_shared.h" 2130f712c9SDave Chinner #include "xfs_format.h" 2230f712c9SDave Chinner #include "xfs_log_format.h" 2330f712c9SDave Chinner #include "xfs_trans_resv.h" 2430f712c9SDave Chinner #include "xfs_bit.h" 2530f712c9SDave Chinner #include "xfs_sb.h" 2630f712c9SDave Chinner #include "xfs_ag.h" 2730f712c9SDave Chinner #include "xfs_mount.h" 2830f712c9SDave Chinner #include "xfs_inode.h" 2930f712c9SDave Chinner #include "xfs_btree.h" 3030f712c9SDave Chinner #include "xfs_ialloc.h" 3130f712c9SDave Chinner #include "xfs_ialloc_btree.h" 3230f712c9SDave Chinner #include "xfs_alloc.h" 3330f712c9SDave Chinner #include "xfs_error.h" 3430f712c9SDave Chinner #include "xfs_trace.h" 3530f712c9SDave Chinner #include "xfs_cksum.h" 3630f712c9SDave Chinner #include "xfs_trans.h" 3730f712c9SDave Chinner 3830f712c9SDave Chinner 3930f712c9SDave Chinner STATIC int 4030f712c9SDave Chinner xfs_inobt_get_minrecs( 4130f712c9SDave Chinner struct xfs_btree_cur *cur, 4230f712c9SDave Chinner int level) 4330f712c9SDave Chinner { 4430f712c9SDave Chinner return cur->bc_mp->m_inobt_mnr[level != 0]; 4530f712c9SDave Chinner } 4630f712c9SDave Chinner 4730f712c9SDave Chinner STATIC struct xfs_btree_cur * 4830f712c9SDave Chinner xfs_inobt_dup_cursor( 4930f712c9SDave Chinner struct xfs_btree_cur *cur) 5030f712c9SDave Chinner { 5130f712c9SDave Chinner return xfs_inobt_init_cursor(cur->bc_mp, cur->bc_tp, 5230f712c9SDave Chinner cur->bc_private.a.agbp, cur->bc_private.a.agno, 5330f712c9SDave Chinner cur->bc_btnum); 5430f712c9SDave Chinner } 5530f712c9SDave Chinner 5630f712c9SDave Chinner STATIC void 5730f712c9SDave Chinner xfs_inobt_set_root( 5830f712c9SDave Chinner struct xfs_btree_cur *cur, 5930f712c9SDave Chinner union xfs_btree_ptr *nptr, 6030f712c9SDave Chinner int inc) /* level change */ 6130f712c9SDave Chinner { 6230f712c9SDave Chinner struct xfs_buf *agbp = cur->bc_private.a.agbp; 6330f712c9SDave Chinner struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp); 6430f712c9SDave Chinner 6530f712c9SDave Chinner agi->agi_root = nptr->s; 6630f712c9SDave Chinner be32_add_cpu(&agi->agi_level, inc); 6730f712c9SDave Chinner xfs_ialloc_log_agi(cur->bc_tp, agbp, XFS_AGI_ROOT | XFS_AGI_LEVEL); 6830f712c9SDave Chinner } 6930f712c9SDave Chinner 7030f712c9SDave Chinner STATIC void 7130f712c9SDave Chinner xfs_finobt_set_root( 7230f712c9SDave Chinner struct xfs_btree_cur *cur, 7330f712c9SDave Chinner union xfs_btree_ptr *nptr, 7430f712c9SDave Chinner int inc) /* level change */ 7530f712c9SDave Chinner { 7630f712c9SDave Chinner struct xfs_buf *agbp = cur->bc_private.a.agbp; 7730f712c9SDave Chinner struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp); 7830f712c9SDave Chinner 7930f712c9SDave Chinner agi->agi_free_root = nptr->s; 8030f712c9SDave Chinner be32_add_cpu(&agi->agi_free_level, inc); 8130f712c9SDave Chinner xfs_ialloc_log_agi(cur->bc_tp, agbp, 8230f712c9SDave Chinner XFS_AGI_FREE_ROOT | XFS_AGI_FREE_LEVEL); 8330f712c9SDave Chinner } 8430f712c9SDave Chinner 8530f712c9SDave Chinner STATIC int 8630f712c9SDave Chinner xfs_inobt_alloc_block( 8730f712c9SDave Chinner struct xfs_btree_cur *cur, 8830f712c9SDave Chinner union xfs_btree_ptr *start, 8930f712c9SDave Chinner union xfs_btree_ptr *new, 9030f712c9SDave Chinner int *stat) 9130f712c9SDave Chinner { 9230f712c9SDave Chinner xfs_alloc_arg_t args; /* block allocation args */ 9330f712c9SDave Chinner int error; /* error return value */ 9430f712c9SDave Chinner xfs_agblock_t sbno = be32_to_cpu(start->s); 9530f712c9SDave Chinner 9630f712c9SDave Chinner XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); 9730f712c9SDave Chinner 9830f712c9SDave Chinner memset(&args, 0, sizeof(args)); 9930f712c9SDave Chinner args.tp = cur->bc_tp; 10030f712c9SDave Chinner args.mp = cur->bc_mp; 10130f712c9SDave Chinner args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.a.agno, sbno); 10230f712c9SDave Chinner args.minlen = 1; 10330f712c9SDave Chinner args.maxlen = 1; 10430f712c9SDave Chinner args.prod = 1; 10530f712c9SDave Chinner args.type = XFS_ALLOCTYPE_NEAR_BNO; 10630f712c9SDave Chinner 10730f712c9SDave Chinner error = xfs_alloc_vextent(&args); 10830f712c9SDave Chinner if (error) { 10930f712c9SDave Chinner XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); 11030f712c9SDave Chinner return error; 11130f712c9SDave Chinner } 11230f712c9SDave Chinner if (args.fsbno == NULLFSBLOCK) { 11330f712c9SDave Chinner XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); 11430f712c9SDave Chinner *stat = 0; 11530f712c9SDave Chinner return 0; 11630f712c9SDave Chinner } 11730f712c9SDave Chinner ASSERT(args.len == 1); 11830f712c9SDave Chinner XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); 11930f712c9SDave Chinner 12030f712c9SDave Chinner new->s = cpu_to_be32(XFS_FSB_TO_AGBNO(args.mp, args.fsbno)); 12130f712c9SDave Chinner *stat = 1; 12230f712c9SDave Chinner return 0; 12330f712c9SDave Chinner } 12430f712c9SDave Chinner 12530f712c9SDave Chinner STATIC int 12630f712c9SDave Chinner xfs_inobt_free_block( 12730f712c9SDave Chinner struct xfs_btree_cur *cur, 12830f712c9SDave Chinner struct xfs_buf *bp) 12930f712c9SDave Chinner { 13030f712c9SDave Chinner xfs_fsblock_t fsbno; 13130f712c9SDave Chinner int error; 13230f712c9SDave Chinner 13330f712c9SDave Chinner fsbno = XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(bp)); 13430f712c9SDave Chinner error = xfs_free_extent(cur->bc_tp, fsbno, 1); 13530f712c9SDave Chinner if (error) 13630f712c9SDave Chinner return error; 13730f712c9SDave Chinner 13830f712c9SDave Chinner xfs_trans_binval(cur->bc_tp, bp); 13930f712c9SDave Chinner return error; 14030f712c9SDave Chinner } 14130f712c9SDave Chinner 14230f712c9SDave Chinner STATIC int 14330f712c9SDave Chinner xfs_inobt_get_maxrecs( 14430f712c9SDave Chinner struct xfs_btree_cur *cur, 14530f712c9SDave Chinner int level) 14630f712c9SDave Chinner { 14730f712c9SDave Chinner return cur->bc_mp->m_inobt_mxr[level != 0]; 14830f712c9SDave Chinner } 14930f712c9SDave Chinner 15030f712c9SDave Chinner STATIC void 15130f712c9SDave Chinner xfs_inobt_init_key_from_rec( 15230f712c9SDave Chinner union xfs_btree_key *key, 15330f712c9SDave Chinner union xfs_btree_rec *rec) 15430f712c9SDave Chinner { 15530f712c9SDave Chinner key->inobt.ir_startino = rec->inobt.ir_startino; 15630f712c9SDave Chinner } 15730f712c9SDave Chinner 15830f712c9SDave Chinner STATIC void 15930f712c9SDave Chinner xfs_inobt_init_rec_from_key( 16030f712c9SDave Chinner union xfs_btree_key *key, 16130f712c9SDave Chinner union xfs_btree_rec *rec) 16230f712c9SDave Chinner { 16330f712c9SDave Chinner rec->inobt.ir_startino = key->inobt.ir_startino; 16430f712c9SDave Chinner } 16530f712c9SDave Chinner 16630f712c9SDave Chinner STATIC void 16730f712c9SDave Chinner xfs_inobt_init_rec_from_cur( 16830f712c9SDave Chinner struct xfs_btree_cur *cur, 16930f712c9SDave Chinner union xfs_btree_rec *rec) 17030f712c9SDave Chinner { 17130f712c9SDave Chinner rec->inobt.ir_startino = cpu_to_be32(cur->bc_rec.i.ir_startino); 17230f712c9SDave Chinner rec->inobt.ir_freecount = cpu_to_be32(cur->bc_rec.i.ir_freecount); 17330f712c9SDave Chinner rec->inobt.ir_free = cpu_to_be64(cur->bc_rec.i.ir_free); 17430f712c9SDave Chinner } 17530f712c9SDave Chinner 17630f712c9SDave Chinner /* 17730f712c9SDave Chinner * initial value of ptr for lookup 17830f712c9SDave Chinner */ 17930f712c9SDave Chinner STATIC void 18030f712c9SDave Chinner xfs_inobt_init_ptr_from_cur( 18130f712c9SDave Chinner struct xfs_btree_cur *cur, 18230f712c9SDave Chinner union xfs_btree_ptr *ptr) 18330f712c9SDave Chinner { 18430f712c9SDave Chinner struct xfs_agi *agi = XFS_BUF_TO_AGI(cur->bc_private.a.agbp); 18530f712c9SDave Chinner 18630f712c9SDave Chinner ASSERT(cur->bc_private.a.agno == be32_to_cpu(agi->agi_seqno)); 18730f712c9SDave Chinner 18830f712c9SDave Chinner ptr->s = agi->agi_root; 18930f712c9SDave Chinner } 19030f712c9SDave Chinner 19130f712c9SDave Chinner STATIC void 19230f712c9SDave Chinner xfs_finobt_init_ptr_from_cur( 19330f712c9SDave Chinner struct xfs_btree_cur *cur, 19430f712c9SDave Chinner union xfs_btree_ptr *ptr) 19530f712c9SDave Chinner { 19630f712c9SDave Chinner struct xfs_agi *agi = XFS_BUF_TO_AGI(cur->bc_private.a.agbp); 19730f712c9SDave Chinner 19830f712c9SDave Chinner ASSERT(cur->bc_private.a.agno == be32_to_cpu(agi->agi_seqno)); 19930f712c9SDave Chinner ptr->s = agi->agi_free_root; 20030f712c9SDave Chinner } 20130f712c9SDave Chinner 20230f712c9SDave Chinner STATIC __int64_t 20330f712c9SDave Chinner xfs_inobt_key_diff( 20430f712c9SDave Chinner struct xfs_btree_cur *cur, 20530f712c9SDave Chinner union xfs_btree_key *key) 20630f712c9SDave Chinner { 20730f712c9SDave Chinner return (__int64_t)be32_to_cpu(key->inobt.ir_startino) - 20830f712c9SDave Chinner cur->bc_rec.i.ir_startino; 20930f712c9SDave Chinner } 21030f712c9SDave Chinner 21130f712c9SDave Chinner static int 21230f712c9SDave Chinner xfs_inobt_verify( 21330f712c9SDave Chinner struct xfs_buf *bp) 21430f712c9SDave Chinner { 21530f712c9SDave Chinner struct xfs_mount *mp = bp->b_target->bt_mount; 21630f712c9SDave Chinner struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); 21730f712c9SDave Chinner struct xfs_perag *pag = bp->b_pag; 21830f712c9SDave Chinner unsigned int level; 21930f712c9SDave Chinner 22030f712c9SDave Chinner /* 22130f712c9SDave Chinner * During growfs operations, we can't verify the exact owner as the 22230f712c9SDave Chinner * perag is not fully initialised and hence not attached to the buffer. 22330f712c9SDave Chinner * 22430f712c9SDave Chinner * Similarly, during log recovery we will have a perag structure 22530f712c9SDave Chinner * attached, but the agi information will not yet have been initialised 22630f712c9SDave Chinner * from the on disk AGI. We don't currently use any of this information, 22730f712c9SDave Chinner * but beware of the landmine (i.e. need to check pag->pagi_init) if we 22830f712c9SDave Chinner * ever do. 22930f712c9SDave Chinner */ 23030f712c9SDave Chinner switch (block->bb_magic) { 23130f712c9SDave Chinner case cpu_to_be32(XFS_IBT_CRC_MAGIC): 23230f712c9SDave Chinner case cpu_to_be32(XFS_FIBT_CRC_MAGIC): 23330f712c9SDave Chinner if (!xfs_sb_version_hascrc(&mp->m_sb)) 23430f712c9SDave Chinner return false; 23530f712c9SDave Chinner if (!uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_uuid)) 23630f712c9SDave Chinner return false; 23730f712c9SDave Chinner if (block->bb_u.s.bb_blkno != cpu_to_be64(bp->b_bn)) 23830f712c9SDave Chinner return false; 23930f712c9SDave Chinner if (pag && 24030f712c9SDave Chinner be32_to_cpu(block->bb_u.s.bb_owner) != pag->pag_agno) 24130f712c9SDave Chinner return false; 24230f712c9SDave Chinner /* fall through */ 24330f712c9SDave Chinner case cpu_to_be32(XFS_IBT_MAGIC): 24430f712c9SDave Chinner case cpu_to_be32(XFS_FIBT_MAGIC): 24530f712c9SDave Chinner break; 24630f712c9SDave Chinner default: 24730f712c9SDave Chinner return 0; 24830f712c9SDave Chinner } 24930f712c9SDave Chinner 25030f712c9SDave Chinner /* numrecs and level verification */ 25130f712c9SDave Chinner level = be16_to_cpu(block->bb_level); 25230f712c9SDave Chinner if (level >= mp->m_in_maxlevels) 25330f712c9SDave Chinner return false; 25430f712c9SDave Chinner if (be16_to_cpu(block->bb_numrecs) > mp->m_inobt_mxr[level != 0]) 25530f712c9SDave Chinner return false; 25630f712c9SDave Chinner 25730f712c9SDave Chinner /* sibling pointer verification */ 25830f712c9SDave Chinner if (!block->bb_u.s.bb_leftsib || 25930f712c9SDave Chinner (be32_to_cpu(block->bb_u.s.bb_leftsib) >= mp->m_sb.sb_agblocks && 26030f712c9SDave Chinner block->bb_u.s.bb_leftsib != cpu_to_be32(NULLAGBLOCK))) 26130f712c9SDave Chinner return false; 26230f712c9SDave Chinner if (!block->bb_u.s.bb_rightsib || 26330f712c9SDave Chinner (be32_to_cpu(block->bb_u.s.bb_rightsib) >= mp->m_sb.sb_agblocks && 26430f712c9SDave Chinner block->bb_u.s.bb_rightsib != cpu_to_be32(NULLAGBLOCK))) 26530f712c9SDave Chinner return false; 26630f712c9SDave Chinner 26730f712c9SDave Chinner return true; 26830f712c9SDave Chinner } 26930f712c9SDave Chinner 27030f712c9SDave Chinner static void 27130f712c9SDave Chinner xfs_inobt_read_verify( 27230f712c9SDave Chinner struct xfs_buf *bp) 27330f712c9SDave Chinner { 27430f712c9SDave Chinner if (!xfs_btree_sblock_verify_crc(bp)) 2752451337dSDave Chinner xfs_buf_ioerror(bp, -EFSBADCRC); 27630f712c9SDave Chinner else if (!xfs_inobt_verify(bp)) 2772451337dSDave Chinner xfs_buf_ioerror(bp, -EFSCORRUPTED); 27830f712c9SDave Chinner 27930f712c9SDave Chinner if (bp->b_error) { 28030f712c9SDave Chinner trace_xfs_btree_corrupt(bp, _RET_IP_); 28130f712c9SDave Chinner xfs_verifier_error(bp); 28230f712c9SDave Chinner } 28330f712c9SDave Chinner } 28430f712c9SDave Chinner 28530f712c9SDave Chinner static void 28630f712c9SDave Chinner xfs_inobt_write_verify( 28730f712c9SDave Chinner struct xfs_buf *bp) 28830f712c9SDave Chinner { 28930f712c9SDave Chinner if (!xfs_inobt_verify(bp)) { 29030f712c9SDave Chinner trace_xfs_btree_corrupt(bp, _RET_IP_); 2912451337dSDave Chinner xfs_buf_ioerror(bp, -EFSCORRUPTED); 29230f712c9SDave Chinner xfs_verifier_error(bp); 29330f712c9SDave Chinner return; 29430f712c9SDave Chinner } 29530f712c9SDave Chinner xfs_btree_sblock_calc_crc(bp); 29630f712c9SDave Chinner 29730f712c9SDave Chinner } 29830f712c9SDave Chinner 29930f712c9SDave Chinner const struct xfs_buf_ops xfs_inobt_buf_ops = { 30030f712c9SDave Chinner .verify_read = xfs_inobt_read_verify, 30130f712c9SDave Chinner .verify_write = xfs_inobt_write_verify, 30230f712c9SDave Chinner }; 30330f712c9SDave Chinner 30430f712c9SDave Chinner #if defined(DEBUG) || defined(XFS_WARN) 30530f712c9SDave Chinner STATIC int 30630f712c9SDave Chinner xfs_inobt_keys_inorder( 30730f712c9SDave Chinner struct xfs_btree_cur *cur, 30830f712c9SDave Chinner union xfs_btree_key *k1, 30930f712c9SDave Chinner union xfs_btree_key *k2) 31030f712c9SDave Chinner { 31130f712c9SDave Chinner return be32_to_cpu(k1->inobt.ir_startino) < 31230f712c9SDave Chinner be32_to_cpu(k2->inobt.ir_startino); 31330f712c9SDave Chinner } 31430f712c9SDave Chinner 31530f712c9SDave Chinner STATIC int 31630f712c9SDave Chinner xfs_inobt_recs_inorder( 31730f712c9SDave Chinner struct xfs_btree_cur *cur, 31830f712c9SDave Chinner union xfs_btree_rec *r1, 31930f712c9SDave Chinner union xfs_btree_rec *r2) 32030f712c9SDave Chinner { 32130f712c9SDave Chinner return be32_to_cpu(r1->inobt.ir_startino) + XFS_INODES_PER_CHUNK <= 32230f712c9SDave Chinner be32_to_cpu(r2->inobt.ir_startino); 32330f712c9SDave Chinner } 32430f712c9SDave Chinner #endif /* DEBUG */ 32530f712c9SDave Chinner 32630f712c9SDave Chinner static const struct xfs_btree_ops xfs_inobt_ops = { 32730f712c9SDave Chinner .rec_len = sizeof(xfs_inobt_rec_t), 32830f712c9SDave Chinner .key_len = sizeof(xfs_inobt_key_t), 32930f712c9SDave Chinner 33030f712c9SDave Chinner .dup_cursor = xfs_inobt_dup_cursor, 33130f712c9SDave Chinner .set_root = xfs_inobt_set_root, 33230f712c9SDave Chinner .alloc_block = xfs_inobt_alloc_block, 33330f712c9SDave Chinner .free_block = xfs_inobt_free_block, 33430f712c9SDave Chinner .get_minrecs = xfs_inobt_get_minrecs, 33530f712c9SDave Chinner .get_maxrecs = xfs_inobt_get_maxrecs, 33630f712c9SDave Chinner .init_key_from_rec = xfs_inobt_init_key_from_rec, 33730f712c9SDave Chinner .init_rec_from_key = xfs_inobt_init_rec_from_key, 33830f712c9SDave Chinner .init_rec_from_cur = xfs_inobt_init_rec_from_cur, 33930f712c9SDave Chinner .init_ptr_from_cur = xfs_inobt_init_ptr_from_cur, 34030f712c9SDave Chinner .key_diff = xfs_inobt_key_diff, 34130f712c9SDave Chinner .buf_ops = &xfs_inobt_buf_ops, 34230f712c9SDave Chinner #if defined(DEBUG) || defined(XFS_WARN) 34330f712c9SDave Chinner .keys_inorder = xfs_inobt_keys_inorder, 34430f712c9SDave Chinner .recs_inorder = xfs_inobt_recs_inorder, 34530f712c9SDave Chinner #endif 34630f712c9SDave Chinner }; 34730f712c9SDave Chinner 34830f712c9SDave Chinner static const struct xfs_btree_ops xfs_finobt_ops = { 34930f712c9SDave Chinner .rec_len = sizeof(xfs_inobt_rec_t), 35030f712c9SDave Chinner .key_len = sizeof(xfs_inobt_key_t), 35130f712c9SDave Chinner 35230f712c9SDave Chinner .dup_cursor = xfs_inobt_dup_cursor, 35330f712c9SDave Chinner .set_root = xfs_finobt_set_root, 35430f712c9SDave Chinner .alloc_block = xfs_inobt_alloc_block, 35530f712c9SDave Chinner .free_block = xfs_inobt_free_block, 35630f712c9SDave Chinner .get_minrecs = xfs_inobt_get_minrecs, 35730f712c9SDave Chinner .get_maxrecs = xfs_inobt_get_maxrecs, 35830f712c9SDave Chinner .init_key_from_rec = xfs_inobt_init_key_from_rec, 35930f712c9SDave Chinner .init_rec_from_key = xfs_inobt_init_rec_from_key, 36030f712c9SDave Chinner .init_rec_from_cur = xfs_inobt_init_rec_from_cur, 36130f712c9SDave Chinner .init_ptr_from_cur = xfs_finobt_init_ptr_from_cur, 36230f712c9SDave Chinner .key_diff = xfs_inobt_key_diff, 36330f712c9SDave Chinner .buf_ops = &xfs_inobt_buf_ops, 36430f712c9SDave Chinner #if defined(DEBUG) || defined(XFS_WARN) 36530f712c9SDave Chinner .keys_inorder = xfs_inobt_keys_inorder, 36630f712c9SDave Chinner .recs_inorder = xfs_inobt_recs_inorder, 36730f712c9SDave Chinner #endif 36830f712c9SDave Chinner }; 36930f712c9SDave Chinner 37030f712c9SDave Chinner /* 37130f712c9SDave Chinner * Allocate a new inode btree cursor. 37230f712c9SDave Chinner */ 37330f712c9SDave Chinner struct xfs_btree_cur * /* new inode btree cursor */ 37430f712c9SDave Chinner xfs_inobt_init_cursor( 37530f712c9SDave Chinner struct xfs_mount *mp, /* file system mount point */ 37630f712c9SDave Chinner struct xfs_trans *tp, /* transaction pointer */ 37730f712c9SDave Chinner struct xfs_buf *agbp, /* buffer for agi structure */ 37830f712c9SDave Chinner xfs_agnumber_t agno, /* allocation group number */ 37930f712c9SDave Chinner xfs_btnum_t btnum) /* ialloc or free ino btree */ 38030f712c9SDave Chinner { 38130f712c9SDave Chinner struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp); 38230f712c9SDave Chinner struct xfs_btree_cur *cur; 38330f712c9SDave Chinner 38430f712c9SDave Chinner cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP); 38530f712c9SDave Chinner 38630f712c9SDave Chinner cur->bc_tp = tp; 38730f712c9SDave Chinner cur->bc_mp = mp; 38830f712c9SDave Chinner cur->bc_btnum = btnum; 38930f712c9SDave Chinner if (btnum == XFS_BTNUM_INO) { 39030f712c9SDave Chinner cur->bc_nlevels = be32_to_cpu(agi->agi_level); 39130f712c9SDave Chinner cur->bc_ops = &xfs_inobt_ops; 39230f712c9SDave Chinner } else { 39330f712c9SDave Chinner cur->bc_nlevels = be32_to_cpu(agi->agi_free_level); 39430f712c9SDave Chinner cur->bc_ops = &xfs_finobt_ops; 39530f712c9SDave Chinner } 39630f712c9SDave Chinner 39730f712c9SDave Chinner cur->bc_blocklog = mp->m_sb.sb_blocklog; 39830f712c9SDave Chinner 39930f712c9SDave Chinner if (xfs_sb_version_hascrc(&mp->m_sb)) 40030f712c9SDave Chinner cur->bc_flags |= XFS_BTREE_CRC_BLOCKS; 40130f712c9SDave Chinner 40230f712c9SDave Chinner cur->bc_private.a.agbp = agbp; 40330f712c9SDave Chinner cur->bc_private.a.agno = agno; 40430f712c9SDave Chinner 40530f712c9SDave Chinner return cur; 40630f712c9SDave Chinner } 40730f712c9SDave Chinner 40830f712c9SDave Chinner /* 40930f712c9SDave Chinner * Calculate number of records in an inobt btree block. 41030f712c9SDave Chinner */ 41130f712c9SDave Chinner int 41230f712c9SDave Chinner xfs_inobt_maxrecs( 41330f712c9SDave Chinner struct xfs_mount *mp, 41430f712c9SDave Chinner int blocklen, 41530f712c9SDave Chinner int leaf) 41630f712c9SDave Chinner { 41730f712c9SDave Chinner blocklen -= XFS_INOBT_BLOCK_LEN(mp); 41830f712c9SDave Chinner 41930f712c9SDave Chinner if (leaf) 42030f712c9SDave Chinner return blocklen / sizeof(xfs_inobt_rec_t); 42130f712c9SDave Chinner return blocklen / (sizeof(xfs_inobt_key_t) + sizeof(xfs_inobt_ptr_t)); 42230f712c9SDave Chinner } 423