Lines Matching +full:scrubber +full:- +full:done

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2017-2023 Oracle. All Rights Reserved.
69 /* Fixed-size array of xchk_dirent structures. */
93 struct xfs_mount *mp = sc->mp; in xchk_dir_check_ftype()
101 if (xfs_mode_to_ftype(VFS_I(ip)->i_mode) != ftype) in xchk_dir_check_ftype()
109 if (xfs_is_metadir_inode(ip) != xfs_is_metadir_inode(sc->ip)) in xchk_dir_check_ftype()
130 if (!xfs_inode_has_attr_fork(ip) || !xfs_need_iread_extents(&ip->i_af)) in xchk_dir_lock_child()
150 struct xfs_scrub *sc = sd->sc; in xchk_dir_parent_pointer()
153 xfs_inode_to_parent_rec(&sd->pptr_rec, sc->ip); in xchk_dir_parent_pointer()
154 error = xfs_parent_lookup(sc->tp, ip, name, &sd->pptr_rec, in xchk_dir_parent_pointer()
155 &sd->pptr_args); in xchk_dir_parent_pointer()
156 if (error == -ENOATTR) in xchk_dir_parent_pointer()
170 struct xfs_scrub *sc = sd->sc; in xchk_dir_check_pptr_fast()
179 /* No self-referential non-dot or dotdot dirents. */ in xchk_dir_check_pptr_fast()
180 if (ip == sc->ip) { in xchk_dir_check_pptr_fast()
182 return -ECANCELED; in xchk_dir_check_pptr_fast()
189 .namelen = name->len, in xchk_dir_check_pptr_fast()
190 .ino = ip->i_ino, in xchk_dir_check_pptr_fast()
194 trace_xchk_dir_defer(sc->ip, name, ip->i_ino); in xchk_dir_check_pptr_fast()
196 error = xfblob_storename(sd->dir_names, &save_de.name_cookie, in xchk_dir_check_pptr_fast()
202 error = xfarray_append(sd->dir_entries, &save_de); in xchk_dir_check_pptr_fast()
230 struct xfs_mount *mp = dp->i_mount; in xchk_dir_actor()
237 offset = xfs_dir2_db_to_da(mp->m_dir_geo, in xchk_dir_actor()
238 xfs_dir2_dataptr_to_db(mp->m_dir_geo, dapos)); in xchk_dir_actor()
246 return -ECANCELED; in xchk_dir_actor()
250 if (!xfs_dir2_namecheck(name->name, name->len)) { in xchk_dir_actor()
252 return -ECANCELED; in xchk_dir_actor()
257 if (ino != dp->i_ino) in xchk_dir_actor()
264 if (xchk_inode_is_dirtree_root(dp) && ino != dp->i_ino) in xchk_dir_actor()
271 if (error == -ENOENT) in xchk_dir_actor()
272 error = -EFSCORRUPTED; in xchk_dir_actor()
277 return -ECANCELED; in xchk_dir_actor()
284 * If _iget returns -EINVAL or -ENOENT then the child inode number is in xchk_dir_actor()
286 * -EFSCORRUPTED or -EFSBADCRC then the child is corrupt which is a in xchk_dir_actor()
290 if (error == -EINVAL || error == -ENOENT) { in xchk_dir_actor()
291 error = -EFSCORRUPTED; in xchk_dir_actor()
298 xchk_dir_check_ftype(sc, offset, ip, name->type); in xchk_dir_actor()
309 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) in xchk_dir_actor()
310 return -ECANCELED; in xchk_dir_actor()
321 struct xfs_da_state_blk *blk = &ds->state->path.blk[level]; in xchk_dir_rec()
322 struct xfs_mount *mp = ds->state->mp; in xchk_dir_rec()
323 struct xfs_inode *dp = ds->dargs.dp; in xchk_dir_rec()
324 struct xfs_da_geometry *geo = mp->m_dir_geo; in xchk_dir_rec()
341 ASSERT(blk->magic == XFS_DIR2_LEAF1_MAGIC || in xchk_dir_rec()
342 blk->magic == XFS_DIR2_LEAFN_MAGIC); in xchk_dir_rec()
344 xfs_dir2_leaf_hdr_from_disk(mp, &hdr, blk->bp->b_addr); in xchk_dir_rec()
345 ent = hdr.ents + blk->index; in xchk_dir_rec()
348 error = xchk_da_btree_hash(ds, level, &ent->hashval); in xchk_dir_rec()
353 ptr = be32_to_cpu(ent->address); in xchk_dir_rec()
362 if (rec_bno >= geo->leafblk) { in xchk_dir_rec()
366 error = xfs_dir3_data_read(ds->dargs.trans, dp, ds->dargs.owner, in xchk_dir_rec()
368 if (!xchk_fblock_process_error(ds->sc, XFS_DATA_FORK, rec_bno, in xchk_dir_rec()
372 xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno); in xchk_dir_rec()
375 xchk_buffer_recheck(ds->sc, bp); in xchk_dir_rec()
377 if (ds->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) in xchk_dir_rec()
380 dent = bp->b_addr + off; in xchk_dir_rec()
383 iter_off = geo->data_entry_offset; in xchk_dir_rec()
384 end = xfs_dir3_data_end_offset(geo, bp->b_addr); in xchk_dir_rec()
386 xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno); in xchk_dir_rec()
390 struct xfs_dir2_data_entry *dep = bp->b_addr + iter_off; in xchk_dir_rec()
391 struct xfs_dir2_data_unused *dup = bp->b_addr + iter_off; in xchk_dir_rec()
394 xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno); in xchk_dir_rec()
398 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { in xchk_dir_rec()
399 iter_off += be16_to_cpu(dup->length); in xchk_dir_rec()
404 iter_off += xfs_dir2_data_entsize(mp, dep->namelen); in xchk_dir_rec()
408 ino = be64_to_cpu(dent->inumber); in xchk_dir_rec()
409 hash = be32_to_cpu(ent->hashval); in xchk_dir_rec()
412 xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno); in xchk_dir_rec()
413 if (dent->namelen == 0) { in xchk_dir_rec()
414 xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno); in xchk_dir_rec()
419 dname.name = dent->name; in xchk_dir_rec()
420 dname.len = dent->namelen; in xchk_dir_rec()
423 xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno); in xchk_dir_rec()
426 xfs_trans_brelse(ds->dargs.trans, bp); in xchk_dir_rec()
446 dup_length = be16_to_cpu(dup->length); in xchk_directory_check_free_entry()
449 if (dup_length < be16_to_cpu(bf[XFS_DIR2_DATA_FD_COUNT - 1].length)) in xchk_directory_check_free_entry()
452 for (dfp = &bf[XFS_DIR2_DATA_FD_COUNT - 1]; dfp >= bf; dfp--) in xchk_directory_check_free_entry()
453 if (dup_length == be16_to_cpu(dfp->length)) in xchk_directory_check_free_entry()
471 struct xfs_mount *mp = sc->mp; in xchk_directory_data_bestfree()
485 error = xfs_dir3_block_read(sc->tp, sc->ip, sc->ip->i_ino, &bp); in xchk_directory_data_bestfree()
488 error = xfs_dir3_data_read(sc->tp, sc->ip, sc->ip->i_ino, lblk, in xchk_directory_data_bestfree()
497 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) in xchk_directory_data_bestfree()
501 bf = xfs_dir2_data_bestfree_p(mp, bp->b_addr); in xchk_directory_data_bestfree()
504 offset = be16_to_cpu(dfp->offset); in xchk_directory_data_bestfree()
507 if (offset >= mp->m_dir_geo->blksize) { in xchk_directory_data_bestfree()
511 dup = bp->b_addr + offset; in xchk_directory_data_bestfree()
515 if (dup->freetag != cpu_to_be16(XFS_DIR2_DATA_FREE_TAG) || in xchk_directory_data_bestfree()
516 be16_to_cpu(dup->length) != be16_to_cpu(dfp->length) || in xchk_directory_data_bestfree()
523 if (smallest_bestfree < be16_to_cpu(dfp->length)) { in xchk_directory_data_bestfree()
528 smallest_bestfree = be16_to_cpu(dfp->length); in xchk_directory_data_bestfree()
533 offset = mp->m_dir_geo->data_entry_offset; in xchk_directory_data_bestfree()
534 end = xfs_dir3_data_end_offset(mp->m_dir_geo, bp->b_addr); in xchk_directory_data_bestfree()
538 dup = bp->b_addr + offset; in xchk_directory_data_bestfree()
541 if (dup->freetag != cpu_to_be16(XFS_DIR2_DATA_FREE_TAG)) { in xchk_directory_data_bestfree()
542 struct xfs_dir2_data_entry *dep = bp->b_addr + offset; in xchk_directory_data_bestfree()
544 newlen = xfs_dir2_data_entsize(mp, dep->namelen); in xchk_directory_data_bestfree()
566 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) in xchk_directory_data_bestfree()
570 newlen = be16_to_cpu(dup->length); in xchk_directory_data_bestfree()
588 xfs_trans_brelse(sc->tp, bp); in xchk_directory_data_bestfree()
608 dfp = xfs_dir2_data_bestfree_p(sc->mp, dbp->b_addr); in xchk_directory_check_freesp()
610 if (len != be16_to_cpu(dfp->length)) in xchk_directory_check_freesp()
613 if (len > 0 && be16_to_cpu(dfp->offset) == 0) in xchk_directory_check_freesp()
630 struct xfs_da_geometry *geo = sc->mp->m_dir_geo; in xchk_directory_leaf1_bestfree()
641 error = xfs_dir3_leaf_read(sc->tp, sc->ip, sc->ip->i_ino, lblk, &bp); in xchk_directory_leaf1_bestfree()
646 leaf = bp->b_addr; in xchk_directory_leaf1_bestfree()
647 xfs_dir2_leaf_hdr_from_disk(sc->ip->i_mount, &leafhdr, leaf); in xchk_directory_leaf1_bestfree()
649 bestcount = be32_to_cpu(ltp->bestcount); in xchk_directory_leaf1_bestfree()
652 if (xfs_has_crc(sc->mp)) { in xchk_directory_leaf1_bestfree()
653 struct xfs_dir3_leaf_hdr *hdr3 = bp->b_addr; in xchk_directory_leaf1_bestfree()
655 if (hdr3->pad != cpu_to_be32(0)) in xchk_directory_leaf1_bestfree()
673 if (leafhdr.count > geo->leaf_max_ents) { in xchk_directory_leaf1_bestfree()
696 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) in xchk_directory_leaf1_bestfree()
702 error = xfs_dir3_data_read(sc->tp, sc->ip, args->owner, in xchk_directory_leaf1_bestfree()
703 xfs_dir2_db_to_da(args->geo, i), in xchk_directory_leaf1_bestfree()
722 xfs_trans_brelse(sc->tp, dbp); in xchk_directory_leaf1_bestfree()
723 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) in xchk_directory_leaf1_bestfree()
727 xfs_trans_brelse(sc->tp, bp); in xchk_directory_leaf1_bestfree()
747 error = xfs_dir2_free_read(sc->tp, sc->ip, sc->ip->i_ino, lblk, &bp); in xchk_directory_free_bestfree()
752 if (xfs_has_crc(sc->mp)) { in xchk_directory_free_bestfree()
753 struct xfs_dir3_free_hdr *hdr3 = bp->b_addr; in xchk_directory_free_bestfree()
755 if (hdr3->pad != cpu_to_be32(0)) in xchk_directory_free_bestfree()
760 xfs_dir2_free_hdr_from_disk(sc->ip->i_mount, &freehdr, bp->b_addr); in xchk_directory_free_bestfree()
767 error = xfs_dir3_data_read(sc->tp, sc->ip, args->owner, in xchk_directory_free_bestfree()
768 (freehdr.firstdb + i) * args->geo->fsbcount, in xchk_directory_free_bestfree()
774 xfs_trans_brelse(sc->tp, dbp); in xchk_directory_free_bestfree()
780 xfs_trans_brelse(sc->tp, bp); in xchk_directory_free_bestfree()
791 .dp = sc->ip, in xchk_directory_blocks()
793 .geo = sc->mp->m_dir_geo, in xchk_directory_blocks()
794 .trans = sc->tp, in xchk_directory_blocks()
795 .owner = sc->ip->i_ino, in xchk_directory_blocks()
797 struct xfs_ifork *ifp = xfs_ifork_ptr(sc->ip, XFS_DATA_FORK); in xchk_directory_blocks()
798 struct xfs_mount *mp = sc->mp; in xchk_directory_blocks()
810 if (ifp->if_format != XFS_DINODE_FMT_EXTENTS && in xchk_directory_blocks()
811 ifp->if_format != XFS_DINODE_FMT_BTREE) in xchk_directory_blocks()
825 found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got); in xchk_directory_blocks()
826 while (found && !(sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) { in xchk_directory_blocks()
834 * Iterate all the fsbcount-aligned block offsets in in xchk_directory_blocks()
837 * discontiguous directory blocks. When we're done in xchk_directory_blocks()
838 * with the extent record, re-query the bmap at the in xchk_directory_blocks()
839 * next fsbcount-aligned offset to avoid redundant in xchk_directory_blocks()
843 args.geo->fsbcount); in xchk_directory_blocks()
845 lblk += args.geo->fsbcount) { in xchk_directory_blocks()
853 lblk = roundup(dabno, args.geo->fsbcount); in xchk_directory_blocks()
854 found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got); in xchk_directory_blocks()
857 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) in xchk_directory_blocks()
861 if (xfs_iext_lookup_extent(sc->ip, ifp, leaf_lblk, &icur, &got) && in xchk_directory_blocks()
863 got.br_blockcount == args.geo->fsbcount && in xchk_directory_blocks()
875 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) in xchk_directory_blocks()
880 found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got); in xchk_directory_blocks()
881 while (found && !(sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) { in xchk_directory_blocks()
884 * Single-block dirs shouldn't even be here. in xchk_directory_blocks()
899 * Iterate all the fsbcount-aligned block offsets in in xchk_directory_blocks()
902 * discontiguous directory blocks. When we're done in xchk_directory_blocks()
903 * with the extent record, re-query the bmap at the in xchk_directory_blocks()
904 * next fsbcount-aligned offset to avoid redundant in xchk_directory_blocks()
908 args.geo->fsbcount); in xchk_directory_blocks()
910 lblk += args.geo->fsbcount) { in xchk_directory_blocks()
917 lblk = roundup(dabno, args.geo->fsbcount); in xchk_directory_blocks()
918 found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got); in xchk_directory_blocks()
926 * of lock contention. Returns 0 if the dirent is still valid, -ENOENT if it
935 struct xfs_scrub *sc = sd->sc; in xchk_dir_revalidate_dirent()
940 * Look up the directory entry. If we get -ENOENT, the directory entry in xchk_dir_revalidate_dirent()
944 error = xchk_dir_lookup(sc, sc->ip, xname, &child_ino); in xchk_dir_revalidate_dirent()
950 return -ENOENT; in xchk_dir_revalidate_dirent()
957 * locks a bunch and put up with revalidation until we get it done.
965 struct xfs_scrub *sc = sd->sc; in xchk_dir_slow_dirent()
971 if (sd->need_revalidate) { in xchk_dir_slow_dirent()
972 error = xchk_dir_revalidate_dirent(sd, xname, dirent->ino); in xchk_dir_slow_dirent()
973 if (error == -ENOENT) in xchk_dir_slow_dirent()
980 error = xchk_iget(sc, dirent->ino, &ip); in xchk_dir_slow_dirent()
981 if (error == -EINVAL || error == -ENOENT) { in xchk_dir_slow_dirent()
994 trace_xchk_dir_slowpath(sc->ip, xname, ip->i_ino); in xchk_dir_slow_dirent()
1002 xchk_iunlock(sc, sc->ilock_flags); in xchk_dir_slow_dirent()
1003 sd->need_revalidate = true; in xchk_dir_slow_dirent()
1005 trace_xchk_dir_ultraslowpath(sc->ip, xname, ip->i_ino); in xchk_dir_slow_dirent()
1012 error = xchk_dir_revalidate_dirent(sd, xname, dirent->ino); in xchk_dir_slow_dirent()
1013 if (error == -ENOENT) { in xchk_dir_slow_dirent()
1037 foreach_xfarray_idx(sd->dir_entries, array_cur) { in xchk_dir_finish_slow_dirents()
1040 if (sd->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) in xchk_dir_finish_slow_dirents()
1043 error = xfarray_load(sd->dir_entries, array_cur, &dirent); in xchk_dir_finish_slow_dirents()
1047 error = xfblob_loadname(sd->dir_names, dirent.name_cookie, in xchk_dir_finish_slow_dirents()
1048 &sd->xname, dirent.namelen); in xchk_dir_finish_slow_dirents()
1052 error = xchk_dir_slow_dirent(sd, &dirent, &sd->xname); in xchk_dir_finish_slow_dirents()
1068 if (!S_ISDIR(VFS_I(sc->ip)->i_mode)) in xchk_directory()
1069 return -ENOENT; in xchk_directory()
1077 if (sc->ip->i_disk_size < xfs_dir2_sf_hdr_size(0)) { in xchk_directory()
1078 xchk_ino_set_corrupt(sc, sc->ip->i_ino); in xchk_directory()
1087 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) in xchk_directory()
1095 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) in xchk_directory()
1100 return -ENOMEM; in xchk_directory()
1101 sd->sc = sc; in xchk_directory()
1102 sd->xname.name = sd->namebuf; in xchk_directory()
1104 if (xfs_has_parent(sc->mp)) { in xchk_directory()
1113 &sd->dir_entries); in xchk_directory()
1119 error = xfblob_create(descr, &sd->dir_names); in xchk_directory()
1126 error = xchk_dir_walk(sc, sc->ip, xchk_dir_actor, sd); in xchk_directory()
1127 if (error == -ECANCELED) in xchk_directory()
1132 if (xfs_has_parent(sc->mp)) { in xchk_directory()
1134 if (error == -ETIMEDOUT) { in xchk_directory()
1144 if (sd->dir_names) in xchk_directory()
1145 xfblob_destroy(sd->dir_names); in xchk_directory()
1147 if (sd->dir_entries) in xchk_directory()
1148 xfarray_destroy(sd->dir_entries); in xchk_directory()
1175 * scrubber to reconstruct the block mappings. Directories always in xchk_dir_looks_zapped()
1181 return dp->i_df.if_format == XFS_DINODE_FMT_EXTENTS && in xchk_dir_looks_zapped()
1182 dp->i_df.if_nextents == 0; in xchk_dir_looks_zapped()