1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
8 #include "libfrog/bitmap.h"
14 #include "err_protos.h"
25 static uint64_t *sb_icount_ag
; /* allocated inodes per ag */
26 static uint64_t *sb_ifree_ag
; /* free inodes per ag */
27 static uint64_t *sb_fdblocks_ag
; /* free data blocks per ag */
33 unsigned int *num_freeblocks
)
37 xfs_agblock_t extent_start
;
38 xfs_extlen_t extent_len
;
48 * scan the bitmap for the ag looking for continuous
49 * extents of free blocks. At this point, we know
50 * that blocks in the bitmap are either set to an
51 * "in use" state or set to unknown (0) since the
52 * bmaps were zero'ed in phase 4 and only blocks
53 * being used by inodes, inode bmaps, ag headers,
54 * and the files themselves were put into the bitmap.
57 ASSERT(agno
< mp
->m_sb
.sb_agcount
);
59 extent_start
= extent_len
= 0;
61 num_extents
= free_blocks
= 0;
63 if (agno
< mp
->m_sb
.sb_agcount
- 1)
64 ag_end
= mp
->m_sb
.sb_agblocks
;
66 ag_end
= mp
->m_sb
.sb_dblocks
-
67 (xfs_rfsblock_t
)mp
->m_sb
.sb_agblocks
*
68 (mp
->m_sb
.sb_agcount
- 1);
71 * ok, now find the number of extents, keep track of the
74 for (agbno
= 0; agbno
< ag_end
; agbno
+= blen
) {
75 bstate
= get_bmap_ext(agno
, agbno
, ag_end
, &blen
);
76 if (bstate
< XR_E_INUSE
) {
80 * found the start of a free extent
92 * free extent ends here, add extent to the
93 * 2 incore extent (avl-to-be-B+) trees
96 #if defined(XR_BLD_FREE_TRACE) && defined(XR_BLD_ADD_EXTENT)
97 fprintf(stderr
, "adding extent %u [%u %u]\n",
98 agno
, extent_start
, extent_len
);
100 add_bno_extent(agno
, extent_start
, extent_len
);
101 add_bcnt_extent(agno
, extent_start
, extent_len
);
102 *num_freeblocks
+= extent_len
;
108 * free extent ends here
110 #if defined(XR_BLD_FREE_TRACE) && defined(XR_BLD_ADD_EXTENT)
111 fprintf(stderr
, "adding extent %u [%u %u]\n",
112 agno
, extent_start
, extent_len
);
114 add_bno_extent(agno
, extent_start
, extent_len
);
115 add_bcnt_extent(agno
, extent_start
, extent_len
);
116 *num_freeblocks
+= extent_len
;
123 * XXX: yet more code that can be shared with mkfs, growfs.
127 struct xfs_mount
*mp
,
129 struct bt_rebuild
*btr_ino
,
130 struct bt_rebuild
*btr_fino
)
132 struct xfs_buf
*agi_buf
;
137 error
= -libxfs_buf_get(mp
->m_dev
,
138 XFS_AG_DADDR(mp
, agno
, XFS_AGI_DADDR(mp
)),
139 mp
->m_sb
.sb_sectsize
/ BBSIZE
, &agi_buf
);
141 do_error(_("Cannot grab AG %u AGI buffer, err=%d"),
143 agi_buf
->b_ops
= &xfs_agi_buf_ops
;
144 agi
= agi_buf
->b_addr
;
145 memset(agi
, 0, mp
->m_sb
.sb_sectsize
);
147 agi
->agi_magicnum
= cpu_to_be32(XFS_AGI_MAGIC
);
148 agi
->agi_versionnum
= cpu_to_be32(XFS_AGI_VERSION
);
149 agi
->agi_seqno
= cpu_to_be32(agno
);
150 if (agno
< mp
->m_sb
.sb_agcount
- 1)
151 agi
->agi_length
= cpu_to_be32(mp
->m_sb
.sb_agblocks
);
153 agi
->agi_length
= cpu_to_be32(mp
->m_sb
.sb_dblocks
-
154 (xfs_rfsblock_t
) mp
->m_sb
.sb_agblocks
* agno
);
155 agi
->agi_count
= cpu_to_be32(btr_ino
->count
);
156 agi
->agi_root
= cpu_to_be32(btr_ino
->newbt
.afake
.af_root
);
157 agi
->agi_level
= cpu_to_be32(btr_ino
->newbt
.afake
.af_levels
);
158 agi
->agi_freecount
= cpu_to_be32(btr_ino
->freecount
);
159 agi
->agi_newino
= cpu_to_be32(btr_ino
->first_agino
);
160 agi
->agi_dirino
= cpu_to_be32(NULLAGINO
);
162 for (i
= 0; i
< XFS_AGI_UNLINKED_BUCKETS
; i
++)
163 agi
->agi_unlinked
[i
] = cpu_to_be32(NULLAGINO
);
166 platform_uuid_copy(&agi
->agi_uuid
, &mp
->m_sb
.sb_meta_uuid
);
168 if (xfs_has_finobt(mp
)) {
170 cpu_to_be32(btr_fino
->newbt
.afake
.af_root
);
171 agi
->agi_free_level
=
172 cpu_to_be32(btr_fino
->newbt
.afake
.af_levels
);
175 if (xfs_has_inobtcounts(mp
)) {
176 agi
->agi_iblocks
= cpu_to_be32(btr_ino
->newbt
.afake
.af_blocks
);
177 agi
->agi_fblocks
= cpu_to_be32(btr_fino
->newbt
.afake
.af_blocks
);
180 libxfs_buf_mark_dirty(agi_buf
);
181 libxfs_buf_relse(agi_buf
);
184 /* Fill the AGFL with any leftover bnobt rebuilder blocks. */
187 struct bt_rebuild
*btr
,
189 unsigned int *agfl_idx
)
191 struct bulkload_resv
*resv
, *n
;
192 struct xfs_mount
*mp
= btr
->newbt
.sc
->mp
;
194 for_each_bulkload_reservation(&btr
->newbt
, resv
, n
) {
197 bno
= resv
->agbno
+ resv
->used
;
198 while (resv
->used
< resv
->len
&&
199 *agfl_idx
< libxfs_agfl_size(mp
)) {
200 agfl_bnos
[(*agfl_idx
)++] = cpu_to_be32(bno
++);
207 * build both the agf and the agfl for an agno given both
210 * XXX: yet more common code that can be shared with mkfs/growfs.
214 struct xfs_mount
*mp
,
216 struct bt_rebuild
*btr_bno
,
217 struct bt_rebuild
*btr_cnt
,
218 struct bt_rebuild
*btr_rmap
,
219 struct bt_rebuild
*btr_refc
,
220 struct bitmap
*lost_blocks
)
222 struct extent_tree_node
*ext_ptr
;
223 struct xfs_buf
*agf_buf
, *agfl_buf
;
224 unsigned int agfl_idx
;
225 struct xfs_agfl
*agfl
;
230 error
= -libxfs_buf_get(mp
->m_dev
,
231 XFS_AG_DADDR(mp
, agno
, XFS_AGF_DADDR(mp
)),
232 mp
->m_sb
.sb_sectsize
/ BBSIZE
, &agf_buf
);
234 do_error(_("Cannot grab AG %u AGF buffer, err=%d"),
236 agf_buf
->b_ops
= &xfs_agf_buf_ops
;
237 agf
= agf_buf
->b_addr
;
238 memset(agf
, 0, mp
->m_sb
.sb_sectsize
);
240 #ifdef XR_BLD_FREE_TRACE
241 fprintf(stderr
, "agf = %p, agf_buf->b_addr = %p\n",
242 agf
, agf_buf
->b_addr
);
246 * set up fixed part of agf
248 agf
->agf_magicnum
= cpu_to_be32(XFS_AGF_MAGIC
);
249 agf
->agf_versionnum
= cpu_to_be32(XFS_AGF_VERSION
);
250 agf
->agf_seqno
= cpu_to_be32(agno
);
252 if (agno
< mp
->m_sb
.sb_agcount
- 1)
253 agf
->agf_length
= cpu_to_be32(mp
->m_sb
.sb_agblocks
);
255 agf
->agf_length
= cpu_to_be32(mp
->m_sb
.sb_dblocks
-
256 (xfs_rfsblock_t
) mp
->m_sb
.sb_agblocks
* agno
);
258 agf
->agf_roots
[XFS_BTNUM_BNO
] =
259 cpu_to_be32(btr_bno
->newbt
.afake
.af_root
);
260 agf
->agf_levels
[XFS_BTNUM_BNO
] =
261 cpu_to_be32(btr_bno
->newbt
.afake
.af_levels
);
262 agf
->agf_roots
[XFS_BTNUM_CNT
] =
263 cpu_to_be32(btr_cnt
->newbt
.afake
.af_root
);
264 agf
->agf_levels
[XFS_BTNUM_CNT
] =
265 cpu_to_be32(btr_cnt
->newbt
.afake
.af_levels
);
266 agf
->agf_freeblks
= cpu_to_be32(btr_bno
->freeblks
);
268 if (xfs_has_rmapbt(mp
)) {
269 agf
->agf_roots
[XFS_BTNUM_RMAP
] =
270 cpu_to_be32(btr_rmap
->newbt
.afake
.af_root
);
271 agf
->agf_levels
[XFS_BTNUM_RMAP
] =
272 cpu_to_be32(btr_rmap
->newbt
.afake
.af_levels
);
273 agf
->agf_rmap_blocks
=
274 cpu_to_be32(btr_rmap
->newbt
.afake
.af_blocks
);
277 if (xfs_has_reflink(mp
)) {
278 agf
->agf_refcount_root
=
279 cpu_to_be32(btr_refc
->newbt
.afake
.af_root
);
280 agf
->agf_refcount_level
=
281 cpu_to_be32(btr_refc
->newbt
.afake
.af_levels
);
282 agf
->agf_refcount_blocks
=
283 cpu_to_be32(btr_refc
->newbt
.afake
.af_blocks
);
287 * Count and record the number of btree blocks consumed if required.
289 if (xfs_has_lazysbcount(mp
)) {
292 * Don't count the root blocks as they are already
295 blks
= btr_bno
->newbt
.afake
.af_blocks
+
296 btr_cnt
->newbt
.afake
.af_blocks
- 2;
297 if (xfs_has_rmapbt(mp
))
298 blks
+= btr_rmap
->newbt
.afake
.af_blocks
- 1;
299 agf
->agf_btreeblks
= cpu_to_be32(blks
);
300 #ifdef XR_BLD_FREE_TRACE
301 fprintf(stderr
, "agf->agf_btreeblks = %u\n",
302 be32_to_cpu(agf
->agf_btreeblks
));
306 #ifdef XR_BLD_FREE_TRACE
307 fprintf(stderr
, "bno root = %u, bcnt root = %u, indices = %u %u\n",
308 be32_to_cpu(agf
->agf_roots
[XFS_BTNUM_BNO
]),
309 be32_to_cpu(agf
->agf_roots
[XFS_BTNUM_CNT
]),
315 platform_uuid_copy(&agf
->agf_uuid
, &mp
->m_sb
.sb_meta_uuid
);
317 /* initialise the AGFL, then fill it if there are blocks left over. */
318 error
= -libxfs_buf_get(mp
->m_dev
,
319 XFS_AG_DADDR(mp
, agno
, XFS_AGFL_DADDR(mp
)),
320 mp
->m_sb
.sb_sectsize
/ BBSIZE
, &agfl_buf
);
322 do_error(_("Cannot grab AG %u AGFL buffer, err=%d"),
324 agfl_buf
->b_ops
= &xfs_agfl_buf_ops
;
325 agfl
= XFS_BUF_TO_AGFL(agfl_buf
);
327 /* setting to 0xff results in initialisation to NULLAGBLOCK */
328 memset(agfl
, 0xff, mp
->m_sb
.sb_sectsize
);
329 freelist
= xfs_buf_to_agfl_bno(agfl_buf
);
330 if (xfs_has_crc(mp
)) {
331 agfl
->agfl_magicnum
= cpu_to_be32(XFS_AGFL_MAGIC
);
332 agfl
->agfl_seqno
= cpu_to_be32(agno
);
333 platform_uuid_copy(&agfl
->agfl_uuid
, &mp
->m_sb
.sb_meta_uuid
);
334 for (agfl_idx
= 0; agfl_idx
< libxfs_agfl_size(mp
); agfl_idx
++)
335 freelist
[agfl_idx
] = cpu_to_be32(NULLAGBLOCK
);
338 /* Fill the AGFL with leftover blocks or save them for later. */
340 freelist
= xfs_buf_to_agfl_bno(agfl_buf
);
341 fill_agfl(btr_bno
, freelist
, &agfl_idx
);
342 fill_agfl(btr_cnt
, freelist
, &agfl_idx
);
343 if (xfs_has_rmapbt(mp
))
344 fill_agfl(btr_rmap
, freelist
, &agfl_idx
);
346 /* Set the AGF counters for the AGFL. */
348 agf
->agf_flfirst
= 0;
349 agf
->agf_fllast
= cpu_to_be32(agfl_idx
- 1);
350 agf
->agf_flcount
= cpu_to_be32(agfl_idx
);
351 rmap_store_agflcount(mp
, agno
, agfl_idx
);
353 #ifdef XR_BLD_FREE_TRACE
354 fprintf(stderr
, "writing agfl for ag %u\n", agno
);
358 agf
->agf_flfirst
= 0;
359 agf
->agf_fllast
= cpu_to_be32(libxfs_agfl_size(mp
) - 1);
360 agf
->agf_flcount
= 0;
363 libxfs_buf_mark_dirty(agfl_buf
);
364 libxfs_buf_relse(agfl_buf
);
366 ext_ptr
= findbiggest_bcnt_extent(agno
);
367 agf
->agf_longest
= cpu_to_be32((ext_ptr
!= NULL
) ?
368 ext_ptr
->ex_blockcount
: 0);
370 ASSERT(be32_to_cpu(agf
->agf_roots
[XFS_BTNUM_BNOi
]) !=
371 be32_to_cpu(agf
->agf_roots
[XFS_BTNUM_CNTi
]));
372 ASSERT(be32_to_cpu(agf
->agf_refcount_root
) !=
373 be32_to_cpu(agf
->agf_roots
[XFS_BTNUM_BNOi
]));
374 ASSERT(be32_to_cpu(agf
->agf_refcount_root
) !=
375 be32_to_cpu(agf
->agf_roots
[XFS_BTNUM_CNTi
]));
377 libxfs_buf_mark_dirty(agf_buf
);
378 libxfs_buf_relse(agf_buf
);
381 * now fix up the free list appropriately
383 fix_freelist(mp
, agno
, true);
385 #ifdef XR_BLD_FREE_TRACE
386 fprintf(stderr
, "wrote agf for ag %u\n", agno
);
391 * update the superblock counters, sync the sb version numbers and
392 * feature bits to the filesystem, and sync up the on-disk superblock
393 * to match the incore superblock.
396 sync_sb(xfs_mount_t
*mp
)
400 bp
= libxfs_getsb(mp
);
402 do_error(_("couldn't get superblock\n"));
404 mp
->m_sb
.sb_icount
= sb_icount
;
405 mp
->m_sb
.sb_ifree
= sb_ifree
;
406 mp
->m_sb
.sb_fdblocks
= sb_fdblocks
;
407 mp
->m_sb
.sb_frextents
= sb_frextents
;
409 update_sb_version(mp
);
411 libxfs_sb_to_disk(bp
->b_addr
, &mp
->m_sb
);
412 libxfs_buf_mark_dirty(bp
);
413 libxfs_buf_relse(bp
);
417 * make sure the root and realtime inodes show up allocated
418 * even if they've been freed. they get reinitialized in phase6.
421 keep_fsinos(xfs_mount_t
*mp
)
423 ino_tree_node_t
*irec
;
426 irec
= find_inode_rec(mp
, XFS_INO_TO_AGNO(mp
, mp
->m_sb
.sb_rootino
),
427 XFS_INO_TO_AGINO(mp
, mp
->m_sb
.sb_rootino
));
429 for (i
= 0; i
< 3; i
++)
430 set_inode_used(irec
, i
);
435 struct xfs_mount
*mp
,
436 struct xfs_perag
*pag
,
437 struct bitmap
*lost_blocks
)
439 struct repair_ctx sc
= { .mp
= mp
, };
440 struct bt_rebuild btr_bno
;
441 struct bt_rebuild btr_cnt
;
442 struct bt_rebuild btr_ino
;
443 struct bt_rebuild btr_fino
;
444 struct bt_rebuild btr_rmap
;
445 struct bt_rebuild btr_refc
;
446 xfs_agnumber_t agno
= pag
->pag_agno
;
447 int extra_blocks
= 0;
449 xfs_agblock_t num_extents
;
450 unsigned int est_agfreeblocks
= 0;
451 unsigned int total_btblocks
;
454 do_log(_(" - agno = %d\n"), agno
);
457 * build up incore bno and bcnt extent btrees
459 num_extents
= mk_incore_fstree(mp
, agno
, &num_freeblocks
);
461 #ifdef XR_BLD_FREE_TRACE
462 fprintf(stderr
, "# of bno extents is %d\n", count_bno_extents(agno
));
465 if (num_extents
== 0) {
467 * XXX - what we probably should do here is pick an inode for
468 * a regular file in the allocation group that has space
469 * allocated and shoot it by traversing the bmap list and
470 * putting all its extents on the incore freespace trees,
471 * clearing the inode, and clearing the in-use bit in the
472 * incore inode tree. Then try mk_incore_fstree() again.
475 _("unable to rebuild AG %u. Not enough free space in on-disk AG.\n"),
480 * Estimate the number of free blocks in this AG after rebuilding
483 total_btblocks
= estimate_agbtree_blocks(pag
, num_extents
);
484 if (num_freeblocks
> total_btblocks
)
485 est_agfreeblocks
= num_freeblocks
- total_btblocks
;
487 init_ino_cursors(&sc
, pag
, est_agfreeblocks
, &sb_icount_ag
[agno
],
488 &sb_ifree_ag
[agno
], &btr_ino
, &btr_fino
);
490 init_rmapbt_cursor(&sc
, pag
, est_agfreeblocks
, &btr_rmap
);
492 init_refc_cursor(&sc
, pag
, est_agfreeblocks
, &btr_refc
);
494 num_extents
= count_bno_extents_blocks(agno
, &num_freeblocks
);
496 * lose two blocks per AG -- the space tree roots are counted as
497 * allocated since the space trees always have roots
499 sb_fdblocks_ag
[agno
] += num_freeblocks
- 2;
501 if (num_extents
== 0) {
503 * XXX - what we probably should do here is pick an inode for
504 * a regular file in the allocation group that has space
505 * allocated and shoot it by traversing the bmap list and
506 * putting all its extents on the incore freespace trees,
507 * clearing the inode, and clearing the in-use bit in the
508 * incore inode tree. Then try mk_incore_fstree() again.
510 do_error(_("unable to rebuild AG %u. No free space.\n"), agno
);
513 #ifdef XR_BLD_FREE_TRACE
514 fprintf(stderr
, "# of bno extents is %d\n", num_extents
);
518 * track blocks that we might really lose
520 init_freespace_cursors(&sc
, pag
, est_agfreeblocks
, &num_extents
,
521 &extra_blocks
, &btr_bno
, &btr_cnt
);
524 * freespace btrees live in the "free space" but the filesystem treats
525 * AGFL blocks as allocated since they aren't described by the
530 * see if we can fit all the extra blocks into the AGFL
532 extra_blocks
= (extra_blocks
- libxfs_agfl_size(mp
) > 0) ?
533 extra_blocks
- libxfs_agfl_size(mp
) : 0;
535 if (extra_blocks
> 0)
536 sb_fdblocks_ag
[agno
] -= extra_blocks
;
538 #ifdef XR_BLD_FREE_TRACE
539 fprintf(stderr
, "# of bno extents is %d\n", count_bno_extents(agno
));
540 fprintf(stderr
, "# of bcnt extents is %d\n", count_bcnt_extents(agno
));
543 build_freespace_btrees(&sc
, agno
, &btr_bno
, &btr_cnt
);
545 #ifdef XR_BLD_FREE_TRACE
546 fprintf(stderr
, "# of free blocks == %d/%d\n", btr_bno
.freeblks
,
549 ASSERT(btr_bno
.freeblks
== btr_cnt
.freeblks
);
551 if (xfs_has_rmapbt(mp
)) {
552 build_rmap_tree(&sc
, agno
, &btr_rmap
);
553 sb_fdblocks_ag
[agno
] += btr_rmap
.newbt
.afake
.af_blocks
- 1;
556 if (xfs_has_reflink(mp
))
557 build_refcount_tree(&sc
, agno
, &btr_refc
);
560 * set up agf and agfl
562 build_agf_agfl(mp
, agno
, &btr_bno
, &btr_cnt
, &btr_rmap
, &btr_refc
,
565 build_inode_btrees(&sc
, agno
, &btr_ino
, &btr_fino
);
568 build_agi(mp
, agno
, &btr_ino
, &btr_fino
);
573 finish_rebuild(mp
, &btr_bno
, lost_blocks
);
574 finish_rebuild(mp
, &btr_cnt
, lost_blocks
);
575 finish_rebuild(mp
, &btr_ino
, lost_blocks
);
576 if (xfs_has_finobt(mp
))
577 finish_rebuild(mp
, &btr_fino
, lost_blocks
);
578 if (xfs_has_rmapbt(mp
))
579 finish_rebuild(mp
, &btr_rmap
, lost_blocks
);
580 if (xfs_has_reflink(mp
))
581 finish_rebuild(mp
, &btr_refc
, lost_blocks
);
584 * release the incore per-AG bno/bcnt trees so the extent nodes
587 release_agbno_extent_tree(agno
);
588 release_agbcnt_extent_tree(agno
);
589 PROG_RPT_INC(prog_rpt_done
[agno
], 1);
592 /* Inject this unused space back into the filesystem. */
599 struct xfs_mount
*mp
= arg
;
600 struct xfs_trans
*tp
;
601 struct xfs_perag
*pag
;
606 error
= -libxfs_trans_alloc_rollable(mp
, 16, &tp
);
610 agno
= XFS_FSB_TO_AGNO(mp
, start
);
611 agbno
= XFS_FSB_TO_AGBNO(mp
, start
);
612 pag
= libxfs_perag_get(mp
, agno
);
613 error
= -libxfs_free_extent(tp
, pag
, agbno
, length
,
614 &XFS_RMAP_OINFO_ANY_OWNER
, XFS_AG_RESV_NONE
);
615 libxfs_perag_put(pag
);
620 return -libxfs_trans_commit(tp
);
625 struct xfs_mount
*mp
)
628 generate_rtinfo(mp
, btmcompute
, sumcompute
);
634 phase5(xfs_mount_t
*mp
)
636 struct bitmap
*lost_blocks
= NULL
;
637 struct xfs_perag
*pag
;
641 do_log(_("Phase 5 - rebuild AG headers and trees...\n"));
642 set_progress_msg(PROG_FMT_REBUILD_AG
, (uint64_t)glob_agcount
);
644 #ifdef XR_BLD_FREE_TRACE
645 fprintf(stderr
, "inobt level 1, maxrec = %d, minrec = %d\n",
646 libxfs_inobt_maxrecs(mp
, mp
->m_sb
.sb_blocksize
, 0),
647 libxfs_inobt_maxrecs(mp
, mp
->m_sb
.sb_blocksize
, 0) / 2);
648 fprintf(stderr
, "inobt level 0 (leaf), maxrec = %d, minrec = %d\n",
649 libxfs_inobt_maxrecs(mp
, mp
->m_sb
.sb_blocksize
, 1),
650 libxfs_inobt_maxrecs(mp
, mp
->m_sb
.sb_blocksize
, 1) / 2);
651 fprintf(stderr
, "xr inobt level 0 (leaf), maxrec = %d\n",
652 XR_INOBT_BLOCK_MAXRECS(mp
, 0));
653 fprintf(stderr
, "xr inobt level 1 (int), maxrec = %d\n",
654 XR_INOBT_BLOCK_MAXRECS(mp
, 1));
655 fprintf(stderr
, "bnobt level 1, maxrec = %d, minrec = %d\n",
656 libxfs_allocbt_maxrecs(mp
, mp
->m_sb
.sb_blocksize
, 0),
657 libxfs_allocbt_maxrecs(mp
, mp
->m_sb
.sb_blocksize
, 0) / 2);
658 fprintf(stderr
, "bnobt level 0 (leaf), maxrec = %d, minrec = %d\n",
659 libxfs_allocbt_maxrecs(mp
, mp
->m_sb
.sb_blocksize
, 1),
660 libxfs_allocbt_maxrecs(mp
, mp
->m_sb
.sb_blocksize
, 1) / 2);
663 * make sure the root and realtime inodes show up allocated
667 /* allocate per ag counters */
668 sb_icount_ag
= calloc(mp
->m_sb
.sb_agcount
, sizeof(uint64_t));
669 if (sb_icount_ag
== NULL
)
670 do_error(_("cannot alloc sb_icount_ag buffers\n"));
672 sb_ifree_ag
= calloc(mp
->m_sb
.sb_agcount
, sizeof(uint64_t));
673 if (sb_ifree_ag
== NULL
)
674 do_error(_("cannot alloc sb_ifree_ag buffers\n"));
676 sb_fdblocks_ag
= calloc(mp
->m_sb
.sb_agcount
, sizeof(uint64_t));
677 if (sb_fdblocks_ag
== NULL
)
678 do_error(_("cannot alloc sb_fdblocks_ag buffers\n"));
680 error
= bitmap_alloc(&lost_blocks
);
682 do_error(_("cannot alloc lost block bitmap\n"));
684 for_each_perag(mp
, agno
, pag
)
685 phase5_func(mp
, pag
, lost_blocks
);
689 /* aggregate per ag counters */
690 for (agno
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++) {
691 sb_icount
+= sb_icount_ag
[agno
];
692 sb_ifree
+= sb_ifree_ag
[agno
];
693 sb_fdblocks
+= sb_fdblocks_ag
[agno
];
697 free(sb_fdblocks_ag
);
699 if (mp
->m_sb
.sb_rblocks
) {
701 _(" - generate realtime summary info and bitmap...\n"));
702 check_rtmetadata(mp
);
705 do_log(_(" - reset superblock...\n"));
708 * sync superblock counter and set version bits correctly
713 * Put the per-AG btree rmap data into the rmapbt now that we've reset
714 * the superblock counters.
716 for (agno
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++) {
717 error
= rmap_store_ag_btree_rec(mp
, agno
);
720 _("unable to add AG %u reverse-mapping data to btree.\n"), agno
);
724 * Put blocks that were unnecessarily reserved for btree
725 * reconstruction back into the filesystem free space data.
727 error
= bitmap_iterate(lost_blocks
, inject_lost_extent
, mp
);
729 do_error(_("Unable to reinsert lost blocks into filesystem.\n"));
730 bitmap_free(&lost_blocks
);