xref: /openbmc/linux/fs/xfs/libxfs/xfs_ialloc_btree.c (revision 2451337d)
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