Lines Matching +full:ip +full:- +full:blocks
1 // SPDX-License-Identifier: GPL-2.0+
35 * told us to fix it. This function returns -EAGAIN to mean "re-run scrub",
40 struct xfs_inode *ip, in xrep_attempt() argument
45 trace_xrep_attempt(ip, sc->sm, error); in xrep_attempt()
47 xchk_ag_btcur_free(&sc->sa); in xrep_attempt()
50 ASSERT(sc->ops->repair); in xrep_attempt()
51 error = sc->ops->repair(sc); in xrep_attempt()
52 trace_xrep_done(ip, sc->sm, error); in xrep_attempt()
59 sc->sm->sm_flags &= ~XFS_SCRUB_FLAGS_OUT; in xrep_attempt()
60 sc->flags |= XREP_ALREADY_FIXED; in xrep_attempt()
61 return -EAGAIN; in xrep_attempt()
62 case -EDEADLOCK: in xrep_attempt()
63 case -EAGAIN: in xrep_attempt()
65 if (!(sc->flags & XCHK_TRY_HARDER)) { in xrep_attempt()
66 sc->flags |= XCHK_TRY_HARDER; in xrep_attempt()
67 return -EAGAIN; in xrep_attempt()
74 return -EFSCORRUPTED; in xrep_attempt()
84 * administrator isn't running xfs_scrub in no-repairs mode.
98 * Repair probe -- userspace uses this to probe if we're willing to repair a
124 if (sc->sa.agi_bp) in xrep_roll_ag_trans()
125 xfs_trans_bhold(sc->tp, sc->sa.agi_bp); in xrep_roll_ag_trans()
126 if (sc->sa.agf_bp) in xrep_roll_ag_trans()
127 xfs_trans_bhold(sc->tp, sc->sa.agf_bp); in xrep_roll_ag_trans()
128 if (sc->sa.agfl_bp) in xrep_roll_ag_trans()
129 xfs_trans_bhold(sc->tp, sc->sa.agfl_bp); in xrep_roll_ag_trans()
138 error = xfs_trans_roll(&sc->tp); in xrep_roll_ag_trans()
143 if (sc->sa.agi_bp) in xrep_roll_ag_trans()
144 xfs_trans_bjoin(sc->tp, sc->sa.agi_bp); in xrep_roll_ag_trans()
145 if (sc->sa.agf_bp) in xrep_roll_ag_trans()
146 xfs_trans_bjoin(sc->tp, sc->sa.agf_bp); in xrep_roll_ag_trans()
147 if (sc->sa.agfl_bp) in xrep_roll_ag_trans()
148 xfs_trans_bjoin(sc->tp, sc->sa.agfl_bp); in xrep_roll_ag_trans()
166 pag->pagf_freeblks > xfs_ag_resv_needed(pag, type) + nr_blocks; in xrep_ag_has_space()
170 * Figure out how many blocks to reserve for an AG repair. We calculate the
171 * worst case estimate for the number of blocks we'd need to rebuild one of
172 * any type of per-AG btree.
178 struct xfs_mount *mp = sc->mp; in xrep_calc_ag_resblks()
179 struct xfs_scrub_metadata *sm = sc->sm; in xrep_calc_ag_resblks()
192 if (!(sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR)) in xrep_calc_ag_resblks()
195 pag = xfs_perag_get(mp, sm->sm_agno); in xrep_calc_ag_resblks()
196 if (pag->pagi_init) { in xrep_calc_ag_resblks()
197 /* Use in-core icount if possible. */ in xrep_calc_ag_resblks()
198 icount = pag->pagi_count; in xrep_calc_ag_resblks()
201 error = xfs_ialloc_read_agi(mp, NULL, sm->sm_agno, &bp); in xrep_calc_ag_resblks()
203 icount = pag->pagi_count; in xrep_calc_ag_resblks()
209 error = xfs_alloc_read_agf(mp, NULL, sm->sm_agno, 0, &bp); in xrep_calc_ag_resblks()
211 struct xfs_agf *agf = bp->b_addr; in xrep_calc_ag_resblks()
213 aglen = be32_to_cpu(agf->agf_length); in xrep_calc_ag_resblks()
214 freelen = be32_to_cpu(agf->agf_freeblks); in xrep_calc_ag_resblks()
215 usedlen = aglen - freelen; in xrep_calc_ag_resblks()
220 /* If the icount is impossible, make some worst-case assumptions. */ in xrep_calc_ag_resblks()
222 !xfs_verify_agino(mp, sm->sm_agno, icount)) { in xrep_calc_ag_resblks()
225 xfs_agino_range(mp, sm->sm_agno, &first, &last); in xrep_calc_ag_resblks()
226 icount = last - first + 1; in xrep_calc_ag_resblks()
229 /* If the block counts are impossible, make worst-case assumptions. */ in xrep_calc_ag_resblks()
231 aglen != xfs_ag_block_count(mp, sm->sm_agno) || in xrep_calc_ag_resblks()
233 aglen = xfs_ag_block_count(mp, sm->sm_agno); in xrep_calc_ag_resblks()
238 trace_xrep_calc_ag_resblks(mp, sm->sm_agno, icount, aglen, in xrep_calc_ag_resblks()
242 * Figure out how many blocks we'd need worst case to rebuild in xrep_calc_ag_resblks()
247 if (xfs_sb_version_hassparseinodes(&mp->m_sb)) in xrep_calc_ag_resblks()
253 if (xfs_sb_version_hasfinobt(&mp->m_sb)) in xrep_calc_ag_resblks()
255 if (xfs_sb_version_hasreflink(&mp->m_sb)) in xrep_calc_ag_resblks()
259 if (xfs_sb_version_hasrmapbt(&mp->m_sb)) { in xrep_calc_ag_resblks()
261 * Guess how many blocks we need to rebuild the rmapbt. in xrep_calc_ag_resblks()
262 * For non-reflink filesystems we can't have more records than in xrep_calc_ag_resblks()
263 * used blocks. However, with reflink it's possible to have in xrep_calc_ag_resblks()
266 * what we hope is an generous over-estimation. in xrep_calc_ag_resblks()
268 if (xfs_sb_version_hasreflink(&mp->m_sb)) in xrep_calc_ag_resblks()
277 trace_xrep_calc_ag_resblks_btsize(mp, sm->sm_agno, bnobt_sz, in xrep_calc_ag_resblks()
298 error = xfs_alloc_get_freelist(sc->tp, sc->sa.agf_bp, &bno, 1); in xrep_alloc_ag_block()
302 return -ENOSPC; in xrep_alloc_ag_block()
303 xfs_extent_busy_reuse(sc->mp, sc->sa.agno, bno, in xrep_alloc_ag_block()
305 *fsbno = XFS_AGB_TO_FSB(sc->mp, sc->sa.agno, bno); in xrep_alloc_ag_block()
307 xfs_ag_resv_rmapbt_alloc(sc->mp, sc->sa.agno); in xrep_alloc_ag_block()
313 args.tp = sc->tp; in xrep_alloc_ag_block()
314 args.mp = sc->mp; in xrep_alloc_ag_block()
316 args.fsbno = XFS_AGB_TO_FSB(args.mp, sc->sa.agno, 0); in xrep_alloc_ag_block()
327 return -ENOSPC; in xrep_alloc_ag_block()
343 struct xfs_trans *tp = sc->tp; in xrep_init_btblock()
344 struct xfs_mount *mp = sc->mp; in xrep_init_btblock()
351 ASSERT(XFS_FSB_TO_AGNO(mp, fsb) == sc->sa.agno); in xrep_init_btblock()
352 error = xfs_trans_get_buf(tp, mp->m_ddev_targp, in xrep_init_btblock()
357 xfs_buf_zero(bp, 0, BBTOB(bp->b_length)); in xrep_init_btblock()
358 xfs_btree_init_block(mp, bp, btnum, 0, 0, sc->sa.agno); in xrep_init_btblock()
360 xfs_trans_log_buf(tp, bp, 0, BBTOB(bp->b_length) - 1); in xrep_init_btblock()
361 bp->b_ops = ops; in xrep_init_btblock()
368 * Reconstructing per-AG Btrees
381 * derive the blocks that were used by the old btree. These blocks can be
389 * result (since the rmapbt lives in the free space) are the blocks from the
392 * Disposal of Blocks from Old per-AG Btrees
395 * to dispose of the blocks that (we think) the old btree was using.
398 * blocks with the same rmap owner that are owned by another data structure
400 * remaining in bitmap are the old btree's blocks.
403 * blocks on disk. The rmap data can tell us if there are multiple owners, so
410 * will be rebuilt (atop different blocks), thereby removing all the cross
433 * Invalidate buffers for per-AG btree blocks we're dumping. This function
450 * at a time. Avoid invalidating AG headers and post-EOFS blocks in xrep_invalidate_blocks()
455 /* Skip AG headers and post-EOFS blocks */ in xrep_invalidate_blocks()
456 if (!xfs_verify_fsbno(sc->mp, fsbno)) in xrep_invalidate_blocks()
458 bp = xfs_buf_incore(sc->mp->m_ddev_targp, in xrep_invalidate_blocks()
459 XFS_FSB_TO_DADDR(sc->mp, fsbno), in xrep_invalidate_blocks()
460 XFS_FSB_TO_BB(sc->mp, 1), XBF_TRYLOCK); in xrep_invalidate_blocks()
462 xfs_trans_bjoin(sc->tp, bp); in xrep_invalidate_blocks()
463 xfs_trans_binval(sc->tp, bp); in xrep_invalidate_blocks()
478 args.mp = sc->mp; in xrep_fix_freelist()
479 args.tp = sc->tp; in xrep_fix_freelist()
480 args.agno = sc->sa.agno; in xrep_fix_freelist()
482 args.pag = sc->sa.pag; in xrep_fix_freelist()
508 error = xfs_rmap_alloc(sc->tp, sc->sa.agf_bp, sc->sa.agno, agbno, 1, in xrep_put_freelist()
514 error = xfs_alloc_put_freelist(sc->tp, sc->sa.agf_bp, sc->sa.agfl_bp, in xrep_put_freelist()
518 xfs_extent_busy_insert(sc->tp, sc->sa.agno, agbno, 1, in xrep_put_freelist()
539 agno = XFS_FSB_TO_AGNO(sc->mp, fsbno); in xrep_reap_block()
540 agbno = XFS_FSB_TO_AGBNO(sc->mp, fsbno); in xrep_reap_block()
543 * If we are repairing per-inode metadata, we need to read in the AGF in xrep_reap_block()
544 * buffer. Otherwise, we're repairing a per-AG structure, so reuse in xrep_reap_block()
547 if (sc->ip) { in xrep_reap_block()
548 error = xfs_alloc_read_agf(sc->mp, sc->tp, agno, 0, &agf_bp); in xrep_reap_block()
552 agf_bp = sc->sa.agf_bp; in xrep_reap_block()
554 cur = xfs_rmapbt_init_cursor(sc->mp, sc->tp, agf_bp, agno); in xrep_reap_block()
569 * metadata structure is crosslinked with a multi-block structure in xrep_reap_block()
576 error = xfs_rmap_free(sc->tp, agf_bp, agno, agbno, 1, oinfo); in xrep_reap_block()
580 error = xfs_free_extent(sc->tp, fsbno, 1, oinfo, resv); in xrep_reap_block()
581 if (agf_bp != sc->sa.agf_bp) in xrep_reap_block()
582 xfs_trans_brelse(sc->tp, agf_bp); in xrep_reap_block()
586 if (sc->ip) in xrep_reap_block()
587 return xfs_trans_roll_inode(&sc->tp, sc->ip); in xrep_reap_block()
591 if (agf_bp != sc->sa.agf_bp) in xrep_reap_block()
592 xfs_trans_brelse(sc->tp, agf_bp); in xrep_reap_block()
609 ASSERT(xfs_sb_version_hasrmapbt(&sc->mp->m_sb)); in xrep_reap_extents()
612 ASSERT(sc->ip != NULL || in xrep_reap_extents()
613 XFS_FSB_TO_AGNO(sc->mp, fsbno) == sc->sa.agno); in xrep_reap_extents()
614 trace_xrep_dispose_btree_extent(sc->mp, in xrep_reap_extents()
615 XFS_FSB_TO_AGNO(sc->mp, fsbno), in xrep_reap_extents()
616 XFS_FSB_TO_AGBNO(sc->mp, fsbno), 1); in xrep_reap_extents()
627 * Finding per-AG Btree Roots for AGF/AGI Reconstruction
669 return (*agbno == bno) ? -ECANCELED : 0; in xrep_findroot_agfl_walk()
681 struct xfs_mount *mp = ri->sc->mp; in xrep_findroot_block()
688 daddr = XFS_AGB_TO_DADDR(mp, ri->sc->sa.agno, agbno); in xrep_findroot_block()
691 * Blocks in the AGFL have stale contents that might just happen to in xrep_findroot_block()
692 * have a matching magic and uuid. We don't want to pull these blocks in xrep_findroot_block()
697 error = xfs_agfl_walk(mp, ri->agf, ri->agfl_bp, in xrep_findroot_block()
699 if (error == -ECANCELED) in xrep_findroot_block()
723 error = xfs_trans_read_buf(mp, ri->sc->tp, mp->m_ddev_targp, daddr, in xrep_findroot_block()
724 mp->m_bsize, 0, &bp, NULL); in xrep_findroot_block()
730 ASSERT(fab->buf_ops->magic[1] != 0); in xrep_findroot_block()
731 if (btblock->bb_magic != fab->buf_ops->magic[1]) in xrep_findroot_block()
748 if (bp->b_ops) { in xrep_findroot_block()
749 if (bp->b_ops != fab->buf_ops) in xrep_findroot_block()
753 if (!uuid_equal(&btblock->bb_u.s.bb_uuid, in xrep_findroot_block()
754 &mp->m_sb.sb_meta_uuid)) in xrep_findroot_block()
761 bp->b_ops = fab->buf_ops; in xrep_findroot_block()
762 fab->buf_ops->verify_read(bp); in xrep_findroot_block()
763 if (bp->b_error) { in xrep_findroot_block()
764 bp->b_ops = NULL; in xrep_findroot_block()
765 bp->b_error = 0; in xrep_findroot_block()
786 * blocks because there can't be two candidate roots. in xrep_findroot_block()
792 if (block_level + 1 == fab->height) { in xrep_findroot_block()
793 fab->root = NULLAGBLOCK; in xrep_findroot_block()
795 } else if (block_level < fab->height) { in xrep_findroot_block()
804 fab->height = block_level + 1; in xrep_findroot_block()
811 if (btblock->bb_u.s.bb_leftsib == cpu_to_be32(NULLAGBLOCK) && in xrep_findroot_block()
812 btblock->bb_u.s.bb_rightsib == cpu_to_be32(NULLAGBLOCK)) in xrep_findroot_block()
813 fab->root = agbno; in xrep_findroot_block()
815 fab->root = NULLAGBLOCK; in xrep_findroot_block()
817 trace_xrep_findroot_block(mp, ri->sc->sa.agno, agbno, in xrep_findroot_block()
818 be32_to_cpu(btblock->bb_magic), fab->height - 1); in xrep_findroot_block()
820 xfs_trans_brelse(ri->sc->tp, bp); in xrep_findroot_block()
825 * Do any of the blocks in this rmap record match one of the btrees we're
841 if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner)) in xrep_findroot_rmap()
845 for (b = 0; b < rec->rm_blockcount; b++) { in xrep_findroot_rmap()
847 for (fab = ri->btree_info; fab->buf_ops; fab++) { in xrep_findroot_rmap()
848 if (rec->rm_owner != fab->rmap_owner) in xrep_findroot_rmap()
851 rec->rm_owner, rec->rm_startblock + b, in xrep_findroot_rmap()
863 /* Find the roots of the per-AG btrees described in btree_info. */
871 struct xfs_mount *mp = sc->mp; in xrep_find_ag_btree_roots()
882 ri.agf = agf_bp->b_addr; in xrep_find_ag_btree_roots()
884 for (fab = btree_info; fab->buf_ops; fab++) { in xrep_find_ag_btree_roots()
885 ASSERT(agfl_bp || fab->rmap_owner != XFS_RMAP_OWN_AG); in xrep_find_ag_btree_roots()
886 ASSERT(XFS_RMAP_NON_INODE_OWNER(fab->rmap_owner)); in xrep_find_ag_btree_roots()
887 fab->root = NULLAGBLOCK; in xrep_find_ag_btree_roots()
888 fab->height = 0; in xrep_find_ag_btree_roots()
891 cur = xfs_rmapbt_init_cursor(mp, sc->tp, agf_bp, sc->sa.agno); in xrep_find_ag_btree_roots()
907 if (!(flag & sc->mp->m_qflags)) in xrep_force_quotacheck()
910 sc->mp->m_qflags &= ~flag; in xrep_force_quotacheck()
911 spin_lock(&sc->mp->m_sb_lock); in xrep_force_quotacheck()
912 sc->mp->m_sb.sb_qflags &= ~flag; in xrep_force_quotacheck()
913 spin_unlock(&sc->mp->m_sb_lock); in xrep_force_quotacheck()
914 xfs_log_sb(sc->tp); in xrep_force_quotacheck()
921 * We cannot allow the dquot code to allocate an on-disk dquot block here
923 * on-disk dquot should already exist anyway. If the quota code signals
933 error = xfs_qm_dqattach_locked(sc->ip, false); in xrep_ino_dqattach()
935 case -EFSBADCRC: in xrep_ino_dqattach()
936 case -EFSCORRUPTED: in xrep_ino_dqattach()
937 case -ENOENT: in xrep_ino_dqattach()
938 xfs_err_ratelimited(sc->mp, in xrep_ino_dqattach()
940 (unsigned long long)sc->ip->i_ino, error); in xrep_ino_dqattach()
941 if (XFS_IS_UQUOTA_ON(sc->mp) && !sc->ip->i_udquot) in xrep_ino_dqattach()
943 if (XFS_IS_GQUOTA_ON(sc->mp) && !sc->ip->i_gdquot) in xrep_ino_dqattach()
945 if (XFS_IS_PQUOTA_ON(sc->mp) && !sc->ip->i_pdquot) in xrep_ino_dqattach()
948 case -ESRCH: in xrep_ino_dqattach()