3838#include "scrub/xfarray.h"
3939#include "scrub/newbt.h"
4040#include "scrub/reap.h"
41+ #include "scrub/rcbag.h"
4142
4243/*
4344 * Rebuilding the Reference Count Btree
9899 * insert all the records.
99100 */
100101
101- /* The only parts of the rmap that we care about for computing refcounts. */
102- struct xrep_refc_rmap {
103- xfs_agblock_t startblock ;
104- xfs_extlen_t blockcount ;
105- } __packed ;
106-
107102struct xrep_refc {
108103 /* refcount extents */
109104 struct xfarray * refcount_records ;
@@ -123,6 +118,20 @@ struct xrep_refc {
123118 xfs_extlen_t btblocks ;
124119};
125120
121+ /* Set us up to repair refcount btrees. */
122+ int
123+ xrep_setup_ag_refcountbt (
124+ struct xfs_scrub * sc )
125+ {
126+ char * descr ;
127+ int error ;
128+
129+ descr = xchk_xfile_ag_descr (sc , "rmap record bag" );
130+ error = xrep_setup_xfbtree (sc , descr );
131+ kfree (descr );
132+ return error ;
133+ }
134+
126135/* Check for any obvious conflicts with this shared/CoW staging extent. */
127136STATIC int
128137xrep_refc_check_ext (
@@ -224,10 +233,9 @@ xrep_refc_rmap_shareable(
224233STATIC int
225234xrep_refc_walk_rmaps (
226235 struct xrep_refc * rr ,
227- struct xrep_refc_rmap * rrm ,
236+ struct xfs_rmap_irec * rmap ,
228237 bool * have_rec )
229238{
230- struct xfs_rmap_irec rmap ;
231239 struct xfs_btree_cur * cur = rr -> sc -> sa .rmap_cur ;
232240 struct xfs_mount * mp = cur -> bc_mp ;
233241 int have_gt ;
@@ -251,31 +259,30 @@ xrep_refc_walk_rmaps(
251259 if (!have_gt )
252260 return 0 ;
253261
254- error = xfs_rmap_get_rec (cur , & rmap , & have_gt );
262+ error = xfs_rmap_get_rec (cur , rmap , & have_gt );
255263 if (error )
256264 return error ;
257265 if (XFS_IS_CORRUPT (mp , !have_gt )) {
258266 xfs_btree_mark_sick (cur );
259267 return - EFSCORRUPTED ;
260268 }
261269
262- if (rmap . rm_owner == XFS_RMAP_OWN_COW ) {
263- error = xrep_refc_stash_cow (rr , rmap . rm_startblock ,
264- rmap . rm_blockcount );
270+ if (rmap -> rm_owner == XFS_RMAP_OWN_COW ) {
271+ error = xrep_refc_stash_cow (rr , rmap -> rm_startblock ,
272+ rmap -> rm_blockcount );
265273 if (error )
266274 return error ;
267- } else if (rmap . rm_owner == XFS_RMAP_OWN_REFC ) {
275+ } else if (rmap -> rm_owner == XFS_RMAP_OWN_REFC ) {
268276 /* refcountbt block, dump it when we're done. */
269- rr -> btblocks += rmap . rm_blockcount ;
277+ rr -> btblocks += rmap -> rm_blockcount ;
270278 error = xagb_bitmap_set (& rr -> old_refcountbt_blocks ,
271- rmap .rm_startblock , rmap .rm_blockcount );
279+ rmap -> rm_startblock ,
280+ rmap -> rm_blockcount );
272281 if (error )
273282 return error ;
274283 }
275- } while (!xrep_refc_rmap_shareable (mp , & rmap ));
284+ } while (!xrep_refc_rmap_shareable (mp , rmap ));
276285
277- rrm -> startblock = rmap .rm_startblock ;
278- rrm -> blockcount = rmap .rm_blockcount ;
279286 * have_rec = true;
280287 return 0 ;
281288}
@@ -357,45 +364,6 @@ xrep_refc_sort_records(
357364 return error ;
358365}
359366
360- #define RRM_NEXT (r ) ((r).startblock + (r).blockcount)
361- /*
362- * Find the next block where the refcount changes, given the next rmap we
363- * looked at and the ones we're already tracking.
364- */
365- static inline int
366- xrep_refc_next_edge (
367- struct xfarray * rmap_bag ,
368- struct xrep_refc_rmap * next_rrm ,
369- bool next_valid ,
370- xfs_agblock_t * nbnop )
371- {
372- struct xrep_refc_rmap rrm ;
373- xfarray_idx_t array_cur = XFARRAY_CURSOR_INIT ;
374- xfs_agblock_t nbno = NULLAGBLOCK ;
375- int error ;
376-
377- if (next_valid )
378- nbno = next_rrm -> startblock ;
379-
380- while ((error = xfarray_iter (rmap_bag , & array_cur , & rrm )) == 1 )
381- nbno = min_t (xfs_agblock_t , nbno , RRM_NEXT (rrm ));
382-
383- if (error )
384- return error ;
385-
386- /*
387- * We should have found /something/ because either next_rrm is the next
388- * interesting rmap to look at after emitting this refcount extent, or
389- * there are other rmaps in rmap_bag contributing to the current
390- * sharing count. But if something is seriously wrong, bail out.
391- */
392- if (nbno == NULLAGBLOCK )
393- return - EFSCORRUPTED ;
394-
395- * nbnop = nbno ;
396- return 0 ;
397- }
398-
399367/*
400368 * Walk forward through the rmap btree to collect all rmaps starting at
401369 * @bno in @rmap_bag. These represent the file(s) that share ownership of
@@ -405,22 +373,21 @@ xrep_refc_next_edge(
405373static int
406374xrep_refc_push_rmaps_at (
407375 struct xrep_refc * rr ,
408- struct xfarray * rmap_bag ,
376+ struct rcbag * rcstack ,
409377 xfs_agblock_t bno ,
410- struct xrep_refc_rmap * rrm ,
411- bool * have ,
412- uint64_t * stack_sz )
378+ struct xfs_rmap_irec * rmap ,
379+ bool * have )
413380{
414381 struct xfs_scrub * sc = rr -> sc ;
415382 int have_gt ;
416383 int error ;
417384
418- while (* have && rrm -> startblock == bno ) {
419- error = xfarray_store_anywhere ( rmap_bag , rrm );
385+ while (* have && rmap -> rm_startblock == bno ) {
386+ error = rcbag_add ( rcstack , rr -> sc -> tp , rmap );
420387 if (error )
421388 return error ;
422- ( * stack_sz ) ++ ;
423- error = xrep_refc_walk_rmaps (rr , rrm , have );
389+
390+ error = xrep_refc_walk_rmaps (rr , rmap , have );
424391 if (error )
425392 return error ;
426393 }
@@ -441,12 +408,9 @@ STATIC int
441408xrep_refc_find_refcounts (
442409 struct xrep_refc * rr )
443410{
444- struct xrep_refc_rmap rrm ;
445411 struct xfs_scrub * sc = rr -> sc ;
446- struct xfarray * rmap_bag ;
447- char * descr ;
448- uint64_t old_stack_sz ;
449- uint64_t stack_sz = 0 ;
412+ struct rcbag * rcstack ;
413+ uint64_t old_stack_height ;
450414 xfs_agblock_t sbno ;
451415 xfs_agblock_t cbno ;
452416 xfs_agblock_t nbno ;
@@ -456,14 +420,11 @@ xrep_refc_find_refcounts(
456420 xrep_ag_btcur_init (sc , & sc -> sa );
457421
458422 /*
459- * Set up a sparse array to store all the rmap records that we're
460- * tracking to generate a reference count record. If this exceeds
423+ * Set up a bag to store all the rmap records that we're tracking to
424+ * generate a reference count record. If the size of the bag exceeds
461425 * MAXREFCOUNT, we clamp rc_refcount.
462426 */
463- descr = xchk_xfile_ag_descr (sc , "rmap record bag" );
464- error = xfarray_create (descr , 0 , sizeof (struct xrep_refc_rmap ),
465- & rmap_bag );
466- kfree (descr );
427+ error = rcbag_init (sc -> mp , sc -> xmbtp , & rcstack );
467428 if (error )
468429 goto out_cur ;
469430
@@ -474,76 +435,68 @@ xrep_refc_find_refcounts(
474435
475436 /* Process reverse mappings into refcount data. */
476437 while (xfs_btree_has_more_records (sc -> sa .rmap_cur )) {
438+ struct xfs_rmap_irec rmap ;
439+
477440 /* Push all rmaps with pblk == sbno onto the stack */
478- error = xrep_refc_walk_rmaps (rr , & rrm , & have );
441+ error = xrep_refc_walk_rmaps (rr , & rmap , & have );
479442 if (error )
480443 goto out_bag ;
481444 if (!have )
482445 break ;
483- sbno = cbno = rrm . startblock ;
484- error = xrep_refc_push_rmaps_at (rr , rmap_bag , sbno ,
485- & rrm , & have , & stack_sz );
446+ sbno = cbno = rmap . rm_startblock ;
447+ error = xrep_refc_push_rmaps_at (rr , rcstack , sbno , & rmap ,
448+ & have );
486449 if (error )
487450 goto out_bag ;
488451
489452 /* Set nbno to the bno of the next refcount change */
490- error = xrep_refc_next_edge ( rmap_bag , & rrm , have , & nbno );
453+ error = rcbag_next_edge ( rcstack , sc -> tp , & rmap , have , & nbno );
491454 if (error )
492455 goto out_bag ;
493456
494457 ASSERT (nbno > sbno );
495- old_stack_sz = stack_sz ;
458+ old_stack_height = rcbag_count ( rcstack ) ;
496459
497460 /* While stack isn't empty... */
498- while (stack_sz ) {
499- xfarray_idx_t array_cur = XFARRAY_CURSOR_INIT ;
500-
461+ while (rcbag_count (rcstack ) > 0 ) {
501462 /* Pop all rmaps that end at nbno */
502- while ((error = xfarray_iter (rmap_bag , & array_cur ,
503- & rrm )) == 1 ) {
504- if (RRM_NEXT (rrm ) != nbno )
505- continue ;
506- error = xfarray_unset (rmap_bag , array_cur - 1 );
507- if (error )
508- goto out_bag ;
509- stack_sz -- ;
510- }
463+ error = rcbag_remove_ending_at (rcstack , sc -> tp , nbno );
511464 if (error )
512465 goto out_bag ;
513466
514467 /* Push array items that start at nbno */
515- error = xrep_refc_walk_rmaps (rr , & rrm , & have );
468+ error = xrep_refc_walk_rmaps (rr , & rmap , & have );
516469 if (error )
517470 goto out_bag ;
518471 if (have ) {
519- error = xrep_refc_push_rmaps_at (rr , rmap_bag ,
520- nbno , & rrm , & have , & stack_sz );
472+ error = xrep_refc_push_rmaps_at (rr , rcstack ,
473+ nbno , & rmap , & have );
521474 if (error )
522475 goto out_bag ;
523476 }
524477
525478 /* Emit refcount if necessary */
526479 ASSERT (nbno > cbno );
527- if (stack_sz != old_stack_sz ) {
528- if (old_stack_sz > 1 ) {
480+ if (rcbag_count ( rcstack ) != old_stack_height ) {
481+ if (old_stack_height > 1 ) {
529482 error = xrep_refc_stash (rr ,
530483 XFS_REFC_DOMAIN_SHARED ,
531484 cbno , nbno - cbno ,
532- old_stack_sz );
485+ old_stack_height );
533486 if (error )
534487 goto out_bag ;
535488 }
536489 cbno = nbno ;
537490 }
538491
539492 /* Stack empty, go find the next rmap */
540- if (stack_sz == 0 )
493+ if (rcbag_count ( rcstack ) == 0 )
541494 break ;
542- old_stack_sz = stack_sz ;
495+ old_stack_height = rcbag_count ( rcstack ) ;
543496 sbno = nbno ;
544497
545498 /* Set nbno to the bno of the next refcount change */
546- error = xrep_refc_next_edge ( rmap_bag , & rrm , have ,
499+ error = rcbag_next_edge ( rcstack , sc -> tp , & rmap , have ,
547500 & nbno );
548501 if (error )
549502 goto out_bag ;
@@ -552,14 +505,13 @@ xrep_refc_find_refcounts(
552505 }
553506 }
554507
555- ASSERT (stack_sz == 0 );
508+ ASSERT (rcbag_count ( rcstack ) == 0 );
556509out_bag :
557- xfarray_destroy ( rmap_bag );
510+ rcbag_free ( & rcstack );
558511out_cur :
559512 xchk_ag_btcur_free (& sc -> sa );
560513 return error ;
561514}
562- #undef RRM_NEXT
563515
564516/* Retrieve refcountbt data for bulk load. */
565517STATIC int
0 commit comments