Merge tag 'mm-hotfixes-stable-2025-07-11-16-16' of git://git.kernel.org/pub/scm/linux...
[linux-2.6-block.git] / fs / xfs / libxfs / xfs_ialloc_btree.c
CommitLineData
0b61f8a4 1// SPDX-License-Identifier: GPL-2.0
1da177e4 2/*
7b718769
NS
3 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
4 * All Rights Reserved.
1da177e4 5 */
1da177e4 6#include "xfs.h"
a844f451 7#include "xfs_fs.h"
632b89e8 8#include "xfs_shared.h"
a4fbe6ab 9#include "xfs_format.h"
239880ef
DC
10#include "xfs_log_format.h"
11#include "xfs_trans_resv.h"
a844f451 12#include "xfs_bit.h"
1da177e4 13#include "xfs_mount.h"
1da177e4 14#include "xfs_btree.h"
c29ce8f4 15#include "xfs_btree_staging.h"
1da177e4 16#include "xfs_ialloc.h"
a4fbe6ab 17#include "xfs_ialloc_btree.h"
1da177e4
LT
18#include "xfs_alloc.h"
19#include "xfs_error.h"
7f47734a 20#include "xfs_health.h"
3d3e6f64 21#include "xfs_trace.h"
239880ef 22#include "xfs_trans.h"
340785cc 23#include "xfs_rmap.h"
30933120 24#include "xfs_ag.h"
1da177e4 25
e7720afa 26static struct kmem_cache *xfs_inobt_cur_cache;
9fa47bdc 27
91cca5df
CH
28STATIC int
29xfs_inobt_get_minrecs(
30 struct xfs_btree_cur *cur,
31 int level)
32{
ef325959 33 return M_IGEO(cur->bc_mp)->inobt_mnr[level != 0];
91cca5df 34}
1da177e4 35
561f7d17
CH
36STATIC struct xfs_btree_cur *
37xfs_inobt_dup_cursor(
38 struct xfs_btree_cur *cur)
39{
77a530e6 40 return xfs_inobt_init_cursor(to_perag(cur->bc_group), cur->bc_tp,
14dd46cf
CH
41 cur->bc_ag.agbp);
42}
43
44STATIC struct xfs_btree_cur *
45xfs_finobt_dup_cursor(
46 struct xfs_btree_cur *cur)
47{
77a530e6 48 return xfs_finobt_init_cursor(to_perag(cur->bc_group), cur->bc_tp,
14dd46cf 49 cur->bc_ag.agbp);
561f7d17
CH
50}
51
344207ce
CH
52STATIC void
53xfs_inobt_set_root(
b5a6e5fe
DW
54 struct xfs_btree_cur *cur,
55 const union xfs_btree_ptr *nptr,
56 int inc) /* level change */
344207ce 57{
576af732 58 struct xfs_buf *agbp = cur->bc_ag.agbp;
370c782b 59 struct xfs_agi *agi = agbp->b_addr;
344207ce
CH
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
aafc3c24
BF
66STATIC void
67xfs_finobt_set_root(
b5a6e5fe
DW
68 struct xfs_btree_cur *cur,
69 const union xfs_btree_ptr *nptr,
70 int inc) /* level change */
aafc3c24 71{
576af732 72 struct xfs_buf *agbp = cur->bc_ag.agbp;
370c782b 73 struct xfs_agi *agi = agbp->b_addr;
aafc3c24
BF
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
2a39946c
DW
81/* Update the inode btree block counter for this btree. */
82static inline void
83xfs_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
ebd9027d 90 if (!xfs_has_inobtcounts(cur->bc_mp))
2a39946c
DW
91 return;
92
ec793e69 93 if (xfs_btree_is_fino(cur->bc_ops))
2a39946c 94 be32_add_cpu(&agi->agi_fblocks, howmuch);
ec793e69 95 else
2a39946c
DW
96 be32_add_cpu(&agi->agi_iblocks, howmuch);
97 xfs_ialloc_log_agi(cur->bc_tp, agbp, XFS_AGI_IBLOCKS);
98}
99
f5eb8e7c 100STATIC int
76d771b4 101__xfs_inobt_alloc_block(
deb06b9a
DW
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)
f5eb8e7c
CH
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
f5eb8e7c
CH
112 memset(&args, 0, sizeof(args));
113 args.tp = cur->bc_tp;
114 args.mp = cur->bc_mp;
77a530e6 115 args.pag = to_perag(cur->bc_group);
7280feda 116 args.oinfo = XFS_RMAP_OINFO_INOBT;
f5eb8e7c
CH
117 args.minlen = 1;
118 args.maxlen = 1;
119 args.prod = 1;
76d771b4 120 args.resv = resv;
f5eb8e7c 121
db4710fd 122 error = xfs_alloc_vextent_near_bno(&args,
856a920a 123 xfs_agbno_to_fsb(args.pag, sbno));
e157ebdc 124 if (error)
f5eb8e7c 125 return error;
e157ebdc 126
f5eb8e7c 127 if (args.fsbno == NULLFSBLOCK) {
f5eb8e7c
CH
128 *stat = 0;
129 return 0;
130 }
131 ASSERT(args.len == 1);
f5eb8e7c
CH
132
133 new->s = cpu_to_be32(XFS_FSB_TO_AGBNO(args.mp, args.fsbno));
134 *stat = 1;
2a39946c 135 xfs_inobt_mod_blockcount(cur, 1);
f5eb8e7c
CH
136 return 0;
137}
138
76d771b4
CH
139STATIC int
140xfs_inobt_alloc_block(
deb06b9a
DW
141 struct xfs_btree_cur *cur,
142 const union xfs_btree_ptr *start,
143 union xfs_btree_ptr *new,
144 int *stat)
76d771b4
CH
145{
146 return __xfs_inobt_alloc_block(cur, start, new, stat, XFS_AG_RESV_NONE);
147}
148
149STATIC int
150xfs_finobt_alloc_block(
deb06b9a
DW
151 struct xfs_btree_cur *cur,
152 const union xfs_btree_ptr *start,
153 union xfs_btree_ptr *new,
154 int *stat)
76d771b4 155{
e1f6ca11 156 if (cur->bc_mp->m_finobt_nores)
ad90bb58 157 return xfs_inobt_alloc_block(cur, start, new, stat);
76d771b4
CH
158 return __xfs_inobt_alloc_block(cur, start, new, stat,
159 XFS_AG_RESV_METADATA);
160}
161
d4b3a4b7 162STATIC int
ad90bb58 163__xfs_inobt_free_block(
d4b3a4b7 164 struct xfs_btree_cur *cur,
ad90bb58
BF
165 struct xfs_buf *bp,
166 enum xfs_ag_resv_type resv)
d4b3a4b7 167{
b2ccab31
DW
168 xfs_fsblock_t fsbno;
169
2a39946c 170 xfs_inobt_mod_blockcount(cur, -1);
b2ccab31 171 fsbno = XFS_DADDR_TO_FSB(cur->bc_mp, xfs_buf_daddr(bp));
b742d7b4 172 return xfs_free_extent_later(cur->bc_tp, fsbno, 1,
980faece 173 &XFS_RMAP_OINFO_INOBT, resv, 0);
ad90bb58
BF
174}
175
176STATIC int
177xfs_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 int
185xfs_finobt_free_block(
186 struct xfs_btree_cur *cur,
187 struct xfs_buf *bp)
188{
e1f6ca11 189 if (cur->bc_mp->m_finobt_nores)
ad90bb58
BF
190 return xfs_inobt_free_block(cur, bp);
191 return __xfs_inobt_free_block(cur, bp, XFS_AG_RESV_METADATA);
d4b3a4b7 192}
f5eb8e7c 193
ce5e42db
CH
194STATIC int
195xfs_inobt_get_maxrecs(
196 struct xfs_btree_cur *cur,
197 int level)
198{
ef325959 199 return M_IGEO(cur->bc_mp)->inobt_mxr[level != 0];
ce5e42db
CH
200}
201
fe033cc8
CH
202STATIC void
203xfs_inobt_init_key_from_rec(
23825cd1
DW
204 union xfs_btree_key *key,
205 const union xfs_btree_rec *rec)
fe033cc8
CH
206{
207 key->inobt.ir_startino = rec->inobt.ir_startino;
208}
209
118bb47e
DW
210STATIC void
211xfs_inobt_init_high_key_from_rec(
23825cd1
DW
212 union xfs_btree_key *key,
213 const union xfs_btree_rec *rec)
118bb47e 214{
23825cd1 215 __u32 x;
118bb47e
DW
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
4b22a571
CH
222STATIC void
223xfs_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);
38c26bfd 228 if (xfs_has_sparseinodes(cur->bc_mp)) {
5419040f
BF
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 }
4b22a571
CH
238 rec->inobt.ir_free = cpu_to_be64(cur->bc_rec.i.ir_free);
239}
240
fe033cc8 241/*
9da096fd 242 * initial value of ptr for lookup
fe033cc8
CH
243 */
244STATIC void
245xfs_inobt_init_ptr_from_cur(
246 struct xfs_btree_cur *cur,
247 union xfs_btree_ptr *ptr)
248{
576af732 249 struct xfs_agi *agi = cur->bc_ag.agbp->b_addr;
fe033cc8 250
77a530e6 251 ASSERT(cur->bc_group->xg_gno == be32_to_cpu(agi->agi_seqno));
fe033cc8
CH
252
253 ptr->s = agi->agi_root;
254}
255
aafc3c24
BF
256STATIC void
257xfs_finobt_init_ptr_from_cur(
258 struct xfs_btree_cur *cur,
259 union xfs_btree_ptr *ptr)
260{
576af732 261 struct xfs_agi *agi = cur->bc_ag.agbp->b_addr;
aafc3c24 262
77a530e6
CH
263 ASSERT(cur->bc_group->xg_gno == be32_to_cpu(agi->agi_seqno));
264
aafc3c24
BF
265 ptr->s = agi->agi_free_root;
266}
267
c8ce540d 268STATIC int64_t
fe033cc8 269xfs_inobt_key_diff(
d29d5577
DW
270 struct xfs_btree_cur *cur,
271 const union xfs_btree_key *key)
fe033cc8 272{
c8ce540d 273 return (int64_t)be32_to_cpu(key->inobt.ir_startino) -
fe033cc8
CH
274 cur->bc_rec.i.ir_startino;
275}
276
118bb47e
DW
277STATIC int64_t
278xfs_inobt_diff_two_keys(
d29d5577
DW
279 struct xfs_btree_cur *cur,
280 const union xfs_btree_key *k1,
4a200a09
DW
281 const union xfs_btree_key *k2,
282 const union xfs_btree_key *mask)
118bb47e 283{
4a200a09
DW
284 ASSERT(!mask || mask->inobt.ir_startino);
285
118bb47e 286 return (int64_t)be32_to_cpu(k1->inobt.ir_startino) -
4a200a09 287 be32_to_cpu(k2->inobt.ir_startino);
118bb47e
DW
288}
289
a6a781a5 290static xfs_failaddr_t
612cfbfe 291xfs_inobt_verify(
3d3e6f64
DC
292 struct xfs_buf *bp)
293{
dbd329f1 294 struct xfs_mount *mp = bp->b_mount;
3d3e6f64 295 struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp);
a6a781a5 296 xfs_failaddr_t fa;
3d3e6f64 297 unsigned int level;
3d3e6f64 298
8473fee3
BF
299 if (!xfs_verify_magic(bp, block->bb_magic))
300 return __this_address;
301
ee1a47ab
CH
302 /*
303 * During growfs operations, we can't verify the exact owner as the
304 * perag is not fully initialised and hence not attached to the buffer.
305 *
306 * Similarly, during log recovery we will have a perag structure
307 * attached, but the agi information will not yet have been initialised
308 * from the on disk AGI. We don't currently use any of this information,
7ac2ff8b
DC
309 * but beware of the landmine (i.e. need to check
310 * xfs_perag_initialised_agi(pag)) if we ever do.
ee1a47ab 311 */
ebd9027d 312 if (xfs_has_crc(mp)) {
5ef819c3 313 fa = xfs_btree_agblock_v5hdr_verify(bp);
a6a781a5
DW
314 if (fa)
315 return fa;
ee1a47ab 316 }
3d3e6f64 317
c5ab131b 318 /* level verification */
ee1a47ab 319 level = be16_to_cpu(block->bb_level);
ef325959 320 if (level >= M_IGEO(mp)->inobt_maxlevels)
a6a781a5 321 return __this_address;
ee1a47ab 322
5ef819c3 323 return xfs_btree_agblock_verify(bp,
ef325959 324 M_IGEO(mp)->inobt_mxr[level != 0]);
612cfbfe
DC
325}
326
327static void
1813dd64 328xfs_inobt_read_verify(
612cfbfe
DC
329 struct xfs_buf *bp)
330{
bc1a09b8
DW
331 xfs_failaddr_t fa;
332
5ef819c3 333 if (!xfs_btree_agblock_verify_crc(bp))
bc1a09b8
DW
334 xfs_verifier_error(bp, -EFSBADCRC, __this_address);
335 else {
336 fa = xfs_inobt_verify(bp);
337 if (fa)
338 xfs_verifier_error(bp, -EFSCORRUPTED, fa);
339 }
ce5028cf 340
31ca03c9 341 if (bp->b_error)
ce5028cf 342 trace_xfs_btree_corrupt(bp, _RET_IP_);
612cfbfe 343}
3d3e6f64 344
1813dd64
DC
345static void
346xfs_inobt_write_verify(
612cfbfe
DC
347 struct xfs_buf *bp)
348{
bc1a09b8
DW
349 xfs_failaddr_t fa;
350
351 fa = xfs_inobt_verify(bp);
352 if (fa) {
ee1a47ab 353 trace_xfs_btree_corrupt(bp, _RET_IP_);
bc1a09b8 354 xfs_verifier_error(bp, -EFSCORRUPTED, fa);
e0d2c23a 355 return;
ee1a47ab 356 }
5ef819c3 357 xfs_btree_agblock_calc_crc(bp);
ee1a47ab 358
3d3e6f64
DC
359}
360
1813dd64 361const struct xfs_buf_ops xfs_inobt_buf_ops = {
233135b7 362 .name = "xfs_inobt",
8473fee3 363 .magic = { cpu_to_be32(XFS_IBT_MAGIC), cpu_to_be32(XFS_IBT_CRC_MAGIC) },
1813dd64
DC
364 .verify_read = xfs_inobt_read_verify,
365 .verify_write = xfs_inobt_write_verify,
b5572597 366 .verify_struct = xfs_inobt_verify,
1813dd64
DC
367};
368
01e68f40
BF
369const struct xfs_buf_ops xfs_finobt_buf_ops = {
370 .name = "xfs_finobt",
8473fee3
BF
371 .magic = { cpu_to_be32(XFS_FIBT_MAGIC),
372 cpu_to_be32(XFS_FIBT_CRC_MAGIC) },
01e68f40
BF
373 .verify_read = xfs_inobt_read_verify,
374 .verify_write = xfs_inobt_write_verify,
375 .verify_struct = xfs_inobt_verify,
376};
377
4a26e66e
CH
378STATIC int
379xfs_inobt_keys_inorder(
8e38dc88
DW
380 struct xfs_btree_cur *cur,
381 const union xfs_btree_key *k1,
382 const union xfs_btree_key *k2)
4a26e66e
CH
383{
384 return be32_to_cpu(k1->inobt.ir_startino) <
385 be32_to_cpu(k2->inobt.ir_startino);
386}
387
388STATIC int
389xfs_inobt_recs_inorder(
8e38dc88
DW
390 struct xfs_btree_cur *cur,
391 const union xfs_btree_rec *r1,
392 const union xfs_btree_rec *r2)
4a26e66e
CH
393{
394 return be32_to_cpu(r1->inobt.ir_startino) + XFS_INODES_PER_CHUNK <=
395 be32_to_cpu(r2->inobt.ir_startino);
396}
4a26e66e 397
6abc7aef
DW
398STATIC enum xbtree_key_contig
399xfs_inobt_keys_contiguous(
400 struct xfs_btree_cur *cur,
401 const union xfs_btree_key *key1,
4a200a09
DW
402 const union xfs_btree_key *key2,
403 const union xfs_btree_key *mask)
6abc7aef 404{
4a200a09
DW
405 ASSERT(!mask || mask->inobt.ir_startino);
406
6abc7aef
DW
407 return xbtree_key_contig(be32_to_cpu(key1->inobt.ir_startino),
408 be32_to_cpu(key2->inobt.ir_startino));
409}
410
d8d6df42 411const struct xfs_btree_ops xfs_inobt_ops = {
77953b97 412 .name = "ino",
4f0cd5a5
CH
413 .type = XFS_BTREE_TYPE_AG,
414
65f1eaea
CH
415 .rec_len = sizeof(xfs_inobt_rec_t),
416 .key_len = sizeof(xfs_inobt_key_t),
1a9d2629 417 .ptr_len = XFS_BTREE_SHORT_PTR_LEN,
65f1eaea 418
90cfae81 419 .lru_refs = XFS_INO_BTREE_REF,
07b7f2e3 420 .statoff = XFS_STATS_CALC_INDEX(xs_ibt_2),
7f47734a 421 .sick_mask = XFS_SICK_AG_INOBT,
90cfae81 422
561f7d17 423 .dup_cursor = xfs_inobt_dup_cursor,
344207ce 424 .set_root = xfs_inobt_set_root,
f5eb8e7c 425 .alloc_block = xfs_inobt_alloc_block,
d4b3a4b7 426 .free_block = xfs_inobt_free_block,
91cca5df 427 .get_minrecs = xfs_inobt_get_minrecs,
ce5e42db 428 .get_maxrecs = xfs_inobt_get_maxrecs,
fe033cc8 429 .init_key_from_rec = xfs_inobt_init_key_from_rec,
118bb47e 430 .init_high_key_from_rec = xfs_inobt_init_high_key_from_rec,
4b22a571 431 .init_rec_from_cur = xfs_inobt_init_rec_from_cur,
fe033cc8
CH
432 .init_ptr_from_cur = xfs_inobt_init_ptr_from_cur,
433 .key_diff = xfs_inobt_key_diff,
1813dd64 434 .buf_ops = &xfs_inobt_buf_ops,
118bb47e 435 .diff_two_keys = xfs_inobt_diff_two_keys,
4a26e66e
CH
436 .keys_inorder = xfs_inobt_keys_inorder,
437 .recs_inorder = xfs_inobt_recs_inorder,
6abc7aef 438 .keys_contiguous = xfs_inobt_keys_contiguous,
561f7d17
CH
439};
440
d8d6df42 441const struct xfs_btree_ops xfs_finobt_ops = {
77953b97 442 .name = "fino",
4f0cd5a5
CH
443 .type = XFS_BTREE_TYPE_AG,
444
aafc3c24
BF
445 .rec_len = sizeof(xfs_inobt_rec_t),
446 .key_len = sizeof(xfs_inobt_key_t),
1a9d2629 447 .ptr_len = XFS_BTREE_SHORT_PTR_LEN,
aafc3c24 448
90cfae81 449 .lru_refs = XFS_INO_BTREE_REF,
07b7f2e3 450 .statoff = XFS_STATS_CALC_INDEX(xs_fibt_2),
7f47734a 451 .sick_mask = XFS_SICK_AG_FINOBT,
90cfae81 452
14dd46cf 453 .dup_cursor = xfs_finobt_dup_cursor,
aafc3c24 454 .set_root = xfs_finobt_set_root,
76d771b4 455 .alloc_block = xfs_finobt_alloc_block,
ad90bb58 456 .free_block = xfs_finobt_free_block,
aafc3c24
BF
457 .get_minrecs = xfs_inobt_get_minrecs,
458 .get_maxrecs = xfs_inobt_get_maxrecs,
459 .init_key_from_rec = xfs_inobt_init_key_from_rec,
118bb47e 460 .init_high_key_from_rec = xfs_inobt_init_high_key_from_rec,
aafc3c24
BF
461 .init_rec_from_cur = xfs_inobt_init_rec_from_cur,
462 .init_ptr_from_cur = xfs_finobt_init_ptr_from_cur,
463 .key_diff = xfs_inobt_key_diff,
01e68f40 464 .buf_ops = &xfs_finobt_buf_ops,
118bb47e 465 .diff_two_keys = xfs_inobt_diff_two_keys,
aafc3c24
BF
466 .keys_inorder = xfs_inobt_keys_inorder,
467 .recs_inorder = xfs_inobt_recs_inorder,
6abc7aef 468 .keys_contiguous = xfs_inobt_keys_contiguous,
aafc3c24
BF
469};
470
561f7d17 471/*
f6c98d92
CH
472 * Create an inode btree cursor.
473 *
474 * For staging cursors tp and agbp are NULL.
561f7d17 475 */
f6c98d92
CH
476struct xfs_btree_cur *
477xfs_inobt_init_cursor(
be9fb17d 478 struct xfs_perag *pag,
f6c98d92 479 struct xfs_trans *tp,
14dd46cf 480 struct xfs_buf *agbp)
561f7d17 481{
e9c4d8bf 482 struct xfs_mount *mp = pag_mount(pag);
561f7d17
CH
483 struct xfs_btree_cur *cur;
484
ec793e69 485 cur = xfs_btree_alloc_cursor(mp, tp, &xfs_inobt_ops,
14dd46cf 486 M_IGEO(mp)->inobt_maxlevels, xfs_inobt_cur_cache);
77a530e6 487 cur->bc_group = xfs_group_hold(pag_group(pag));
14dd46cf
CH
488 cur->bc_ag.agbp = agbp;
489 if (agbp) {
490 struct xfs_agi *agi = agbp->b_addr;
07b7f2e3 491
14dd46cf
CH
492 cur->bc_nlevels = be32_to_cpu(agi->agi_level);
493 }
494 return cur;
495}
496
497/*
498 * Create a free inode btree cursor.
499 *
500 * For staging cursors tp and agbp are NULL.
501 */
502struct xfs_btree_cur *
503xfs_finobt_init_cursor(
504 struct xfs_perag *pag,
505 struct xfs_trans *tp,
506 struct xfs_buf *agbp)
507{
e9c4d8bf 508 struct xfs_mount *mp = pag_mount(pag);
14dd46cf 509 struct xfs_btree_cur *cur;
aafc3c24 510
ec793e69 511 cur = xfs_btree_alloc_cursor(mp, tp, &xfs_finobt_ops,
07b7f2e3 512 M_IGEO(mp)->inobt_maxlevels, xfs_inobt_cur_cache);
77a530e6 513 cur->bc_group = xfs_group_hold(pag_group(pag));
c29ce8f4 514 cur->bc_ag.agbp = agbp;
f6c98d92
CH
515 if (agbp) {
516 struct xfs_agi *agi = agbp->b_addr;
517
14dd46cf 518 cur->bc_nlevels = be32_to_cpu(agi->agi_free_level);
f6c98d92 519 }
c29ce8f4
DW
520 return cur;
521}
561f7d17 522
c29ce8f4
DW
523/*
524 * Install a new inobt btree root. Caller is responsible for invalidating
525 * and freeing the old btree blocks.
526 */
527void
528xfs_inobt_commit_staged_btree(
529 struct xfs_btree_cur *cur,
530 struct xfs_trans *tp,
531 struct xfs_buf *agbp)
532{
533 struct xfs_agi *agi = agbp->b_addr;
534 struct xbtree_afakeroot *afake = cur->bc_ag.afake;
11f74423 535 int fields;
c29ce8f4
DW
536
537 ASSERT(cur->bc_flags & XFS_BTREE_STAGING);
538
ec793e69 539 if (xfs_btree_is_ino(cur->bc_ops)) {
11f74423 540 fields = XFS_AGI_ROOT | XFS_AGI_LEVEL;
c29ce8f4
DW
541 agi->agi_root = cpu_to_be32(afake->af_root);
542 agi->agi_level = cpu_to_be32(afake->af_levels);
ebd9027d 543 if (xfs_has_inobtcounts(cur->bc_mp)) {
11f74423
DW
544 agi->agi_iblocks = cpu_to_be32(afake->af_blocks);
545 fields |= XFS_AGI_IBLOCKS;
546 }
547 xfs_ialloc_log_agi(tp, agbp, fields);
2b9e7f26 548 xfs_btree_commit_afakeroot(cur, tp, agbp);
c29ce8f4 549 } else {
11f74423 550 fields = XFS_AGI_FREE_ROOT | XFS_AGI_FREE_LEVEL;
c29ce8f4
DW
551 agi->agi_free_root = cpu_to_be32(afake->af_root);
552 agi->agi_free_level = cpu_to_be32(afake->af_levels);
ebd9027d 553 if (xfs_has_inobtcounts(cur->bc_mp)) {
11f74423
DW
554 agi->agi_fblocks = cpu_to_be32(afake->af_blocks);
555 fields |= XFS_AGI_IBLOCKS;
556 }
557 xfs_ialloc_log_agi(tp, agbp, fields);
2b9e7f26 558 xfs_btree_commit_afakeroot(cur, tp, agbp);
c29ce8f4
DW
559 }
560}
561
0ed5f735
DW
562/* Calculate number of records in an inode btree block. */
563static inline unsigned int
564xfs_inobt_block_maxrecs(
565 unsigned int blocklen,
566 bool leaf)
567{
568 if (leaf)
569 return blocklen / sizeof(xfs_inobt_rec_t);
570 return blocklen / (sizeof(xfs_inobt_key_t) + sizeof(xfs_inobt_ptr_t));
571}
572
60197e8d
CH
573/*
574 * Calculate number of records in an inobt btree block.
575 */
411a7125 576unsigned int
60197e8d
CH
577xfs_inobt_maxrecs(
578 struct xfs_mount *mp,
411a7125
DW
579 unsigned int blocklen,
580 bool leaf)
60197e8d 581{
7cc95a82 582 blocklen -= XFS_INOBT_BLOCK_LEN(mp);
0ed5f735
DW
583 return xfs_inobt_block_maxrecs(blocklen, leaf);
584}
60197e8d 585
0ed5f735
DW
586/*
587 * Maximum number of inode btree records per AG. Pretend that we can fill an
588 * entire AG completely full of inodes except for the AG headers.
589 */
590#define XFS_MAX_INODE_RECORDS \
591 ((XFS_MAX_AG_BYTES - (4 * BBSIZE)) / XFS_DINODE_MIN_SIZE) / \
592 XFS_INODES_PER_CHUNK
593
594/* Compute the max possible height for the inode btree. */
595static inline unsigned int
596xfs_inobt_maxlevels_ondisk(void)
597{
598 unsigned int minrecs[2];
599 unsigned int blocklen;
600
601 blocklen = min(XFS_MIN_BLOCKSIZE - XFS_BTREE_SBLOCK_LEN,
602 XFS_MIN_CRC_BLOCKSIZE - XFS_BTREE_SBLOCK_CRC_LEN);
603
604 minrecs[0] = xfs_inobt_block_maxrecs(blocklen, true) / 2;
605 minrecs[1] = xfs_inobt_block_maxrecs(blocklen, false) / 2;
606
607 return xfs_btree_compute_maxlevels(minrecs, XFS_MAX_INODE_RECORDS);
608}
609
610/* Compute the max possible height for the free inode btree. */
611static inline unsigned int
612xfs_finobt_maxlevels_ondisk(void)
613{
614 unsigned int minrecs[2];
615 unsigned int blocklen;
616
617 blocklen = XFS_MIN_CRC_BLOCKSIZE - XFS_BTREE_SBLOCK_CRC_LEN;
618
619 minrecs[0] = xfs_inobt_block_maxrecs(blocklen, true) / 2;
620 minrecs[1] = xfs_inobt_block_maxrecs(blocklen, false) / 2;
621
622 return xfs_btree_compute_maxlevels(minrecs, XFS_MAX_INODE_RECORDS);
623}
624
625/* Compute the max possible height for either inode btree. */
626unsigned int
627xfs_iallocbt_maxlevels_ondisk(void)
628{
629 return max(xfs_inobt_maxlevels_ondisk(),
630 xfs_finobt_maxlevels_ondisk());
60197e8d 631}
4148c347
BF
632
633/*
634 * Convert the inode record holemask to an inode allocation bitmap. The inode
635 * allocation bitmap is inode granularity and specifies whether an inode is
636 * physically allocated on disk (not whether the inode is considered allocated
637 * or free by the fs).
638 *
639 * A bit value of 1 means the inode is allocated, a value of 0 means it is free.
640 */
641uint64_t
642xfs_inobt_irec_to_allocmask(
366a0b8d 643 const struct xfs_inobt_rec_incore *rec)
4148c347
BF
644{
645 uint64_t bitmap = 0;
646 uint64_t inodespbit;
647 int nextbit;
648 uint allocbitmap;
649
650 /*
651 * The holemask has 16-bits for a 64 inode record. Therefore each
652 * holemask bit represents multiple inodes. Create a mask of bits to set
653 * in the allocmask for each holemask bit.
654 */
655 inodespbit = (1 << XFS_INODES_PER_HOLEMASK_BIT) - 1;
656
657 /*
658 * Allocated inodes are represented by 0 bits in holemask. Invert the 0
659 * bits to 1 and convert to a uint so we can use xfs_next_bit(). Mask
660 * anything beyond the 16 holemask bits since this casts to a larger
661 * type.
662 */
663 allocbitmap = ~rec->ir_holemask & ((1 << XFS_INOBT_HOLEMASK_BITS) - 1);
664
665 /*
666 * allocbitmap is the inverted holemask so every set bit represents
667 * allocated inodes. To expand from 16-bit holemask granularity to
668 * 64-bit (e.g., bit-per-inode), set inodespbit bits in the target
669 * bitmap for every holemask bit.
670 */
671 nextbit = xfs_next_bit(&allocbitmap, 1, 0);
672 while (nextbit != -1) {
673 ASSERT(nextbit < (sizeof(rec->ir_holemask) * NBBY));
674
675 bitmap |= (inodespbit <<
676 (nextbit * XFS_INODES_PER_HOLEMASK_BIT));
677
678 nextbit = xfs_next_bit(&allocbitmap, 1, nextbit + 1);
679 }
680
681 return bitmap;
682}
56d1115c
BF
683
684#if defined(DEBUG) || defined(XFS_WARN)
685/*
686 * Verify that an in-core inode record has a valid inode count.
687 */
688int
689xfs_inobt_rec_check_count(
690 struct xfs_mount *mp,
691 struct xfs_inobt_rec_incore *rec)
692{
693 int inocount = 0;
694 int nextbit = 0;
695 uint64_t allocbmap;
696 int wordsz;
697
698 wordsz = sizeof(allocbmap) / sizeof(unsigned int);
699 allocbmap = xfs_inobt_irec_to_allocmask(rec);
700
701 nextbit = xfs_next_bit((uint *) &allocbmap, wordsz, nextbit);
702 while (nextbit != -1) {
703 inocount++;
704 nextbit = xfs_next_bit((uint *) &allocbmap, wordsz,
705 nextbit + 1);
706 }
707
708 if (inocount != rec->ir_count)
709 return -EFSCORRUPTED;
710
711 return 0;
712}
713#endif /* DEBUG */
76d771b4
CH
714
715static xfs_extlen_t
716xfs_inobt_max_size(
3829c9a1 717 struct xfs_perag *pag)
76d771b4 718{
e9c4d8bf 719 struct xfs_mount *mp = pag_mount(pag);
e0b5b97d 720 xfs_agblock_t agblocks = pag_group(pag)->xg_block_count;
c0876897 721
76d771b4 722 /* Bail out if we're uninitialized, which can happen in mkfs. */
ef325959 723 if (M_IGEO(mp)->inobt_mxr[0] == 0)
76d771b4
CH
724 return 0;
725
5cd213b0
DW
726 /*
727 * The log is permanently allocated, so the space it occupies will
728 * never be available for the kinds of things that would require btree
729 * expansion. We therefore can pretend the space isn't there.
730 */
e9c4d8bf 731 if (xfs_ag_contains_log(mp, pag_agno(pag)))
5cd213b0
DW
732 agblocks -= mp->m_sb.sb_logblocks;
733
ef325959 734 return xfs_btree_calc_size(M_IGEO(mp)->inobt_mnr,
c0876897
DC
735 (uint64_t)agblocks * mp->m_sb.sb_inopblock /
736 XFS_INODES_PER_CHUNK);
76d771b4
CH
737}
738
739static int
4bfb028a 740xfs_finobt_count_blocks(
30933120 741 struct xfs_perag *pag,
bab8b795 742 struct xfs_trans *tp,
76d771b4
CH
743 xfs_extlen_t *tree_blocks)
744{
a211432c 745 struct xfs_buf *agbp = NULL;
3038fd81 746 struct xfs_btree_cur *cur;
bd27c7bc 747 xfs_filblks_t blocks;
76d771b4
CH
748 int error;
749
549d3c9a 750 error = xfs_ialloc_read_agi(pag, tp, 0, &agbp);
76d771b4
CH
751 if (error)
752 return error;
753
95179935 754 cur = xfs_finobt_init_cursor(pag, tp, agbp);
bd27c7bc 755 error = xfs_btree_count_blocks(cur, &blocks);
0b04b6b8 756 xfs_btree_del_cursor(cur, error);
ebcbef3a 757 xfs_trans_brelse(tp, agbp);
bd27c7bc 758 *tree_blocks = blocks;
76d771b4
CH
759
760 return error;
761}
762
1ac35f06
DW
763/* Read finobt block count from AGI header. */
764static int
765xfs_finobt_read_blocks(
30933120 766 struct xfs_perag *pag,
99b13c7f 767 struct xfs_trans *tp,
1ac35f06
DW
768 xfs_extlen_t *tree_blocks)
769{
770 struct xfs_buf *agbp;
771 struct xfs_agi *agi;
772 int error;
773
549d3c9a 774 error = xfs_ialloc_read_agi(pag, tp, 0, &agbp);
1ac35f06
DW
775 if (error)
776 return error;
777
778 agi = agbp->b_addr;
779 *tree_blocks = be32_to_cpu(agi->agi_fblocks);
780 xfs_trans_brelse(tp, agbp);
781 return 0;
782}
783
76d771b4
CH
784/*
785 * Figure out how many blocks to reserve and how many are used by this btree.
786 */
787int
788xfs_finobt_calc_reserves(
30933120 789 struct xfs_perag *pag,
bab8b795 790 struct xfs_trans *tp,
76d771b4
CH
791 xfs_extlen_t *ask,
792 xfs_extlen_t *used)
793{
794 xfs_extlen_t tree_len = 0;
795 int error;
796
e9c4d8bf 797 if (!xfs_has_finobt(pag_mount(pag)))
76d771b4
CH
798 return 0;
799
e9c4d8bf 800 if (xfs_has_inobtcounts(pag_mount(pag)))
99b13c7f 801 error = xfs_finobt_read_blocks(pag, tp, &tree_len);
1ac35f06 802 else
4bfb028a 803 error = xfs_finobt_count_blocks(pag, tp, &tree_len);
76d771b4
CH
804 if (error)
805 return error;
806
3829c9a1 807 *ask += xfs_inobt_max_size(pag);
76d771b4
CH
808 *used += tree_len;
809 return 0;
810}
14861c47
DW
811
812/* Calculate the inobt btree size for some records. */
813xfs_extlen_t
814xfs_iallocbt_calc_size(
815 struct xfs_mount *mp,
816 unsigned long long len)
817{
ef325959 818 return xfs_btree_calc_size(M_IGEO(mp)->inobt_mnr, len);
14861c47 819}
9fa47bdc
DW
820
821int __init
822xfs_inobt_init_cur_cache(void)
823{
824 xfs_inobt_cur_cache = kmem_cache_create("xfs_inobt_cur",
825 xfs_btree_cur_sizeof(xfs_inobt_maxlevels_ondisk()),
826 0, 0, NULL);
827
828 if (!xfs_inobt_cur_cache)
829 return -ENOMEM;
830 return 0;
831}
832
833void
834xfs_inobt_destroy_cur_cache(void)
835{
836 kmem_cache_destroy(xfs_inobt_cur_cache);
837 xfs_inobt_cur_cache = NULL;
838}