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