Lines Matching +full:reverse +full:- +full:data
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (c) 2020-2024 Oracle. All Rights Reserved.
50 * Realtime Reverse Mapping Btree Repair
53 * This isn't quite as difficult as repairing the rmap btree on the data
54 * device, since we only store the data fork extents of realtime files on the
59 * Collecting entries for the new realtime rmap btree is easy -- all we have
60 * to do is generate rtrmap entries from the data fork mappings of all realtime
61 * files in the filesystem. We then scan the rmap btrees of the data device
64 * To rebuild the realtime rmap btree, we bulk-load the collected mappings into
93 /* in-memory btree cursor for the ->get_blocks walk */
100 /* Set us up to repair rt reverse mapping btrees. */
111 descr = xchk_xfile_rtgroup_descr(sc, "reverse mapping records"); in xrep_setup_rtrmapbt()
119 return -ENOMEM; in xrep_setup_rtrmapbt()
121 rr->sc = sc; in xrep_setup_rtrmapbt()
122 sc->buf = rr; in xrep_setup_rtrmapbt()
132 if (xfs_rtrmap_check_irec(sc->sr.rtg, rec) != NULL) in xrep_rtrmap_check_mapping()
133 return -EFSCORRUPTED; in xrep_rtrmap_check_mapping()
136 return xrep_require_rtext_inuse(sc, rec->rm_startblock, in xrep_rtrmap_check_mapping()
137 rec->rm_blockcount); in xrep_rtrmap_check_mapping()
140 /* Store a reverse-mapping record. */
157 struct xfs_scrub *sc = rr->sc; in xrep_rtrmap_stash()
164 if (xchk_iscan_aborted(&rr->iscan)) in xrep_rtrmap_stash()
165 return -EFSCORRUPTED; in xrep_rtrmap_stash()
167 trace_xrep_rtrmap_found(sc->mp, &rmap); in xrep_rtrmap_stash()
169 /* Add entry to in-memory btree. */ in xrep_rtrmap_stash()
170 mutex_lock(&rr->lock); in xrep_rtrmap_stash()
171 mcur = xfs_rtrmapbt_mem_cursor(sc->sr.rtg, sc->tp, &rr->rtrmap_btree); in xrep_rtrmap_stash()
177 error = xfbtree_trans_commit(&rr->rtrmap_btree, sc->tp); in xrep_rtrmap_stash()
181 mutex_unlock(&rr->lock); in xrep_rtrmap_stash()
185 xfbtree_trans_cancel(&rr->rtrmap_btree, sc->tp); in xrep_rtrmap_stash()
187 xchk_iscan_abort(&rr->iscan); in xrep_rtrmap_stash()
188 mutex_unlock(&rr->lock); in xrep_rtrmap_stash()
197 * Accumulate rmap data here to turn multiple adjacent bmaps into a
210 if (rf->accum.rm_blockcount == 0) in xrep_rtrmap_stash_accumulated()
213 return xrep_rtrmap_stash(rf->rr, rf->accum.rm_startblock, in xrep_rtrmap_stash_accumulated()
214 rf->accum.rm_blockcount, rf->accum.rm_owner, in xrep_rtrmap_stash_accumulated()
215 rf->accum.rm_offset, rf->accum.rm_flags); in xrep_rtrmap_stash_accumulated()
226 struct xfs_rmap_irec *accum = &rf->accum; in xrep_rtrmap_visit_bmbt()
227 struct xfs_mount *mp = rf->rr->sc->mp; in xrep_rtrmap_visit_bmbt()
232 if (xfs_rtb_to_rgno(mp, rec->br_startblock) != in xrep_rtrmap_visit_bmbt()
233 rtg_rgno(rf->rr->sc->sr.rtg)) in xrep_rtrmap_visit_bmbt()
236 if (rec->br_state == XFS_EXT_UNWRITTEN) in xrep_rtrmap_visit_bmbt()
240 rgbno = xfs_rtb_to_rgbno(mp, rec->br_startblock); in xrep_rtrmap_visit_bmbt()
241 if (accum->rm_blockcount > 0 && in xrep_rtrmap_visit_bmbt()
242 rec->br_startoff == accum->rm_offset + accum->rm_blockcount && in xrep_rtrmap_visit_bmbt()
243 rgbno == accum->rm_startblock + accum->rm_blockcount && in xrep_rtrmap_visit_bmbt()
244 rmap_flags == accum->rm_flags) { in xrep_rtrmap_visit_bmbt()
245 accum->rm_blockcount += rec->br_blockcount; in xrep_rtrmap_visit_bmbt()
254 accum->rm_startblock = rgbno; in xrep_rtrmap_visit_bmbt()
255 accum->rm_blockcount = rec->br_blockcount; in xrep_rtrmap_visit_bmbt()
256 accum->rm_offset = rec->br_startoff; in xrep_rtrmap_visit_bmbt()
257 accum->rm_flags = rmap_flags; in xrep_rtrmap_visit_bmbt()
272 struct xrep_rtrmap *rr = rf->rr; in xrep_rtrmap_scan_bmbt()
288 cur = xfs_bmbt_init_cursor(rr->sc->mp, rr->sc->tp, ip, XFS_DATA_FORK); in xrep_rtrmap_scan_bmbt()
300 * Iterate the in-core extent cache to collect rmap records for anything in
330 .accum = { .rm_owner = ip->i_ino, }, in xrep_rtrmap_scan_dfork()
336 if (ifp->if_format == XFS_DINODE_FMT_BTREE) { in xrep_rtrmap_scan_dfork()
347 } else if (ifp->if_format != XFS_DINODE_FMT_EXTENTS) { in xrep_rtrmap_scan_dfork()
348 /* realtime data forks should only be extents or btree */ in xrep_rtrmap_scan_dfork()
349 return -EFSCORRUPTED; in xrep_rtrmap_scan_dfork()
356 /* Record reverse mappings for a file. */
366 if (rr->sc->ip == ip) in xrep_rtrmap_scan_inode()
371 /* Check the data fork if it's on the realtime device. */ in xrep_rtrmap_scan_inode()
378 xchk_iscan_mark_visited(&rr->iscan, ip); in xrep_rtrmap_scan_inode()
394 if (xchk_should_terminate(rr->sc, &error)) in xrep_rtrmap_walk_rmap()
398 if (rec->rm_owner != rr->sc->ip->i_ino) in xrep_rtrmap_walk_rmap()
401 error = xrep_check_ino_btree_mapping(rr->sc, rec); in xrep_rtrmap_walk_rmap()
405 return xfsb_bitmap_set(&rr->old_rtrmapbt_blocks, in xrep_rtrmap_walk_rmap()
406 xfs_gbno_to_fsb(cur->bc_group, rec->rm_startblock), in xrep_rtrmap_walk_rmap()
407 rec->rm_blockcount); in xrep_rtrmap_walk_rmap()
410 /* Scan one AG for reverse mappings for the realtime rmap btree. */
416 struct xfs_scrub *sc = rr->sc; in xrep_rtrmap_scan_ag()
419 error = xrep_ag_init(sc, pag, &sc->sa); in xrep_rtrmap_scan_ag()
423 error = xfs_rmap_query_all(sc->sa.rmap_cur, xrep_rtrmap_walk_rmap, rr); in xrep_rtrmap_scan_ag()
424 xchk_ag_free(sc, &sc->sa); in xrep_rtrmap_scan_ag()
440 struct xrep_rtrmap *rr = rsr->rr; in xrep_rtrmap_stash_run()
443 return xrep_rtrmap_stash(rr, rgbno, len, rsr->owner, 0, 0); in xrep_rtrmap_stash_run()
458 .owner = oinfo->oi_owner, in xrep_rtrmap_stash_bitmap()
474 irec->rc_domain != XFS_REFC_DOMAIN_COW) in xrep_rtrmap_walk_cowblocks()
475 return -EFSCORRUPTED; in xrep_rtrmap_walk_cowblocks()
477 return xrgb_bitmap_set(bitmap, irec->rc_startblock, in xrep_rtrmap_walk_cowblocks()
478 irec->rc_blockcount); in xrep_rtrmap_walk_cowblocks()
495 .rc_startblock = -1U, in xrep_rtrmap_find_refcount_rmaps()
498 struct xfs_scrub *sc = rr->sc; in xrep_rtrmap_find_refcount_rmaps()
501 if (!xfs_has_rtreflink(sc->mp)) in xrep_rtrmap_find_refcount_rmaps()
507 error = xfs_refcount_query_range(sc->sr.refc_cur, &low, &high, in xrep_rtrmap_find_refcount_rmaps()
532 error = xrep_rtrmap_check_mapping(rr->sc, rec); in xrep_rtrmap_check_record()
536 rr->nr_records++; in xrep_rtrmap_check_record()
540 /* Generate all the reverse-mappings for the realtime device. */
545 struct xfs_scrub *sc = rr->sc; in xrep_rtrmap_find_rmaps()
552 if (xfs_has_rtsb(sc->mp) && rtg_rgno(rr->sc->sr.rtg) == 0) { in xrep_rtrmap_find_rmaps()
553 error = xrep_rtrmap_stash(rr, 0, sc->mp->m_sb.sb_rextsize, in xrep_rtrmap_find_rmaps()
560 xrep_rtgroup_btcur_init(sc, &sc->sr); in xrep_rtrmap_find_rmaps()
562 xchk_rtgroup_btcur_free(&sc->sr); in xrep_rtrmap_find_rmaps()
582 xchk_rtgroup_unlock(&sc->sr); in xrep_rtrmap_find_rmaps()
587 while ((error = xchk_iscan_iter(&rr->iscan, &ip)) == 1) { in xrep_rtrmap_find_rmaps()
596 xchk_iscan_iter_finish(&rr->iscan); in xrep_rtrmap_find_rmaps()
608 error = xchk_rtgroup_lock(sc, &sc->sr, XCHK_RTGLOCK_ALL); in xrep_rtrmap_find_rmaps()
613 * If a hook failed to update the in-memory btree, we lack the data to in xrep_rtrmap_find_rmaps()
616 if (xchk_iscan_aborted(&rr->iscan)) in xrep_rtrmap_find_rmaps()
617 return -EFSCORRUPTED; in xrep_rtrmap_find_rmaps()
620 while ((pag = xfs_perag_next(sc->mp, pag))) { in xrep_rtrmap_find_rmaps()
631 * all actively-owned rt files in the filesystem. At the same time, in xrep_rtrmap_find_rmaps()
635 mcur = xfs_rtrmapbt_mem_cursor(rr->sc->sr.rtg, NULL, &rr->rtrmap_btree); in xrep_rtrmap_find_rmaps()
636 rr->nr_records = 0; in xrep_rtrmap_find_rmaps()
645 /* Retrieve rtrmapbt data for bulk load. */
662 error = xfs_btree_increment(rr->mcur, 0, &stat); in xrep_rtrmap_get_records()
666 return -EFSCORRUPTED; in xrep_rtrmap_get_records()
668 error = xfs_rmap_get_rec(rr->mcur, &cur->bc_rec.r, &stat); in xrep_rtrmap_get_records()
672 return -EFSCORRUPTED; in xrep_rtrmap_get_records()
675 cur->bc_ops->init_rec_from_cur(cur, block_rec); in xrep_rtrmap_get_records()
690 return xrep_newbt_claim_block(cur, &rr->new_btree, ptr); in xrep_rtrmap_claim_block()
701 return xfs_rtrmap_broot_space_calc(cur->bc_mp, level, nr_this_level); in xrep_rtrmap_iroot_size()
714 struct xfs_scrub *sc = rr->sc; in xrep_rtrmap_build_new_tree()
715 struct xfs_rtgroup *rtg = sc->sr.rtg; in xrep_rtrmap_build_new_tree()
725 error = xrep_newbt_init_metadir_inode(&rr->new_btree, sc); in xrep_rtrmap_build_new_tree()
729 rr->new_btree.bload.get_records = xrep_rtrmap_get_records; in xrep_rtrmap_build_new_tree()
730 rr->new_btree.bload.claim_block = xrep_rtrmap_claim_block; in xrep_rtrmap_build_new_tree()
731 rr->new_btree.bload.iroot_size = xrep_rtrmap_iroot_size; in xrep_rtrmap_build_new_tree()
734 xfs_btree_stage_ifakeroot(rmap_cur, &rr->new_btree.ifake); in xrep_rtrmap_build_new_tree()
738 &rr->new_btree.bload, rr->nr_records); in xrep_rtrmap_build_new_tree()
753 error = xfs_trans_reserve_more_inode(sc->tp, rtg_rmap(rtg), in xrep_rtrmap_build_new_tree()
754 rr->new_btree.bload.nr_blocks, 0, true); in xrep_rtrmap_build_new_tree()
759 error = xrep_newbt_alloc_blocks(&rr->new_btree, in xrep_rtrmap_build_new_tree()
760 rr->new_btree.bload.nr_blocks); in xrep_rtrmap_build_new_tree()
765 * Create a cursor to the in-memory btree so that we can bulk load the in xrep_rtrmap_build_new_tree()
768 rr->mcur = xfs_rtrmapbt_mem_cursor(sc->sr.rtg, NULL, &rr->rtrmap_btree); in xrep_rtrmap_build_new_tree()
769 error = xfs_btree_goto_left_edge(rr->mcur); in xrep_rtrmap_build_new_tree()
774 rr->new_btree.ifake.if_fork->if_format = XFS_DINODE_FMT_META_BTREE; in xrep_rtrmap_build_new_tree()
775 error = xfs_btree_bload(rmap_cur, &rr->new_btree.bload, rr); in xrep_rtrmap_build_new_tree()
784 xfs_rtrmapbt_commit_staged_btree(rmap_cur, sc->tp); in xrep_rtrmap_build_new_tree()
785 xrep_inode_set_nblocks(rr->sc, rr->new_btree.ifake.if_blocks); in xrep_rtrmap_build_new_tree()
787 xfs_btree_del_cursor(rr->mcur, 0); in xrep_rtrmap_build_new_tree()
788 rr->mcur = NULL; in xrep_rtrmap_build_new_tree()
792 * updating the in-memory btree. Abort the scan to stop live updates. in xrep_rtrmap_build_new_tree()
794 xchk_iscan_abort(&rr->iscan); in xrep_rtrmap_build_new_tree()
797 error = xrep_newbt_commit(&rr->new_btree); in xrep_rtrmap_build_new_tree()
804 xfs_btree_del_cursor(rr->mcur, error); in xrep_rtrmap_build_new_tree()
807 xrep_newbt_cancel(&rr->new_btree); in xrep_rtrmap_build_new_tree()
822 * aren't cross-linked with something else. in xrep_rtrmap_remove_old_tree()
824 error = xrep_reap_metadir_fsblocks(rr->sc, &rr->old_rtrmapbt_blocks); in xrep_rtrmap_remove_old_tree()
832 return xrep_reset_metafile_resv(rr->sc); in xrep_rtrmap_remove_old_tree()
847 if (XFS_RMAP_NON_INODE_OWNER(oi->oi_owner)) in xrep_rtrmapbt_want_live_update()
851 return xchk_iscan_want_live_update(iscan, oi->oi_owner); in xrep_rtrmapbt_want_live_update()
864 void *data) in xrep_rtrmapbt_live_update() argument
866 struct xfs_rmap_update_params *p = data; in xrep_rtrmapbt_live_update()
875 mp = rr->sc->mp; in xrep_rtrmapbt_live_update()
877 if (!xrep_rtrmapbt_want_live_update(&rr->iscan, &p->oinfo)) in xrep_rtrmapbt_live_update()
880 trace_xrep_rmap_live_update(rtg_group(rr->sc->sr.rtg), action, p); in xrep_rtrmapbt_live_update()
886 mutex_lock(&rr->lock); in xrep_rtrmapbt_live_update()
887 mcur = xfs_rtrmapbt_mem_cursor(rr->sc->sr.rtg, tp, &rr->rtrmap_btree); in xrep_rtrmapbt_live_update()
888 error = __xfs_rmap_finish_intent(mcur, action, p->startblock, in xrep_rtrmapbt_live_update()
889 p->blockcount, &p->oinfo, p->unwritten); in xrep_rtrmapbt_live_update()
894 error = xfbtree_trans_commit(&rr->rtrmap_btree, tp); in xrep_rtrmapbt_live_update()
899 mutex_unlock(&rr->lock); in xrep_rtrmapbt_live_update()
903 xfbtree_trans_cancel(&rr->rtrmap_btree, tp); in xrep_rtrmapbt_live_update()
906 xchk_iscan_abort(&rr->iscan); in xrep_rtrmapbt_live_update()
907 mutex_unlock(&rr->lock); in xrep_rtrmapbt_live_update()
917 struct xfs_scrub *sc = rr->sc; in xrep_rtrmap_setup_scan()
920 mutex_init(&rr->lock); in xrep_rtrmap_setup_scan()
921 xfsb_bitmap_init(&rr->old_rtrmapbt_blocks); in xrep_rtrmap_setup_scan()
924 error = xfs_rtrmapbt_mem_init(sc->mp, &rr->rtrmap_btree, sc->xmbtp, in xrep_rtrmap_setup_scan()
925 rtg_rgno(sc->sr.rtg)); in xrep_rtrmap_setup_scan()
930 xchk_iscan_start(sc, 30000, 100, &rr->iscan); in xrep_rtrmap_setup_scan()
933 * Hook into live rtrmap operations so that we can update our in-memory in xrep_rtrmap_setup_scan()
938 ASSERT(sc->flags & XCHK_FSGATES_RMAP); in xrep_rtrmap_setup_scan()
939 xfs_rmap_hook_setup(&rr->rhook, xrep_rtrmapbt_live_update); in xrep_rtrmap_setup_scan()
940 error = xfs_rmap_hook_add(rtg_group(sc->sr.rtg), &rr->rhook); in xrep_rtrmap_setup_scan()
946 xchk_iscan_teardown(&rr->iscan); in xrep_rtrmap_setup_scan()
947 xfbtree_destroy(&rr->rtrmap_btree); in xrep_rtrmap_setup_scan()
949 xfsb_bitmap_destroy(&rr->old_rtrmapbt_blocks); in xrep_rtrmap_setup_scan()
950 mutex_destroy(&rr->lock); in xrep_rtrmap_setup_scan()
959 struct xfs_scrub *sc = rr->sc; in xrep_rtrmap_teardown()
961 xchk_iscan_abort(&rr->iscan); in xrep_rtrmap_teardown()
962 xfs_rmap_hook_del(rtg_group(sc->sr.rtg), &rr->rhook); in xrep_rtrmap_teardown()
963 xchk_iscan_teardown(&rr->iscan); in xrep_rtrmap_teardown()
964 xfbtree_destroy(&rr->rtrmap_btree); in xrep_rtrmap_teardown()
965 xfsb_bitmap_destroy(&rr->old_rtrmapbt_blocks); in xrep_rtrmap_teardown()
966 mutex_destroy(&rr->lock); in xrep_rtrmap_teardown()
974 struct xrep_rtrmap *rr = sc->buf; in xrep_rtrmapbt()
991 xfs_trans_ijoin(sc->tp, sc->ip, 0); in xrep_rtrmapbt()