]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - repair/phase5.c
xfs_repair: drop lostblocks from build_agf_agfl
[thirdparty/xfsprogs-dev.git] / repair / phase5.c
CommitLineData
959ef981 1// SPDX-License-Identifier: GPL-2.0
2bd0ea18 2/*
da23017d
NS
3 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
4 * All Rights Reserved.
2bd0ea18
NS
5 */
6
6b803e5a 7#include "libxfs.h"
2bd0ea18
NS
8#include "avl.h"
9#include "globals.h"
10#include "agheader.h"
11#include "incore.h"
12#include "protos.h"
13#include "err_protos.h"
14#include "dinode.h"
15#include "rt.h"
16#include "versions.h"
3b6ac903 17#include "threads.h"
06fbdda9 18#include "progress.h"
934b5548
DW
19#include "slab.h"
20#include "rmap.h"
2bd0ea18
NS
21
22/*
23 * we maintain the current slice (path from root to leaf)
24 * of the btree incore. when we need a new block, we ask
25 * the block allocator for the address of a block on that
26 * level, map the block in, and set up the appropriate
27 * pointers (child, silbing, etc.) and keys that should
28 * point to the new block.
29 */
30typedef struct bt_stat_level {
31 /*
32 * set in setup_cursor routine and maintained in the tree-building
33 * routines
34 */
35 xfs_buf_t *buf_p; /* 2 buffer pointers to ... */
36 xfs_buf_t *prev_buf_p;
37 xfs_agblock_t agbno; /* current block being filled */
38 xfs_agblock_t prev_agbno; /* previous block */
39 /*
40 * set in calculate/init cursor routines for each btree level
41 */
42 int num_recs_tot; /* # tree recs in level */
43 int num_blocks; /* # tree blocks in level */
44 int num_recs_pb; /* num_recs_tot / num_blocks */
45 int modulo; /* num_recs_tot % num_blocks */
46} bt_stat_level_t;
47
48typedef struct bt_status {
49 int init; /* cursor set up once? */
50 int num_levels; /* # of levels in btree */
51 xfs_extlen_t num_tot_blocks; /* # blocks alloc'ed for tree */
52 xfs_extlen_t num_free_blocks;/* # blocks currently unused */
53
54 xfs_agblock_t root; /* root block */
55 /*
56 * list of blocks to be used to set up this tree
57 * and pointer to the first unused block on the list
58 */
59 xfs_agblock_t *btree_blocks; /* block list */
60 xfs_agblock_t *free_btree_blocks; /* first unused block */
61 /*
62 * per-level status info
63 */
64 bt_stat_level_t level[XFS_BTREE_MAXLEVELS];
62cf990a 65 uint64_t owner; /* owner */
2bd0ea18
NS
66} bt_status_t;
67
d6412d17
BF
68/*
69 * extra metadata for the agi
70 */
71struct agi_stat {
72 xfs_agino_t first_agino;
73 xfs_agino_t count;
74 xfs_agino_t freecount;
75};
76
14f8b681
DW
77static uint64_t *sb_icount_ag; /* allocated inodes per ag */
78static uint64_t *sb_ifree_ag; /* free inodes per ag */
79static uint64_t *sb_fdblocks_ag; /* free data blocks per ag */
2bd0ea18 80
8b8a6b02 81static int
2bd0ea18
NS
82mk_incore_fstree(xfs_mount_t *mp, xfs_agnumber_t agno)
83{
84 int in_extent;
85 int num_extents;
86 xfs_agblock_t extent_start;
87 xfs_extlen_t extent_len;
88 xfs_agblock_t agbno;
89 xfs_agblock_t ag_end;
90 uint free_blocks;
8961bfde
BN
91 xfs_extlen_t blen;
92 int bstate;
2bd0ea18
NS
93
94 /*
95 * scan the bitmap for the ag looking for continuous
96 * extents of free blocks. At this point, we know
97 * that blocks in the bitmap are either set to an
98 * "in use" state or set to unknown (0) since the
dab9b8d6 99 * bmaps were zero'ed in phase 4 and only blocks
2bd0ea18
NS
100 * being used by inodes, inode bmaps, ag headers,
101 * and the files themselves were put into the bitmap.
102 *
103 */
104 ASSERT(agno < mp->m_sb.sb_agcount);
105
106 extent_start = extent_len = 0;
107 in_extent = 0;
108 num_extents = free_blocks = 0;
109
110 if (agno < mp->m_sb.sb_agcount - 1)
111 ag_end = mp->m_sb.sb_agblocks;
112 else
113 ag_end = mp->m_sb.sb_dblocks -
5a35bf2c 114 (xfs_rfsblock_t)mp->m_sb.sb_agblocks *
003e8e41 115 (mp->m_sb.sb_agcount - 1);
2bd0ea18
NS
116
117 /*
118 * ok, now find the number of extents, keep track of the
119 * largest extent.
120 */
8961bfde
BN
121 for (agbno = 0; agbno < ag_end; agbno += blen) {
122 bstate = get_bmap_ext(agno, agbno, ag_end, &blen);
123 if (bstate < XR_E_INUSE) {
124 free_blocks += blen;
2bd0ea18
NS
125 if (in_extent == 0) {
126 /*
127 * found the start of a free extent
128 */
129 in_extent = 1;
130 num_extents++;
131 extent_start = agbno;
8961bfde 132 extent_len = blen;
2bd0ea18 133 } else {
8961bfde 134 extent_len += blen;
2bd0ea18
NS
135 }
136 } else {
137 if (in_extent) {
138 /*
139 * free extent ends here, add extent to the
140 * 2 incore extent (avl-to-be-B+) trees
141 */
142 in_extent = 0;
143#if defined(XR_BLD_FREE_TRACE) && defined(XR_BLD_ADD_EXTENT)
144 fprintf(stderr, "adding extent %u [%u %u]\n",
145 agno, extent_start, extent_len);
146#endif
147 add_bno_extent(agno, extent_start, extent_len);
148 add_bcnt_extent(agno, extent_start, extent_len);
149 }
150 }
151 }
152 if (in_extent) {
153 /*
154 * free extent ends here
155 */
2bd0ea18
NS
156#if defined(XR_BLD_FREE_TRACE) && defined(XR_BLD_ADD_EXTENT)
157 fprintf(stderr, "adding extent %u [%u %u]\n",
158 agno, extent_start, extent_len);
159#endif
160 add_bno_extent(agno, extent_start, extent_len);
161 add_bcnt_extent(agno, extent_start, extent_len);
162 }
163
164 return(num_extents);
165}
166
8b8a6b02 167static xfs_agblock_t
2bd0ea18
NS
168get_next_blockaddr(xfs_agnumber_t agno, int level, bt_status_t *curs)
169{
170 ASSERT(curs->free_btree_blocks < curs->btree_blocks +
171 curs->num_tot_blocks);
172 ASSERT(curs->num_free_blocks > 0);
173
174 curs->num_free_blocks--;
175 return(*curs->free_btree_blocks++);
176}
177
178/*
179 * set up the dynamically allocated block allocation data in the btree
180 * cursor that depends on the info in the static portion of the cursor.
181 * allocates space from the incore bno/bcnt extent trees and sets up
182 * the first path up the left side of the tree. Also sets up the
183 * cursor pointer to the btree root. called by init_freespace_cursor()
184 * and init_ino_cursor()
185 */
8b8a6b02 186static void
2bd0ea18
NS
187setup_cursor(xfs_mount_t *mp, xfs_agnumber_t agno, bt_status_t *curs)
188{
189 int j;
190 unsigned int u;
191 xfs_extlen_t big_extent_len;
192 xfs_agblock_t big_extent_start;
193 extent_tree_node_t *ext_ptr;
194 extent_tree_node_t *bno_ext_ptr;
195 xfs_extlen_t blocks_allocated;
196 xfs_agblock_t *agb_ptr;
62cf990a 197 int error;
2bd0ea18
NS
198
199 /*
200 * get the number of blocks we need to allocate, then
201 * set up block number array, set the free block pointer
202 * to the first block in the array, and null the array
203 */
204 big_extent_len = curs->num_tot_blocks;
205 blocks_allocated = 0;
206
207 ASSERT(big_extent_len > 0);
208
2c2e994d 209 if ((curs->btree_blocks = malloc(sizeof(xfs_agblock_t)
507f4e33
NS
210 * big_extent_len)) == NULL)
211 do_error(_("could not set up btree block array\n"));
2bd0ea18
NS
212
213 agb_ptr = curs->free_btree_blocks = curs->btree_blocks;
214
215 for (j = 0; j < curs->num_free_blocks; j++, agb_ptr++)
216 *agb_ptr = NULLAGBLOCK;
217
218 /*
219 * grab the smallest extent and use it up, then get the
220 * next smallest. This mimics the init_*_cursor code.
221 */
6761d5a4 222 ext_ptr = findfirst_bcnt_extent(agno);
2bd0ea18
NS
223
224 agb_ptr = curs->btree_blocks;
2bd0ea18
NS
225
226 /*
227 * set up the free block array
228 */
229 while (blocks_allocated < big_extent_len) {
6761d5a4
DW
230 if (!ext_ptr)
231 do_error(
232_("error - not enough free space in filesystem\n"));
2bd0ea18
NS
233 /*
234 * use up the extent we've got
235 */
236 for (u = 0; u < ext_ptr->ex_blockcount &&
237 blocks_allocated < big_extent_len; u++) {
238 ASSERT(agb_ptr < curs->btree_blocks
239 + curs->num_tot_blocks);
240 *agb_ptr++ = ext_ptr->ex_startblock + u;
241 blocks_allocated++;
242 }
243
2d273771 244 error = rmap_add_ag_rec(mp, agno, ext_ptr->ex_startblock, u,
62cf990a
DW
245 curs->owner);
246 if (error)
247 do_error(_("could not set up btree rmaps: %s\n"),
248 strerror(-error));
249
2bd0ea18
NS
250 /*
251 * if we only used part of this last extent, then we
252 * need only to reset the extent in the extent
253 * trees and we're done
254 */
255 if (u < ext_ptr->ex_blockcount) {
256 big_extent_start = ext_ptr->ex_startblock + u;
257 big_extent_len = ext_ptr->ex_blockcount - u;
258
259 ASSERT(big_extent_len > 0);
260
261 bno_ext_ptr = find_bno_extent(agno,
262 ext_ptr->ex_startblock);
263 ASSERT(bno_ext_ptr != NULL);
264 get_bno_extent(agno, bno_ext_ptr);
265 release_extent_tree_node(bno_ext_ptr);
266
267 ext_ptr = get_bcnt_extent(agno, ext_ptr->ex_startblock,
268 ext_ptr->ex_blockcount);
269 release_extent_tree_node(ext_ptr);
270#ifdef XR_BLD_FREE_TRACE
271 fprintf(stderr, "releasing extent: %u [%u %u]\n",
272 agno, ext_ptr->ex_startblock,
273 ext_ptr->ex_blockcount);
274 fprintf(stderr, "blocks_allocated = %d\n",
275 blocks_allocated);
276#endif
277
278 add_bno_extent(agno, big_extent_start, big_extent_len);
279 add_bcnt_extent(agno, big_extent_start, big_extent_len);
280
281 return;
282 }
283 /*
284 * delete the used-up extent from both extent trees and
285 * find next biggest extent
286 */
287#ifdef XR_BLD_FREE_TRACE
288 fprintf(stderr, "releasing extent: %u [%u %u]\n",
289 agno, ext_ptr->ex_startblock, ext_ptr->ex_blockcount);
290#endif
291 bno_ext_ptr = find_bno_extent(agno, ext_ptr->ex_startblock);
292 ASSERT(bno_ext_ptr != NULL);
293 get_bno_extent(agno, bno_ext_ptr);
294 release_extent_tree_node(bno_ext_ptr);
295
296 ext_ptr = get_bcnt_extent(agno, ext_ptr->ex_startblock,
297 ext_ptr->ex_blockcount);
298 ASSERT(ext_ptr != NULL);
299 release_extent_tree_node(ext_ptr);
300
301 ext_ptr = findfirst_bcnt_extent(agno);
302 }
303#ifdef XR_BLD_FREE_TRACE
304 fprintf(stderr, "blocks_allocated = %d\n",
305 blocks_allocated);
306#endif
307}
308
8b8a6b02 309static void
2bd0ea18
NS
310write_cursor(bt_status_t *curs)
311{
312 int i;
313
314 for (i = 0; i < curs->num_levels; i++) {
315#if defined(XR_BLD_FREE_TRACE) || defined(XR_BLD_INO_TRACE)
316 fprintf(stderr, "writing bt block %u\n", curs->level[i].agbno);
317#endif
318 if (curs->level[i].prev_buf_p != NULL) {
319 ASSERT(curs->level[i].prev_agbno != NULLAGBLOCK);
cdded3d8
DC
320#if defined(XR_BLD_FREE_TRACE) || defined(XR_BLD_INO_TRACE)
321 fprintf(stderr, "writing bt prev block %u\n",
322 curs->level[i].prev_agbno);
323#endif
f524ae04 324 libxfs_buf_mark_dirty(curs->level[i].prev_buf_p);
18b4f688 325 libxfs_buf_relse(curs->level[i].prev_buf_p);
2bd0ea18 326 }
f524ae04 327 libxfs_buf_mark_dirty(curs->level[i].buf_p);
18b4f688 328 libxfs_buf_relse(curs->level[i].buf_p);
2bd0ea18
NS
329 }
330}
331
8b8a6b02 332static void
2bd0ea18
NS
333finish_cursor(bt_status_t *curs)
334{
335 ASSERT(curs->num_free_blocks == 0);
336 free(curs->btree_blocks);
337}
338
339/*
9851fd79
DC
340 * We need to leave some free records in the tree for the corner case of
341 * setting up the AGFL. This may require allocation of blocks, and as
342 * such can require insertion of new records into the tree (e.g. moving
343 * a record in the by-count tree when a long extent is shortened). If we
344 * pack the records into the leaves with no slack space, this requires a
345 * leaf split to occur and a block to be allocated from the free list.
346 * If we don't have any blocks on the free list (because we are setting
347 * it up!), then we fail, and the filesystem will fail with the same
348 * failure at runtime. Hence leave a couple of records slack space in
349 * each block to allow immediate modification of the tree without
350 * requiring splits to be done.
2bd0ea18 351 */
6df28d12
GX
352static void
353compute_level_geometry(
354 struct xfs_mount *mp,
355 struct bt_stat_level *lptr,
356 uint64_t nr_this_level,
357 int slack,
358 bool leaf)
359{
360 unsigned int maxrecs = mp->m_alloc_mxr[!leaf];
361 unsigned int desired_npb;
362
363 desired_npb = max(mp->m_alloc_mnr[!leaf], maxrecs - slack);
364 lptr->num_recs_tot = nr_this_level;
365 lptr->num_blocks = max(1ULL, nr_this_level / desired_npb);
366
367 lptr->num_recs_pb = nr_this_level / lptr->num_blocks;
368 lptr->modulo = nr_this_level % lptr->num_blocks;
369 if (lptr->num_recs_pb > maxrecs ||
370 (lptr->num_recs_pb == maxrecs && lptr->modulo)) {
371 lptr->num_blocks++;
372
373 lptr->num_recs_pb = nr_this_level / lptr->num_blocks;
374 lptr->modulo = nr_this_level % lptr->num_blocks;
375 }
376}
2bd0ea18
NS
377
378/*
379 * this calculates a freespace cursor for an ag.
380 * btree_curs is an in/out. returns the number of
381 * blocks that will show up in the AGFL.
382 */
8b8a6b02 383static int
2bd0ea18
NS
384calculate_freespace_cursor(xfs_mount_t *mp, xfs_agnumber_t agno,
385 xfs_agblock_t *extents, bt_status_t *btree_curs)
386{
387 xfs_extlen_t blocks_needed; /* a running count */
388 xfs_extlen_t blocks_allocated_pt; /* per tree */
389 xfs_extlen_t blocks_allocated_total; /* for both trees */
390 xfs_agblock_t num_extents;
391 int i;
392 int extents_used;
393 int extra_blocks;
6df28d12 394 uint64_t old_blocks;
2bd0ea18
NS
395 bt_stat_level_t *lptr;
396 bt_stat_level_t *p_lptr;
397 extent_tree_node_t *ext_ptr;
398 int level;
2bd0ea18
NS
399
400 num_extents = *extents;
401 extents_used = 0;
402
403 ASSERT(num_extents != 0);
404
405 lptr = &btree_curs->level[0];
406 btree_curs->init = 1;
407
408 /*
409 * figure out how much space we need for the leaf level
410 * of the tree and set up the cursor for the leaf level
411 * (note that the same code is duplicated further down)
412 */
6df28d12 413 compute_level_geometry(mp, lptr, num_extents, 2, true);
2bd0ea18
NS
414 level = 1;
415
9851fd79
DC
416#ifdef XR_BLD_FREE_TRACE
417 fprintf(stderr, "%s 0 %d %d %d %d\n", __func__,
418 lptr->num_blocks,
419 lptr->num_recs_pb,
420 lptr->modulo,
421 lptr->num_recs_tot);
422#endif
2bd0ea18
NS
423 /*
424 * if we need more levels, set them up. # of records
425 * per level is the # of blocks in the level below it
426 */
6df28d12
GX
427 while (lptr->num_blocks > 1) {
428 p_lptr = lptr;
429 lptr = &btree_curs->level[level];
430
431 compute_level_geometry(mp, lptr,
432 p_lptr->num_blocks, 0, false);
9851fd79 433#ifdef XR_BLD_FREE_TRACE
6df28d12
GX
434 fprintf(stderr, "%s %d %d %d %d %d\n", __func__,
435 level,
436 lptr->num_blocks,
437 lptr->num_recs_pb,
438 lptr->modulo,
439 lptr->num_recs_tot);
9851fd79 440#endif
6df28d12 441 level++;
2bd0ea18 442 }
6df28d12 443 ASSERT(level < XFS_BTREE_MAXLEVELS);
2bd0ea18
NS
444 ASSERT(lptr->num_blocks == 1);
445 btree_curs->num_levels = level;
446
447 /*
448 * ok, now we have a hypothetical cursor that
449 * will work for both the bno and bcnt trees.
450 * now figure out if using up blocks to set up the
451 * trees will perturb the shape of the freespace tree.
452 * if so, we've over-allocated. the freespace trees
453 * as they will be *after* accounting for the free space
454 * we've used up will need fewer blocks to to represent
455 * than we've allocated. We can use the AGFL to hold
342f8bad 456 * xfs_agfl_size (sector/struct xfs_agfl) blocks but that's it.
b8165508 457 * Thus we limit things to xfs_agfl_size/2 for each of the 2 btrees.
2bd0ea18
NS
458 * if the number of extra blocks is more than that,
459 * we'll have to be called again.
460 */
461 for (blocks_needed = 0, i = 0; i < level; i++) {
462 blocks_needed += btree_curs->level[i].num_blocks;
463 }
464
465 /*
466 * record the # of blocks we've allocated
467 */
468 blocks_allocated_pt = blocks_needed;
469 blocks_needed *= 2;
470 blocks_allocated_total = blocks_needed;
471
472 /*
473 * figure out how many free extents will be used up by
474 * our space allocation
475 */
507f4e33
NS
476 if ((ext_ptr = findfirst_bcnt_extent(agno)) == NULL)
477 do_error(_("can't rebuild fs trees -- not enough free space "
478 "on ag %u\n"), agno);
2bd0ea18 479
2bd0ea18
NS
480 while (ext_ptr != NULL && blocks_needed > 0) {
481 if (ext_ptr->ex_blockcount <= blocks_needed) {
482 blocks_needed -= ext_ptr->ex_blockcount;
483 extents_used++;
484 } else {
485 blocks_needed = 0;
486 }
487
488 ext_ptr = findnext_bcnt_extent(agno, ext_ptr);
489
490#ifdef XR_BLD_FREE_TRACE
491 if (ext_ptr != NULL) {
492 fprintf(stderr, "got next extent [%u %u]\n",
493 ext_ptr->ex_startblock, ext_ptr->ex_blockcount);
494 } else {
495 fprintf(stderr, "out of extents\n");
496 }
497#endif
498 }
507f4e33
NS
499 if (blocks_needed > 0)
500 do_error(_("ag %u - not enough free space to build freespace "
501 "btrees\n"), agno);
2bd0ea18
NS
502
503 ASSERT(num_extents >= extents_used);
504
505 num_extents -= extents_used;
506
507 /*
508 * see if the number of leaf blocks will change as a result
509 * of the number of extents changing
510 */
6df28d12
GX
511 old_blocks = btree_curs->level[0].num_blocks;
512 compute_level_geometry(mp, &btree_curs->level[0], num_extents, 2, true);
513 extra_blocks = 0;
514
515 if (old_blocks != btree_curs->level[0].num_blocks) {
2bd0ea18
NS
516 /*
517 * yes -- recalculate the cursor. If the number of
b8165508 518 * excess (overallocated) blocks is < xfs_agfl_size/2, we're ok.
2bd0ea18
NS
519 * we can put those into the AGFL. we don't try
520 * and get things to converge exactly (reach a
521 * state with zero excess blocks) because there
522 * exist pathological cases which will never
523 * converge. first, check for the zero-case.
524 */
525 if (num_extents == 0) {
526 /*
527 * ok, we've used up all the free blocks
528 * trying to lay out the leaf level. go
529 * to a one block (empty) btree and put the
530 * already allocated blocks into the AGFL
531 */
532 if (btree_curs->level[0].num_blocks != 1) {
533 /*
534 * we really needed more blocks because
535 * the old tree had more than one level.
536 * this is bad.
537 */
507f4e33
NS
538 do_warn(_("not enough free blocks left to "
539 "describe all free blocks in AG "
540 "%u\n"), agno);
2bd0ea18
NS
541 }
542#ifdef XR_BLD_FREE_TRACE
543 fprintf(stderr,
544 "ag %u -- no free extents, alloc'ed %d\n",
545 agno, blocks_allocated_pt);
546#endif
547 lptr->num_blocks = 1;
548 lptr->modulo = 0;
549 lptr->num_recs_pb = 0;
550 lptr->num_recs_tot = 0;
551
552 btree_curs->num_levels = 1;
553
554 /*
555 * don't reset the allocation stats, assume
556 * they're all extra blocks
557 * don't forget to return the total block count
558 * not the per-tree block count. these are the
559 * extras that will go into the AGFL. subtract
560 * two for the root blocks.
561 */
562 btree_curs->num_tot_blocks = blocks_allocated_pt;
563 btree_curs->num_free_blocks = blocks_allocated_pt;
564
565 *extents = 0;
566
567 return(blocks_allocated_total - 2);
568 }
569
570 lptr = &btree_curs->level[0];
2bd0ea18
NS
571 level = 1;
572
573 /*
574 * if we need more levels, set them up
575 */
6df28d12
GX
576 while (lptr->num_blocks > 1) {
577 p_lptr = lptr;
578 lptr = &btree_curs->level[level++];
579
580 compute_level_geometry(mp, lptr,
581 p_lptr->num_blocks, 0, false);
2bd0ea18 582 }
6df28d12 583 ASSERT(level < XFS_BTREE_MAXLEVELS);
2bd0ea18
NS
584 ASSERT(lptr->num_blocks == 1);
585 btree_curs->num_levels = level;
586
587 /*
588 * now figure out the number of excess blocks
589 */
590 for (blocks_needed = 0, i = 0; i < level; i++) {
591 blocks_needed += btree_curs->level[i].num_blocks;
592 }
593 blocks_needed *= 2;
594
595 ASSERT(blocks_allocated_total >= blocks_needed);
596 extra_blocks = blocks_allocated_total - blocks_needed;
2bd0ea18
NS
597 }
598
599 btree_curs->num_tot_blocks = blocks_allocated_pt;
600 btree_curs->num_free_blocks = blocks_allocated_pt;
601
602 *extents = num_extents;
603
604 return(extra_blocks);
605}
606
b4709906
DW
607/* Map btnum to buffer ops for the types that need it. */
608static const struct xfs_buf_ops *
609btnum_to_ops(
610 xfs_btnum_t btnum)
611{
612 switch (btnum) {
613 case XFS_BTNUM_BNO:
fce74e98 614 return &xfs_bnobt_buf_ops;
b4709906 615 case XFS_BTNUM_CNT:
fce74e98 616 return &xfs_cntbt_buf_ops;
b4709906 617 case XFS_BTNUM_INO:
b4709906 618 return &xfs_inobt_buf_ops;
035ae96e
BF
619 case XFS_BTNUM_FINO:
620 return &xfs_finobt_buf_ops;
b4709906
DW
621 case XFS_BTNUM_RMAP:
622 return &xfs_rmapbt_buf_ops;
623 case XFS_BTNUM_REFC:
624 return &xfs_refcountbt_buf_ops;
625 default:
626 ASSERT(0);
627 return NULL;
628 }
629}
630
8b8a6b02 631static void
2bd0ea18
NS
632prop_freespace_cursor(xfs_mount_t *mp, xfs_agnumber_t agno,
633 bt_status_t *btree_curs, xfs_agblock_t startblock,
912ba355 634 xfs_extlen_t blockcount, int level, xfs_btnum_t btnum)
2bd0ea18 635{
b3563c19 636 struct xfs_btree_block *bt_hdr;
2bd0ea18
NS
637 xfs_alloc_key_t *bt_key;
638 xfs_alloc_ptr_t *bt_ptr;
639 xfs_agblock_t agbno;
640 bt_stat_level_t *lptr;
b4709906 641 const struct xfs_buf_ops *ops = btnum_to_ops(btnum);
58a8b31f 642 int error;
e0607266 643
912ba355 644 ASSERT(btnum == XFS_BTNUM_BNO || btnum == XFS_BTNUM_CNT);
2bd0ea18
NS
645
646 level++;
647
648 if (level >= btree_curs->num_levels)
649 return;
650
651 lptr = &btree_curs->level[level];
b3563c19 652 bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p);
2bd0ea18 653
5e656dbb 654 if (be16_to_cpu(bt_hdr->bb_numrecs) == 0) {
2bd0ea18
NS
655 /*
656 * only happens once when initializing the
657 * left-hand side of the tree.
658 */
659 prop_freespace_cursor(mp, agno, btree_curs, startblock,
912ba355 660 blockcount, level, btnum);
2bd0ea18
NS
661 }
662
5e656dbb
BN
663 if (be16_to_cpu(bt_hdr->bb_numrecs) ==
664 lptr->num_recs_pb + (lptr->modulo > 0)) {
2bd0ea18
NS
665 /*
666 * write out current prev block, grab us a new block,
667 * and set the rightsib pointer of current block
668 */
669#ifdef XR_BLD_FREE_TRACE
670 fprintf(stderr, " %d ", lptr->prev_agbno);
671#endif
672 if (lptr->prev_agbno != NULLAGBLOCK) {
673 ASSERT(lptr->prev_buf_p != NULL);
f524ae04 674 libxfs_buf_mark_dirty(lptr->prev_buf_p);
18b4f688 675 libxfs_buf_relse(lptr->prev_buf_p);
2bd0ea18
NS
676 }
677 lptr->prev_agbno = lptr->agbno;;
678 lptr->prev_buf_p = lptr->buf_p;
679 agbno = get_next_blockaddr(agno, level, btree_curs);
680
b3563c19 681 bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(agbno);
2bd0ea18 682
58a8b31f
DW
683 error = -libxfs_buf_get(mp->m_dev,
684 XFS_AGB_TO_DADDR(mp, agno, agbno),
685 XFS_FSB_TO_BB(mp, 1), &lptr->buf_p);
686 if (error)
687 do_error(
688 _("Cannot grab free space btree buffer, err=%d"),
689 error);
2bd0ea18
NS
690 lptr->agbno = agbno;
691
692 if (lptr->modulo)
693 lptr->modulo--;
694
695 /*
696 * initialize block header
697 */
b4709906 698 lptr->buf_p->b_ops = ops;
b3563c19 699 bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p);
dab9b8d6 700 memset(bt_hdr, 0, mp->m_sb.sb_blocksize);
e394a4b1 701 libxfs_btree_init_block(mp, lptr->buf_p, btnum, level,
4aa01a59 702 0, agno);
2bd0ea18 703
b3563c19 704 bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno);
2bd0ea18
NS
705
706 /*
707 * propagate extent record for first extent in new block up
708 */
709 prop_freespace_cursor(mp, agno, btree_curs, startblock,
912ba355 710 blockcount, level, btnum);
2bd0ea18
NS
711 }
712 /*
713 * add extent info to current block
714 */
5e656dbb 715 be16_add_cpu(&bt_hdr->bb_numrecs, 1);
2bd0ea18 716
b3563c19
BN
717 bt_key = XFS_ALLOC_KEY_ADDR(mp, bt_hdr,
718 be16_to_cpu(bt_hdr->bb_numrecs));
719 bt_ptr = XFS_ALLOC_PTR_ADDR(mp, bt_hdr,
720 be16_to_cpu(bt_hdr->bb_numrecs),
721 mp->m_alloc_mxr[1]);
2bd0ea18 722
5e656dbb
BN
723 bt_key->ar_startblock = cpu_to_be32(startblock);
724 bt_key->ar_blockcount = cpu_to_be32(blockcount);
725 *bt_ptr = cpu_to_be32(btree_curs->level[level-1].agbno);
2bd0ea18
NS
726}
727
728/*
912ba355 729 * rebuilds a freespace tree given a cursor and type
2bd0ea18
NS
730 * of tree to build (bno or bcnt). returns the number of free blocks
731 * represented by the tree.
732 */
8b8a6b02 733static xfs_extlen_t
2bd0ea18 734build_freespace_tree(xfs_mount_t *mp, xfs_agnumber_t agno,
912ba355 735 bt_status_t *btree_curs, xfs_btnum_t btnum)
2bd0ea18
NS
736{
737 xfs_agnumber_t i;
738 xfs_agblock_t j;
b3563c19 739 struct xfs_btree_block *bt_hdr;
2bd0ea18
NS
740 xfs_alloc_rec_t *bt_rec;
741 int level;
742 xfs_agblock_t agbno;
743 extent_tree_node_t *ext_ptr;
744 bt_stat_level_t *lptr;
745 xfs_extlen_t freeblks;
b4709906 746 const struct xfs_buf_ops *ops = btnum_to_ops(btnum);
58a8b31f 747 int error;
912ba355
ES
748
749 ASSERT(btnum == XFS_BTNUM_BNO || btnum == XFS_BTNUM_CNT);
2bd0ea18
NS
750
751#ifdef XR_BLD_FREE_TRACE
752 fprintf(stderr, "in build_freespace_tree, agno = %d\n", agno);
753#endif
754 level = btree_curs->num_levels;
755 freeblks = 0;
756
757 ASSERT(level > 0);
758
759 /*
760 * initialize the first block on each btree level
761 */
762 for (i = 0; i < level; i++) {
763 lptr = &btree_curs->level[i];
764
765 agbno = get_next_blockaddr(agno, i, btree_curs);
58a8b31f
DW
766 error = -libxfs_buf_get(mp->m_dev,
767 XFS_AGB_TO_DADDR(mp, agno, agbno),
768 XFS_FSB_TO_BB(mp, 1), &lptr->buf_p);
769 if (error)
770 do_error(
771 _("Cannot grab free space btree buffer, err=%d"),
772 error);
2bd0ea18
NS
773
774 if (i == btree_curs->num_levels - 1)
775 btree_curs->root = agbno;
776
777 lptr->agbno = agbno;
778 lptr->prev_agbno = NULLAGBLOCK;
779 lptr->prev_buf_p = NULL;
780 /*
781 * initialize block header
782 */
b4709906 783 lptr->buf_p->b_ops = ops;
b3563c19 784 bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p);
dab9b8d6 785 memset(bt_hdr, 0, mp->m_sb.sb_blocksize);
4aa01a59 786 libxfs_btree_init_block(mp, lptr->buf_p, btnum, i, 0, agno);
2bd0ea18
NS
787 }
788 /*
789 * run along leaf, setting up records. as we have to switch
790 * blocks, call the prop_freespace_cursor routine to set up the new
791 * pointers for the parent. that can recurse up to the root
792 * if required. set the sibling pointers for leaf level here.
793 */
912ba355 794 if (btnum == XFS_BTNUM_BNO)
2bd0ea18 795 ext_ptr = findfirst_bno_extent(agno);
dfc130f3 796 else
2bd0ea18
NS
797 ext_ptr = findfirst_bcnt_extent(agno);
798
799#ifdef XR_BLD_FREE_TRACE
800 fprintf(stderr, "bft, agno = %d, start = %u, count = %u\n",
801 agno, ext_ptr->ex_startblock, ext_ptr->ex_blockcount);
802#endif
803
804 lptr = &btree_curs->level[0];
805
806 for (i = 0; i < btree_curs->level[0].num_blocks; i++) {
807 /*
808 * block initialization, lay in block header
809 */
b4709906 810 lptr->buf_p->b_ops = ops;
b3563c19 811 bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p);
dab9b8d6 812 memset(bt_hdr, 0, mp->m_sb.sb_blocksize);
4aa01a59 813 libxfs_btree_init_block(mp, lptr->buf_p, btnum, 0, 0, agno);
2bd0ea18 814
b3563c19 815 bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno);
5e656dbb
BN
816 bt_hdr->bb_numrecs = cpu_to_be16(lptr->num_recs_pb +
817 (lptr->modulo > 0));
2bd0ea18
NS
818#ifdef XR_BLD_FREE_TRACE
819 fprintf(stderr, "bft, bb_numrecs = %d\n",
5e656dbb 820 be16_to_cpu(bt_hdr->bb_numrecs));
2bd0ea18
NS
821#endif
822
823 if (lptr->modulo > 0)
824 lptr->modulo--;
825
826 /*
827 * initialize values in the path up to the root if
828 * this is a multi-level btree
829 */
830 if (btree_curs->num_levels > 1)
831 prop_freespace_cursor(mp, agno, btree_curs,
832 ext_ptr->ex_startblock,
833 ext_ptr->ex_blockcount,
912ba355 834 0, btnum);
2bd0ea18 835
b3563c19
BN
836 bt_rec = (xfs_alloc_rec_t *)
837 ((char *)bt_hdr + XFS_ALLOC_BLOCK_LEN(mp));
5e656dbb 838 for (j = 0; j < be16_to_cpu(bt_hdr->bb_numrecs); j++) {
2bd0ea18 839 ASSERT(ext_ptr != NULL);
5e656dbb
BN
840 bt_rec[j].ar_startblock = cpu_to_be32(
841 ext_ptr->ex_startblock);
842 bt_rec[j].ar_blockcount = cpu_to_be32(
843 ext_ptr->ex_blockcount);
2bd0ea18 844 freeblks += ext_ptr->ex_blockcount;
912ba355 845 if (btnum == XFS_BTNUM_BNO)
2bd0ea18
NS
846 ext_ptr = findnext_bno_extent(ext_ptr);
847 else
848 ext_ptr = findnext_bcnt_extent(agno, ext_ptr);
849#if 0
850#ifdef XR_BLD_FREE_TRACE
851 if (ext_ptr == NULL)
852 fprintf(stderr, "null extent pointer, j = %d\n",
853 j);
854 else
855 fprintf(stderr,
856 "bft, agno = %d, start = %u, count = %u\n",
857 agno, ext_ptr->ex_startblock,
858 ext_ptr->ex_blockcount);
859#endif
860#endif
861 }
862
863 if (ext_ptr != NULL) {
864 /*
865 * get next leaf level block
866 */
867 if (lptr->prev_buf_p != NULL) {
868#ifdef XR_BLD_FREE_TRACE
869 fprintf(stderr, " writing fst agbno %u\n",
870 lptr->prev_agbno);
871#endif
872 ASSERT(lptr->prev_agbno != NULLAGBLOCK);
f524ae04 873 libxfs_buf_mark_dirty(lptr->prev_buf_p);
18b4f688 874 libxfs_buf_relse(lptr->prev_buf_p);
2bd0ea18
NS
875 }
876 lptr->prev_buf_p = lptr->buf_p;
877 lptr->prev_agbno = lptr->agbno;
5e656dbb 878 lptr->agbno = get_next_blockaddr(agno, 0, btree_curs);
b3563c19 879 bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(lptr->agbno);
2bd0ea18 880
58a8b31f 881 error = -libxfs_buf_get(mp->m_dev,
2bd0ea18 882 XFS_AGB_TO_DADDR(mp, agno, lptr->agbno),
58a8b31f
DW
883 XFS_FSB_TO_BB(mp, 1),
884 &lptr->buf_p);
885 if (error)
886 do_error(
887 _("Cannot grab free space btree buffer, err=%d"),
888 error);
2bd0ea18
NS
889 }
890 }
891
892 return(freeblks);
893}
894
895/*
b3563c19 896 * XXX(hch): any reason we don't just look at mp->m_inobt_mxr?
2bd0ea18 897 */
2bd0ea18 898#define XR_INOBT_BLOCK_MAXRECS(mp, level) \
e2f60652 899 libxfs_inobt_maxrecs((mp), (mp)->m_sb.sb_blocksize, \
b3563c19 900 (level) == 0)
2bd0ea18
NS
901
902/*
903 * we don't have to worry here about how chewing up free extents
904 * may perturb things because inode tree building happens before
905 * freespace tree building.
906 */
8b8a6b02 907static void
2bd0ea18 908init_ino_cursor(xfs_mount_t *mp, xfs_agnumber_t agno, bt_status_t *btree_curs,
14f8b681 909 uint64_t *num_inos, uint64_t *num_free_inos, int finobt)
2bd0ea18 910{
14f8b681
DW
911 uint64_t ninos;
912 uint64_t nfinos;
824b5810
BF
913 int rec_nfinos;
914 int rec_ninos;
2bd0ea18
NS
915 ino_tree_node_t *ino_rec;
916 int num_recs;
917 int level;
918 bt_stat_level_t *lptr;
919 bt_stat_level_t *p_lptr;
920 xfs_extlen_t blocks_allocated;
921 int i;
922
923 *num_inos = *num_free_inos = 0;
924 ninos = nfinos = 0;
925
926 lptr = &btree_curs->level[0];
927 btree_curs->init = 1;
62cf990a 928 btree_curs->owner = XFS_RMAP_OWN_INOBT;
2bd0ea18 929
2bd0ea18
NS
930 /*
931 * build up statistics
932 */
5292eb51 933 ino_rec = findfirst_inode_rec(agno);
2bd0ea18 934 for (num_recs = 0; ino_rec != NULL; ino_rec = next_ino_rec(ino_rec)) {
824b5810 935 rec_ninos = 0;
bbdb21b6 936 rec_nfinos = 0;
2bd0ea18
NS
937 for (i = 0; i < XFS_INODES_PER_CHUNK; i++) {
938 ASSERT(is_inode_confirmed(ino_rec, i));
824b5810
BF
939 /*
940 * sparse inodes are not factored into superblock (free)
941 * inode counts
942 */
943 if (is_inode_sparse(ino_rec, i))
944 continue;
2bd0ea18 945 if (is_inode_free(ino_rec, i))
bbdb21b6 946 rec_nfinos++;
824b5810 947 rec_ninos++;
2bd0ea18 948 }
bbdb21b6
BF
949
950 /*
951 * finobt only considers records with free inodes
952 */
953 if (finobt && !rec_nfinos)
954 continue;
955
956 nfinos += rec_nfinos;
824b5810 957 ninos += rec_ninos;
bbdb21b6 958 num_recs++;
2bd0ea18
NS
959 }
960
5292eb51
BF
961 if (num_recs == 0) {
962 /*
963 * easy corner-case -- no inode records
964 */
965 lptr->num_blocks = 1;
966 lptr->modulo = 0;
967 lptr->num_recs_pb = 0;
968 lptr->num_recs_tot = 0;
969
970 btree_curs->num_levels = 1;
971 btree_curs->num_tot_blocks = btree_curs->num_free_blocks = 1;
972
973 setup_cursor(mp, agno, btree_curs);
974
975 return;
976 }
977
2bd0ea18
NS
978 blocks_allocated = lptr->num_blocks = howmany(num_recs,
979 XR_INOBT_BLOCK_MAXRECS(mp, 0));
980
981 lptr->modulo = num_recs % lptr->num_blocks;
982 lptr->num_recs_pb = num_recs / lptr->num_blocks;
983 lptr->num_recs_tot = num_recs;
984 level = 1;
985
986 if (lptr->num_blocks > 1) {
987 for (; btree_curs->level[level-1].num_blocks > 1
988 && level < XFS_BTREE_MAXLEVELS;
989 level++) {
990 lptr = &btree_curs->level[level];
991 p_lptr = &btree_curs->level[level - 1];
992 lptr->num_blocks = howmany(p_lptr->num_blocks,
993 XR_INOBT_BLOCK_MAXRECS(mp, level));
994 lptr->modulo = p_lptr->num_blocks % lptr->num_blocks;
995 lptr->num_recs_pb = p_lptr->num_blocks
996 / lptr->num_blocks;
997 lptr->num_recs_tot = p_lptr->num_blocks;
998
999 blocks_allocated += lptr->num_blocks;
1000 }
1001 }
1002 ASSERT(lptr->num_blocks == 1);
1003 btree_curs->num_levels = level;
1004
1005 btree_curs->num_tot_blocks = btree_curs->num_free_blocks
1006 = blocks_allocated;
1007
1008 setup_cursor(mp, agno, btree_curs);
1009
1010 *num_inos = ninos;
1011 *num_free_inos = nfinos;
1012
1013 return;
1014}
1015
8b8a6b02 1016static void
2bd0ea18 1017prop_ino_cursor(xfs_mount_t *mp, xfs_agnumber_t agno, bt_status_t *btree_curs,
051dae5e 1018 xfs_btnum_t btnum, xfs_agino_t startino, int level)
2bd0ea18 1019{
b3563c19 1020 struct xfs_btree_block *bt_hdr;
2bd0ea18
NS
1021 xfs_inobt_key_t *bt_key;
1022 xfs_inobt_ptr_t *bt_ptr;
1023 xfs_agblock_t agbno;
1024 bt_stat_level_t *lptr;
b4709906 1025 const struct xfs_buf_ops *ops = btnum_to_ops(btnum);
58a8b31f 1026 int error;
2bd0ea18
NS
1027
1028 level++;
1029
1030 if (level >= btree_curs->num_levels)
1031 return;
1032
1033 lptr = &btree_curs->level[level];
b3563c19 1034 bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p);
2bd0ea18 1035
5e656dbb 1036 if (be16_to_cpu(bt_hdr->bb_numrecs) == 0) {
2bd0ea18
NS
1037 /*
1038 * this only happens once to initialize the
1039 * first path up the left side of the tree
1040 * where the agbno's are already set up
1041 */
051dae5e 1042 prop_ino_cursor(mp, agno, btree_curs, btnum, startino, level);
2bd0ea18
NS
1043 }
1044
5e656dbb 1045 if (be16_to_cpu(bt_hdr->bb_numrecs) ==
2bd0ea18
NS
1046 lptr->num_recs_pb + (lptr->modulo > 0)) {
1047 /*
1048 * write out current prev block, grab us a new block,
1049 * and set the rightsib pointer of current block
1050 */
1051#ifdef XR_BLD_INO_TRACE
1052 fprintf(stderr, " ino prop agbno %d ", lptr->prev_agbno);
1053#endif
1054 if (lptr->prev_agbno != NULLAGBLOCK) {
1055 ASSERT(lptr->prev_buf_p != NULL);
f524ae04 1056 libxfs_buf_mark_dirty(lptr->prev_buf_p);
18b4f688 1057 libxfs_buf_relse(lptr->prev_buf_p);
2bd0ea18
NS
1058 }
1059 lptr->prev_agbno = lptr->agbno;;
1060 lptr->prev_buf_p = lptr->buf_p;
1061 agbno = get_next_blockaddr(agno, level, btree_curs);
1062
b3563c19 1063 bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(agbno);
2bd0ea18 1064
58a8b31f
DW
1065 error = -libxfs_buf_get(mp->m_dev,
1066 XFS_AGB_TO_DADDR(mp, agno, agbno),
1067 XFS_FSB_TO_BB(mp, 1), &lptr->buf_p);
1068 if (error)
1069 do_error(_("Cannot grab inode btree buffer, err=%d"),
1070 error);
2bd0ea18
NS
1071 lptr->agbno = agbno;
1072
1073 if (lptr->modulo)
1074 lptr->modulo--;
1075
1076 /*
1077 * initialize block header
1078 */
b4709906 1079 lptr->buf_p->b_ops = ops;
b3563c19 1080 bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p);
dab9b8d6 1081 memset(bt_hdr, 0, mp->m_sb.sb_blocksize);
051dae5e 1082 libxfs_btree_init_block(mp, lptr->buf_p, btnum,
4aa01a59 1083 level, 0, agno);
2bd0ea18 1084
b3563c19 1085 bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno);
e0607266 1086
2bd0ea18
NS
1087 /*
1088 * propagate extent record for first extent in new block up
1089 */
051dae5e 1090 prop_ino_cursor(mp, agno, btree_curs, btnum, startino, level);
2bd0ea18
NS
1091 }
1092 /*
1093 * add inode info to current block
1094 */
5e656dbb 1095 be16_add_cpu(&bt_hdr->bb_numrecs, 1);
2bd0ea18 1096
b3563c19
BN
1097 bt_key = XFS_INOBT_KEY_ADDR(mp, bt_hdr,
1098 be16_to_cpu(bt_hdr->bb_numrecs));
1099 bt_ptr = XFS_INOBT_PTR_ADDR(mp, bt_hdr,
1100 be16_to_cpu(bt_hdr->bb_numrecs),
e7fd2b6f 1101 M_IGEO(mp)->inobt_mxr[1]);
2bd0ea18 1102
5e656dbb
BN
1103 bt_key->ir_startino = cpu_to_be32(startino);
1104 *bt_ptr = cpu_to_be32(btree_curs->level[level-1].agbno);
2bd0ea18
NS
1105}
1106
e0607266
DC
1107/*
1108 * XXX: yet more code that can be shared with mkfs, growfs.
1109 */
8b8a6b02 1110static void
bbdb21b6
BF
1111build_agi(xfs_mount_t *mp, xfs_agnumber_t agno, bt_status_t *btree_curs,
1112 bt_status_t *finobt_curs, struct agi_stat *agi_stat)
2bd0ea18
NS
1113{
1114 xfs_buf_t *agi_buf;
1115 xfs_agi_t *agi;
1116 int i;
58a8b31f 1117 int error;
2bd0ea18 1118
58a8b31f 1119 error = -libxfs_buf_get(mp->m_dev,
9440d84d 1120 XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
58a8b31f
DW
1121 mp->m_sb.sb_sectsize / BBSIZE, &agi_buf);
1122 if (error)
1123 do_error(_("Cannot grab AG %u AGI buffer, err=%d"),
1124 agno, error);
e0607266 1125 agi_buf->b_ops = &xfs_agi_buf_ops;
c99cea5c 1126 agi = agi_buf->b_addr;
dab9b8d6 1127 memset(agi, 0, mp->m_sb.sb_sectsize);
2bd0ea18 1128
5e656dbb
BN
1129 agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC);
1130 agi->agi_versionnum = cpu_to_be32(XFS_AGI_VERSION);
1131 agi->agi_seqno = cpu_to_be32(agno);
2bd0ea18 1132 if (agno < mp->m_sb.sb_agcount - 1)
5e656dbb 1133 agi->agi_length = cpu_to_be32(mp->m_sb.sb_agblocks);
2bd0ea18 1134 else
5e656dbb 1135 agi->agi_length = cpu_to_be32(mp->m_sb.sb_dblocks -
5a35bf2c 1136 (xfs_rfsblock_t) mp->m_sb.sb_agblocks * agno);
d6412d17 1137 agi->agi_count = cpu_to_be32(agi_stat->count);
5e656dbb
BN
1138 agi->agi_root = cpu_to_be32(btree_curs->root);
1139 agi->agi_level = cpu_to_be32(btree_curs->num_levels);
d6412d17
BF
1140 agi->agi_freecount = cpu_to_be32(agi_stat->freecount);
1141 agi->agi_newino = cpu_to_be32(agi_stat->first_agino);
5e656dbb
BN
1142 agi->agi_dirino = cpu_to_be32(NULLAGINO);
1143
f8149110 1144 for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++)
5e656dbb 1145 agi->agi_unlinked[i] = cpu_to_be32(NULLAGINO);
2bd0ea18 1146
e0607266 1147 if (xfs_sb_version_hascrc(&mp->m_sb))
9c4e12fb 1148 platform_uuid_copy(&agi->agi_uuid, &mp->m_sb.sb_meta_uuid);
e0607266 1149
bbdb21b6
BF
1150 if (xfs_sb_version_hasfinobt(&mp->m_sb)) {
1151 agi->agi_free_root = cpu_to_be32(finobt_curs->root);
1152 agi->agi_free_level = cpu_to_be32(finobt_curs->num_levels);
1153 }
1154
f524ae04 1155 libxfs_buf_mark_dirty(agi_buf);
18b4f688 1156 libxfs_buf_relse(agi_buf);
2bd0ea18
NS
1157}
1158
1159/*
1160 * rebuilds an inode tree given a cursor. We're lazy here and call
1161 * the routine that builds the agi
1162 */
8b8a6b02 1163static void
2bd0ea18 1164build_ino_tree(xfs_mount_t *mp, xfs_agnumber_t agno,
912ba355
ES
1165 bt_status_t *btree_curs, xfs_btnum_t btnum,
1166 struct agi_stat *agi_stat)
2bd0ea18
NS
1167{
1168 xfs_agnumber_t i;
1169 xfs_agblock_t j;
1170 xfs_agblock_t agbno;
1171 xfs_agino_t first_agino;
b3563c19 1172 struct xfs_btree_block *bt_hdr;
2bd0ea18
NS
1173 xfs_inobt_rec_t *bt_rec;
1174 ino_tree_node_t *ino_rec;
1175 bt_stat_level_t *lptr;
b4709906 1176 const struct xfs_buf_ops *ops = btnum_to_ops(btnum);
2bd0ea18
NS
1177 xfs_agino_t count = 0;
1178 xfs_agino_t freecount = 0;
1179 int inocnt;
c9dae796 1180 uint8_t finocnt;
2bd0ea18
NS
1181 int k;
1182 int level = btree_curs->num_levels;
c9dae796
BF
1183 int spmask;
1184 uint64_t sparse;
1185 uint16_t holemask;
58a8b31f 1186 int error;
e394a4b1 1187
912ba355 1188 ASSERT(btnum == XFS_BTNUM_INO || btnum == XFS_BTNUM_FINO);
2bd0ea18
NS
1189
1190 for (i = 0; i < level; i++) {
1191 lptr = &btree_curs->level[i];
1192
1193 agbno = get_next_blockaddr(agno, i, btree_curs);
58a8b31f
DW
1194 error = -libxfs_buf_get(mp->m_dev,
1195 XFS_AGB_TO_DADDR(mp, agno, agbno),
1196 XFS_FSB_TO_BB(mp, 1), &lptr->buf_p);
1197 if (error)
1198 do_error(_("Cannot grab inode btree buffer, err=%d"),
1199 error);
2bd0ea18
NS
1200
1201 if (i == btree_curs->num_levels - 1)
1202 btree_curs->root = agbno;
1203
1204 lptr->agbno = agbno;
1205 lptr->prev_agbno = NULLAGBLOCK;
1206 lptr->prev_buf_p = NULL;
1207 /*
1208 * initialize block header
1209 */
e0607266 1210
b4709906 1211 lptr->buf_p->b_ops = ops;
b3563c19 1212 bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p);
dab9b8d6 1213 memset(bt_hdr, 0, mp->m_sb.sb_blocksize);
4aa01a59 1214 libxfs_btree_init_block(mp, lptr->buf_p, btnum, i, 0, agno);
2bd0ea18 1215 }
e0607266 1216
2bd0ea18
NS
1217 /*
1218 * run along leaf, setting up records. as we have to switch
1219 * blocks, call the prop_ino_cursor routine to set up the new
1220 * pointers for the parent. that can recurse up to the root
1221 * if required. set the sibling pointers for leaf level here.
1222 */
912ba355 1223 if (btnum == XFS_BTNUM_FINO)
bbdb21b6
BF
1224 ino_rec = findfirst_free_inode_rec(agno);
1225 else
1226 ino_rec = findfirst_inode_rec(agno);
2bd0ea18
NS
1227
1228 if (ino_rec != NULL)
1229 first_agino = ino_rec->ino_startnum;
1230 else
1231 first_agino = NULLAGINO;
1232
1233 lptr = &btree_curs->level[0];
1234
1235 for (i = 0; i < lptr->num_blocks; i++) {
1236 /*
1237 * block initialization, lay in block header
1238 */
b4709906 1239 lptr->buf_p->b_ops = ops;
b3563c19 1240 bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p);
dab9b8d6 1241 memset(bt_hdr, 0, mp->m_sb.sb_blocksize);
4aa01a59 1242 libxfs_btree_init_block(mp, lptr->buf_p, btnum, 0, 0, agno);
2bd0ea18 1243
b3563c19 1244 bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno);
5e656dbb
BN
1245 bt_hdr->bb_numrecs = cpu_to_be16(lptr->num_recs_pb +
1246 (lptr->modulo > 0));
2bd0ea18
NS
1247
1248 if (lptr->modulo > 0)
1249 lptr->modulo--;
1250
1251 if (lptr->num_recs_pb > 0)
051dae5e 1252 prop_ino_cursor(mp, agno, btree_curs, btnum,
2bd0ea18
NS
1253 ino_rec->ino_startnum, 0);
1254
b3563c19
BN
1255 bt_rec = (xfs_inobt_rec_t *)
1256 ((char *)bt_hdr + XFS_INOBT_BLOCK_LEN(mp));
5e656dbb 1257 for (j = 0; j < be16_to_cpu(bt_hdr->bb_numrecs); j++) {
2bd0ea18 1258 ASSERT(ino_rec != NULL);
5e656dbb
BN
1259 bt_rec[j].ir_startino =
1260 cpu_to_be32(ino_rec->ino_startnum);
1261 bt_rec[j].ir_free = cpu_to_be64(ino_rec->ir_free);
2bd0ea18 1262
c9dae796 1263 inocnt = finocnt = 0;
2bd0ea18
NS
1264 for (k = 0; k < sizeof(xfs_inofree_t)*NBBY; k++) {
1265 ASSERT(is_inode_confirmed(ino_rec, k));
c9dae796
BF
1266
1267 if (is_inode_sparse(ino_rec, k))
1268 continue;
1269 if (is_inode_free(ino_rec, k))
1270 finocnt++;
1271 inocnt++;
2bd0ea18
NS
1272 }
1273
ac9a3f73
BF
1274 /*
1275 * Set the freecount and check whether we need to update
1276 * the sparse format fields. Otherwise, skip to the next
1277 * record.
1278 */
1279 inorec_set_freecount(mp, &bt_rec[j], finocnt);
1280 if (!xfs_sb_version_hassparseinodes(&mp->m_sb))
c9dae796 1281 goto nextrec;
c9dae796
BF
1282
1283 /*
1284 * Convert the 64-bit in-core sparse inode state to the
1285 * 16-bit on-disk holemask.
1286 */
1287 holemask = 0;
1288 spmask = (1 << XFS_INODES_PER_HOLEMASK_BIT) - 1;
1289 sparse = ino_rec->ir_sparse;
1290 for (k = 0; k < XFS_INOBT_HOLEMASK_BITS; k++) {
1291 if (sparse & spmask) {
1292 ASSERT((sparse & spmask) == spmask);
1293 holemask |= (1 << k);
1294 } else
1295 ASSERT((sparse & spmask) == 0);
1296 sparse >>= XFS_INODES_PER_HOLEMASK_BIT;
1297 }
1298
c9dae796
BF
1299 bt_rec[j].ir_u.sp.ir_count = inocnt;
1300 bt_rec[j].ir_u.sp.ir_holemask = cpu_to_be16(holemask);
1301
1302nextrec:
1303 freecount += finocnt;
1304 count += inocnt;
bbdb21b6 1305
912ba355 1306 if (btnum == XFS_BTNUM_FINO)
bbdb21b6
BF
1307 ino_rec = next_free_ino_rec(ino_rec);
1308 else
1309 ino_rec = next_ino_rec(ino_rec);
2bd0ea18
NS
1310 }
1311
1312 if (ino_rec != NULL) {
1313 /*
1314 * get next leaf level block
1315 */
1316 if (lptr->prev_buf_p != NULL) {
1317#ifdef XR_BLD_INO_TRACE
1318 fprintf(stderr, "writing inobt agbno %u\n",
1319 lptr->prev_agbno);
1320#endif
1321 ASSERT(lptr->prev_agbno != NULLAGBLOCK);
f524ae04 1322 libxfs_buf_mark_dirty(lptr->prev_buf_p);
18b4f688 1323 libxfs_buf_relse(lptr->prev_buf_p);
2bd0ea18
NS
1324 }
1325 lptr->prev_buf_p = lptr->buf_p;
1326 lptr->prev_agbno = lptr->agbno;
5e656dbb 1327 lptr->agbno = get_next_blockaddr(agno, 0, btree_curs);
b3563c19 1328 bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(lptr->agbno);
2bd0ea18 1329
58a8b31f 1330 error = -libxfs_buf_get(mp->m_dev,
2bd0ea18 1331 XFS_AGB_TO_DADDR(mp, agno, lptr->agbno),
58a8b31f
DW
1332 XFS_FSB_TO_BB(mp, 1),
1333 &lptr->buf_p);
1334 if (error)
1335 do_error(
1336 _("Cannot grab inode btree buffer, err=%d"),
1337 error);
2bd0ea18
NS
1338 }
1339 }
1340
d6412d17
BF
1341 if (agi_stat) {
1342 agi_stat->first_agino = first_agino;
1343 agi_stat->count = count;
1344 agi_stat->freecount = freecount;
1345 }
2bd0ea18
NS
1346}
1347
934b5548
DW
1348/* rebuild the rmap tree */
1349
1350/*
1351 * we don't have to worry here about how chewing up free extents
1352 * may perturb things because rmap tree building happens before
1353 * freespace tree building.
1354 */
1355static void
1356init_rmapbt_cursor(
1357 struct xfs_mount *mp,
1358 xfs_agnumber_t agno,
1359 struct bt_status *btree_curs)
1360{
1361 size_t num_recs;
1362 int level;
1363 struct bt_stat_level *lptr;
1364 struct bt_stat_level *p_lptr;
1365 xfs_extlen_t blocks_allocated;
934b5548
DW
1366
1367 if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) {
1368 memset(btree_curs, 0, sizeof(struct bt_status));
1369 return;
1370 }
1371
1372 lptr = &btree_curs->level[0];
1373 btree_curs->init = 1;
62cf990a 1374 btree_curs->owner = XFS_RMAP_OWN_AG;
934b5548
DW
1375
1376 /*
1377 * build up statistics
1378 */
1379 num_recs = rmap_record_count(mp, agno);
1380 if (num_recs == 0) {
1381 /*
1382 * easy corner-case -- no rmap records
1383 */
1384 lptr->num_blocks = 1;
1385 lptr->modulo = 0;
1386 lptr->num_recs_pb = 0;
1387 lptr->num_recs_tot = 0;
1388
1389 btree_curs->num_levels = 1;
1390 btree_curs->num_tot_blocks = btree_curs->num_free_blocks = 1;
1391
1392 setup_cursor(mp, agno, btree_curs);
1393
1394 return;
1395 }
1396
1397 /*
1398 * Leave enough slack in the rmapbt that we can insert the
1399 * metadata AG entries without too many splits.
1400 */
6df28d12
GX
1401 compute_level_geometry(mp, lptr, num_recs,
1402 num_recs > mp->m_rmap_mxr[0] ? 10 : 0, true);
1403 blocks_allocated = lptr->num_blocks;
934b5548
DW
1404 level = 1;
1405
6df28d12
GX
1406 while (lptr->num_blocks > 1) {
1407 p_lptr = lptr;
1408 lptr = &btree_curs->level[level++];
934b5548 1409
6df28d12
GX
1410 compute_level_geometry(mp, lptr,
1411 p_lptr->num_blocks, 0, false);
1412 blocks_allocated += lptr->num_blocks;
934b5548 1413 }
6df28d12 1414 ASSERT(level < XFS_BTREE_MAXLEVELS);
934b5548
DW
1415 ASSERT(lptr->num_blocks == 1);
1416 btree_curs->num_levels = level;
1417
1418 btree_curs->num_tot_blocks = btree_curs->num_free_blocks
1419 = blocks_allocated;
1420
1421 setup_cursor(mp, agno, btree_curs);
1422}
1423
1424static void
1425prop_rmap_cursor(
1426 struct xfs_mount *mp,
1427 xfs_agnumber_t agno,
1428 struct bt_status *btree_curs,
1429 struct xfs_rmap_irec *rm_rec,
1430 int level)
1431{
1432 struct xfs_btree_block *bt_hdr;
1433 struct xfs_rmap_key *bt_key;
1434 xfs_rmap_ptr_t *bt_ptr;
1435 xfs_agblock_t agbno;
1436 struct bt_stat_level *lptr;
b4709906 1437 const struct xfs_buf_ops *ops = btnum_to_ops(XFS_BTNUM_RMAP);
58a8b31f 1438 int error;
934b5548
DW
1439
1440 level++;
1441
1442 if (level >= btree_curs->num_levels)
1443 return;
1444
1445 lptr = &btree_curs->level[level];
1446 bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p);
1447
1448 if (be16_to_cpu(bt_hdr->bb_numrecs) == 0) {
1449 /*
1450 * this only happens once to initialize the
1451 * first path up the left side of the tree
1452 * where the agbno's are already set up
1453 */
1454 prop_rmap_cursor(mp, agno, btree_curs, rm_rec, level);
1455 }
1456
1457 if (be16_to_cpu(bt_hdr->bb_numrecs) ==
1458 lptr->num_recs_pb + (lptr->modulo > 0)) {
1459 /*
1460 * write out current prev block, grab us a new block,
1461 * and set the rightsib pointer of current block
1462 */
1463#ifdef XR_BLD_INO_TRACE
138ce9ff 1464 fprintf(stderr, " rmap prop agbno %d ", lptr->prev_agbno);
934b5548
DW
1465#endif
1466 if (lptr->prev_agbno != NULLAGBLOCK) {
1467 ASSERT(lptr->prev_buf_p != NULL);
f524ae04 1468 libxfs_buf_mark_dirty(lptr->prev_buf_p);
18b4f688 1469 libxfs_buf_relse(lptr->prev_buf_p);
934b5548
DW
1470 }
1471 lptr->prev_agbno = lptr->agbno;
1472 lptr->prev_buf_p = lptr->buf_p;
1473 agbno = get_next_blockaddr(agno, level, btree_curs);
1474
1475 bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(agbno);
1476
58a8b31f
DW
1477 error = -libxfs_buf_get(mp->m_dev,
1478 XFS_AGB_TO_DADDR(mp, agno, agbno),
1479 XFS_FSB_TO_BB(mp, 1), &lptr->buf_p);
1480 if (error)
1481 do_error(_("Cannot grab rmapbt buffer, err=%d"),
1482 error);
934b5548
DW
1483 lptr->agbno = agbno;
1484
1485 if (lptr->modulo)
1486 lptr->modulo--;
1487
1488 /*
1489 * initialize block header
1490 */
b4709906 1491 lptr->buf_p->b_ops = ops;
934b5548
DW
1492 bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p);
1493 memset(bt_hdr, 0, mp->m_sb.sb_blocksize);
e394a4b1 1494 libxfs_btree_init_block(mp, lptr->buf_p, XFS_BTNUM_RMAP,
4aa01a59 1495 level, 0, agno);
934b5548
DW
1496
1497 bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno);
1498
1499 /*
1500 * propagate extent record for first extent in new block up
1501 */
1502 prop_rmap_cursor(mp, agno, btree_curs, rm_rec, level);
1503 }
1504 /*
138ce9ff 1505 * add rmap info to current block
934b5548
DW
1506 */
1507 be16_add_cpu(&bt_hdr->bb_numrecs, 1);
1508
1509 bt_key = XFS_RMAP_KEY_ADDR(bt_hdr,
1510 be16_to_cpu(bt_hdr->bb_numrecs));
1511 bt_ptr = XFS_RMAP_PTR_ADDR(bt_hdr,
1512 be16_to_cpu(bt_hdr->bb_numrecs),
1513 mp->m_rmap_mxr[1]);
1514
1515 bt_key->rm_startblock = cpu_to_be32(rm_rec->rm_startblock);
1516 bt_key->rm_owner = cpu_to_be64(rm_rec->rm_owner);
1517 bt_key->rm_offset = cpu_to_be64(rm_rec->rm_offset);
1518
1519 *bt_ptr = cpu_to_be32(btree_curs->level[level-1].agbno);
1520}
1521
1522static void
1523prop_rmap_highkey(
1524 struct xfs_mount *mp,
1525 xfs_agnumber_t agno,
1526 struct bt_status *btree_curs,
1527 struct xfs_rmap_irec *rm_highkey)
1528{
1529 struct xfs_btree_block *bt_hdr;
1530 struct xfs_rmap_key *bt_key;
1531 struct bt_stat_level *lptr;
138ce9ff 1532 struct xfs_rmap_irec key = {0};
934b5548
DW
1533 struct xfs_rmap_irec high_key;
1534 int level;
1535 int i;
1536 int numrecs;
1537
934b5548
DW
1538 high_key = *rm_highkey;
1539 for (level = 1; level < btree_curs->num_levels; level++) {
1540 lptr = &btree_curs->level[level];
1541 bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p);
1542 numrecs = be16_to_cpu(bt_hdr->bb_numrecs);
1543 bt_key = XFS_RMAP_HIGH_KEY_ADDR(bt_hdr, numrecs);
1544
1545 bt_key->rm_startblock = cpu_to_be32(high_key.rm_startblock);
1546 bt_key->rm_owner = cpu_to_be64(high_key.rm_owner);
1547 bt_key->rm_offset = cpu_to_be64(
1548 libxfs_rmap_irec_offset_pack(&high_key));
1549
0ba6dae9 1550 for (i = 1; i <= numrecs; i++) {
934b5548
DW
1551 bt_key = XFS_RMAP_HIGH_KEY_ADDR(bt_hdr, i);
1552 key.rm_startblock = be32_to_cpu(bt_key->rm_startblock);
1553 key.rm_owner = be64_to_cpu(bt_key->rm_owner);
1554 key.rm_offset = be64_to_cpu(bt_key->rm_offset);
1555 if (rmap_diffkeys(&key, &high_key) > 0)
1556 high_key = key;
1557 }
1558 }
1559}
1560
1561/*
1562 * rebuilds a rmap btree given a cursor.
1563 */
1564static void
1565build_rmap_tree(
1566 struct xfs_mount *mp,
1567 xfs_agnumber_t agno,
1568 struct bt_status *btree_curs)
1569{
1570 xfs_agnumber_t i;
1571 xfs_agblock_t j;
1572 xfs_agblock_t agbno;
1573 struct xfs_btree_block *bt_hdr;
1574 struct xfs_rmap_irec *rm_rec;
1575 struct xfs_slab_cursor *rmap_cur;
1576 struct xfs_rmap_rec *bt_rec;
138ce9ff
DW
1577 struct xfs_rmap_irec highest_key = {0};
1578 struct xfs_rmap_irec hi_key = {0};
934b5548 1579 struct bt_stat_level *lptr;
b4709906 1580 const struct xfs_buf_ops *ops = btnum_to_ops(XFS_BTNUM_RMAP);
f9cd7f89 1581 int numrecs;
934b5548
DW
1582 int level = btree_curs->num_levels;
1583 int error;
1584
1585 highest_key.rm_flags = 0;
1586 for (i = 0; i < level; i++) {
1587 lptr = &btree_curs->level[i];
1588
1589 agbno = get_next_blockaddr(agno, i, btree_curs);
58a8b31f
DW
1590 error = -libxfs_buf_get(mp->m_dev,
1591 XFS_AGB_TO_DADDR(mp, agno, agbno),
1592 XFS_FSB_TO_BB(mp, 1), &lptr->buf_p);
1593 if (error)
1594 do_error(_("Cannot grab rmapbt buffer, err=%d"),
1595 error);
934b5548
DW
1596
1597 if (i == btree_curs->num_levels - 1)
1598 btree_curs->root = agbno;
1599
1600 lptr->agbno = agbno;
1601 lptr->prev_agbno = NULLAGBLOCK;
1602 lptr->prev_buf_p = NULL;
1603 /*
1604 * initialize block header
1605 */
1606
b4709906 1607 lptr->buf_p->b_ops = ops;
934b5548
DW
1608 bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p);
1609 memset(bt_hdr, 0, mp->m_sb.sb_blocksize);
e394a4b1 1610 libxfs_btree_init_block(mp, lptr->buf_p, XFS_BTNUM_RMAP,
4aa01a59 1611 i, 0, agno);
934b5548
DW
1612 }
1613
1614 /*
1615 * run along leaf, setting up records. as we have to switch
1616 * blocks, call the prop_rmap_cursor routine to set up the new
1617 * pointers for the parent. that can recurse up to the root
1618 * if required. set the sibling pointers for leaf level here.
1619 */
2d273771 1620 error = rmap_init_cursor(agno, &rmap_cur);
934b5548
DW
1621 if (error)
1622 do_error(
1623_("Insufficient memory to construct reverse-map cursor."));
1624 rm_rec = pop_slab_cursor(rmap_cur);
1625 lptr = &btree_curs->level[0];
1626
f9cd7f89
DW
1627 for (i = 0; i < lptr->num_blocks; i++) {
1628 numrecs = lptr->num_recs_pb + (lptr->modulo > 0);
1629 ASSERT(rm_rec != NULL || numrecs == 0);
1630
934b5548
DW
1631 /*
1632 * block initialization, lay in block header
1633 */
b4709906 1634 lptr->buf_p->b_ops = ops;
934b5548
DW
1635 bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p);
1636 memset(bt_hdr, 0, mp->m_sb.sb_blocksize);
e394a4b1 1637 libxfs_btree_init_block(mp, lptr->buf_p, XFS_BTNUM_RMAP,
4aa01a59 1638 0, 0, agno);
934b5548
DW
1639
1640 bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno);
f9cd7f89 1641 bt_hdr->bb_numrecs = cpu_to_be16(numrecs);
934b5548
DW
1642
1643 if (lptr->modulo > 0)
1644 lptr->modulo--;
1645
138ce9ff
DW
1646 if (lptr->num_recs_pb > 0) {
1647 ASSERT(rm_rec != NULL);
934b5548 1648 prop_rmap_cursor(mp, agno, btree_curs, rm_rec, 0);
138ce9ff 1649 }
934b5548
DW
1650
1651 bt_rec = (struct xfs_rmap_rec *)
1652 ((char *)bt_hdr + XFS_RMAP_BLOCK_LEN);
1653 highest_key.rm_startblock = 0;
1654 highest_key.rm_owner = 0;
1655 highest_key.rm_offset = 0;
1656 for (j = 0; j < be16_to_cpu(bt_hdr->bb_numrecs); j++) {
1657 ASSERT(rm_rec != NULL);
1658 bt_rec[j].rm_startblock =
1659 cpu_to_be32(rm_rec->rm_startblock);
1660 bt_rec[j].rm_blockcount =
1661 cpu_to_be32(rm_rec->rm_blockcount);
1662 bt_rec[j].rm_owner = cpu_to_be64(rm_rec->rm_owner);
1663 bt_rec[j].rm_offset = cpu_to_be64(
1664 libxfs_rmap_irec_offset_pack(rm_rec));
1665 rmap_high_key_from_rec(rm_rec, &hi_key);
1666 if (rmap_diffkeys(&hi_key, &highest_key) > 0)
1667 highest_key = hi_key;
1668
1669 rm_rec = pop_slab_cursor(rmap_cur);
1670 }
1671
1672 /* Now go set the parent key */
1673 prop_rmap_highkey(mp, agno, btree_curs, &highest_key);
1674
1675 if (rm_rec != NULL) {
1676 /*
1677 * get next leaf level block
1678 */
1679 if (lptr->prev_buf_p != NULL) {
1680#ifdef XR_BLD_RL_TRACE
1681 fprintf(stderr, "writing rmapbt agbno %u\n",
1682 lptr->prev_agbno);
1683#endif
1684 ASSERT(lptr->prev_agbno != NULLAGBLOCK);
f524ae04 1685 libxfs_buf_mark_dirty(lptr->prev_buf_p);
18b4f688 1686 libxfs_buf_relse(lptr->prev_buf_p);
934b5548
DW
1687 }
1688 lptr->prev_buf_p = lptr->buf_p;
1689 lptr->prev_agbno = lptr->agbno;
1690 lptr->agbno = get_next_blockaddr(agno, 0, btree_curs);
1691 bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(lptr->agbno);
1692
58a8b31f 1693 error = -libxfs_buf_get(mp->m_dev,
934b5548 1694 XFS_AGB_TO_DADDR(mp, agno, lptr->agbno),
58a8b31f
DW
1695 XFS_FSB_TO_BB(mp, 1),
1696 &lptr->buf_p);
1697 if (error)
1698 do_error(
1699 _("Cannot grab rmapbt buffer, err=%d"),
1700 error);
934b5548
DW
1701 }
1702 }
1703 free_slab_cursor(&rmap_cur);
1704}
1705
586a8fc3
DW
1706/* rebuild the refcount tree */
1707
1708/*
1709 * we don't have to worry here about how chewing up free extents
1710 * may perturb things because reflink tree building happens before
1711 * freespace tree building.
1712 */
1713static void
1714init_refc_cursor(
1715 struct xfs_mount *mp,
1716 xfs_agnumber_t agno,
1717 struct bt_status *btree_curs)
1718{
1719 size_t num_recs;
1720 int level;
1721 struct bt_stat_level *lptr;
1722 struct bt_stat_level *p_lptr;
1723 xfs_extlen_t blocks_allocated;
1724
1725 if (!xfs_sb_version_hasreflink(&mp->m_sb)) {
1726 memset(btree_curs, 0, sizeof(struct bt_status));
1727 return;
1728 }
1729
1730 lptr = &btree_curs->level[0];
1731 btree_curs->init = 1;
1732 btree_curs->owner = XFS_RMAP_OWN_REFC;
1733
1734 /*
1735 * build up statistics
1736 */
1737 num_recs = refcount_record_count(mp, agno);
1738 if (num_recs == 0) {
1739 /*
1740 * easy corner-case -- no refcount records
1741 */
1742 lptr->num_blocks = 1;
1743 lptr->modulo = 0;
1744 lptr->num_recs_pb = 0;
1745 lptr->num_recs_tot = 0;
1746
1747 btree_curs->num_levels = 1;
1748 btree_curs->num_tot_blocks = btree_curs->num_free_blocks = 1;
1749
1750 setup_cursor(mp, agno, btree_curs);
1751
1752 return;
1753 }
1754
1755 blocks_allocated = lptr->num_blocks = howmany(num_recs,
1756 mp->m_refc_mxr[0]);
1757
1758 lptr->modulo = num_recs % lptr->num_blocks;
1759 lptr->num_recs_pb = num_recs / lptr->num_blocks;
1760 lptr->num_recs_tot = num_recs;
1761 level = 1;
1762
1763 if (lptr->num_blocks > 1) {
1764 for (; btree_curs->level[level-1].num_blocks > 1
1765 && level < XFS_BTREE_MAXLEVELS;
1766 level++) {
1767 lptr = &btree_curs->level[level];
1768 p_lptr = &btree_curs->level[level - 1];
1769 lptr->num_blocks = howmany(p_lptr->num_blocks,
1770 mp->m_refc_mxr[1]);
1771 lptr->modulo = p_lptr->num_blocks % lptr->num_blocks;
1772 lptr->num_recs_pb = p_lptr->num_blocks
1773 / lptr->num_blocks;
1774 lptr->num_recs_tot = p_lptr->num_blocks;
1775
1776 blocks_allocated += lptr->num_blocks;
1777 }
1778 }
1779 ASSERT(lptr->num_blocks == 1);
1780 btree_curs->num_levels = level;
1781
1782 btree_curs->num_tot_blocks = btree_curs->num_free_blocks
1783 = blocks_allocated;
1784
1785 setup_cursor(mp, agno, btree_curs);
1786}
1787
1788static void
1789prop_refc_cursor(
1790 struct xfs_mount *mp,
1791 xfs_agnumber_t agno,
1792 struct bt_status *btree_curs,
1793 xfs_agblock_t startbno,
1794 int level)
1795{
1796 struct xfs_btree_block *bt_hdr;
1797 struct xfs_refcount_key *bt_key;
1798 xfs_refcount_ptr_t *bt_ptr;
1799 xfs_agblock_t agbno;
1800 struct bt_stat_level *lptr;
b4709906 1801 const struct xfs_buf_ops *ops = btnum_to_ops(XFS_BTNUM_REFC);
58a8b31f 1802 int error;
586a8fc3
DW
1803
1804 level++;
1805
1806 if (level >= btree_curs->num_levels)
1807 return;
1808
1809 lptr = &btree_curs->level[level];
1810 bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p);
1811
1812 if (be16_to_cpu(bt_hdr->bb_numrecs) == 0) {
1813 /*
1814 * this only happens once to initialize the
1815 * first path up the left side of the tree
1816 * where the agbno's are already set up
1817 */
1818 prop_refc_cursor(mp, agno, btree_curs, startbno, level);
1819 }
1820
1821 if (be16_to_cpu(bt_hdr->bb_numrecs) ==
1822 lptr->num_recs_pb + (lptr->modulo > 0)) {
1823 /*
1824 * write out current prev block, grab us a new block,
1825 * and set the rightsib pointer of current block
1826 */
1827#ifdef XR_BLD_INO_TRACE
1828 fprintf(stderr, " ino prop agbno %d ", lptr->prev_agbno);
1829#endif
1830 if (lptr->prev_agbno != NULLAGBLOCK) {
1831 ASSERT(lptr->prev_buf_p != NULL);
f524ae04 1832 libxfs_buf_mark_dirty(lptr->prev_buf_p);
18b4f688 1833 libxfs_buf_relse(lptr->prev_buf_p);
586a8fc3
DW
1834 }
1835 lptr->prev_agbno = lptr->agbno;
1836 lptr->prev_buf_p = lptr->buf_p;
1837 agbno = get_next_blockaddr(agno, level, btree_curs);
1838
1839 bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(agbno);
1840
58a8b31f
DW
1841 error = -libxfs_buf_get(mp->m_dev,
1842 XFS_AGB_TO_DADDR(mp, agno, agbno),
1843 XFS_FSB_TO_BB(mp, 1), &lptr->buf_p);
1844 if (error)
1845 do_error(_("Cannot grab refcountbt buffer, err=%d"),
1846 error);
586a8fc3
DW
1847 lptr->agbno = agbno;
1848
1849 if (lptr->modulo)
1850 lptr->modulo--;
1851
1852 /*
1853 * initialize block header
1854 */
b4709906 1855 lptr->buf_p->b_ops = ops;
586a8fc3
DW
1856 bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p);
1857 memset(bt_hdr, 0, mp->m_sb.sb_blocksize);
e394a4b1 1858 libxfs_btree_init_block(mp, lptr->buf_p, XFS_BTNUM_REFC,
4aa01a59 1859 level, 0, agno);
586a8fc3
DW
1860
1861 bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno);
1862
1863 /*
1864 * propagate extent record for first extent in new block up
1865 */
1866 prop_refc_cursor(mp, agno, btree_curs, startbno, level);
1867 }
1868 /*
1869 * add inode info to current block
1870 */
1871 be16_add_cpu(&bt_hdr->bb_numrecs, 1);
1872
1873 bt_key = XFS_REFCOUNT_KEY_ADDR(bt_hdr,
1874 be16_to_cpu(bt_hdr->bb_numrecs));
1875 bt_ptr = XFS_REFCOUNT_PTR_ADDR(bt_hdr,
1876 be16_to_cpu(bt_hdr->bb_numrecs),
1877 mp->m_refc_mxr[1]);
1878
1879 bt_key->rc_startblock = cpu_to_be32(startbno);
1880 *bt_ptr = cpu_to_be32(btree_curs->level[level-1].agbno);
1881}
1882
1883/*
1884 * rebuilds a refcount btree given a cursor.
1885 */
1886static void
1887build_refcount_tree(
1888 struct xfs_mount *mp,
1889 xfs_agnumber_t agno,
1890 struct bt_status *btree_curs)
1891{
1892 xfs_agnumber_t i;
1893 xfs_agblock_t j;
1894 xfs_agblock_t agbno;
1895 struct xfs_btree_block *bt_hdr;
1896 struct xfs_refcount_irec *refc_rec;
1897 struct xfs_slab_cursor *refc_cur;
1898 struct xfs_refcount_rec *bt_rec;
1899 struct bt_stat_level *lptr;
b4709906 1900 const struct xfs_buf_ops *ops = btnum_to_ops(XFS_BTNUM_REFC);
f9cd7f89 1901 int numrecs;
586a8fc3
DW
1902 int level = btree_curs->num_levels;
1903 int error;
1904
1905 for (i = 0; i < level; i++) {
1906 lptr = &btree_curs->level[i];
1907
1908 agbno = get_next_blockaddr(agno, i, btree_curs);
58a8b31f
DW
1909 error = -libxfs_buf_get(mp->m_dev,
1910 XFS_AGB_TO_DADDR(mp, agno, agbno),
1911 XFS_FSB_TO_BB(mp, 1), &lptr->buf_p);
1912 if (error)
1913 do_error(_("Cannot grab refcountbt buffer, err=%d"),
1914 error);
586a8fc3
DW
1915
1916 if (i == btree_curs->num_levels - 1)
1917 btree_curs->root = agbno;
1918
1919 lptr->agbno = agbno;
1920 lptr->prev_agbno = NULLAGBLOCK;
1921 lptr->prev_buf_p = NULL;
1922 /*
1923 * initialize block header
1924 */
1925
b4709906 1926 lptr->buf_p->b_ops = ops;
586a8fc3
DW
1927 bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p);
1928 memset(bt_hdr, 0, mp->m_sb.sb_blocksize);
e394a4b1 1929 libxfs_btree_init_block(mp, lptr->buf_p, XFS_BTNUM_REFC,
4aa01a59 1930 i, 0, agno);
586a8fc3
DW
1931 }
1932
1933 /*
1934 * run along leaf, setting up records. as we have to switch
1935 * blocks, call the prop_refc_cursor routine to set up the new
1936 * pointers for the parent. that can recurse up to the root
1937 * if required. set the sibling pointers for leaf level here.
1938 */
1939 error = init_refcount_cursor(agno, &refc_cur);
1940 if (error)
1941 do_error(
1942_("Insufficient memory to construct refcount cursor."));
1943 refc_rec = pop_slab_cursor(refc_cur);
1944 lptr = &btree_curs->level[0];
1945
f9cd7f89
DW
1946 for (i = 0; i < lptr->num_blocks; i++) {
1947 numrecs = lptr->num_recs_pb + (lptr->modulo > 0);
1948 ASSERT(refc_rec != NULL || numrecs == 0);
1949
586a8fc3
DW
1950 /*
1951 * block initialization, lay in block header
1952 */
b4709906 1953 lptr->buf_p->b_ops = ops;
586a8fc3
DW
1954 bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p);
1955 memset(bt_hdr, 0, mp->m_sb.sb_blocksize);
e394a4b1 1956 libxfs_btree_init_block(mp, lptr->buf_p, XFS_BTNUM_REFC,
4aa01a59 1957 0, 0, agno);
586a8fc3
DW
1958
1959 bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno);
f9cd7f89 1960 bt_hdr->bb_numrecs = cpu_to_be16(numrecs);
586a8fc3
DW
1961
1962 if (lptr->modulo > 0)
1963 lptr->modulo--;
1964
1965 if (lptr->num_recs_pb > 0)
1966 prop_refc_cursor(mp, agno, btree_curs,
1967 refc_rec->rc_startblock, 0);
1968
1969 bt_rec = (struct xfs_refcount_rec *)
1970 ((char *)bt_hdr + XFS_REFCOUNT_BLOCK_LEN);
1971 for (j = 0; j < be16_to_cpu(bt_hdr->bb_numrecs); j++) {
1972 ASSERT(refc_rec != NULL);
1973 bt_rec[j].rc_startblock =
1974 cpu_to_be32(refc_rec->rc_startblock);
1975 bt_rec[j].rc_blockcount =
1976 cpu_to_be32(refc_rec->rc_blockcount);
1977 bt_rec[j].rc_refcount = cpu_to_be32(refc_rec->rc_refcount);
1978
1979 refc_rec = pop_slab_cursor(refc_cur);
1980 }
1981
1982 if (refc_rec != NULL) {
1983 /*
1984 * get next leaf level block
1985 */
1986 if (lptr->prev_buf_p != NULL) {
1987#ifdef XR_BLD_RL_TRACE
1988 fprintf(stderr, "writing refcntbt agbno %u\n",
1989 lptr->prev_agbno);
1990#endif
1991 ASSERT(lptr->prev_agbno != NULLAGBLOCK);
f524ae04 1992 libxfs_buf_mark_dirty(lptr->prev_buf_p);
18b4f688 1993 libxfs_buf_relse(lptr->prev_buf_p);
586a8fc3
DW
1994 }
1995 lptr->prev_buf_p = lptr->buf_p;
1996 lptr->prev_agbno = lptr->agbno;
1997 lptr->agbno = get_next_blockaddr(agno, 0, btree_curs);
1998 bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(lptr->agbno);
1999
58a8b31f 2000 error = -libxfs_buf_get(mp->m_dev,
586a8fc3 2001 XFS_AGB_TO_DADDR(mp, agno, lptr->agbno),
58a8b31f
DW
2002 XFS_FSB_TO_BB(mp, 1),
2003 &lptr->buf_p);
2004 if (error)
2005 do_error(
2006 _("Cannot grab refcountbt buffer, err=%d"),
2007 error);
586a8fc3
DW
2008 }
2009 }
2010 free_slab_cursor(&refc_cur);
2011}
2012
2bd0ea18
NS
2013/*
2014 * build both the agf and the agfl for an agno given both
e0607266
DC
2015 * btree cursors.
2016 *
2017 * XXX: yet more common code that can be shared with mkfs/growfs.
2bd0ea18 2018 */
8b8a6b02 2019static void
934b5548
DW
2020build_agf_agfl(
2021 struct xfs_mount *mp,
2022 xfs_agnumber_t agno,
2023 struct bt_status *bno_bt,
2024 struct bt_status *bcnt_bt,
2025 xfs_extlen_t freeblks, /* # free blocks in tree */
ef4332b8 2026 struct bt_status *rmap_bt,
586a8fc3 2027 struct bt_status *refcnt_bt,
ef4332b8 2028 struct xfs_slab *lost_fsb)
2bd0ea18 2029{
934b5548
DW
2030 struct extent_tree_node *ext_ptr;
2031 struct xfs_buf *agf_buf, *agfl_buf;
2bd0ea18 2032 int i;
934b5548
DW
2033 struct xfs_agfl *agfl;
2034 struct xfs_agf *agf;
ef4332b8 2035 xfs_fsblock_t fsb;
84232448 2036 __be32 *freelist;
ef4332b8 2037 int error;
2bd0ea18 2038
58a8b31f 2039 error = -libxfs_buf_get(mp->m_dev,
9440d84d 2040 XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)),
58a8b31f
DW
2041 mp->m_sb.sb_sectsize / BBSIZE, &agf_buf);
2042 if (error)
2043 do_error(_("Cannot grab AG %u AGF buffer, err=%d"),
2044 agno, error);
e0607266 2045 agf_buf->b_ops = &xfs_agf_buf_ops;
0bc284c2 2046 agf = agf_buf->b_addr;
dab9b8d6 2047 memset(agf, 0, mp->m_sb.sb_sectsize);
2bd0ea18
NS
2048
2049#ifdef XR_BLD_FREE_TRACE
ef4109d1 2050 fprintf(stderr, "agf = %p, agf_buf->b_addr = %p\n",
7c7c113c 2051 agf, agf_buf->b_addr);
2bd0ea18
NS
2052#endif
2053
2054 /*
2055 * set up fixed part of agf
2056 */
5e656dbb
BN
2057 agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC);
2058 agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION);
2059 agf->agf_seqno = cpu_to_be32(agno);
2bd0ea18
NS
2060
2061 if (agno < mp->m_sb.sb_agcount - 1)
5e656dbb 2062 agf->agf_length = cpu_to_be32(mp->m_sb.sb_agblocks);
2bd0ea18 2063 else
5e656dbb 2064 agf->agf_length = cpu_to_be32(mp->m_sb.sb_dblocks -
5a35bf2c 2065 (xfs_rfsblock_t) mp->m_sb.sb_agblocks * agno);
2bd0ea18 2066
5e656dbb
BN
2067 agf->agf_roots[XFS_BTNUM_BNO] = cpu_to_be32(bno_bt->root);
2068 agf->agf_levels[XFS_BTNUM_BNO] = cpu_to_be32(bno_bt->num_levels);
2069 agf->agf_roots[XFS_BTNUM_CNT] = cpu_to_be32(bcnt_bt->root);
2070 agf->agf_levels[XFS_BTNUM_CNT] = cpu_to_be32(bcnt_bt->num_levels);
934b5548
DW
2071 agf->agf_roots[XFS_BTNUM_RMAP] = cpu_to_be32(rmap_bt->root);
2072 agf->agf_levels[XFS_BTNUM_RMAP] = cpu_to_be32(rmap_bt->num_levels);
5e656dbb 2073 agf->agf_freeblks = cpu_to_be32(freeblks);
934b5548
DW
2074 agf->agf_rmap_blocks = cpu_to_be32(rmap_bt->num_tot_blocks -
2075 rmap_bt->num_free_blocks);
586a8fc3
DW
2076 agf->agf_refcount_root = cpu_to_be32(refcnt_bt->root);
2077 agf->agf_refcount_level = cpu_to_be32(refcnt_bt->num_levels);
2078 agf->agf_refcount_blocks = cpu_to_be32(refcnt_bt->num_tot_blocks -
2079 refcnt_bt->num_free_blocks);
2bd0ea18 2080
cdded3d8
DC
2081 /*
2082 * Count and record the number of btree blocks consumed if required.
2083 */
5e656dbb 2084 if (xfs_sb_version_haslazysbcount(&mp->m_sb)) {
934b5548 2085 unsigned int blks;
cdded3d8
DC
2086 /*
2087 * Don't count the root blocks as they are already
2088 * accounted for.
2089 */
934b5548 2090 blks = (bno_bt->num_tot_blocks - bno_bt->num_free_blocks) +
cdded3d8 2091 (bcnt_bt->num_tot_blocks - bcnt_bt->num_free_blocks) -
934b5548
DW
2092 2;
2093 if (xfs_sb_version_hasrmapbt(&mp->m_sb))
2094 blks += rmap_bt->num_tot_blocks - rmap_bt->num_free_blocks - 1;
2095 agf->agf_btreeblks = cpu_to_be32(blks);
cdded3d8
DC
2096#ifdef XR_BLD_FREE_TRACE
2097 fprintf(stderr, "agf->agf_btreeblks = %u\n",
5e656dbb 2098 be32_to_cpu(agf->agf_btreeblks));
cdded3d8
DC
2099#endif
2100 }
2101
2bd0ea18
NS
2102#ifdef XR_BLD_FREE_TRACE
2103 fprintf(stderr, "bno root = %u, bcnt root = %u, indices = %u %u\n",
5e656dbb
BN
2104 be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNO]),
2105 be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNT]),
2bd0ea18
NS
2106 XFS_BTNUM_BNO,
2107 XFS_BTNUM_CNT);
2108#endif
2109
e0607266 2110 if (xfs_sb_version_hascrc(&mp->m_sb))
9c4e12fb 2111 platform_uuid_copy(&agf->agf_uuid, &mp->m_sb.sb_meta_uuid);
e0607266
DC
2112
2113 /* initialise the AGFL, then fill it if there are blocks left over. */
58a8b31f 2114 error = -libxfs_buf_get(mp->m_dev,
e0607266 2115 XFS_AG_DADDR(mp, agno, XFS_AGFL_DADDR(mp)),
58a8b31f
DW
2116 mp->m_sb.sb_sectsize / BBSIZE, &agfl_buf);
2117 if (error)
2118 do_error(_("Cannot grab AG %u AGFL buffer, err=%d"),
2119 agno, error);
e0607266
DC
2120 agfl_buf->b_ops = &xfs_agfl_buf_ops;
2121 agfl = XFS_BUF_TO_AGFL(agfl_buf);
2122
2123 /* setting to 0xff results in initialisation to NULLAGBLOCK */
2124 memset(agfl, 0xff, mp->m_sb.sb_sectsize);
0c02ef9b 2125 freelist = xfs_buf_to_agfl_bno(agfl_buf);
e0607266
DC
2126 if (xfs_sb_version_hascrc(&mp->m_sb)) {
2127 agfl->agfl_magicnum = cpu_to_be32(XFS_AGFL_MAGIC);
2128 agfl->agfl_seqno = cpu_to_be32(agno);
9c4e12fb 2129 platform_uuid_copy(&agfl->agfl_uuid, &mp->m_sb.sb_meta_uuid);
b8165508 2130 for (i = 0; i < libxfs_agfl_size(mp); i++)
0c02ef9b 2131 freelist[i] = cpu_to_be32(NULLAGBLOCK);
e0607266 2132 }
b134e771 2133
2bd0ea18
NS
2134 /*
2135 * do we have left-over blocks in the btree cursors that should
2136 * be used to fill the AGFL?
2137 */
2138 if (bno_bt->num_free_blocks > 0 || bcnt_bt->num_free_blocks > 0) {
2139 /*
e0607266 2140 * yes, now grab as many blocks as we can
2bd0ea18 2141 */
ef4332b8 2142 i = 0;
b8165508
DC
2143 while (bno_bt->num_free_blocks > 0 && i < libxfs_agfl_size(mp))
2144 {
84232448 2145 freelist[i] = cpu_to_be32(
5e656dbb 2146 get_next_blockaddr(agno, 0, bno_bt));
2bd0ea18
NS
2147 i++;
2148 }
2149
b8165508
DC
2150 while (bcnt_bt->num_free_blocks > 0 && i < libxfs_agfl_size(mp))
2151 {
84232448 2152 freelist[i] = cpu_to_be32(
5e656dbb 2153 get_next_blockaddr(agno, 0, bcnt_bt));
2bd0ea18
NS
2154 i++;
2155 }
2156 /*
2157 * now throw the rest of the blocks away and complain
2158 */
ef4332b8
DW
2159 while (bno_bt->num_free_blocks > 0) {
2160 fsb = XFS_AGB_TO_FSB(mp, agno,
2161 get_next_blockaddr(agno, 0, bno_bt));
2162 error = slab_add(lost_fsb, &fsb);
2163 if (error)
2164 do_error(
2165_("Insufficient memory saving lost blocks.\n"));
2bd0ea18 2166 }
ef4332b8
DW
2167 while (bcnt_bt->num_free_blocks > 0) {
2168 fsb = XFS_AGB_TO_FSB(mp, agno,
2169 get_next_blockaddr(agno, 0, bcnt_bt));
2170 error = slab_add(lost_fsb, &fsb);
2171 if (error)
2172 do_error(
2173_("Insufficient memory saving lost blocks.\n"));
2bd0ea18
NS
2174 }
2175
46eca962 2176 agf->agf_flfirst = 0;
5e656dbb
BN
2177 agf->agf_fllast = cpu_to_be32(i - 1);
2178 agf->agf_flcount = cpu_to_be32(i);
62cf990a 2179 rmap_store_agflcount(mp, agno, i);
2bd0ea18
NS
2180
2181#ifdef XR_BLD_FREE_TRACE
2182 fprintf(stderr, "writing agfl for ag %u\n", agno);
2183#endif
2184
2bd0ea18 2185 } else {
46eca962 2186 agf->agf_flfirst = 0;
b8165508 2187 agf->agf_fllast = cpu_to_be32(libxfs_agfl_size(mp) - 1);
46eca962 2188 agf->agf_flcount = 0;
2bd0ea18
NS
2189 }
2190
f524ae04 2191 libxfs_buf_mark_dirty(agfl_buf);
18b4f688 2192 libxfs_buf_relse(agfl_buf);
e0607266 2193
2bd0ea18 2194 ext_ptr = findbiggest_bcnt_extent(agno);
5e656dbb
BN
2195 agf->agf_longest = cpu_to_be32((ext_ptr != NULL) ?
2196 ext_ptr->ex_blockcount : 0);
2bd0ea18 2197
5e656dbb
BN
2198 ASSERT(be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNOi]) !=
2199 be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNTi]));
586a8fc3
DW
2200 ASSERT(be32_to_cpu(agf->agf_refcount_root) !=
2201 be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNOi]));
2202 ASSERT(be32_to_cpu(agf->agf_refcount_root) !=
2203 be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNTi]));
2bd0ea18 2204
f524ae04 2205 libxfs_buf_mark_dirty(agf_buf);
18b4f688 2206 libxfs_buf_relse(agf_buf);
2bd0ea18 2207
e0607266
DC
2208 /*
2209 * now fix up the free list appropriately
e0607266 2210 */
62cf990a 2211 fix_freelist(mp, agno, true);
e0607266 2212
2bd0ea18 2213#ifdef XR_BLD_FREE_TRACE
7c7c113c 2214 fprintf(stderr, "wrote agf for ag %u\n", agno);
2bd0ea18
NS
2215#endif
2216}
2217
2218/*
2219 * update the superblock counters, sync the sb version numbers and
2220 * feature bits to the filesystem, and sync up the on-disk superblock
2221 * to match the incore superblock.
2222 */
8b8a6b02 2223static void
2bd0ea18
NS
2224sync_sb(xfs_mount_t *mp)
2225{
2bd0ea18
NS
2226 xfs_buf_t *bp;
2227
67c4a324 2228 bp = libxfs_getsb(mp);
2bd0ea18 2229 if (!bp)
507f4e33 2230 do_error(_("couldn't get superblock\n"));
2bd0ea18 2231
2bd0ea18
NS
2232 mp->m_sb.sb_icount = sb_icount;
2233 mp->m_sb.sb_ifree = sb_ifree;
2234 mp->m_sb.sb_fdblocks = sb_fdblocks;
2235 mp->m_sb.sb_frextents = sb_frextents;
2236
2237 update_sb_version(mp);
2238
d6522f1d 2239 libxfs_sb_to_disk(bp->b_addr, &mp->m_sb);
f524ae04 2240 libxfs_buf_mark_dirty(bp);
18b4f688 2241 libxfs_buf_relse(bp);
2bd0ea18
NS
2242}
2243
2244/*
2245 * make sure the root and realtime inodes show up allocated
2246 * even if they've been freed. they get reinitialized in phase6.
2247 */
8b8a6b02 2248static void
2bd0ea18
NS
2249keep_fsinos(xfs_mount_t *mp)
2250{
2251 ino_tree_node_t *irec;
2252 int i;
2253
1ae311d5 2254 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino),
2bd0ea18
NS
2255 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino));
2256
2257 for (i = 0; i < 3; i++)
2258 set_inode_used(irec, i);
2259}
2260
2556c98b
BN
2261static void
2262phase5_func(
2263 xfs_mount_t *mp,
ef4332b8
DW
2264 xfs_agnumber_t agno,
2265 struct xfs_slab *lost_fsb)
2bd0ea18 2266{
14f8b681
DW
2267 uint64_t num_inos;
2268 uint64_t num_free_inos;
2269 uint64_t finobt_num_inos;
2270 uint64_t finobt_num_free_inos;
2bd0ea18
NS
2271 bt_status_t bno_btree_curs;
2272 bt_status_t bcnt_btree_curs;
2273 bt_status_t ino_btree_curs;
bbdb21b6 2274 bt_status_t fino_btree_curs;
934b5548 2275 bt_status_t rmap_btree_curs;
586a8fc3 2276 bt_status_t refcnt_btree_curs;
2bd0ea18
NS
2277 int extra_blocks = 0;
2278 uint num_freeblocks;
2279 xfs_extlen_t freeblks1;
1e77098c 2280#ifdef DEBUG
2bd0ea18 2281 xfs_extlen_t freeblks2;
1e77098c 2282#endif
2bd0ea18 2283 xfs_agblock_t num_extents;
d6412d17 2284 struct agi_stat agi_stat = {0,};
2bd0ea18 2285
3b6ac903
MV
2286 if (verbose)
2287 do_log(_(" - agno = %d\n"), agno);
2bd0ea18 2288
3b6ac903 2289 {
2bd0ea18
NS
2290 /*
2291 * build up incore bno and bcnt extent btrees
2292 */
2293 num_extents = mk_incore_fstree(mp, agno);
2294
2295#ifdef XR_BLD_FREE_TRACE
2296 fprintf(stderr, "# of bno extents is %d\n",
2297 count_bno_extents(agno));
2298#endif
2299
2300 if (num_extents == 0) {
2301 /*
2302 * XXX - what we probably should do here is pick an
2303 * inode for a regular file in the allocation group
2304 * that has space allocated and shoot it by traversing
2305 * the bmap list and putting all its extents on the
2306 * incore freespace trees, clearing the inode,
2307 * and clearing the in-use bit in the incore inode
2308 * tree. Then try mk_incore_fstree() again.
2309 */
507f4e33
NS
2310 do_error(_("unable to rebuild AG %u. "
2311 "Not enough free space in on-disk AG.\n"),
2312 agno);
2bd0ea18
NS
2313 }
2314
2bd0ea18
NS
2315 /*
2316 * ok, now set up the btree cursors for the
2317 * on-disk btrees (includs pre-allocating all
2318 * required blocks for the trees themselves)
2319 */
bbdb21b6
BF
2320 init_ino_cursor(mp, agno, &ino_btree_curs, &num_inos,
2321 &num_free_inos, 0);
2322
2323 if (xfs_sb_version_hasfinobt(&mp->m_sb))
2324 init_ino_cursor(mp, agno, &fino_btree_curs,
2325 &finobt_num_inos, &finobt_num_free_inos,
2326 1);
2bd0ea18 2327
3b6ac903
MV
2328 sb_icount_ag[agno] += num_inos;
2329 sb_ifree_ag[agno] += num_free_inos;
2bd0ea18 2330
934b5548
DW
2331 /*
2332 * Set up the btree cursors for the on-disk rmap btrees,
2333 * which includes pre-allocating all required blocks.
2334 */
2335 init_rmapbt_cursor(mp, agno, &rmap_btree_curs);
2336
586a8fc3
DW
2337 /*
2338 * Set up the btree cursors for the on-disk refcount btrees,
2339 * which includes pre-allocating all required blocks.
2340 */
2341 init_refc_cursor(mp, agno, &refcnt_btree_curs);
2342
2bd0ea18
NS
2343 num_extents = count_bno_extents_blocks(agno, &num_freeblocks);
2344 /*
2345 * lose two blocks per AG -- the space tree roots
2346 * are counted as allocated since the space trees
2347 * always have roots
2348 */
3b6ac903 2349 sb_fdblocks_ag[agno] += num_freeblocks - 2;
2bd0ea18
NS
2350
2351 if (num_extents == 0) {
2352 /*
2353 * XXX - what we probably should do here is pick an
2354 * inode for a regular file in the allocation group
2355 * that has space allocated and shoot it by traversing
2356 * the bmap list and putting all its extents on the
2357 * incore freespace trees, clearing the inode,
2358 * and clearing the in-use bit in the incore inode
2359 * tree. Then try mk_incore_fstree() again.
2360 */
507f4e33
NS
2361 do_error(
2362 _("unable to rebuild AG %u. No free space.\n"), agno);
2bd0ea18
NS
2363 }
2364
2365#ifdef XR_BLD_FREE_TRACE
2366 fprintf(stderr, "# of bno extents is %d\n", num_extents);
2367#endif
2368
2369 /*
2370 * track blocks that we might really lose
2371 */
2372 extra_blocks = calculate_freespace_cursor(mp, agno,
2373 &num_extents, &bno_btree_curs);
2374
2375 /*
2376 * freespace btrees live in the "free space" but
2377 * the filesystem treats AGFL blocks as allocated
2378 * since they aren't described by the freespace trees
2379 */
2380
2381 /*
2382 * see if we can fit all the extra blocks into the AGFL
2383 */
b8165508
DC
2384 extra_blocks = (extra_blocks - libxfs_agfl_size(mp) > 0)
2385 ? extra_blocks - libxfs_agfl_size(mp)
2bd0ea18
NS
2386 : 0;
2387
ef4332b8 2388 if (extra_blocks > 0)
3b6ac903 2389 sb_fdblocks_ag[agno] -= extra_blocks;
2bd0ea18
NS
2390
2391 bcnt_btree_curs = bno_btree_curs;
2392
62cf990a
DW
2393 bno_btree_curs.owner = XFS_RMAP_OWN_AG;
2394 bcnt_btree_curs.owner = XFS_RMAP_OWN_AG;
2bd0ea18
NS
2395 setup_cursor(mp, agno, &bno_btree_curs);
2396 setup_cursor(mp, agno, &bcnt_btree_curs);
2397
2398#ifdef XR_BLD_FREE_TRACE
2399 fprintf(stderr, "# of bno extents is %d\n",
2400 count_bno_extents(agno));
2401 fprintf(stderr, "# of bcnt extents is %d\n",
2402 count_bcnt_extents(agno));
2403#endif
46eca962 2404
2bd0ea18
NS
2405 /*
2406 * now rebuild the freespace trees
2407 */
46eca962 2408 freeblks1 = build_freespace_tree(mp, agno,
912ba355 2409 &bno_btree_curs, XFS_BTNUM_BNO);
2bd0ea18
NS
2410#ifdef XR_BLD_FREE_TRACE
2411 fprintf(stderr, "# of free blocks == %d\n", freeblks1);
2412#endif
2413 write_cursor(&bno_btree_curs);
2414
1e77098c 2415#ifdef DEBUG
46eca962 2416 freeblks2 = build_freespace_tree(mp, agno,
912ba355 2417 &bcnt_btree_curs, XFS_BTNUM_CNT);
1e77098c
MV
2418#else
2419 (void) build_freespace_tree(mp, agno,
912ba355 2420 &bcnt_btree_curs, XFS_BTNUM_CNT);
1e77098c 2421#endif
2bd0ea18
NS
2422 write_cursor(&bcnt_btree_curs);
2423
2424 ASSERT(freeblks1 == freeblks2);
2425
934b5548
DW
2426 if (xfs_sb_version_hasrmapbt(&mp->m_sb)) {
2427 build_rmap_tree(mp, agno, &rmap_btree_curs);
2428 write_cursor(&rmap_btree_curs);
2429 sb_fdblocks_ag[agno] += (rmap_btree_curs.num_tot_blocks -
2430 rmap_btree_curs.num_free_blocks) - 1;
2431 }
2432
586a8fc3
DW
2433 if (xfs_sb_version_hasreflink(&mp->m_sb)) {
2434 build_refcount_tree(mp, agno, &refcnt_btree_curs);
2435 write_cursor(&refcnt_btree_curs);
2436 }
2437
2bd0ea18
NS
2438 /*
2439 * set up agf and agfl
2440 */
98206665
DW
2441 build_agf_agfl(mp, agno, &bno_btree_curs, &bcnt_btree_curs,
2442 freeblks1, &rmap_btree_curs,
2443 &refcnt_btree_curs, lost_fsb);
2bd0ea18 2444 /*
d6412d17 2445 * build inode allocation tree.
2bd0ea18 2446 */
912ba355
ES
2447 build_ino_tree(mp, agno, &ino_btree_curs, XFS_BTNUM_INO,
2448 &agi_stat);
2bd0ea18 2449 write_cursor(&ino_btree_curs);
d6412d17 2450
bbdb21b6
BF
2451 /*
2452 * build free inode tree
2453 */
2454 if (xfs_sb_version_hasfinobt(&mp->m_sb)) {
912ba355
ES
2455 build_ino_tree(mp, agno, &fino_btree_curs,
2456 XFS_BTNUM_FINO, NULL);
bbdb21b6
BF
2457 write_cursor(&fino_btree_curs);
2458 }
2459
d6412d17 2460 /* build the agi */
bbdb21b6
BF
2461 build_agi(mp, agno, &ino_btree_curs, &fino_btree_curs,
2462 &agi_stat);
d6412d17 2463
2bd0ea18
NS
2464 /*
2465 * tear down cursors
2466 */
2467 finish_cursor(&bno_btree_curs);
2468 finish_cursor(&ino_btree_curs);
934b5548
DW
2469 if (xfs_sb_version_hasrmapbt(&mp->m_sb))
2470 finish_cursor(&rmap_btree_curs);
586a8fc3
DW
2471 if (xfs_sb_version_hasreflink(&mp->m_sb))
2472 finish_cursor(&refcnt_btree_curs);
bbdb21b6
BF
2473 if (xfs_sb_version_hasfinobt(&mp->m_sb))
2474 finish_cursor(&fino_btree_curs);
2bd0ea18 2475 finish_cursor(&bcnt_btree_curs);
62cf990a 2476
2bd0ea18
NS
2477 /*
2478 * release the incore per-AG bno/bcnt trees so
2479 * the extent nodes can be recycled
2480 */
2481 release_agbno_extent_tree(agno);
2482 release_agbcnt_extent_tree(agno);
2483 }
06fbdda9 2484 PROG_RPT_INC(prog_rpt_done[agno], 1);
3b6ac903
MV
2485}
2486
ef4332b8
DW
2487/* Inject lost blocks back into the filesystem. */
2488static int
2489inject_lost_blocks(
2490 struct xfs_mount *mp,
2491 struct xfs_slab *lost_fsbs)
2492{
2493 struct xfs_trans *tp = NULL;
2494 struct xfs_slab_cursor *cur = NULL;
2495 xfs_fsblock_t *fsb;
ef4332b8
DW
2496 int error;
2497
ef4332b8
DW
2498 error = init_slab_cursor(lost_fsbs, NULL, &cur);
2499 if (error)
2500 return error;
2501
2502 while ((fsb = pop_slab_cursor(cur)) != NULL) {
225e4bb2 2503 error = -libxfs_trans_alloc_rollable(mp, 16, &tp);
ef4332b8
DW
2504 if (error)
2505 goto out_cancel;
2506
007347e3 2507 error = -libxfs_free_extent(tp, *fsb, 1, &XFS_RMAP_OINFO_AG,
cf8ce220 2508 XFS_AG_RESV_NONE);
ef4332b8
DW
2509 if (error)
2510 goto out_cancel;
2511
2512 error = -libxfs_trans_commit(tp);
2513 if (error)
2514 goto out_cancel;
2515 tp = NULL;
2516 }
2517
2518out_cancel:
2519 if (tp)
2520 libxfs_trans_cancel(tp);
2521 free_slab_cursor(&cur);
2522 return error;
2523}
2524
3b6ac903
MV
2525void
2526phase5(xfs_mount_t *mp)
2527{
ef4332b8 2528 struct xfs_slab *lost_fsb;
2556c98b 2529 xfs_agnumber_t agno;
ef4332b8 2530 int error;
3b6ac903
MV
2531
2532 do_log(_("Phase 5 - rebuild AG headers and trees...\n"));
14f8b681 2533 set_progress_msg(PROG_FMT_REBUILD_AG, (uint64_t)glob_agcount);
3b6ac903
MV
2534
2535#ifdef XR_BLD_FREE_TRACE
2536 fprintf(stderr, "inobt level 1, maxrec = %d, minrec = %d\n",
e2f60652
DW
2537 libxfs_inobt_maxrecs(mp, mp->m_sb.sb_blocksize, 0),
2538 libxfs_inobt_maxrecs(mp, mp->m_sb.sb_blocksize, 0) / 2);
3b6ac903 2539 fprintf(stderr, "inobt level 0 (leaf), maxrec = %d, minrec = %d\n",
e2f60652
DW
2540 libxfs_inobt_maxrecs(mp, mp->m_sb.sb_blocksize, 1),
2541 libxfs_inobt_maxrecs(mp, mp->m_sb.sb_blocksize, 1) / 2);
3b6ac903
MV
2542 fprintf(stderr, "xr inobt level 0 (leaf), maxrec = %d\n",
2543 XR_INOBT_BLOCK_MAXRECS(mp, 0));
2544 fprintf(stderr, "xr inobt level 1 (int), maxrec = %d\n",
2545 XR_INOBT_BLOCK_MAXRECS(mp, 1));
2546 fprintf(stderr, "bnobt level 1, maxrec = %d, minrec = %d\n",
e2f60652
DW
2547 libxfs_allocbt_maxrecs(mp, mp->m_sb.sb_blocksize, 0),
2548 libxfs_allocbt_maxrecs(mp, mp->m_sb.sb_blocksize, 0) / 2);
3b6ac903 2549 fprintf(stderr, "bnobt level 0 (leaf), maxrec = %d, minrec = %d\n",
e2f60652
DW
2550 libxfs_allocbt_maxrecs(mp, mp->m_sb.sb_blocksize, 1),
2551 libxfs_allocbt_maxrecs(mp, mp->m_sb.sb_blocksize, 1) / 2);
3b6ac903
MV
2552#endif
2553 /*
2554 * make sure the root and realtime inodes show up allocated
2555 */
2556 keep_fsinos(mp);
2557
2558 /* allocate per ag counters */
14f8b681 2559 sb_icount_ag = calloc(mp->m_sb.sb_agcount, sizeof(uint64_t));
3b6ac903
MV
2560 if (sb_icount_ag == NULL)
2561 do_error(_("cannot alloc sb_icount_ag buffers\n"));
2562
14f8b681 2563 sb_ifree_ag = calloc(mp->m_sb.sb_agcount, sizeof(uint64_t));
3b6ac903
MV
2564 if (sb_ifree_ag == NULL)
2565 do_error(_("cannot alloc sb_ifree_ag buffers\n"));
2566
14f8b681 2567 sb_fdblocks_ag = calloc(mp->m_sb.sb_agcount, sizeof(uint64_t));
3b6ac903
MV
2568 if (sb_fdblocks_ag == NULL)
2569 do_error(_("cannot alloc sb_fdblocks_ag buffers\n"));
2570
ef4332b8
DW
2571 error = init_slab(&lost_fsb, sizeof(xfs_fsblock_t));
2572 if (error)
2573 do_error(_("cannot alloc lost block slab\n"));
2574
2556c98b 2575 for (agno = 0; agno < mp->m_sb.sb_agcount; agno++)
ef4332b8 2576 phase5_func(mp, agno, lost_fsb);
2556c98b 2577
06fbdda9 2578 print_final_rpt();
3b6ac903
MV
2579
2580 /* aggregate per ag counters */
2581 for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
2582 sb_icount += sb_icount_ag[agno];
2583 sb_ifree += sb_ifree_ag[agno];
2584 sb_fdblocks += sb_fdblocks_ag[agno];
2585 }
2586 free(sb_icount_ag);
2587 free(sb_ifree_ag);
2588 free(sb_fdblocks_ag);
2bd0ea18
NS
2589
2590 if (mp->m_sb.sb_rblocks) {
2591 do_log(
507f4e33 2592 _(" - generate realtime summary info and bitmap...\n"));
2bd0ea18
NS
2593 rtinit(mp);
2594 generate_rtinfo(mp, btmcompute, sumcompute);
2bd0ea18
NS
2595 }
2596
507f4e33 2597 do_log(_(" - reset superblock...\n"));
2bd0ea18
NS
2598
2599 /*
2600 * sync superblock counter and set version bits correctly
2601 */
2602 sync_sb(mp);
2603
ac8b6c38
DW
2604 /*
2605 * Put the per-AG btree rmap data into the rmapbt now that we've reset
2606 * the superblock counters.
2607 */
2608 for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
2609 error = rmap_store_ag_btree_rec(mp, agno);
2610 if (error)
2611 do_error(
2612_("unable to add AG %u reverse-mapping data to btree.\n"), agno);
2613 }
2614
2615 /*
2616 * Put blocks that were unnecessarily reserved for btree
2617 * reconstruction back into the filesystem free space data.
2618 */
ef4332b8
DW
2619 error = inject_lost_blocks(mp, lost_fsb);
2620 if (error)
2621 do_error(_("Unable to reinsert lost blocks into filesystem.\n"));
2622 free_slab(&lost_fsb);
2623
2bd0ea18 2624 bad_ino_btree = 0;
3b6ac903 2625
2bd0ea18 2626}