836 lines · c
1// SPDX-License-Identifier: GPL-2.02/*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_bit.h"13#include "xfs_mount.h"14#include "xfs_btree.h"15#include "xfs_btree_staging.h"16#include "xfs_ialloc.h"17#include "xfs_ialloc_btree.h"18#include "xfs_alloc.h"19#include "xfs_error.h"20#include "xfs_health.h"21#include "xfs_trace.h"22#include "xfs_trans.h"23#include "xfs_rmap.h"24#include "xfs_ag.h"25 26static struct kmem_cache *xfs_inobt_cur_cache;27 28STATIC int29xfs_inobt_get_minrecs(30 struct xfs_btree_cur *cur,31 int level)32{33 return M_IGEO(cur->bc_mp)->inobt_mnr[level != 0];34}35 36STATIC struct xfs_btree_cur *37xfs_inobt_dup_cursor(38 struct xfs_btree_cur *cur)39{40 return xfs_inobt_init_cursor(cur->bc_ag.pag, cur->bc_tp,41 cur->bc_ag.agbp);42}43 44STATIC struct xfs_btree_cur *45xfs_finobt_dup_cursor(46 struct xfs_btree_cur *cur)47{48 return xfs_finobt_init_cursor(cur->bc_ag.pag, cur->bc_tp,49 cur->bc_ag.agbp);50}51 52STATIC void53xfs_inobt_set_root(54 struct xfs_btree_cur *cur,55 const union xfs_btree_ptr *nptr,56 int inc) /* level change */57{58 struct xfs_buf *agbp = cur->bc_ag.agbp;59 struct xfs_agi *agi = agbp->b_addr;60 61 agi->agi_root = nptr->s;62 be32_add_cpu(&agi->agi_level, inc);63 xfs_ialloc_log_agi(cur->bc_tp, agbp, XFS_AGI_ROOT | XFS_AGI_LEVEL);64}65 66STATIC void67xfs_finobt_set_root(68 struct xfs_btree_cur *cur,69 const union xfs_btree_ptr *nptr,70 int inc) /* level change */71{72 struct xfs_buf *agbp = cur->bc_ag.agbp;73 struct xfs_agi *agi = agbp->b_addr;74 75 agi->agi_free_root = nptr->s;76 be32_add_cpu(&agi->agi_free_level, inc);77 xfs_ialloc_log_agi(cur->bc_tp, agbp,78 XFS_AGI_FREE_ROOT | XFS_AGI_FREE_LEVEL);79}80 81/* Update the inode btree block counter for this btree. */82static inline void83xfs_inobt_mod_blockcount(84 struct xfs_btree_cur *cur,85 int howmuch)86{87 struct xfs_buf *agbp = cur->bc_ag.agbp;88 struct xfs_agi *agi = agbp->b_addr;89 90 if (!xfs_has_inobtcounts(cur->bc_mp))91 return;92 93 if (xfs_btree_is_fino(cur->bc_ops))94 be32_add_cpu(&agi->agi_fblocks, howmuch);95 else96 be32_add_cpu(&agi->agi_iblocks, howmuch);97 xfs_ialloc_log_agi(cur->bc_tp, agbp, XFS_AGI_IBLOCKS);98}99 100STATIC int101__xfs_inobt_alloc_block(102 struct xfs_btree_cur *cur,103 const union xfs_btree_ptr *start,104 union xfs_btree_ptr *new,105 int *stat,106 enum xfs_ag_resv_type resv)107{108 xfs_alloc_arg_t args; /* block allocation args */109 int error; /* error return value */110 xfs_agblock_t sbno = be32_to_cpu(start->s);111 112 memset(&args, 0, sizeof(args));113 args.tp = cur->bc_tp;114 args.mp = cur->bc_mp;115 args.pag = cur->bc_ag.pag;116 args.oinfo = XFS_RMAP_OINFO_INOBT;117 args.minlen = 1;118 args.maxlen = 1;119 args.prod = 1;120 args.resv = resv;121 122 error = xfs_alloc_vextent_near_bno(&args,123 XFS_AGB_TO_FSB(args.mp, args.pag->pag_agno, sbno));124 if (error)125 return error;126 127 if (args.fsbno == NULLFSBLOCK) {128 *stat = 0;129 return 0;130 }131 ASSERT(args.len == 1);132 133 new->s = cpu_to_be32(XFS_FSB_TO_AGBNO(args.mp, args.fsbno));134 *stat = 1;135 xfs_inobt_mod_blockcount(cur, 1);136 return 0;137}138 139STATIC int140xfs_inobt_alloc_block(141 struct xfs_btree_cur *cur,142 const union xfs_btree_ptr *start,143 union xfs_btree_ptr *new,144 int *stat)145{146 return __xfs_inobt_alloc_block(cur, start, new, stat, XFS_AG_RESV_NONE);147}148 149STATIC int150xfs_finobt_alloc_block(151 struct xfs_btree_cur *cur,152 const union xfs_btree_ptr *start,153 union xfs_btree_ptr *new,154 int *stat)155{156 if (cur->bc_mp->m_finobt_nores)157 return xfs_inobt_alloc_block(cur, start, new, stat);158 return __xfs_inobt_alloc_block(cur, start, new, stat,159 XFS_AG_RESV_METADATA);160}161 162STATIC int163__xfs_inobt_free_block(164 struct xfs_btree_cur *cur,165 struct xfs_buf *bp,166 enum xfs_ag_resv_type resv)167{168 xfs_fsblock_t fsbno;169 170 xfs_inobt_mod_blockcount(cur, -1);171 fsbno = XFS_DADDR_TO_FSB(cur->bc_mp, xfs_buf_daddr(bp));172 return xfs_free_extent_later(cur->bc_tp, fsbno, 1,173 &XFS_RMAP_OINFO_INOBT, resv, 0);174}175 176STATIC int177xfs_inobt_free_block(178 struct xfs_btree_cur *cur,179 struct xfs_buf *bp)180{181 return __xfs_inobt_free_block(cur, bp, XFS_AG_RESV_NONE);182}183 184STATIC int185xfs_finobt_free_block(186 struct xfs_btree_cur *cur,187 struct xfs_buf *bp)188{189 if (cur->bc_mp->m_finobt_nores)190 return xfs_inobt_free_block(cur, bp);191 return __xfs_inobt_free_block(cur, bp, XFS_AG_RESV_METADATA);192}193 194STATIC int195xfs_inobt_get_maxrecs(196 struct xfs_btree_cur *cur,197 int level)198{199 return M_IGEO(cur->bc_mp)->inobt_mxr[level != 0];200}201 202STATIC void203xfs_inobt_init_key_from_rec(204 union xfs_btree_key *key,205 const union xfs_btree_rec *rec)206{207 key->inobt.ir_startino = rec->inobt.ir_startino;208}209 210STATIC void211xfs_inobt_init_high_key_from_rec(212 union xfs_btree_key *key,213 const union xfs_btree_rec *rec)214{215 __u32 x;216 217 x = be32_to_cpu(rec->inobt.ir_startino);218 x += XFS_INODES_PER_CHUNK - 1;219 key->inobt.ir_startino = cpu_to_be32(x);220}221 222STATIC void223xfs_inobt_init_rec_from_cur(224 struct xfs_btree_cur *cur,225 union xfs_btree_rec *rec)226{227 rec->inobt.ir_startino = cpu_to_be32(cur->bc_rec.i.ir_startino);228 if (xfs_has_sparseinodes(cur->bc_mp)) {229 rec->inobt.ir_u.sp.ir_holemask =230 cpu_to_be16(cur->bc_rec.i.ir_holemask);231 rec->inobt.ir_u.sp.ir_count = cur->bc_rec.i.ir_count;232 rec->inobt.ir_u.sp.ir_freecount = cur->bc_rec.i.ir_freecount;233 } else {234 /* ir_holemask/ir_count not supported on-disk */235 rec->inobt.ir_u.f.ir_freecount =236 cpu_to_be32(cur->bc_rec.i.ir_freecount);237 }238 rec->inobt.ir_free = cpu_to_be64(cur->bc_rec.i.ir_free);239}240 241/*242 * initial value of ptr for lookup243 */244STATIC void245xfs_inobt_init_ptr_from_cur(246 struct xfs_btree_cur *cur,247 union xfs_btree_ptr *ptr)248{249 struct xfs_agi *agi = cur->bc_ag.agbp->b_addr;250 251 ASSERT(cur->bc_ag.pag->pag_agno == be32_to_cpu(agi->agi_seqno));252 253 ptr->s = agi->agi_root;254}255 256STATIC void257xfs_finobt_init_ptr_from_cur(258 struct xfs_btree_cur *cur,259 union xfs_btree_ptr *ptr)260{261 struct xfs_agi *agi = cur->bc_ag.agbp->b_addr;262 263 ASSERT(cur->bc_ag.pag->pag_agno == be32_to_cpu(agi->agi_seqno));264 ptr->s = agi->agi_free_root;265}266 267STATIC int64_t268xfs_inobt_key_diff(269 struct xfs_btree_cur *cur,270 const union xfs_btree_key *key)271{272 return (int64_t)be32_to_cpu(key->inobt.ir_startino) -273 cur->bc_rec.i.ir_startino;274}275 276STATIC int64_t277xfs_inobt_diff_two_keys(278 struct xfs_btree_cur *cur,279 const union xfs_btree_key *k1,280 const union xfs_btree_key *k2,281 const union xfs_btree_key *mask)282{283 ASSERT(!mask || mask->inobt.ir_startino);284 285 return (int64_t)be32_to_cpu(k1->inobt.ir_startino) -286 be32_to_cpu(k2->inobt.ir_startino);287}288 289static xfs_failaddr_t290xfs_inobt_verify(291 struct xfs_buf *bp)292{293 struct xfs_mount *mp = bp->b_mount;294 struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp);295 xfs_failaddr_t fa;296 unsigned int level;297 298 if (!xfs_verify_magic(bp, block->bb_magic))299 return __this_address;300 301 /*302 * During growfs operations, we can't verify the exact owner as the303 * perag is not fully initialised and hence not attached to the buffer.304 *305 * Similarly, during log recovery we will have a perag structure306 * attached, but the agi information will not yet have been initialised307 * from the on disk AGI. We don't currently use any of this information,308 * but beware of the landmine (i.e. need to check309 * xfs_perag_initialised_agi(pag)) if we ever do.310 */311 if (xfs_has_crc(mp)) {312 fa = xfs_btree_agblock_v5hdr_verify(bp);313 if (fa)314 return fa;315 }316 317 /* level verification */318 level = be16_to_cpu(block->bb_level);319 if (level >= M_IGEO(mp)->inobt_maxlevels)320 return __this_address;321 322 return xfs_btree_agblock_verify(bp,323 M_IGEO(mp)->inobt_mxr[level != 0]);324}325 326static void327xfs_inobt_read_verify(328 struct xfs_buf *bp)329{330 xfs_failaddr_t fa;331 332 if (!xfs_btree_agblock_verify_crc(bp))333 xfs_verifier_error(bp, -EFSBADCRC, __this_address);334 else {335 fa = xfs_inobt_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 void345xfs_inobt_write_verify(346 struct xfs_buf *bp)347{348 xfs_failaddr_t fa;349 350 fa = xfs_inobt_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_agblock_calc_crc(bp);357 358}359 360const struct xfs_buf_ops xfs_inobt_buf_ops = {361 .name = "xfs_inobt",362 .magic = { cpu_to_be32(XFS_IBT_MAGIC), cpu_to_be32(XFS_IBT_CRC_MAGIC) },363 .verify_read = xfs_inobt_read_verify,364 .verify_write = xfs_inobt_write_verify,365 .verify_struct = xfs_inobt_verify,366};367 368const struct xfs_buf_ops xfs_finobt_buf_ops = {369 .name = "xfs_finobt",370 .magic = { cpu_to_be32(XFS_FIBT_MAGIC),371 cpu_to_be32(XFS_FIBT_CRC_MAGIC) },372 .verify_read = xfs_inobt_read_verify,373 .verify_write = xfs_inobt_write_verify,374 .verify_struct = xfs_inobt_verify,375};376 377STATIC int378xfs_inobt_keys_inorder(379 struct xfs_btree_cur *cur,380 const union xfs_btree_key *k1,381 const union xfs_btree_key *k2)382{383 return be32_to_cpu(k1->inobt.ir_startino) <384 be32_to_cpu(k2->inobt.ir_startino);385}386 387STATIC int388xfs_inobt_recs_inorder(389 struct xfs_btree_cur *cur,390 const union xfs_btree_rec *r1,391 const union xfs_btree_rec *r2)392{393 return be32_to_cpu(r1->inobt.ir_startino) + XFS_INODES_PER_CHUNK <=394 be32_to_cpu(r2->inobt.ir_startino);395}396 397STATIC enum xbtree_key_contig398xfs_inobt_keys_contiguous(399 struct xfs_btree_cur *cur,400 const union xfs_btree_key *key1,401 const union xfs_btree_key *key2,402 const union xfs_btree_key *mask)403{404 ASSERT(!mask || mask->inobt.ir_startino);405 406 return xbtree_key_contig(be32_to_cpu(key1->inobt.ir_startino),407 be32_to_cpu(key2->inobt.ir_startino));408}409 410const struct xfs_btree_ops xfs_inobt_ops = {411 .name = "ino",412 .type = XFS_BTREE_TYPE_AG,413 414 .rec_len = sizeof(xfs_inobt_rec_t),415 .key_len = sizeof(xfs_inobt_key_t),416 .ptr_len = XFS_BTREE_SHORT_PTR_LEN,417 418 .lru_refs = XFS_INO_BTREE_REF,419 .statoff = XFS_STATS_CALC_INDEX(xs_ibt_2),420 .sick_mask = XFS_SICK_AG_INOBT,421 422 .dup_cursor = xfs_inobt_dup_cursor,423 .set_root = xfs_inobt_set_root,424 .alloc_block = xfs_inobt_alloc_block,425 .free_block = xfs_inobt_free_block,426 .get_minrecs = xfs_inobt_get_minrecs,427 .get_maxrecs = xfs_inobt_get_maxrecs,428 .init_key_from_rec = xfs_inobt_init_key_from_rec,429 .init_high_key_from_rec = xfs_inobt_init_high_key_from_rec,430 .init_rec_from_cur = xfs_inobt_init_rec_from_cur,431 .init_ptr_from_cur = xfs_inobt_init_ptr_from_cur,432 .key_diff = xfs_inobt_key_diff,433 .buf_ops = &xfs_inobt_buf_ops,434 .diff_two_keys = xfs_inobt_diff_two_keys,435 .keys_inorder = xfs_inobt_keys_inorder,436 .recs_inorder = xfs_inobt_recs_inorder,437 .keys_contiguous = xfs_inobt_keys_contiguous,438};439 440const struct xfs_btree_ops xfs_finobt_ops = {441 .name = "fino",442 .type = XFS_BTREE_TYPE_AG,443 444 .rec_len = sizeof(xfs_inobt_rec_t),445 .key_len = sizeof(xfs_inobt_key_t),446 .ptr_len = XFS_BTREE_SHORT_PTR_LEN,447 448 .lru_refs = XFS_INO_BTREE_REF,449 .statoff = XFS_STATS_CALC_INDEX(xs_fibt_2),450 .sick_mask = XFS_SICK_AG_FINOBT,451 452 .dup_cursor = xfs_finobt_dup_cursor,453 .set_root = xfs_finobt_set_root,454 .alloc_block = xfs_finobt_alloc_block,455 .free_block = xfs_finobt_free_block,456 .get_minrecs = xfs_inobt_get_minrecs,457 .get_maxrecs = xfs_inobt_get_maxrecs,458 .init_key_from_rec = xfs_inobt_init_key_from_rec,459 .init_high_key_from_rec = xfs_inobt_init_high_key_from_rec,460 .init_rec_from_cur = xfs_inobt_init_rec_from_cur,461 .init_ptr_from_cur = xfs_finobt_init_ptr_from_cur,462 .key_diff = xfs_inobt_key_diff,463 .buf_ops = &xfs_finobt_buf_ops,464 .diff_two_keys = xfs_inobt_diff_two_keys,465 .keys_inorder = xfs_inobt_keys_inorder,466 .recs_inorder = xfs_inobt_recs_inorder,467 .keys_contiguous = xfs_inobt_keys_contiguous,468};469 470/*471 * Create an inode btree cursor.472 *473 * For staging cursors tp and agbp are NULL.474 */475struct xfs_btree_cur *476xfs_inobt_init_cursor(477 struct xfs_perag *pag,478 struct xfs_trans *tp,479 struct xfs_buf *agbp)480{481 struct xfs_mount *mp = pag->pag_mount;482 struct xfs_btree_cur *cur;483 484 cur = xfs_btree_alloc_cursor(mp, tp, &xfs_inobt_ops,485 M_IGEO(mp)->inobt_maxlevels, xfs_inobt_cur_cache);486 cur->bc_ag.pag = xfs_perag_hold(pag);487 cur->bc_ag.agbp = agbp;488 if (agbp) {489 struct xfs_agi *agi = agbp->b_addr;490 491 cur->bc_nlevels = be32_to_cpu(agi->agi_level);492 }493 return cur;494}495 496/*497 * Create a free inode btree cursor.498 *499 * For staging cursors tp and agbp are NULL.500 */501struct xfs_btree_cur *502xfs_finobt_init_cursor(503 struct xfs_perag *pag,504 struct xfs_trans *tp,505 struct xfs_buf *agbp)506{507 struct xfs_mount *mp = pag->pag_mount;508 struct xfs_btree_cur *cur;509 510 cur = xfs_btree_alloc_cursor(mp, tp, &xfs_finobt_ops,511 M_IGEO(mp)->inobt_maxlevels, xfs_inobt_cur_cache);512 cur->bc_ag.pag = xfs_perag_hold(pag);513 cur->bc_ag.agbp = agbp;514 if (agbp) {515 struct xfs_agi *agi = agbp->b_addr;516 517 cur->bc_nlevels = be32_to_cpu(agi->agi_free_level);518 }519 return cur;520}521 522/*523 * Install a new inobt btree root. Caller is responsible for invalidating524 * and freeing the old btree blocks.525 */526void527xfs_inobt_commit_staged_btree(528 struct xfs_btree_cur *cur,529 struct xfs_trans *tp,530 struct xfs_buf *agbp)531{532 struct xfs_agi *agi = agbp->b_addr;533 struct xbtree_afakeroot *afake = cur->bc_ag.afake;534 int fields;535 536 ASSERT(cur->bc_flags & XFS_BTREE_STAGING);537 538 if (xfs_btree_is_ino(cur->bc_ops)) {539 fields = XFS_AGI_ROOT | XFS_AGI_LEVEL;540 agi->agi_root = cpu_to_be32(afake->af_root);541 agi->agi_level = cpu_to_be32(afake->af_levels);542 if (xfs_has_inobtcounts(cur->bc_mp)) {543 agi->agi_iblocks = cpu_to_be32(afake->af_blocks);544 fields |= XFS_AGI_IBLOCKS;545 }546 xfs_ialloc_log_agi(tp, agbp, fields);547 xfs_btree_commit_afakeroot(cur, tp, agbp);548 } else {549 fields = XFS_AGI_FREE_ROOT | XFS_AGI_FREE_LEVEL;550 agi->agi_free_root = cpu_to_be32(afake->af_root);551 agi->agi_free_level = cpu_to_be32(afake->af_levels);552 if (xfs_has_inobtcounts(cur->bc_mp)) {553 agi->agi_fblocks = cpu_to_be32(afake->af_blocks);554 fields |= XFS_AGI_IBLOCKS;555 }556 xfs_ialloc_log_agi(tp, agbp, fields);557 xfs_btree_commit_afakeroot(cur, tp, agbp);558 }559}560 561/* Calculate number of records in an inode btree block. */562static inline unsigned int563xfs_inobt_block_maxrecs(564 unsigned int blocklen,565 bool leaf)566{567 if (leaf)568 return blocklen / sizeof(xfs_inobt_rec_t);569 return blocklen / (sizeof(xfs_inobt_key_t) + sizeof(xfs_inobt_ptr_t));570}571 572/*573 * Calculate number of records in an inobt btree block.574 */575unsigned int576xfs_inobt_maxrecs(577 struct xfs_mount *mp,578 unsigned int blocklen,579 bool leaf)580{581 blocklen -= XFS_INOBT_BLOCK_LEN(mp);582 return xfs_inobt_block_maxrecs(blocklen, leaf);583}584 585/*586 * Maximum number of inode btree records per AG. Pretend that we can fill an587 * entire AG completely full of inodes except for the AG headers.588 */589#define XFS_MAX_INODE_RECORDS \590 ((XFS_MAX_AG_BYTES - (4 * BBSIZE)) / XFS_DINODE_MIN_SIZE) / \591 XFS_INODES_PER_CHUNK592 593/* Compute the max possible height for the inode btree. */594static inline unsigned int595xfs_inobt_maxlevels_ondisk(void)596{597 unsigned int minrecs[2];598 unsigned int blocklen;599 600 blocklen = min(XFS_MIN_BLOCKSIZE - XFS_BTREE_SBLOCK_LEN,601 XFS_MIN_CRC_BLOCKSIZE - XFS_BTREE_SBLOCK_CRC_LEN);602 603 minrecs[0] = xfs_inobt_block_maxrecs(blocklen, true) / 2;604 minrecs[1] = xfs_inobt_block_maxrecs(blocklen, false) / 2;605 606 return xfs_btree_compute_maxlevels(minrecs, XFS_MAX_INODE_RECORDS);607}608 609/* Compute the max possible height for the free inode btree. */610static inline unsigned int611xfs_finobt_maxlevels_ondisk(void)612{613 unsigned int minrecs[2];614 unsigned int blocklen;615 616 blocklen = XFS_MIN_CRC_BLOCKSIZE - XFS_BTREE_SBLOCK_CRC_LEN;617 618 minrecs[0] = xfs_inobt_block_maxrecs(blocklen, true) / 2;619 minrecs[1] = xfs_inobt_block_maxrecs(blocklen, false) / 2;620 621 return xfs_btree_compute_maxlevels(minrecs, XFS_MAX_INODE_RECORDS);622}623 624/* Compute the max possible height for either inode btree. */625unsigned int626xfs_iallocbt_maxlevels_ondisk(void)627{628 return max(xfs_inobt_maxlevels_ondisk(),629 xfs_finobt_maxlevels_ondisk());630}631 632/*633 * Convert the inode record holemask to an inode allocation bitmap. The inode634 * allocation bitmap is inode granularity and specifies whether an inode is635 * physically allocated on disk (not whether the inode is considered allocated636 * or free by the fs).637 *638 * A bit value of 1 means the inode is allocated, a value of 0 means it is free.639 */640uint64_t641xfs_inobt_irec_to_allocmask(642 const struct xfs_inobt_rec_incore *rec)643{644 uint64_t bitmap = 0;645 uint64_t inodespbit;646 int nextbit;647 uint allocbitmap;648 649 /*650 * The holemask has 16-bits for a 64 inode record. Therefore each651 * holemask bit represents multiple inodes. Create a mask of bits to set652 * in the allocmask for each holemask bit.653 */654 inodespbit = (1 << XFS_INODES_PER_HOLEMASK_BIT) - 1;655 656 /*657 * Allocated inodes are represented by 0 bits in holemask. Invert the 0658 * bits to 1 and convert to a uint so we can use xfs_next_bit(). Mask659 * anything beyond the 16 holemask bits since this casts to a larger660 * type.661 */662 allocbitmap = ~rec->ir_holemask & ((1 << XFS_INOBT_HOLEMASK_BITS) - 1);663 664 /*665 * allocbitmap is the inverted holemask so every set bit represents666 * allocated inodes. To expand from 16-bit holemask granularity to667 * 64-bit (e.g., bit-per-inode), set inodespbit bits in the target668 * bitmap for every holemask bit.669 */670 nextbit = xfs_next_bit(&allocbitmap, 1, 0);671 while (nextbit != -1) {672 ASSERT(nextbit < (sizeof(rec->ir_holemask) * NBBY));673 674 bitmap |= (inodespbit <<675 (nextbit * XFS_INODES_PER_HOLEMASK_BIT));676 677 nextbit = xfs_next_bit(&allocbitmap, 1, nextbit + 1);678 }679 680 return bitmap;681}682 683#if defined(DEBUG) || defined(XFS_WARN)684/*685 * Verify that an in-core inode record has a valid inode count.686 */687int688xfs_inobt_rec_check_count(689 struct xfs_mount *mp,690 struct xfs_inobt_rec_incore *rec)691{692 int inocount = 0;693 int nextbit = 0;694 uint64_t allocbmap;695 int wordsz;696 697 wordsz = sizeof(allocbmap) / sizeof(unsigned int);698 allocbmap = xfs_inobt_irec_to_allocmask(rec);699 700 nextbit = xfs_next_bit((uint *) &allocbmap, wordsz, nextbit);701 while (nextbit != -1) {702 inocount++;703 nextbit = xfs_next_bit((uint *) &allocbmap, wordsz,704 nextbit + 1);705 }706 707 if (inocount != rec->ir_count)708 return -EFSCORRUPTED;709 710 return 0;711}712#endif /* DEBUG */713 714static xfs_extlen_t715xfs_inobt_max_size(716 struct xfs_perag *pag)717{718 struct xfs_mount *mp = pag->pag_mount;719 xfs_agblock_t agblocks = pag->block_count;720 721 /* Bail out if we're uninitialized, which can happen in mkfs. */722 if (M_IGEO(mp)->inobt_mxr[0] == 0)723 return 0;724 725 /*726 * The log is permanently allocated, so the space it occupies will727 * never be available for the kinds of things that would require btree728 * expansion. We therefore can pretend the space isn't there.729 */730 if (xfs_ag_contains_log(mp, pag->pag_agno))731 agblocks -= mp->m_sb.sb_logblocks;732 733 return xfs_btree_calc_size(M_IGEO(mp)->inobt_mnr,734 (uint64_t)agblocks * mp->m_sb.sb_inopblock /735 XFS_INODES_PER_CHUNK);736}737 738static int739xfs_finobt_count_blocks(740 struct xfs_perag *pag,741 struct xfs_trans *tp,742 xfs_extlen_t *tree_blocks)743{744 struct xfs_buf *agbp = NULL;745 struct xfs_btree_cur *cur;746 int error;747 748 error = xfs_ialloc_read_agi(pag, tp, 0, &agbp);749 if (error)750 return error;751 752 cur = xfs_finobt_init_cursor(pag, tp, agbp);753 error = xfs_btree_count_blocks(cur, tree_blocks);754 xfs_btree_del_cursor(cur, error);755 xfs_trans_brelse(tp, agbp);756 757 return error;758}759 760/* Read finobt block count from AGI header. */761static int762xfs_finobt_read_blocks(763 struct xfs_perag *pag,764 struct xfs_trans *tp,765 xfs_extlen_t *tree_blocks)766{767 struct xfs_buf *agbp;768 struct xfs_agi *agi;769 int error;770 771 error = xfs_ialloc_read_agi(pag, tp, 0, &agbp);772 if (error)773 return error;774 775 agi = agbp->b_addr;776 *tree_blocks = be32_to_cpu(agi->agi_fblocks);777 xfs_trans_brelse(tp, agbp);778 return 0;779}780 781/*782 * Figure out how many blocks to reserve and how many are used by this btree.783 */784int785xfs_finobt_calc_reserves(786 struct xfs_perag *pag,787 struct xfs_trans *tp,788 xfs_extlen_t *ask,789 xfs_extlen_t *used)790{791 xfs_extlen_t tree_len = 0;792 int error;793 794 if (!xfs_has_finobt(pag->pag_mount))795 return 0;796 797 if (xfs_has_inobtcounts(pag->pag_mount))798 error = xfs_finobt_read_blocks(pag, tp, &tree_len);799 else800 error = xfs_finobt_count_blocks(pag, tp, &tree_len);801 if (error)802 return error;803 804 *ask += xfs_inobt_max_size(pag);805 *used += tree_len;806 return 0;807}808 809/* Calculate the inobt btree size for some records. */810xfs_extlen_t811xfs_iallocbt_calc_size(812 struct xfs_mount *mp,813 unsigned long long len)814{815 return xfs_btree_calc_size(M_IGEO(mp)->inobt_mnr, len);816}817 818int __init819xfs_inobt_init_cur_cache(void)820{821 xfs_inobt_cur_cache = kmem_cache_create("xfs_inobt_cur",822 xfs_btree_cur_sizeof(xfs_inobt_maxlevels_ondisk()),823 0, 0, NULL);824 825 if (!xfs_inobt_cur_cache)826 return -ENOMEM;827 return 0;828}829 830void831xfs_inobt_destroy_cur_cache(void)832{833 kmem_cache_destroy(xfs_inobt_cur_cache);834 xfs_inobt_cur_cache = NULL;835}836