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