Lines Matching +full:ip +full:- +full:block

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2022-2023 Oracle. All Rights Reserved.
58 * if the rmapbt says there is an owner of this block other than @oinfo, then
59 * the block is crosslinked. Remove the reverse mapping and continue.
61 * If there is one rmap record, we can free the block, which removes the
62 * reverse mapping but doesn't add the block to the free space. Our repair
63 * strategy is to hope the other metadata objects crosslinked on this block
67 * If there are no rmap records at all, we also free the block. If the btree
70 * had to have been an rmap entry for the block to have ended up on @bitmap,
74 * the btree we're trying to rebuild and the block is indeed owned by another
75 * data structure with the same rmap owner, then the block will be in sublist
77 * with only the same rmap owner but the block is not owned by something with
78 * the same rmap owner, the block will be freed.
107 /* Put a block back on the AGFL. */
122 * Since we're "freeing" a lost block onto the AGFL, we have to in xreap_put_freelist()
123 * create an rmap for the block prior to merging it or else other in xreap_put_freelist()
126 error = xfs_rmap_alloc(sc->tp, sc->sa.agf_bp, sc->sa.pag, agbno, 1, in xreap_put_freelist()
131 /* Put the block on the AGFL. */ in xreap_put_freelist()
132 error = xfs_alloc_read_agfl(sc->sa.pag, sc->tp, &agfl_bp); in xreap_put_freelist()
136 error = xfs_alloc_put_freelist(sc->sa.pag, sc->tp, sc->sa.agf_bp, in xreap_put_freelist()
140 xfs_extent_busy_insert(sc->tp, sc->sa.pag, agbno, 1, in xreap_put_freelist()
149 if (rs->force_roll) in xreap_dirty()
151 if (rs->deferred) in xreap_dirty()
153 if (rs->invalidated) in xreap_dirty()
155 if (rs->total_deferred) in xreap_dirty()
170 if (rs->force_roll) in xreap_want_roll()
172 if (rs->deferred > XREP_MAX_ITRUNCATE_EFIS) in xreap_want_roll()
174 if (rs->invalidated > XREAP_MAX_BINVAL) in xreap_want_roll()
181 rs->total_deferred += rs->deferred; in xreap_reset()
182 rs->deferred = 0; in xreap_reset()
183 rs->invalidated = 0; in xreap_reset()
184 rs->force_roll = false; in xreap_reset()
199 if (rs->force_roll) in xreap_want_defer_finish()
201 if (rs->total_deferred > XREAP_MAX_DEFER_CHAIN) in xreap_want_defer_finish()
208 rs->total_deferred = 0; in xreap_defer_finish_reset()
209 rs->deferred = 0; in xreap_defer_finish_reset()
210 rs->invalidated = 0; in xreap_defer_finish_reset()
211 rs->force_roll = false; in xreap_defer_finish_reset()
240 scan->__sector_count += scan->daddr_step; in xrep_bufscan_advance()
241 while (scan->__sector_count <= scan->max_sectors) { in xrep_bufscan_advance()
245 error = xfs_buf_incore(mp->m_ddev_targp, scan->daddr, in xrep_bufscan_advance()
246 scan->__sector_count, XBF_LIVESCAN, &bp); in xrep_bufscan_advance()
250 scan->__sector_count += scan->daddr_step; in xrep_bufscan_advance()
263 struct xfs_scrub *sc = rs->sc; in xreap_agextent_binval()
264 struct xfs_perag *pag = sc->sa.pag; in xreap_agextent_binval()
265 struct xfs_mount *mp = sc->mp; in xreap_agextent_binval()
266 xfs_agnumber_t agno = sc->sa.pag->pag_agno; in xreap_agextent_binval()
271 * Avoid invalidating AG headers and post-EOFS blocks because we never in xreap_agextent_binval()
275 !xfs_verify_agbno(pag, agbno_next - 1)) in xreap_agextent_binval()
289 agbno_next - bno), in xreap_agextent_binval()
295 xfs_trans_bjoin(sc->tp, bp); in xreap_agextent_binval()
296 xfs_trans_binval(sc->tp, bp); in xreap_agextent_binval()
297 rs->invalidated++; in xreap_agextent_binval()
304 if (rs->invalidated > XREAP_MAX_BINVAL) { in xreap_agextent_binval()
305 *aglenp -= agbno_next - bno; in xreap_agextent_binval()
314 trace_xreap_agextent_binval(sc->sa.pag, agbno, *aglenp); in xreap_agextent_binval()
319 * call. Cross-linked blocks should have their reverse mappings removed, but
320 * single-owner extents can be freed. AGFL blocks can only be put back one at
331 struct xfs_scrub *sc = rs->sc; in xreap_agextent_select()
339 * block of this extent. If so, the block is crosslinked. in xreap_agextent_select()
341 cur = xfs_rmapbt_init_cursor(sc->mp, sc->tp, sc->sa.agf_bp, in xreap_agextent_select()
342 sc->sa.pag); in xreap_agextent_select()
343 error = xfs_rmap_has_other_keys(cur, agbno, 1, rs->oinfo, in xreap_agextent_select()
349 if (rs->resv == XFS_AG_RESV_AGFL) in xreap_agextent_select()
359 error = xfs_rmap_has_other_keys(cur, bno, 1, rs->oinfo, in xreap_agextent_select()
373 trace_xreap_agextent_select(sc->sa.pag, agbno, len, *crosslinked); in xreap_agextent_select()
390 struct xfs_scrub *sc = rs->sc; in xreap_agextent_iter()
394 fsbno = XFS_AGB_TO_FSB(sc->mp, sc->sa.pag->pag_agno, agbno); in xreap_agextent_iter()
397 * If there are other rmappings, this block is cross linked and must in xreap_agextent_iter()
399 * we were the only owner of the block, so free the extent, which will in xreap_agextent_iter()
402 * XXX: XFS doesn't support detecting the case where a single block in xreap_agextent_iter()
403 * metadata structure is crosslinked with a multi-block structure in xreap_agextent_iter()
410 trace_xreap_dispose_unmap_extent(sc->sa.pag, agbno, *aglenp); in xreap_agextent_iter()
412 rs->force_roll = true; in xreap_agextent_iter()
414 if (rs->oinfo == &XFS_RMAP_OINFO_COW) { in xreap_agextent_iter()
420 xfs_refcount_free_cow_extent(sc->tp, fsbno, *aglenp); in xreap_agextent_iter()
424 return xfs_rmap_free(sc->tp, sc->sa.agf_bp, sc->sa.pag, agbno, in xreap_agextent_iter()
425 *aglenp, rs->oinfo); in xreap_agextent_iter()
428 trace_xreap_dispose_free_extent(sc->sa.pag, agbno, *aglenp); in xreap_agextent_iter()
449 if (rs->oinfo == &XFS_RMAP_OINFO_COW) { in xreap_agextent_iter()
450 ASSERT(rs->resv == XFS_AG_RESV_NONE); in xreap_agextent_iter()
452 xfs_refcount_free_cow_extent(sc->tp, fsbno, *aglenp); in xreap_agextent_iter()
453 error = xfs_free_extent_later(sc->tp, fsbno, *aglenp, NULL, in xreap_agextent_iter()
454 rs->resv, XFS_FREE_EXTENT_SKIP_DISCARD); in xreap_agextent_iter()
458 rs->force_roll = true; in xreap_agextent_iter()
463 if (rs->resv == XFS_AG_RESV_AGFL) { in xreap_agextent_iter()
469 rs->force_roll = true; in xreap_agextent_iter()
479 error = xfs_free_extent_later(sc->tp, fsbno, *aglenp, rs->oinfo, in xreap_agextent_iter()
480 rs->resv, XFS_FREE_EXTENT_SKIP_DISCARD); in xreap_agextent_iter()
484 rs->deferred++; in xreap_agextent_iter()
485 if (rs->deferred % 2 == 0) in xreap_agextent_iter()
486 xfs_defer_add_barrier(sc->tp); in xreap_agextent_iter()
491 * Break an AG metadata extent into sub-extents by fate (crosslinked, not
492 * crosslinked), and dispose of each sub-extent separately.
501 struct xfs_scrub *sc = rs->sc; in xreap_agmeta_extent()
506 ASSERT(sc->ip == NULL); in xreap_agmeta_extent()
539 /* Dispose of every block of every AG metadata extent in the bitmap. */
554 ASSERT(xfs_has_rmapbt(sc->mp)); in xrep_reap_agblocks()
555 ASSERT(sc->ip == NULL); in xrep_reap_agblocks()
568 * Break a file metadata extent into sub-extents by fate (crosslinked, not
569 * crosslinked), and dispose of each sub-extent separately. The extent must
579 struct xfs_scrub *sc = rs->sc; in xreap_fsmeta_extent()
580 xfs_agnumber_t agno = XFS_FSB_TO_AGNO(sc->mp, fsbno); in xreap_fsmeta_extent()
581 xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(sc->mp, fsbno); in xreap_fsmeta_extent()
586 ASSERT(sc->ip != NULL); in xreap_fsmeta_extent()
587 ASSERT(!sc->sa.pag); in xreap_fsmeta_extent()
593 sc->sa.pag = xfs_perag_get(sc->mp, agno); in xreap_fsmeta_extent()
594 if (!sc->sa.pag) in xreap_fsmeta_extent()
595 return -EFSCORRUPTED; in xreap_fsmeta_extent()
597 error = xfs_alloc_read_agf(sc->sa.pag, sc->tp, 0, &sc->sa.agf_bp); in xreap_fsmeta_extent()
629 xfs_trans_bhold(sc->tp, sc->sa.agf_bp); in xreap_fsmeta_extent()
630 error = xfs_trans_roll_inode(&sc->tp, sc->ip); in xreap_fsmeta_extent()
631 xfs_trans_bjoin(sc->tp, sc->sa.agf_bp); in xreap_fsmeta_extent()
641 xfs_trans_brelse(sc->tp, sc->sa.agf_bp); in xreap_fsmeta_extent()
642 sc->sa.agf_bp = NULL; in xreap_fsmeta_extent()
644 xfs_perag_put(sc->sa.pag); in xreap_fsmeta_extent()
645 sc->sa.pag = NULL; in xreap_fsmeta_extent()
650 * Dispose of every block of every fs metadata extent in the bitmap.
666 ASSERT(xfs_has_rmapbt(sc->mp)); in xrep_reap_fsblocks()
667 ASSERT(sc->ip != NULL); in xrep_reap_fsblocks()
684 * This first step determines the longest subset of the passed-in imap
691 struct xfs_inode *ip, in xreap_bmapi_select() argument
704 agbno = XFS_FSB_TO_AGBNO(sc->mp, imap->br_startblock); in xreap_bmapi_select()
705 agbno_next = agbno + imap->br_blockcount; in xreap_bmapi_select()
707 cur = xfs_rmapbt_init_cursor(sc->mp, sc->tp, sc->sa.agf_bp, in xreap_bmapi_select()
708 sc->sa.pag); in xreap_bmapi_select()
710 xfs_rmap_ino_owner(&oinfo, ip->i_ino, whichfork, imap->br_startoff); in xreap_bmapi_select()
732 imap->br_blockcount = len; in xreap_bmapi_select()
733 trace_xreap_bmapi_select(sc->sa.pag, agbno, len, *crosslinked); in xreap_bmapi_select()
752 for (i = 0; i < bp->b_map_count; i++) { in xreap_buf_loggable()
756 chunks = DIV_ROUND_UP(BBTOB(bp->b_maps[i].bm_len), in xreap_buf_loggable()
773 struct xfs_inode *ip, in xreap_bmapi_binval() argument
777 struct xfs_mount *mp = sc->mp; in xreap_bmapi_binval()
778 struct xfs_perag *pag = sc->sa.pag; in xreap_bmapi_binval()
783 xfs_agnumber_t agno = sc->sa.pag->pag_agno; in xreap_bmapi_binval()
791 * Avoid invalidating AG headers and post-EOFS blocks because we never in xreap_bmapi_binval()
794 agbno = bno = XFS_FSB_TO_AGBNO(sc->mp, imap->br_startblock); in xreap_bmapi_binval()
795 agbno_next = agbno + imap->br_blockcount; in xreap_bmapi_binval()
797 !xfs_verify_agbno(pag, agbno_next - 1)) in xreap_bmapi_binval()
802 * means that for each block in the mapping, there could exist an in xreap_bmapi_binval()
803 * xfs_buf indexed by that block with any length up to the maximum in xreap_bmapi_binval()
808 off = imap->br_startoff + imap->br_blockcount; in xreap_bmapi_binval()
814 error = xfs_bmapi_read(ip, off, max_off - off, &hmap, in xreap_bmapi_binval()
820 return -EFSCORRUPTED; in xreap_bmapi_binval()
828 scan_blocks = off - imap->br_startoff; in xreap_bmapi_binval()
849 xfs_trans_bjoin(sc->tp, bp); in xreap_bmapi_binval()
850 xfs_trans_binval(sc->tp, bp); in xreap_bmapi_binval()
863 imap->br_blockcount = agbno_next - bno; in xreap_bmapi_binval()
869 scan_blocks--; in xreap_bmapi_binval()
873 trace_xreap_bmapi_binval(sc->sa.pag, agbno, imap->br_blockcount); in xreap_bmapi_binval()
879 * The number of blocks disposed of is returned in @imap->br_blockcount.
884 struct xfs_inode *ip, in xrep_reap_bmapi_iter() argument
893 * If there are other rmappings, this block is cross linked and in xrep_reap_bmapi_iter()
897 * anybody else who thinks they own the block, even though that in xrep_reap_bmapi_iter()
900 trace_xreap_dispose_unmap_extent(sc->sa.pag, in xrep_reap_bmapi_iter()
901 XFS_FSB_TO_AGBNO(sc->mp, imap->br_startblock), in xrep_reap_bmapi_iter()
902 imap->br_blockcount); in xrep_reap_bmapi_iter()
909 xfs_bmap_unmap_extent(sc->tp, ip, whichfork, imap); in xrep_reap_bmapi_iter()
910 xfs_trans_mod_dquot_byino(sc->tp, ip, XFS_TRANS_DQ_BCOUNT, in xrep_reap_bmapi_iter()
911 -(int64_t)imap->br_blockcount); in xrep_reap_bmapi_iter()
912 xfs_rmap_unmap_extent(sc->tp, ip, whichfork, imap); in xrep_reap_bmapi_iter()
917 * If the block is not crosslinked, we can invalidate all the incore in xrep_reap_bmapi_iter()
920 * by a block starting before the first block of the extent but overlap in xrep_reap_bmapi_iter()
923 trace_xreap_dispose_free_extent(sc->sa.pag, in xrep_reap_bmapi_iter()
924 XFS_FSB_TO_AGBNO(sc->mp, imap->br_startblock), in xrep_reap_bmapi_iter()
925 imap->br_blockcount); in xrep_reap_bmapi_iter()
933 error = xreap_bmapi_binval(sc, ip, whichfork, imap); in xrep_reap_bmapi_iter()
934 if (error || imap->br_blockcount == 0) in xrep_reap_bmapi_iter()
942 xfs_bmap_unmap_extent(sc->tp, ip, whichfork, imap); in xrep_reap_bmapi_iter()
943 xfs_trans_mod_dquot_byino(sc->tp, ip, XFS_TRANS_DQ_BCOUNT, in xrep_reap_bmapi_iter()
944 -(int64_t)imap->br_blockcount); in xrep_reap_bmapi_iter()
945 return xfs_free_extent_later(sc->tp, imap->br_startblock, in xrep_reap_bmapi_iter()
946 imap->br_blockcount, NULL, XFS_AG_RESV_NONE, in xrep_reap_bmapi_iter()
957 struct xfs_inode *ip, in xreap_ifork_extent() argument
965 ASSERT(sc->sa.pag == NULL); in xreap_ifork_extent()
967 trace_xreap_ifork_extent(sc, ip, whichfork, imap); in xreap_ifork_extent()
969 agno = XFS_FSB_TO_AGNO(sc->mp, imap->br_startblock); in xreap_ifork_extent()
970 sc->sa.pag = xfs_perag_get(sc->mp, agno); in xreap_ifork_extent()
971 if (!sc->sa.pag) in xreap_ifork_extent()
972 return -EFSCORRUPTED; in xreap_ifork_extent()
974 error = xfs_alloc_read_agf(sc->sa.pag, sc->tp, 0, &sc->sa.agf_bp); in xreap_ifork_extent()
982 error = xreap_bmapi_select(sc, ip, whichfork, imap, &crosslinked); in xreap_ifork_extent()
986 error = xrep_reap_bmapi_iter(sc, ip, whichfork, imap, crosslinked); in xreap_ifork_extent()
991 xfs_trans_brelse(sc->tp, sc->sa.agf_bp); in xreap_ifork_extent()
992 sc->sa.agf_bp = NULL; in xreap_ifork_extent()
994 xfs_perag_put(sc->sa.pag); in xreap_ifork_extent()
995 sc->sa.pag = NULL; in xreap_ifork_extent()
1000 * Dispose of each block mapped to the given fork of the given file. Callers
1001 * must hold ILOCK_EXCL, and ip can only be sc->ip or sc->tempip. The fork
1007 struct xfs_inode *ip, in xrep_reap_ifork() argument
1014 ASSERT(xfs_has_rmapbt(sc->mp)); in xrep_reap_ifork()
1015 ASSERT(ip == sc->ip || ip == sc->tempip); in xrep_reap_ifork()
1016 ASSERT(whichfork == XFS_ATTR_FORK || !XFS_IS_REALTIME_INODE(ip)); in xrep_reap_ifork()
1023 error = xfs_bmapi_read(ip, off, XFS_MAX_FILEOFF - off, &imap, in xrep_reap_ifork()
1029 return -EFSCORRUPTED; in xrep_reap_ifork()
1037 error = xreap_ifork_extent(sc, ip, whichfork, &imap); in xrep_reap_ifork()
1041 error = xfs_defer_finish(&sc->tp); in xrep_reap_ifork()