]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - repair/phase5.c
xfs_repair: check the ftype of dot and dotdot directory entries
[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"
c94d40ce 8#include "libfrog/bitmap.h"
2bd0ea18
NS
9#include "avl.h"
10#include "globals.h"
11#include "agheader.h"
12#include "incore.h"
13#include "protos.h"
14#include "err_protos.h"
15#include "dinode.h"
16#include "rt.h"
17#include "versions.h"
3b6ac903 18#include "threads.h"
06fbdda9 19#include "progress.h"
934b5548
DW
20#include "slab.h"
21#include "rmap.h"
7e5ec4e4
DW
22#include "bulkload.h"
23#include "agbtree.h"
2bd0ea18 24
14f8b681
DW
25static uint64_t *sb_icount_ag; /* allocated inodes per ag */
26static uint64_t *sb_ifree_ag; /* free inodes per ag */
27static uint64_t *sb_fdblocks_ag; /* free data blocks per ag */
2bd0ea18 28
8b8a6b02 29static int
7e5ec4e4
DW
30mk_incore_fstree(
31 struct xfs_mount *mp,
32 xfs_agnumber_t agno,
33 unsigned int *num_freeblocks)
2bd0ea18
NS
34{
35 int in_extent;
36 int num_extents;
37 xfs_agblock_t extent_start;
38 xfs_extlen_t extent_len;
39 xfs_agblock_t agbno;
40 xfs_agblock_t ag_end;
41 uint free_blocks;
8961bfde
BN
42 xfs_extlen_t blen;
43 int bstate;
2bd0ea18 44
7e5ec4e4
DW
45 *num_freeblocks = 0;
46
2bd0ea18
NS
47 /*
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
dab9b8d6 52 * bmaps were zero'ed in phase 4 and only blocks
2bd0ea18
NS
53 * being used by inodes, inode bmaps, ag headers,
54 * and the files themselves were put into the bitmap.
55 *
56 */
57 ASSERT(agno < mp->m_sb.sb_agcount);
58
59 extent_start = extent_len = 0;
60 in_extent = 0;
61 num_extents = free_blocks = 0;
62
63 if (agno < mp->m_sb.sb_agcount - 1)
64 ag_end = mp->m_sb.sb_agblocks;
65 else
66 ag_end = mp->m_sb.sb_dblocks -
5a35bf2c 67 (xfs_rfsblock_t)mp->m_sb.sb_agblocks *
003e8e41 68 (mp->m_sb.sb_agcount - 1);
2bd0ea18
NS
69
70 /*
71 * ok, now find the number of extents, keep track of the
72 * largest extent.
73 */
8961bfde
BN
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) {
77 free_blocks += blen;
2bd0ea18
NS
78 if (in_extent == 0) {
79 /*
80 * found the start of a free extent
81 */
82 in_extent = 1;
83 num_extents++;
84 extent_start = agbno;
8961bfde 85 extent_len = blen;
2bd0ea18 86 } else {
8961bfde 87 extent_len += blen;
2bd0ea18
NS
88 }
89 } else {
90 if (in_extent) {
91 /*
92 * free extent ends here, add extent to the
93 * 2 incore extent (avl-to-be-B+) trees
94 */
95 in_extent = 0;
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);
99#endif
100 add_bno_extent(agno, extent_start, extent_len);
101 add_bcnt_extent(agno, extent_start, extent_len);
7e5ec4e4 102 *num_freeblocks += extent_len;
2bd0ea18
NS
103 }
104 }
105 }
106 if (in_extent) {
107 /*
108 * free extent ends here
109 */
2bd0ea18
NS
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);
113#endif
114 add_bno_extent(agno, extent_start, extent_len);
115 add_bcnt_extent(agno, extent_start, extent_len);
7e5ec4e4 116 *num_freeblocks += extent_len;
2bd0ea18
NS
117 }
118
119 return(num_extents);
120}
121
2bd0ea18 122/*
7a21223c 123 * XXX: yet more code that can be shared with mkfs, growfs.
2bd0ea18 124 */
8b8a6b02 125static void
7a21223c
DW
126build_agi(
127 struct xfs_mount *mp,
128 xfs_agnumber_t agno,
129 struct bt_rebuild *btr_ino,
130 struct bt_rebuild *btr_fino)
2bd0ea18 131{
7a21223c
DW
132 struct xfs_buf *agi_buf;
133 struct xfs_agi *agi;
2bd0ea18 134 int i;
58a8b31f 135 int error;
2bd0ea18 136
58a8b31f 137 error = -libxfs_buf_get(mp->m_dev,
9440d84d 138 XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
58a8b31f
DW
139 mp->m_sb.sb_sectsize / BBSIZE, &agi_buf);
140 if (error)
141 do_error(_("Cannot grab AG %u AGI buffer, err=%d"),
142 agno, error);
e0607266 143 agi_buf->b_ops = &xfs_agi_buf_ops;
c99cea5c 144 agi = agi_buf->b_addr;
dab9b8d6 145 memset(agi, 0, mp->m_sb.sb_sectsize);
2bd0ea18 146
5e656dbb
BN
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);
2bd0ea18 150 if (agno < mp->m_sb.sb_agcount - 1)
5e656dbb 151 agi->agi_length = cpu_to_be32(mp->m_sb.sb_agblocks);
2bd0ea18 152 else
5e656dbb 153 agi->agi_length = cpu_to_be32(mp->m_sb.sb_dblocks -
5a35bf2c 154 (xfs_rfsblock_t) mp->m_sb.sb_agblocks * agno);
7a21223c
DW
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);
5e656dbb
BN
160 agi->agi_dirino = cpu_to_be32(NULLAGINO);
161
f8149110 162 for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++)
5e656dbb 163 agi->agi_unlinked[i] = cpu_to_be32(NULLAGINO);
2bd0ea18 164
2660e653 165 if (xfs_has_crc(mp))
9c4e12fb 166 platform_uuid_copy(&agi->agi_uuid, &mp->m_sb.sb_meta_uuid);
e0607266 167
2660e653 168 if (xfs_has_finobt(mp)) {
7a21223c
DW
169 agi->agi_free_root =
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);
bbdb21b6
BF
173 }
174
2660e653 175 if (xfs_has_inobtcounts(mp)) {
086250dc
DW
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);
178 }
179
f524ae04 180 libxfs_buf_mark_dirty(agi_buf);
18b4f688 181 libxfs_buf_relse(agi_buf);
2bd0ea18
NS
182}
183
7e5ec4e4
DW
184/* Fill the AGFL with any leftover bnobt rebuilder blocks. */
185static void
186fill_agfl(
187 struct bt_rebuild *btr,
188 __be32 *agfl_bnos,
189 unsigned int *agfl_idx)
190{
191 struct bulkload_resv *resv, *n;
192 struct xfs_mount *mp = btr->newbt.sc->mp;
193
194 for_each_bulkload_reservation(&btr->newbt, resv, n) {
195 xfs_agblock_t bno;
196
197 bno = XFS_FSB_TO_AGBNO(mp, resv->fsbno + resv->used);
198 while (resv->used < resv->len &&
199 *agfl_idx < libxfs_agfl_size(mp)) {
200 agfl_bnos[(*agfl_idx)++] = cpu_to_be32(bno++);
201 resv->used++;
202 }
203 }
204}
205
2bd0ea18
NS
206/*
207 * build both the agf and the agfl for an agno given both
e0607266
DC
208 * btree cursors.
209 *
210 * XXX: yet more common code that can be shared with mkfs/growfs.
2bd0ea18 211 */
8b8a6b02 212static void
934b5548
DW
213build_agf_agfl(
214 struct xfs_mount *mp,
215 xfs_agnumber_t agno,
7e5ec4e4
DW
216 struct bt_rebuild *btr_bno,
217 struct bt_rebuild *btr_cnt,
dc9f4f5e 218 struct bt_rebuild *btr_rmap,
3c1ce0fc 219 struct bt_rebuild *btr_refc,
c94d40ce 220 struct bitmap *lost_blocks)
2bd0ea18 221{
934b5548
DW
222 struct extent_tree_node *ext_ptr;
223 struct xfs_buf *agf_buf, *agfl_buf;
3acf0068 224 unsigned int agfl_idx;
934b5548
DW
225 struct xfs_agfl *agfl;
226 struct xfs_agf *agf;
84232448 227 __be32 *freelist;
ef4332b8 228 int error;
2bd0ea18 229
58a8b31f 230 error = -libxfs_buf_get(mp->m_dev,
9440d84d 231 XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)),
58a8b31f
DW
232 mp->m_sb.sb_sectsize / BBSIZE, &agf_buf);
233 if (error)
234 do_error(_("Cannot grab AG %u AGF buffer, err=%d"),
235 agno, error);
e0607266 236 agf_buf->b_ops = &xfs_agf_buf_ops;
0bc284c2 237 agf = agf_buf->b_addr;
dab9b8d6 238 memset(agf, 0, mp->m_sb.sb_sectsize);
2bd0ea18
NS
239
240#ifdef XR_BLD_FREE_TRACE
ef4109d1 241 fprintf(stderr, "agf = %p, agf_buf->b_addr = %p\n",
7c7c113c 242 agf, agf_buf->b_addr);
2bd0ea18
NS
243#endif
244
245 /*
246 * set up fixed part of agf
247 */
5e656dbb
BN
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);
2bd0ea18
NS
251
252 if (agno < mp->m_sb.sb_agcount - 1)
5e656dbb 253 agf->agf_length = cpu_to_be32(mp->m_sb.sb_agblocks);
2bd0ea18 254 else
5e656dbb 255 agf->agf_length = cpu_to_be32(mp->m_sb.sb_dblocks -
5a35bf2c 256 (xfs_rfsblock_t) mp->m_sb.sb_agblocks * agno);
2bd0ea18 257
7e5ec4e4
DW
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);
7e5ec4e4 266 agf->agf_freeblks = cpu_to_be32(btr_bno->freeblks);
dc9f4f5e 267
2660e653 268 if (xfs_has_rmapbt(mp)) {
dc9f4f5e
DW
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);
275 }
276
2660e653 277 if (xfs_has_reflink(mp)) {
3c1ce0fc
DW
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);
284 }
2bd0ea18 285
cdded3d8
DC
286 /*
287 * Count and record the number of btree blocks consumed if required.
288 */
2660e653 289 if (xfs_has_lazysbcount(mp)) {
934b5548 290 unsigned int blks;
cdded3d8
DC
291 /*
292 * Don't count the root blocks as they are already
293 * accounted for.
294 */
7e5ec4e4
DW
295 blks = btr_bno->newbt.afake.af_blocks +
296 btr_cnt->newbt.afake.af_blocks - 2;
2660e653 297 if (xfs_has_rmapbt(mp))
dc9f4f5e 298 blks += btr_rmap->newbt.afake.af_blocks - 1;
934b5548 299 agf->agf_btreeblks = cpu_to_be32(blks);
cdded3d8
DC
300#ifdef XR_BLD_FREE_TRACE
301 fprintf(stderr, "agf->agf_btreeblks = %u\n",
5e656dbb 302 be32_to_cpu(agf->agf_btreeblks));
cdded3d8
DC
303#endif
304 }
305
2bd0ea18
NS
306#ifdef XR_BLD_FREE_TRACE
307 fprintf(stderr, "bno root = %u, bcnt root = %u, indices = %u %u\n",
5e656dbb
BN
308 be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNO]),
309 be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNT]),
2bd0ea18
NS
310 XFS_BTNUM_BNO,
311 XFS_BTNUM_CNT);
312#endif
313
2660e653 314 if (xfs_has_crc(mp))
9c4e12fb 315 platform_uuid_copy(&agf->agf_uuid, &mp->m_sb.sb_meta_uuid);
e0607266
DC
316
317 /* initialise the AGFL, then fill it if there are blocks left over. */
58a8b31f 318 error = -libxfs_buf_get(mp->m_dev,
e0607266 319 XFS_AG_DADDR(mp, agno, XFS_AGFL_DADDR(mp)),
58a8b31f
DW
320 mp->m_sb.sb_sectsize / BBSIZE, &agfl_buf);
321 if (error)
322 do_error(_("Cannot grab AG %u AGFL buffer, err=%d"),
323 agno, error);
e0607266
DC
324 agfl_buf->b_ops = &xfs_agfl_buf_ops;
325 agfl = XFS_BUF_TO_AGFL(agfl_buf);
326
327 /* setting to 0xff results in initialisation to NULLAGBLOCK */
328 memset(agfl, 0xff, mp->m_sb.sb_sectsize);
0c02ef9b 329 freelist = xfs_buf_to_agfl_bno(agfl_buf);
2660e653 330 if (xfs_has_crc(mp)) {
e0607266
DC
331 agfl->agfl_magicnum = cpu_to_be32(XFS_AGFL_MAGIC);
332 agfl->agfl_seqno = cpu_to_be32(agno);
9c4e12fb 333 platform_uuid_copy(&agfl->agfl_uuid, &mp->m_sb.sb_meta_uuid);
3acf0068
DW
334 for (agfl_idx = 0; agfl_idx < libxfs_agfl_size(mp); agfl_idx++)
335 freelist[agfl_idx] = cpu_to_be32(NULLAGBLOCK);
e0607266 336 }
b134e771 337
7e5ec4e4
DW
338 /* Fill the AGFL with leftover blocks or save them for later. */
339 agfl_idx = 0;
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);
2660e653 343 if (xfs_has_rmapbt(mp))
dc9f4f5e 344 fill_agfl(btr_rmap, freelist, &agfl_idx);
2bd0ea18 345
7e5ec4e4
DW
346 /* Set the AGF counters for the AGFL. */
347 if (agfl_idx > 0) {
46eca962 348 agf->agf_flfirst = 0;
3acf0068
DW
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);
2bd0ea18
NS
352
353#ifdef XR_BLD_FREE_TRACE
354 fprintf(stderr, "writing agfl for ag %u\n", agno);
355#endif
356
2bd0ea18 357 } else {
46eca962 358 agf->agf_flfirst = 0;
b8165508 359 agf->agf_fllast = cpu_to_be32(libxfs_agfl_size(mp) - 1);
46eca962 360 agf->agf_flcount = 0;
2bd0ea18
NS
361 }
362
f524ae04 363 libxfs_buf_mark_dirty(agfl_buf);
18b4f688 364 libxfs_buf_relse(agfl_buf);
e0607266 365
2bd0ea18 366 ext_ptr = findbiggest_bcnt_extent(agno);
5e656dbb
BN
367 agf->agf_longest = cpu_to_be32((ext_ptr != NULL) ?
368 ext_ptr->ex_blockcount : 0);
2bd0ea18 369
5e656dbb
BN
370 ASSERT(be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNOi]) !=
371 be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNTi]));
586a8fc3
DW
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]));
2bd0ea18 376
f524ae04 377 libxfs_buf_mark_dirty(agf_buf);
18b4f688 378 libxfs_buf_relse(agf_buf);
2bd0ea18 379
e0607266
DC
380 /*
381 * now fix up the free list appropriately
e0607266 382 */
62cf990a 383 fix_freelist(mp, agno, true);
e0607266 384
2bd0ea18 385#ifdef XR_BLD_FREE_TRACE
7c7c113c 386 fprintf(stderr, "wrote agf for ag %u\n", agno);
2bd0ea18
NS
387#endif
388}
389
390/*
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.
394 */
8b8a6b02 395static void
2bd0ea18
NS
396sync_sb(xfs_mount_t *mp)
397{
167137fe 398 struct xfs_buf *bp;
2bd0ea18 399
67c4a324 400 bp = libxfs_getsb(mp);
2bd0ea18 401 if (!bp)
507f4e33 402 do_error(_("couldn't get superblock\n"));
2bd0ea18 403
2bd0ea18
NS
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;
408
409 update_sb_version(mp);
410
d6522f1d 411 libxfs_sb_to_disk(bp->b_addr, &mp->m_sb);
f524ae04 412 libxfs_buf_mark_dirty(bp);
18b4f688 413 libxfs_buf_relse(bp);
2bd0ea18
NS
414}
415
416/*
417 * make sure the root and realtime inodes show up allocated
418 * even if they've been freed. they get reinitialized in phase6.
419 */
8b8a6b02 420static void
2bd0ea18
NS
421keep_fsinos(xfs_mount_t *mp)
422{
423 ino_tree_node_t *irec;
424 int i;
425
1ae311d5 426 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino),
2bd0ea18
NS
427 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino));
428
429 for (i = 0; i < 3; i++)
430 set_inode_used(irec, i);
431}
432
2556c98b
BN
433static void
434phase5_func(
7e5ec4e4 435 struct xfs_mount *mp,
195c248c 436 struct xfs_perag *pag,
c94d40ce 437 struct bitmap *lost_blocks)
2bd0ea18 438{
7e5ec4e4 439 struct repair_ctx sc = { .mp = mp, };
7e5ec4e4
DW
440 struct bt_rebuild btr_bno;
441 struct bt_rebuild btr_cnt;
7a21223c
DW
442 struct bt_rebuild btr_ino;
443 struct bt_rebuild btr_fino;
dc9f4f5e 444 struct bt_rebuild btr_rmap;
3c1ce0fc 445 struct bt_rebuild btr_refc;
195c248c 446 xfs_agnumber_t agno = pag->pag_agno;
7e5ec4e4
DW
447 int extra_blocks = 0;
448 uint num_freeblocks;
449 xfs_agblock_t num_extents;
2bd0ea18 450
3b6ac903
MV
451 if (verbose)
452 do_log(_(" - agno = %d\n"), agno);
2bd0ea18 453
e48f6fbc
ES
454 /*
455 * build up incore bno and bcnt extent btrees
456 */
7e5ec4e4 457 num_extents = mk_incore_fstree(mp, agno, &num_freeblocks);
2bd0ea18
NS
458
459#ifdef XR_BLD_FREE_TRACE
e48f6fbc 460 fprintf(stderr, "# of bno extents is %d\n", count_bno_extents(agno));
2bd0ea18
NS
461#endif
462
e48f6fbc 463 if (num_extents == 0) {
2bd0ea18 464 /*
e48f6fbc
ES
465 * XXX - what we probably should do here is pick an inode for
466 * a regular file in the allocation group that has space
467 * allocated and shoot it by traversing the bmap list and
468 * putting all its extents on the incore freespace trees,
469 * clearing the inode, and clearing the in-use bit in the
470 * incore inode tree. Then try mk_incore_fstree() again.
2bd0ea18 471 */
e48f6fbc
ES
472 do_error(
473_("unable to rebuild AG %u. Not enough free space in on-disk AG.\n"),
474 agno);
475 }
bbdb21b6 476
a426d0e1 477 init_ino_cursors(&sc, pag, num_freeblocks, &sb_icount_ag[agno],
7a21223c 478 &sb_ifree_ag[agno], &btr_ino, &btr_fino);
934b5548 479
195c248c 480 init_rmapbt_cursor(&sc, pag, num_freeblocks, &btr_rmap);
586a8fc3 481
971fceb4 482 init_refc_cursor(&sc, pag, num_freeblocks, &btr_refc);
e48f6fbc
ES
483
484 num_extents = count_bno_extents_blocks(agno, &num_freeblocks);
485 /*
486 * lose two blocks per AG -- the space tree roots are counted as
487 * allocated since the space trees always have roots
488 */
489 sb_fdblocks_ag[agno] += num_freeblocks - 2;
490
491 if (num_extents == 0) {
2bd0ea18 492 /*
e48f6fbc
ES
493 * XXX - what we probably should do here is pick an inode for
494 * a regular file in the allocation group that has space
495 * allocated and shoot it by traversing the bmap list and
496 * putting all its extents on the incore freespace trees,
497 * clearing the inode, and clearing the in-use bit in the
498 * incore inode tree. Then try mk_incore_fstree() again.
2bd0ea18 499 */
e48f6fbc
ES
500 do_error(_("unable to rebuild AG %u. No free space.\n"), agno);
501 }
2bd0ea18
NS
502
503#ifdef XR_BLD_FREE_TRACE
e48f6fbc 504 fprintf(stderr, "# of bno extents is %d\n", num_extents);
2bd0ea18
NS
505#endif
506
e48f6fbc
ES
507 /*
508 * track blocks that we might really lose
509 */
ecb44e84 510 init_freespace_cursors(&sc, pag, num_freeblocks, &num_extents,
7e5ec4e4 511 &extra_blocks, &btr_bno, &btr_cnt);
2bd0ea18 512
e48f6fbc
ES
513 /*
514 * freespace btrees live in the "free space" but the filesystem treats
515 * AGFL blocks as allocated since they aren't described by the
516 * freespace trees
517 */
2bd0ea18 518
e48f6fbc
ES
519 /*
520 * see if we can fit all the extra blocks into the AGFL
521 */
522 extra_blocks = (extra_blocks - libxfs_agfl_size(mp) > 0) ?
523 extra_blocks - libxfs_agfl_size(mp) : 0;
2bd0ea18 524
e48f6fbc
ES
525 if (extra_blocks > 0)
526 sb_fdblocks_ag[agno] -= extra_blocks;
2bd0ea18 527
2bd0ea18 528#ifdef XR_BLD_FREE_TRACE
e48f6fbc
ES
529 fprintf(stderr, "# of bno extents is %d\n", count_bno_extents(agno));
530 fprintf(stderr, "# of bcnt extents is %d\n", count_bcnt_extents(agno));
2bd0ea18 531#endif
46eca962 532
7e5ec4e4 533 build_freespace_btrees(&sc, agno, &btr_bno, &btr_cnt);
2bd0ea18 534
7e5ec4e4
DW
535#ifdef XR_BLD_FREE_TRACE
536 fprintf(stderr, "# of free blocks == %d/%d\n", btr_bno.freeblks,
537 btr_cnt.freeblks);
1e77098c 538#endif
7e5ec4e4 539 ASSERT(btr_bno.freeblks == btr_cnt.freeblks);
2bd0ea18 540
2660e653 541 if (xfs_has_rmapbt(mp)) {
dc9f4f5e
DW
542 build_rmap_tree(&sc, agno, &btr_rmap);
543 sb_fdblocks_ag[agno] += btr_rmap.newbt.afake.af_blocks - 1;
e48f6fbc 544 }
934b5548 545
2660e653 546 if (xfs_has_reflink(mp))
3c1ce0fc 547 build_refcount_tree(&sc, agno, &btr_refc);
586a8fc3 548
e48f6fbc
ES
549 /*
550 * set up agf and agfl
551 */
3c1ce0fc 552 build_agf_agfl(mp, agno, &btr_bno, &btr_cnt, &btr_rmap, &btr_refc,
c94d40ce 553 lost_blocks);
7e5ec4e4 554
7a21223c 555 build_inode_btrees(&sc, agno, &btr_ino, &btr_fino);
bbdb21b6 556
e48f6fbc 557 /* build the agi */
7a21223c 558 build_agi(mp, agno, &btr_ino, &btr_fino);
d6412d17 559
e48f6fbc
ES
560 /*
561 * tear down cursors
562 */
c94d40ce
DW
563 finish_rebuild(mp, &btr_bno, lost_blocks);
564 finish_rebuild(mp, &btr_cnt, lost_blocks);
565 finish_rebuild(mp, &btr_ino, lost_blocks);
2660e653 566 if (xfs_has_finobt(mp))
c94d40ce 567 finish_rebuild(mp, &btr_fino, lost_blocks);
2660e653 568 if (xfs_has_rmapbt(mp))
c94d40ce 569 finish_rebuild(mp, &btr_rmap, lost_blocks);
2660e653 570 if (xfs_has_reflink(mp))
c94d40ce 571 finish_rebuild(mp, &btr_refc, lost_blocks);
62cf990a 572
e48f6fbc
ES
573 /*
574 * release the incore per-AG bno/bcnt trees so the extent nodes
575 * can be recycled
576 */
577 release_agbno_extent_tree(agno);
578 release_agbcnt_extent_tree(agno);
06fbdda9 579 PROG_RPT_INC(prog_rpt_done[agno], 1);
3b6ac903
MV
580}
581
c94d40ce 582/* Inject this unused space back into the filesystem. */
ef4332b8 583static int
c94d40ce
DW
584inject_lost_extent(
585 uint64_t start,
586 uint64_t length,
587 void *arg)
ef4332b8 588{
c94d40ce
DW
589 struct xfs_mount *mp = arg;
590 struct xfs_trans *tp;
ef4332b8
DW
591 int error;
592
c94d40ce 593 error = -libxfs_trans_alloc_rollable(mp, 16, &tp);
ef4332b8
DW
594 if (error)
595 return error;
596
c94d40ce
DW
597 error = -libxfs_free_extent(tp, start, length,
598 &XFS_RMAP_OINFO_ANY_OWNER, XFS_AG_RESV_NONE);
599 if (error)
600 return error;
ef4332b8 601
c94d40ce 602 return -libxfs_trans_commit(tp);
ef4332b8
DW
603}
604
3b6ac903
MV
605void
606phase5(xfs_mount_t *mp)
607{
c94d40ce 608 struct bitmap *lost_blocks = NULL;
195c248c 609 struct xfs_perag *pag;
2556c98b 610 xfs_agnumber_t agno;
ef4332b8 611 int error;
3b6ac903
MV
612
613 do_log(_("Phase 5 - rebuild AG headers and trees...\n"));
14f8b681 614 set_progress_msg(PROG_FMT_REBUILD_AG, (uint64_t)glob_agcount);
3b6ac903
MV
615
616#ifdef XR_BLD_FREE_TRACE
617 fprintf(stderr, "inobt level 1, maxrec = %d, minrec = %d\n",
e2f60652
DW
618 libxfs_inobt_maxrecs(mp, mp->m_sb.sb_blocksize, 0),
619 libxfs_inobt_maxrecs(mp, mp->m_sb.sb_blocksize, 0) / 2);
3b6ac903 620 fprintf(stderr, "inobt level 0 (leaf), maxrec = %d, minrec = %d\n",
e2f60652
DW
621 libxfs_inobt_maxrecs(mp, mp->m_sb.sb_blocksize, 1),
622 libxfs_inobt_maxrecs(mp, mp->m_sb.sb_blocksize, 1) / 2);
3b6ac903
MV
623 fprintf(stderr, "xr inobt level 0 (leaf), maxrec = %d\n",
624 XR_INOBT_BLOCK_MAXRECS(mp, 0));
625 fprintf(stderr, "xr inobt level 1 (int), maxrec = %d\n",
626 XR_INOBT_BLOCK_MAXRECS(mp, 1));
627 fprintf(stderr, "bnobt level 1, maxrec = %d, minrec = %d\n",
e2f60652
DW
628 libxfs_allocbt_maxrecs(mp, mp->m_sb.sb_blocksize, 0),
629 libxfs_allocbt_maxrecs(mp, mp->m_sb.sb_blocksize, 0) / 2);
3b6ac903 630 fprintf(stderr, "bnobt level 0 (leaf), maxrec = %d, minrec = %d\n",
e2f60652
DW
631 libxfs_allocbt_maxrecs(mp, mp->m_sb.sb_blocksize, 1),
632 libxfs_allocbt_maxrecs(mp, mp->m_sb.sb_blocksize, 1) / 2);
3b6ac903
MV
633#endif
634 /*
635 * make sure the root and realtime inodes show up allocated
636 */
637 keep_fsinos(mp);
638
639 /* allocate per ag counters */
14f8b681 640 sb_icount_ag = calloc(mp->m_sb.sb_agcount, sizeof(uint64_t));
3b6ac903
MV
641 if (sb_icount_ag == NULL)
642 do_error(_("cannot alloc sb_icount_ag buffers\n"));
643
14f8b681 644 sb_ifree_ag = calloc(mp->m_sb.sb_agcount, sizeof(uint64_t));
3b6ac903
MV
645 if (sb_ifree_ag == NULL)
646 do_error(_("cannot alloc sb_ifree_ag buffers\n"));
647
14f8b681 648 sb_fdblocks_ag = calloc(mp->m_sb.sb_agcount, sizeof(uint64_t));
3b6ac903
MV
649 if (sb_fdblocks_ag == NULL)
650 do_error(_("cannot alloc sb_fdblocks_ag buffers\n"));
651
c94d40ce 652 error = bitmap_alloc(&lost_blocks);
ef4332b8 653 if (error)
c94d40ce 654 do_error(_("cannot alloc lost block bitmap\n"));
ef4332b8 655
195c248c
DC
656 for_each_perag(mp, agno, pag)
657 phase5_func(mp, pag, lost_blocks);
2556c98b 658
06fbdda9 659 print_final_rpt();
3b6ac903
MV
660
661 /* aggregate per ag counters */
662 for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
663 sb_icount += sb_icount_ag[agno];
664 sb_ifree += sb_ifree_ag[agno];
665 sb_fdblocks += sb_fdblocks_ag[agno];
666 }
667 free(sb_icount_ag);
668 free(sb_ifree_ag);
669 free(sb_fdblocks_ag);
2bd0ea18
NS
670
671 if (mp->m_sb.sb_rblocks) {
672 do_log(
507f4e33 673 _(" - generate realtime summary info and bitmap...\n"));
2bd0ea18
NS
674 rtinit(mp);
675 generate_rtinfo(mp, btmcompute, sumcompute);
2bd0ea18
NS
676 }
677
507f4e33 678 do_log(_(" - reset superblock...\n"));
2bd0ea18
NS
679
680 /*
681 * sync superblock counter and set version bits correctly
682 */
683 sync_sb(mp);
684
ac8b6c38
DW
685 /*
686 * Put the per-AG btree rmap data into the rmapbt now that we've reset
687 * the superblock counters.
688 */
689 for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
690 error = rmap_store_ag_btree_rec(mp, agno);
691 if (error)
692 do_error(
693_("unable to add AG %u reverse-mapping data to btree.\n"), agno);
694 }
695
696 /*
697 * Put blocks that were unnecessarily reserved for btree
698 * reconstruction back into the filesystem free space data.
699 */
c94d40ce 700 error = bitmap_iterate(lost_blocks, inject_lost_extent, mp);
ef4332b8
DW
701 if (error)
702 do_error(_("Unable to reinsert lost blocks into filesystem.\n"));
c94d40ce 703 bitmap_free(&lost_blocks);
ef4332b8 704
2bd0ea18 705 bad_ino_btree = 0;
3b6ac903 706
2bd0ea18 707}