cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

xfs_alloc_btree.c (15854B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
      4 * All Rights Reserved.
      5 */
      6#include "xfs.h"
      7#include "xfs_fs.h"
      8#include "xfs_shared.h"
      9#include "xfs_format.h"
     10#include "xfs_log_format.h"
     11#include "xfs_trans_resv.h"
     12#include "xfs_mount.h"
     13#include "xfs_btree.h"
     14#include "xfs_btree_staging.h"
     15#include "xfs_alloc_btree.h"
     16#include "xfs_alloc.h"
     17#include "xfs_extent_busy.h"
     18#include "xfs_error.h"
     19#include "xfs_trace.h"
     20#include "xfs_trans.h"
     21#include "xfs_ag.h"
     22
     23static struct kmem_cache	*xfs_allocbt_cur_cache;
     24
     25STATIC struct xfs_btree_cur *
     26xfs_allocbt_dup_cursor(
     27	struct xfs_btree_cur	*cur)
     28{
     29	return xfs_allocbt_init_cursor(cur->bc_mp, cur->bc_tp,
     30			cur->bc_ag.agbp, cur->bc_ag.pag, cur->bc_btnum);
     31}
     32
     33STATIC void
     34xfs_allocbt_set_root(
     35	struct xfs_btree_cur		*cur,
     36	const union xfs_btree_ptr	*ptr,
     37	int				inc)
     38{
     39	struct xfs_buf		*agbp = cur->bc_ag.agbp;
     40	struct xfs_agf		*agf = agbp->b_addr;
     41	int			btnum = cur->bc_btnum;
     42
     43	ASSERT(ptr->s != 0);
     44
     45	agf->agf_roots[btnum] = ptr->s;
     46	be32_add_cpu(&agf->agf_levels[btnum], inc);
     47	cur->bc_ag.pag->pagf_levels[btnum] += inc;
     48
     49	xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_ROOTS | XFS_AGF_LEVELS);
     50}
     51
     52STATIC int
     53xfs_allocbt_alloc_block(
     54	struct xfs_btree_cur		*cur,
     55	const union xfs_btree_ptr	*start,
     56	union xfs_btree_ptr		*new,
     57	int				*stat)
     58{
     59	int			error;
     60	xfs_agblock_t		bno;
     61
     62	/* Allocate the new block from the freelist. If we can't, give up.  */
     63	error = xfs_alloc_get_freelist(cur->bc_tp, cur->bc_ag.agbp,
     64				       &bno, 1);
     65	if (error)
     66		return error;
     67
     68	if (bno == NULLAGBLOCK) {
     69		*stat = 0;
     70		return 0;
     71	}
     72
     73	atomic64_inc(&cur->bc_mp->m_allocbt_blks);
     74	xfs_extent_busy_reuse(cur->bc_mp, cur->bc_ag.agbp->b_pag, bno, 1, false);
     75
     76	new->s = cpu_to_be32(bno);
     77
     78	*stat = 1;
     79	return 0;
     80}
     81
     82STATIC int
     83xfs_allocbt_free_block(
     84	struct xfs_btree_cur	*cur,
     85	struct xfs_buf		*bp)
     86{
     87	struct xfs_buf		*agbp = cur->bc_ag.agbp;
     88	xfs_agblock_t		bno;
     89	int			error;
     90
     91	bno = xfs_daddr_to_agbno(cur->bc_mp, xfs_buf_daddr(bp));
     92	error = xfs_alloc_put_freelist(cur->bc_tp, agbp, NULL, bno, 1);
     93	if (error)
     94		return error;
     95
     96	atomic64_dec(&cur->bc_mp->m_allocbt_blks);
     97	xfs_extent_busy_insert(cur->bc_tp, agbp->b_pag, bno, 1,
     98			      XFS_EXTENT_BUSY_SKIP_DISCARD);
     99	return 0;
    100}
    101
    102/*
    103 * Update the longest extent in the AGF
    104 */
    105STATIC void
    106xfs_allocbt_update_lastrec(
    107	struct xfs_btree_cur		*cur,
    108	const struct xfs_btree_block	*block,
    109	const union xfs_btree_rec	*rec,
    110	int				ptr,
    111	int				reason)
    112{
    113	struct xfs_agf		*agf = cur->bc_ag.agbp->b_addr;
    114	struct xfs_perag	*pag;
    115	__be32			len;
    116	int			numrecs;
    117
    118	ASSERT(cur->bc_btnum == XFS_BTNUM_CNT);
    119
    120	switch (reason) {
    121	case LASTREC_UPDATE:
    122		/*
    123		 * If this is the last leaf block and it's the last record,
    124		 * then update the size of the longest extent in the AG.
    125		 */
    126		if (ptr != xfs_btree_get_numrecs(block))
    127			return;
    128		len = rec->alloc.ar_blockcount;
    129		break;
    130	case LASTREC_INSREC:
    131		if (be32_to_cpu(rec->alloc.ar_blockcount) <=
    132		    be32_to_cpu(agf->agf_longest))
    133			return;
    134		len = rec->alloc.ar_blockcount;
    135		break;
    136	case LASTREC_DELREC:
    137		numrecs = xfs_btree_get_numrecs(block);
    138		if (ptr <= numrecs)
    139			return;
    140		ASSERT(ptr == numrecs + 1);
    141
    142		if (numrecs) {
    143			xfs_alloc_rec_t *rrp;
    144
    145			rrp = XFS_ALLOC_REC_ADDR(cur->bc_mp, block, numrecs);
    146			len = rrp->ar_blockcount;
    147		} else {
    148			len = 0;
    149		}
    150
    151		break;
    152	default:
    153		ASSERT(0);
    154		return;
    155	}
    156
    157	agf->agf_longest = len;
    158	pag = cur->bc_ag.agbp->b_pag;
    159	pag->pagf_longest = be32_to_cpu(len);
    160	xfs_alloc_log_agf(cur->bc_tp, cur->bc_ag.agbp, XFS_AGF_LONGEST);
    161}
    162
    163STATIC int
    164xfs_allocbt_get_minrecs(
    165	struct xfs_btree_cur	*cur,
    166	int			level)
    167{
    168	return cur->bc_mp->m_alloc_mnr[level != 0];
    169}
    170
    171STATIC int
    172xfs_allocbt_get_maxrecs(
    173	struct xfs_btree_cur	*cur,
    174	int			level)
    175{
    176	return cur->bc_mp->m_alloc_mxr[level != 0];
    177}
    178
    179STATIC void
    180xfs_allocbt_init_key_from_rec(
    181	union xfs_btree_key		*key,
    182	const union xfs_btree_rec	*rec)
    183{
    184	key->alloc.ar_startblock = rec->alloc.ar_startblock;
    185	key->alloc.ar_blockcount = rec->alloc.ar_blockcount;
    186}
    187
    188STATIC void
    189xfs_bnobt_init_high_key_from_rec(
    190	union xfs_btree_key		*key,
    191	const union xfs_btree_rec	*rec)
    192{
    193	__u32				x;
    194
    195	x = be32_to_cpu(rec->alloc.ar_startblock);
    196	x += be32_to_cpu(rec->alloc.ar_blockcount) - 1;
    197	key->alloc.ar_startblock = cpu_to_be32(x);
    198	key->alloc.ar_blockcount = 0;
    199}
    200
    201STATIC void
    202xfs_cntbt_init_high_key_from_rec(
    203	union xfs_btree_key		*key,
    204	const union xfs_btree_rec	*rec)
    205{
    206	key->alloc.ar_blockcount = rec->alloc.ar_blockcount;
    207	key->alloc.ar_startblock = 0;
    208}
    209
    210STATIC void
    211xfs_allocbt_init_rec_from_cur(
    212	struct xfs_btree_cur	*cur,
    213	union xfs_btree_rec	*rec)
    214{
    215	rec->alloc.ar_startblock = cpu_to_be32(cur->bc_rec.a.ar_startblock);
    216	rec->alloc.ar_blockcount = cpu_to_be32(cur->bc_rec.a.ar_blockcount);
    217}
    218
    219STATIC void
    220xfs_allocbt_init_ptr_from_cur(
    221	struct xfs_btree_cur	*cur,
    222	union xfs_btree_ptr	*ptr)
    223{
    224	struct xfs_agf		*agf = cur->bc_ag.agbp->b_addr;
    225
    226	ASSERT(cur->bc_ag.pag->pag_agno == be32_to_cpu(agf->agf_seqno));
    227
    228	ptr->s = agf->agf_roots[cur->bc_btnum];
    229}
    230
    231STATIC int64_t
    232xfs_bnobt_key_diff(
    233	struct xfs_btree_cur		*cur,
    234	const union xfs_btree_key	*key)
    235{
    236	struct xfs_alloc_rec_incore	*rec = &cur->bc_rec.a;
    237	const struct xfs_alloc_rec	*kp = &key->alloc;
    238
    239	return (int64_t)be32_to_cpu(kp->ar_startblock) - rec->ar_startblock;
    240}
    241
    242STATIC int64_t
    243xfs_cntbt_key_diff(
    244	struct xfs_btree_cur		*cur,
    245	const union xfs_btree_key	*key)
    246{
    247	struct xfs_alloc_rec_incore	*rec = &cur->bc_rec.a;
    248	const struct xfs_alloc_rec	*kp = &key->alloc;
    249	int64_t				diff;
    250
    251	diff = (int64_t)be32_to_cpu(kp->ar_blockcount) - rec->ar_blockcount;
    252	if (diff)
    253		return diff;
    254
    255	return (int64_t)be32_to_cpu(kp->ar_startblock) - rec->ar_startblock;
    256}
    257
    258STATIC int64_t
    259xfs_bnobt_diff_two_keys(
    260	struct xfs_btree_cur		*cur,
    261	const union xfs_btree_key	*k1,
    262	const union xfs_btree_key	*k2)
    263{
    264	return (int64_t)be32_to_cpu(k1->alloc.ar_startblock) -
    265			  be32_to_cpu(k2->alloc.ar_startblock);
    266}
    267
    268STATIC int64_t
    269xfs_cntbt_diff_two_keys(
    270	struct xfs_btree_cur		*cur,
    271	const union xfs_btree_key	*k1,
    272	const union xfs_btree_key	*k2)
    273{
    274	int64_t				diff;
    275
    276	diff =  be32_to_cpu(k1->alloc.ar_blockcount) -
    277		be32_to_cpu(k2->alloc.ar_blockcount);
    278	if (diff)
    279		return diff;
    280
    281	return  be32_to_cpu(k1->alloc.ar_startblock) -
    282		be32_to_cpu(k2->alloc.ar_startblock);
    283}
    284
    285static xfs_failaddr_t
    286xfs_allocbt_verify(
    287	struct xfs_buf		*bp)
    288{
    289	struct xfs_mount	*mp = bp->b_mount;
    290	struct xfs_btree_block	*block = XFS_BUF_TO_BLOCK(bp);
    291	struct xfs_perag	*pag = bp->b_pag;
    292	xfs_failaddr_t		fa;
    293	unsigned int		level;
    294	xfs_btnum_t		btnum = XFS_BTNUM_BNOi;
    295
    296	if (!xfs_verify_magic(bp, block->bb_magic))
    297		return __this_address;
    298
    299	if (xfs_has_crc(mp)) {
    300		fa = xfs_btree_sblock_v5hdr_verify(bp);
    301		if (fa)
    302			return fa;
    303	}
    304
    305	/*
    306	 * The perag may not be attached during grow operations or fully
    307	 * initialized from the AGF during log recovery. Therefore we can only
    308	 * check against maximum tree depth from those contexts.
    309	 *
    310	 * Otherwise check against the per-tree limit. Peek at one of the
    311	 * verifier magic values to determine the type of tree we're verifying
    312	 * against.
    313	 */
    314	level = be16_to_cpu(block->bb_level);
    315	if (bp->b_ops->magic[0] == cpu_to_be32(XFS_ABTC_MAGIC))
    316		btnum = XFS_BTNUM_CNTi;
    317	if (pag && pag->pagf_init) {
    318		if (level >= pag->pagf_levels[btnum])
    319			return __this_address;
    320	} else if (level >= mp->m_alloc_maxlevels)
    321		return __this_address;
    322
    323	return xfs_btree_sblock_verify(bp, mp->m_alloc_mxr[level != 0]);
    324}
    325
    326static void
    327xfs_allocbt_read_verify(
    328	struct xfs_buf	*bp)
    329{
    330	xfs_failaddr_t	fa;
    331
    332	if (!xfs_btree_sblock_verify_crc(bp))
    333		xfs_verifier_error(bp, -EFSBADCRC, __this_address);
    334	else {
    335		fa = xfs_allocbt_verify(bp);
    336		if (fa)
    337			xfs_verifier_error(bp, -EFSCORRUPTED, fa);
    338	}
    339
    340	if (bp->b_error)
    341		trace_xfs_btree_corrupt(bp, _RET_IP_);
    342}
    343
    344static void
    345xfs_allocbt_write_verify(
    346	struct xfs_buf	*bp)
    347{
    348	xfs_failaddr_t	fa;
    349
    350	fa = xfs_allocbt_verify(bp);
    351	if (fa) {
    352		trace_xfs_btree_corrupt(bp, _RET_IP_);
    353		xfs_verifier_error(bp, -EFSCORRUPTED, fa);
    354		return;
    355	}
    356	xfs_btree_sblock_calc_crc(bp);
    357
    358}
    359
    360const struct xfs_buf_ops xfs_bnobt_buf_ops = {
    361	.name = "xfs_bnobt",
    362	.magic = { cpu_to_be32(XFS_ABTB_MAGIC),
    363		   cpu_to_be32(XFS_ABTB_CRC_MAGIC) },
    364	.verify_read = xfs_allocbt_read_verify,
    365	.verify_write = xfs_allocbt_write_verify,
    366	.verify_struct = xfs_allocbt_verify,
    367};
    368
    369const struct xfs_buf_ops xfs_cntbt_buf_ops = {
    370	.name = "xfs_cntbt",
    371	.magic = { cpu_to_be32(XFS_ABTC_MAGIC),
    372		   cpu_to_be32(XFS_ABTC_CRC_MAGIC) },
    373	.verify_read = xfs_allocbt_read_verify,
    374	.verify_write = xfs_allocbt_write_verify,
    375	.verify_struct = xfs_allocbt_verify,
    376};
    377
    378STATIC int
    379xfs_bnobt_keys_inorder(
    380	struct xfs_btree_cur		*cur,
    381	const union xfs_btree_key	*k1,
    382	const union xfs_btree_key	*k2)
    383{
    384	return be32_to_cpu(k1->alloc.ar_startblock) <
    385	       be32_to_cpu(k2->alloc.ar_startblock);
    386}
    387
    388STATIC int
    389xfs_bnobt_recs_inorder(
    390	struct xfs_btree_cur		*cur,
    391	const union xfs_btree_rec	*r1,
    392	const union xfs_btree_rec	*r2)
    393{
    394	return be32_to_cpu(r1->alloc.ar_startblock) +
    395		be32_to_cpu(r1->alloc.ar_blockcount) <=
    396		be32_to_cpu(r2->alloc.ar_startblock);
    397}
    398
    399STATIC int
    400xfs_cntbt_keys_inorder(
    401	struct xfs_btree_cur		*cur,
    402	const union xfs_btree_key	*k1,
    403	const union xfs_btree_key	*k2)
    404{
    405	return be32_to_cpu(k1->alloc.ar_blockcount) <
    406		be32_to_cpu(k2->alloc.ar_blockcount) ||
    407		(k1->alloc.ar_blockcount == k2->alloc.ar_blockcount &&
    408		 be32_to_cpu(k1->alloc.ar_startblock) <
    409		 be32_to_cpu(k2->alloc.ar_startblock));
    410}
    411
    412STATIC int
    413xfs_cntbt_recs_inorder(
    414	struct xfs_btree_cur		*cur,
    415	const union xfs_btree_rec	*r1,
    416	const union xfs_btree_rec	*r2)
    417{
    418	return be32_to_cpu(r1->alloc.ar_blockcount) <
    419		be32_to_cpu(r2->alloc.ar_blockcount) ||
    420		(r1->alloc.ar_blockcount == r2->alloc.ar_blockcount &&
    421		 be32_to_cpu(r1->alloc.ar_startblock) <
    422		 be32_to_cpu(r2->alloc.ar_startblock));
    423}
    424
    425static const struct xfs_btree_ops xfs_bnobt_ops = {
    426	.rec_len		= sizeof(xfs_alloc_rec_t),
    427	.key_len		= sizeof(xfs_alloc_key_t),
    428
    429	.dup_cursor		= xfs_allocbt_dup_cursor,
    430	.set_root		= xfs_allocbt_set_root,
    431	.alloc_block		= xfs_allocbt_alloc_block,
    432	.free_block		= xfs_allocbt_free_block,
    433	.update_lastrec		= xfs_allocbt_update_lastrec,
    434	.get_minrecs		= xfs_allocbt_get_minrecs,
    435	.get_maxrecs		= xfs_allocbt_get_maxrecs,
    436	.init_key_from_rec	= xfs_allocbt_init_key_from_rec,
    437	.init_high_key_from_rec	= xfs_bnobt_init_high_key_from_rec,
    438	.init_rec_from_cur	= xfs_allocbt_init_rec_from_cur,
    439	.init_ptr_from_cur	= xfs_allocbt_init_ptr_from_cur,
    440	.key_diff		= xfs_bnobt_key_diff,
    441	.buf_ops		= &xfs_bnobt_buf_ops,
    442	.diff_two_keys		= xfs_bnobt_diff_two_keys,
    443	.keys_inorder		= xfs_bnobt_keys_inorder,
    444	.recs_inorder		= xfs_bnobt_recs_inorder,
    445};
    446
    447static const struct xfs_btree_ops xfs_cntbt_ops = {
    448	.rec_len		= sizeof(xfs_alloc_rec_t),
    449	.key_len		= sizeof(xfs_alloc_key_t),
    450
    451	.dup_cursor		= xfs_allocbt_dup_cursor,
    452	.set_root		= xfs_allocbt_set_root,
    453	.alloc_block		= xfs_allocbt_alloc_block,
    454	.free_block		= xfs_allocbt_free_block,
    455	.update_lastrec		= xfs_allocbt_update_lastrec,
    456	.get_minrecs		= xfs_allocbt_get_minrecs,
    457	.get_maxrecs		= xfs_allocbt_get_maxrecs,
    458	.init_key_from_rec	= xfs_allocbt_init_key_from_rec,
    459	.init_high_key_from_rec	= xfs_cntbt_init_high_key_from_rec,
    460	.init_rec_from_cur	= xfs_allocbt_init_rec_from_cur,
    461	.init_ptr_from_cur	= xfs_allocbt_init_ptr_from_cur,
    462	.key_diff		= xfs_cntbt_key_diff,
    463	.buf_ops		= &xfs_cntbt_buf_ops,
    464	.diff_two_keys		= xfs_cntbt_diff_two_keys,
    465	.keys_inorder		= xfs_cntbt_keys_inorder,
    466	.recs_inorder		= xfs_cntbt_recs_inorder,
    467};
    468
    469/* Allocate most of a new allocation btree cursor. */
    470STATIC struct xfs_btree_cur *
    471xfs_allocbt_init_common(
    472	struct xfs_mount	*mp,
    473	struct xfs_trans	*tp,
    474	struct xfs_perag	*pag,
    475	xfs_btnum_t		btnum)
    476{
    477	struct xfs_btree_cur	*cur;
    478
    479	ASSERT(btnum == XFS_BTNUM_BNO || btnum == XFS_BTNUM_CNT);
    480
    481	cur = xfs_btree_alloc_cursor(mp, tp, btnum, mp->m_alloc_maxlevels,
    482			xfs_allocbt_cur_cache);
    483	cur->bc_ag.abt.active = false;
    484
    485	if (btnum == XFS_BTNUM_CNT) {
    486		cur->bc_ops = &xfs_cntbt_ops;
    487		cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_abtc_2);
    488		cur->bc_flags = XFS_BTREE_LASTREC_UPDATE;
    489	} else {
    490		cur->bc_ops = &xfs_bnobt_ops;
    491		cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_abtb_2);
    492	}
    493
    494	/* take a reference for the cursor */
    495	atomic_inc(&pag->pag_ref);
    496	cur->bc_ag.pag = pag;
    497
    498	if (xfs_has_crc(mp))
    499		cur->bc_flags |= XFS_BTREE_CRC_BLOCKS;
    500
    501	return cur;
    502}
    503
    504/*
    505 * Allocate a new allocation btree cursor.
    506 */
    507struct xfs_btree_cur *			/* new alloc btree cursor */
    508xfs_allocbt_init_cursor(
    509	struct xfs_mount	*mp,		/* file system mount point */
    510	struct xfs_trans	*tp,		/* transaction pointer */
    511	struct xfs_buf		*agbp,		/* buffer for agf structure */
    512	struct xfs_perag	*pag,
    513	xfs_btnum_t		btnum)		/* btree identifier */
    514{
    515	struct xfs_agf		*agf = agbp->b_addr;
    516	struct xfs_btree_cur	*cur;
    517
    518	cur = xfs_allocbt_init_common(mp, tp, pag, btnum);
    519	if (btnum == XFS_BTNUM_CNT)
    520		cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]);
    521	else
    522		cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]);
    523
    524	cur->bc_ag.agbp = agbp;
    525
    526	return cur;
    527}
    528
    529/* Create a free space btree cursor with a fake root for staging. */
    530struct xfs_btree_cur *
    531xfs_allocbt_stage_cursor(
    532	struct xfs_mount	*mp,
    533	struct xbtree_afakeroot	*afake,
    534	struct xfs_perag	*pag,
    535	xfs_btnum_t		btnum)
    536{
    537	struct xfs_btree_cur	*cur;
    538
    539	cur = xfs_allocbt_init_common(mp, NULL, pag, btnum);
    540	xfs_btree_stage_afakeroot(cur, afake);
    541	return cur;
    542}
    543
    544/*
    545 * Install a new free space btree root.  Caller is responsible for invalidating
    546 * and freeing the old btree blocks.
    547 */
    548void
    549xfs_allocbt_commit_staged_btree(
    550	struct xfs_btree_cur	*cur,
    551	struct xfs_trans	*tp,
    552	struct xfs_buf		*agbp)
    553{
    554	struct xfs_agf		*agf = agbp->b_addr;
    555	struct xbtree_afakeroot	*afake = cur->bc_ag.afake;
    556
    557	ASSERT(cur->bc_flags & XFS_BTREE_STAGING);
    558
    559	agf->agf_roots[cur->bc_btnum] = cpu_to_be32(afake->af_root);
    560	agf->agf_levels[cur->bc_btnum] = cpu_to_be32(afake->af_levels);
    561	xfs_alloc_log_agf(tp, agbp, XFS_AGF_ROOTS | XFS_AGF_LEVELS);
    562
    563	if (cur->bc_btnum == XFS_BTNUM_BNO) {
    564		xfs_btree_commit_afakeroot(cur, tp, agbp, &xfs_bnobt_ops);
    565	} else {
    566		cur->bc_flags |= XFS_BTREE_LASTREC_UPDATE;
    567		xfs_btree_commit_afakeroot(cur, tp, agbp, &xfs_cntbt_ops);
    568	}
    569}
    570
    571/* Calculate number of records in an alloc btree block. */
    572static inline unsigned int
    573xfs_allocbt_block_maxrecs(
    574	unsigned int		blocklen,
    575	bool			leaf)
    576{
    577	if (leaf)
    578		return blocklen / sizeof(xfs_alloc_rec_t);
    579	return blocklen / (sizeof(xfs_alloc_key_t) + sizeof(xfs_alloc_ptr_t));
    580}
    581
    582/*
    583 * Calculate number of records in an alloc btree block.
    584 */
    585int
    586xfs_allocbt_maxrecs(
    587	struct xfs_mount	*mp,
    588	int			blocklen,
    589	int			leaf)
    590{
    591	blocklen -= XFS_ALLOC_BLOCK_LEN(mp);
    592	return xfs_allocbt_block_maxrecs(blocklen, leaf);
    593}
    594
    595/* Free space btrees are at their largest when every other block is free. */
    596#define XFS_MAX_FREESP_RECORDS	((XFS_MAX_AG_BLOCKS + 1) / 2)
    597
    598/* Compute the max possible height for free space btrees. */
    599unsigned int
    600xfs_allocbt_maxlevels_ondisk(void)
    601{
    602	unsigned int		minrecs[2];
    603	unsigned int		blocklen;
    604
    605	blocklen = min(XFS_MIN_BLOCKSIZE - XFS_BTREE_SBLOCK_LEN,
    606		       XFS_MIN_CRC_BLOCKSIZE - XFS_BTREE_SBLOCK_CRC_LEN);
    607
    608	minrecs[0] = xfs_allocbt_block_maxrecs(blocklen, true) / 2;
    609	minrecs[1] = xfs_allocbt_block_maxrecs(blocklen, false) / 2;
    610
    611	return xfs_btree_compute_maxlevels(minrecs, XFS_MAX_FREESP_RECORDS);
    612}
    613
    614/* Calculate the freespace btree size for some records. */
    615xfs_extlen_t
    616xfs_allocbt_calc_size(
    617	struct xfs_mount	*mp,
    618	unsigned long long	len)
    619{
    620	return xfs_btree_calc_size(mp->m_alloc_mnr, len);
    621}
    622
    623int __init
    624xfs_allocbt_init_cur_cache(void)
    625{
    626	xfs_allocbt_cur_cache = kmem_cache_create("xfs_bnobt_cur",
    627			xfs_btree_cur_sizeof(xfs_allocbt_maxlevels_ondisk()),
    628			0, 0, NULL);
    629
    630	if (!xfs_allocbt_cur_cache)
    631		return -ENOMEM;
    632	return 0;
    633}
    634
    635void
    636xfs_allocbt_destroy_cur_cache(void)
    637{
    638	kmem_cache_destroy(xfs_allocbt_cur_cache);
    639	xfs_allocbt_cur_cache = NULL;
    640}