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

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. */
90 struct xfs_inode *ip, in xchk_dir_check_ftype() argument
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()
112 struct xfs_inode *ip) in xchk_dir_lock_child() argument
114 if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) in xchk_dir_lock_child()
117 if (!xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) { in xchk_dir_lock_child()
118 xfs_iunlock(ip, XFS_IOLOCK_SHARED); in xchk_dir_lock_child()
122 if (!xfs_inode_has_attr_fork(ip) || !xfs_need_iread_extents(&ip->i_af)) in xchk_dir_lock_child()
125 xfs_iunlock(ip, XFS_ILOCK_SHARED); in xchk_dir_lock_child()
127 if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) { in xchk_dir_lock_child()
128 xfs_iunlock(ip, XFS_IOLOCK_SHARED); in xchk_dir_lock_child()
140 struct xfs_inode *ip) in xchk_dir_parent_pointer() argument
142 struct xfs_scrub *sc = sd->sc; in xchk_dir_parent_pointer()
145 xfs_inode_to_parent_rec(&sd->pptr_rec, sc->ip); in xchk_dir_parent_pointer()
146 error = xfs_parent_lookup(sc->tp, ip, name, &sd->pptr_rec, in xchk_dir_parent_pointer()
147 &sd->pptr_args); in xchk_dir_parent_pointer()
148 if (error == -ENOATTR) in xchk_dir_parent_pointer()
160 struct xfs_inode *ip) in xchk_dir_check_pptr_fast() argument
162 struct xfs_scrub *sc = sd->sc; in xchk_dir_check_pptr_fast()
171 /* No self-referential non-dot or dotdot dirents. */ in xchk_dir_check_pptr_fast()
172 if (ip == sc->ip) { in xchk_dir_check_pptr_fast()
174 return -ECANCELED; in xchk_dir_check_pptr_fast()
178 lockmode = xchk_dir_lock_child(sc, ip); in xchk_dir_check_pptr_fast()
181 .namelen = name->len, in xchk_dir_check_pptr_fast()
182 .ino = ip->i_ino, in xchk_dir_check_pptr_fast()
186 trace_xchk_dir_defer(sc->ip, name, ip->i_ino); in xchk_dir_check_pptr_fast()
188 error = xfblob_storename(sd->dir_names, &save_de.name_cookie, in xchk_dir_check_pptr_fast()
194 error = xfarray_append(sd->dir_entries, &save_de); in xchk_dir_check_pptr_fast()
202 error = xchk_dir_parent_pointer(sd, name, ip); in xchk_dir_check_pptr_fast()
203 xfs_iunlock(ip, lockmode); in xchk_dir_check_pptr_fast()
222 struct xfs_mount *mp = dp->i_mount; in xchk_dir_actor()
223 struct xfs_inode *ip; in xchk_dir_actor() local
229 offset = xfs_dir2_db_to_da(mp->m_dir_geo, in xchk_dir_actor()
230 xfs_dir2_dataptr_to_db(mp->m_dir_geo, dapos)); in xchk_dir_actor()
238 return -ECANCELED; in xchk_dir_actor()
242 if (!xfs_dir2_namecheck(name->name, name->len)) { in xchk_dir_actor()
244 return -ECANCELED; in xchk_dir_actor()
249 if (ino != dp->i_ino) in xchk_dir_actor()
256 if (dp->i_ino == mp->m_sb.sb_rootino && ino != dp->i_ino) in xchk_dir_actor()
263 if (error == -ENOENT) in xchk_dir_actor()
264 error = -EFSCORRUPTED; in xchk_dir_actor()
269 return -ECANCELED; in xchk_dir_actor()
276 * If _iget returns -EINVAL or -ENOENT then the child inode number is in xchk_dir_actor()
278 * -EFSCORRUPTED or -EFSBADCRC then the child is corrupt which is a in xchk_dir_actor()
281 error = xchk_iget(sc, ino, &ip); in xchk_dir_actor()
282 if (error == -EINVAL || error == -ENOENT) { in xchk_dir_actor()
283 error = -EFSCORRUPTED; in xchk_dir_actor()
290 xchk_dir_check_ftype(sc, offset, ip, name->type); in xchk_dir_actor()
293 error = xchk_dir_check_pptr_fast(sd, dapos, name, ip); in xchk_dir_actor()
299 xchk_irele(sc, ip); in xchk_dir_actor()
301 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) in xchk_dir_actor()
302 return -ECANCELED; in xchk_dir_actor()
313 struct xfs_da_state_blk *blk = &ds->state->path.blk[level]; in xchk_dir_rec()
314 struct xfs_mount *mp = ds->state->mp; in xchk_dir_rec()
315 struct xfs_inode *dp = ds->dargs.dp; in xchk_dir_rec()
316 struct xfs_da_geometry *geo = mp->m_dir_geo; in xchk_dir_rec()
333 ASSERT(blk->magic == XFS_DIR2_LEAF1_MAGIC || in xchk_dir_rec()
334 blk->magic == XFS_DIR2_LEAFN_MAGIC); in xchk_dir_rec()
336 xfs_dir2_leaf_hdr_from_disk(mp, &hdr, blk->bp->b_addr); in xchk_dir_rec()
337 ent = hdr.ents + blk->index; in xchk_dir_rec()
340 error = xchk_da_btree_hash(ds, level, &ent->hashval); in xchk_dir_rec()
345 ptr = be32_to_cpu(ent->address); in xchk_dir_rec()
354 if (rec_bno >= geo->leafblk) { in xchk_dir_rec()
358 error = xfs_dir3_data_read(ds->dargs.trans, dp, ds->dargs.owner, in xchk_dir_rec()
360 if (!xchk_fblock_process_error(ds->sc, XFS_DATA_FORK, rec_bno, in xchk_dir_rec()
364 xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno); in xchk_dir_rec()
367 xchk_buffer_recheck(ds->sc, bp); in xchk_dir_rec()
369 if (ds->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) in xchk_dir_rec()
372 dent = bp->b_addr + off; in xchk_dir_rec()
375 iter_off = geo->data_entry_offset; in xchk_dir_rec()
376 end = xfs_dir3_data_end_offset(geo, bp->b_addr); in xchk_dir_rec()
378 xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno); in xchk_dir_rec()
382 struct xfs_dir2_data_entry *dep = bp->b_addr + iter_off; in xchk_dir_rec()
383 struct xfs_dir2_data_unused *dup = bp->b_addr + iter_off; in xchk_dir_rec()
386 xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno); in xchk_dir_rec()
390 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { in xchk_dir_rec()
391 iter_off += be16_to_cpu(dup->length); in xchk_dir_rec()
396 iter_off += xfs_dir2_data_entsize(mp, dep->namelen); in xchk_dir_rec()
400 ino = be64_to_cpu(dent->inumber); in xchk_dir_rec()
401 hash = be32_to_cpu(ent->hashval); in xchk_dir_rec()
404 xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno); in xchk_dir_rec()
405 if (dent->namelen == 0) { in xchk_dir_rec()
406 xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno); in xchk_dir_rec()
411 dname.name = dent->name; in xchk_dir_rec()
412 dname.len = dent->namelen; in xchk_dir_rec()
415 xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno); in xchk_dir_rec()
418 xfs_trans_brelse(ds->dargs.trans, bp); in xchk_dir_rec()
438 dup_length = be16_to_cpu(dup->length); in xchk_directory_check_free_entry()
441 if (dup_length < be16_to_cpu(bf[XFS_DIR2_DATA_FD_COUNT - 1].length)) in xchk_directory_check_free_entry()
444 for (dfp = &bf[XFS_DIR2_DATA_FD_COUNT - 1]; dfp >= bf; dfp--) in xchk_directory_check_free_entry()
445 if (dup_length == be16_to_cpu(dfp->length)) in xchk_directory_check_free_entry()
452 /* Check free space info in a directory data block. */
463 struct xfs_mount *mp = sc->mp; in xchk_directory_data_bestfree()
474 /* dir block format */ in xchk_directory_data_bestfree()
477 error = xfs_dir3_block_read(sc->tp, sc->ip, sc->ip->i_ino, &bp); in xchk_directory_data_bestfree()
480 error = xfs_dir3_data_read(sc->tp, sc->ip, sc->ip->i_ino, lblk, in xchk_directory_data_bestfree()
489 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) in xchk_directory_data_bestfree()
493 bf = xfs_dir2_data_bestfree_p(mp, bp->b_addr); in xchk_directory_data_bestfree()
496 offset = be16_to_cpu(dfp->offset); in xchk_directory_data_bestfree()
499 if (offset >= mp->m_dir_geo->blksize) { in xchk_directory_data_bestfree()
503 dup = bp->b_addr + offset; in xchk_directory_data_bestfree()
507 if (dup->freetag != cpu_to_be16(XFS_DIR2_DATA_FREE_TAG) || in xchk_directory_data_bestfree()
508 be16_to_cpu(dup->length) != be16_to_cpu(dfp->length) || in xchk_directory_data_bestfree()
515 if (smallest_bestfree < be16_to_cpu(dfp->length)) { in xchk_directory_data_bestfree()
520 smallest_bestfree = be16_to_cpu(dfp->length); in xchk_directory_data_bestfree()
525 offset = mp->m_dir_geo->data_entry_offset; in xchk_directory_data_bestfree()
526 end = xfs_dir3_data_end_offset(mp->m_dir_geo, bp->b_addr); in xchk_directory_data_bestfree()
530 dup = bp->b_addr + offset; in xchk_directory_data_bestfree()
533 if (dup->freetag != cpu_to_be16(XFS_DIR2_DATA_FREE_TAG)) { in xchk_directory_data_bestfree()
534 struct xfs_dir2_data_entry *dep = bp->b_addr + offset; in xchk_directory_data_bestfree()
536 newlen = xfs_dir2_data_entsize(mp, dep->namelen); in xchk_directory_data_bestfree()
558 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) in xchk_directory_data_bestfree()
562 newlen = be16_to_cpu(dup->length); in xchk_directory_data_bestfree()
580 xfs_trans_brelse(sc->tp, bp); in xchk_directory_data_bestfree()
586 * Does the free space length in the free space index block ($len) match
587 * the longest length in the directory data block's bestfree array?
588 * Assume that we've already checked that the data block's bestfree
600 dfp = xfs_dir2_data_bestfree_p(sc->mp, dbp->b_addr); in xchk_directory_check_freesp()
602 if (len != be16_to_cpu(dfp->length)) in xchk_directory_check_freesp()
605 if (len > 0 && be16_to_cpu(dfp->offset) == 0) in xchk_directory_check_freesp()
609 /* Check free space info in a directory leaf1 block. */
622 struct xfs_da_geometry *geo = sc->mp->m_dir_geo; in xchk_directory_leaf1_bestfree()
632 /* Read the free space block. */ in xchk_directory_leaf1_bestfree()
633 error = xfs_dir3_leaf_read(sc->tp, sc->ip, sc->ip->i_ino, lblk, &bp); in xchk_directory_leaf1_bestfree()
638 leaf = bp->b_addr; in xchk_directory_leaf1_bestfree()
639 xfs_dir2_leaf_hdr_from_disk(sc->ip->i_mount, &leafhdr, leaf); in xchk_directory_leaf1_bestfree()
641 bestcount = be32_to_cpu(ltp->bestcount); in xchk_directory_leaf1_bestfree()
644 if (xfs_has_crc(sc->mp)) { in xchk_directory_leaf1_bestfree()
645 struct xfs_dir3_leaf_hdr *hdr3 = bp->b_addr; in xchk_directory_leaf1_bestfree()
647 if (hdr3->pad != cpu_to_be32(0)) in xchk_directory_leaf1_bestfree()
654 * between the last data block and i_disk_size. This seems like an in xchk_directory_leaf1_bestfree()
665 if (leafhdr.count > geo->leaf_max_ents) { in xchk_directory_leaf1_bestfree()
688 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) in xchk_directory_leaf1_bestfree()
694 error = xfs_dir3_data_read(sc->tp, sc->ip, args->owner, in xchk_directory_leaf1_bestfree()
695 xfs_dir2_db_to_da(args->geo, i), in xchk_directory_leaf1_bestfree()
714 xfs_trans_brelse(sc->tp, dbp); in xchk_directory_leaf1_bestfree()
715 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) in xchk_directory_leaf1_bestfree()
719 xfs_trans_brelse(sc->tp, bp); in xchk_directory_leaf1_bestfree()
723 /* Check free space info in a directory freespace block. */
738 /* Read the free space block */ in xchk_directory_free_bestfree()
739 error = xfs_dir2_free_read(sc->tp, sc->ip, sc->ip->i_ino, lblk, &bp); in xchk_directory_free_bestfree()
744 if (xfs_has_crc(sc->mp)) { in xchk_directory_free_bestfree()
745 struct xfs_dir3_free_hdr *hdr3 = bp->b_addr; in xchk_directory_free_bestfree()
747 if (hdr3->pad != cpu_to_be32(0)) in xchk_directory_free_bestfree()
752 xfs_dir2_free_hdr_from_disk(sc->ip->i_mount, &freehdr, bp->b_addr); in xchk_directory_free_bestfree()
759 error = xfs_dir3_data_read(sc->tp, sc->ip, args->owner, in xchk_directory_free_bestfree()
760 (freehdr.firstdb + i) * args->geo->fsbcount, in xchk_directory_free_bestfree()
766 xfs_trans_brelse(sc->tp, dbp); in xchk_directory_free_bestfree()
772 xfs_trans_brelse(sc->tp, bp); in xchk_directory_free_bestfree()
783 .dp = sc->ip, in xchk_directory_blocks()
785 .geo = sc->mp->m_dir_geo, in xchk_directory_blocks()
786 .trans = sc->tp, in xchk_directory_blocks()
787 .owner = sc->ip->i_ino, in xchk_directory_blocks()
789 struct xfs_ifork *ifp = xfs_ifork_ptr(sc->ip, XFS_DATA_FORK); in xchk_directory_blocks()
790 struct xfs_mount *mp = sc->mp; in xchk_directory_blocks()
802 if (ifp->if_format != XFS_DINODE_FMT_EXTENTS && in xchk_directory_blocks()
803 ifp->if_format != XFS_DINODE_FMT_BTREE) in xchk_directory_blocks()
810 /* Is this a block dir? */ in xchk_directory_blocks()
817 found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got); in xchk_directory_blocks()
818 while (found && !(sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) { in xchk_directory_blocks()
824 * Check each data block's bestfree data. in xchk_directory_blocks()
826 * Iterate all the fsbcount-aligned block offsets in in xchk_directory_blocks()
827 * this directory. The directory block reading code is in xchk_directory_blocks()
830 * with the extent record, re-query the bmap at the in xchk_directory_blocks()
831 * next fsbcount-aligned offset to avoid redundant in xchk_directory_blocks()
832 * block checks. in xchk_directory_blocks()
835 args.geo->fsbcount); in xchk_directory_blocks()
837 lblk += args.geo->fsbcount) { in xchk_directory_blocks()
845 lblk = roundup(dabno, args.geo->fsbcount); in xchk_directory_blocks()
846 found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got); in xchk_directory_blocks()
849 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) in xchk_directory_blocks()
852 /* Look for a leaf1 block, which has free info. */ in xchk_directory_blocks()
853 if (xfs_iext_lookup_extent(sc->ip, ifp, leaf_lblk, &icur, &got) && in xchk_directory_blocks()
855 got.br_blockcount == args.geo->fsbcount && in xchk_directory_blocks()
867 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) in xchk_directory_blocks()
872 found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got); in xchk_directory_blocks()
873 while (found && !(sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) { in xchk_directory_blocks()
876 * Single-block dirs shouldn't even be here. in xchk_directory_blocks()
889 * Check each dir free block's bestfree data. in xchk_directory_blocks()
891 * Iterate all the fsbcount-aligned block offsets in in xchk_directory_blocks()
892 * this directory. The directory block reading code is in xchk_directory_blocks()
895 * with the extent record, re-query the bmap at the in xchk_directory_blocks()
896 * next fsbcount-aligned offset to avoid redundant in xchk_directory_blocks()
897 * block checks. in xchk_directory_blocks()
900 args.geo->fsbcount); in xchk_directory_blocks()
902 lblk += args.geo->fsbcount) { in xchk_directory_blocks()
909 lblk = roundup(dabno, args.geo->fsbcount); in xchk_directory_blocks()
910 found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got); in xchk_directory_blocks()
918 * of lock contention. Returns 0 if the dirent is still valid, -ENOENT if it
927 struct xfs_scrub *sc = sd->sc; in xchk_dir_revalidate_dirent()
932 * Look up the directory entry. If we get -ENOENT, the directory entry in xchk_dir_revalidate_dirent()
936 error = xchk_dir_lookup(sc, sc->ip, xname, &child_ino); in xchk_dir_revalidate_dirent()
942 return -ENOENT; in xchk_dir_revalidate_dirent()
957 struct xfs_scrub *sc = sd->sc; in xchk_dir_slow_dirent()
958 struct xfs_inode *ip; in xchk_dir_slow_dirent() local
963 if (sd->need_revalidate) { in xchk_dir_slow_dirent()
964 error = xchk_dir_revalidate_dirent(sd, xname, dirent->ino); in xchk_dir_slow_dirent()
965 if (error == -ENOENT) in xchk_dir_slow_dirent()
972 error = xchk_iget(sc, dirent->ino, &ip); in xchk_dir_slow_dirent()
973 if (error == -EINVAL || error == -ENOENT) { in xchk_dir_slow_dirent()
984 lockmode = xchk_dir_lock_child(sc, ip); in xchk_dir_slow_dirent()
986 trace_xchk_dir_slowpath(sc->ip, xname, ip->i_ino); in xchk_dir_slow_dirent()
994 xchk_iunlock(sc, sc->ilock_flags); in xchk_dir_slow_dirent()
995 sd->need_revalidate = true; in xchk_dir_slow_dirent()
997 trace_xchk_dir_ultraslowpath(sc->ip, xname, ip->i_ino); in xchk_dir_slow_dirent()
999 error = xchk_dir_trylock_for_pptrs(sc, ip, &lockmode); in xchk_dir_slow_dirent()
1004 error = xchk_dir_revalidate_dirent(sd, xname, dirent->ino); in xchk_dir_slow_dirent()
1005 if (error == -ENOENT) { in xchk_dir_slow_dirent()
1013 error = xchk_dir_parent_pointer(sd, xname, ip); in xchk_dir_slow_dirent()
1015 xfs_iunlock(ip, lockmode); in xchk_dir_slow_dirent()
1017 xchk_irele(sc, ip); in xchk_dir_slow_dirent()
1029 foreach_xfarray_idx(sd->dir_entries, array_cur) { in xchk_dir_finish_slow_dirents()
1032 if (sd->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) in xchk_dir_finish_slow_dirents()
1035 error = xfarray_load(sd->dir_entries, array_cur, &dirent); in xchk_dir_finish_slow_dirents()
1039 error = xfblob_loadname(sd->dir_names, dirent.name_cookie, in xchk_dir_finish_slow_dirents()
1040 &sd->xname, dirent.namelen); in xchk_dir_finish_slow_dirents()
1044 error = xchk_dir_slow_dirent(sd, &dirent, &sd->xname); in xchk_dir_finish_slow_dirents()
1060 if (!S_ISDIR(VFS_I(sc->ip)->i_mode)) in xchk_directory()
1061 return -ENOENT; in xchk_directory()
1069 if (sc->ip->i_disk_size < xfs_dir2_sf_hdr_size(0)) { in xchk_directory()
1070 xchk_ino_set_corrupt(sc, sc->ip->i_ino); in xchk_directory()
1079 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) in xchk_directory()
1087 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) in xchk_directory()
1092 return -ENOMEM; in xchk_directory()
1093 sd->sc = sc; in xchk_directory()
1094 sd->xname.name = sd->namebuf; in xchk_directory()
1096 if (xfs_has_parent(sc->mp)) { in xchk_directory()
1105 &sd->dir_entries); in xchk_directory()
1111 error = xfblob_create(descr, &sd->dir_names); in xchk_directory()
1118 error = xchk_dir_walk(sc, sc->ip, xchk_dir_actor, sd); in xchk_directory()
1119 if (error == -ECANCELED) in xchk_directory()
1124 if (xfs_has_parent(sc->mp)) { in xchk_directory()
1126 if (error == -ETIMEDOUT) { in xchk_directory()
1136 if (sd->dir_names) in xchk_directory()
1137 xfblob_destroy(sd->dir_names); in xchk_directory()
1139 if (sd->dir_entries) in xchk_directory()
1140 xfarray_destroy(sd->dir_entries); in xchk_directory()
1167 * scrubber to reconstruct the block mappings. Directories always in xchk_dir_looks_zapped()
1173 return dp->i_df.if_format == XFS_DINODE_FMT_EXTENTS && in xchk_dir_looks_zapped()
1174 dp->i_df.if_nextents == 0; in xchk_dir_looks_zapped()