brintos

brintos / linux-shallow public Read only

0
0
Text · 30.2 KiB · bf9199e Raw
1176 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (C) 2017-2023 Oracle.  All Rights Reserved.4 * Author: Darrick J. Wong <djwong@kernel.org>5 */6#include "xfs.h"7#include "xfs_fs.h"8#include "xfs_shared.h"9#include "xfs_format.h"10#include "xfs_trans_resv.h"11#include "xfs_mount.h"12#include "xfs_log_format.h"13#include "xfs_trans.h"14#include "xfs_inode.h"15#include "xfs_icache.h"16#include "xfs_dir2.h"17#include "xfs_dir2_priv.h"18#include "xfs_health.h"19#include "xfs_attr.h"20#include "xfs_parent.h"21#include "scrub/scrub.h"22#include "scrub/common.h"23#include "scrub/dabtree.h"24#include "scrub/readdir.h"25#include "scrub/health.h"26#include "scrub/repair.h"27#include "scrub/trace.h"28#include "scrub/xfile.h"29#include "scrub/xfarray.h"30#include "scrub/xfblob.h"31 32/* Set us up to scrub directories. */33int34xchk_setup_directory(35	struct xfs_scrub	*sc)36{37	int			error;38 39	if (xchk_could_repair(sc)) {40		error = xrep_setup_directory(sc);41		if (error)42			return error;43	}44 45	return xchk_setup_inode_contents(sc, 0);46}47 48/* Directories */49 50/* Deferred directory entry that we saved for later. */51struct xchk_dirent {52	/* Cookie for retrieval of the dirent name. */53	xfblob_cookie		name_cookie;54 55	/* Child inode number. */56	xfs_ino_t		ino;57 58	/* Length of the pptr name. */59	uint8_t			namelen;60};61 62struct xchk_dir {63	struct xfs_scrub	*sc;64 65	/* information for parent pointer validation. */66	struct xfs_parent_rec	pptr_rec;67	struct xfs_da_args	pptr_args;68 69	/* Fixed-size array of xchk_dirent structures. */70	struct xfarray		*dir_entries;71 72	/* Blobs containing dirent names. */73	struct xfblob		*dir_names;74 75	/* If we've cycled the ILOCK, we must revalidate deferred dirents. */76	bool			need_revalidate;77 78	/* Name buffer for dirent revalidation. */79	struct xfs_name		xname;80	uint8_t			namebuf[MAXNAMELEN];81};82 83/* Scrub a directory entry. */84 85/* Check that an inode's mode matches a given XFS_DIR3_FT_* type. */86STATIC void87xchk_dir_check_ftype(88	struct xfs_scrub	*sc,89	xfs_fileoff_t		offset,90	struct xfs_inode	*ip,91	int			ftype)92{93	struct xfs_mount	*mp = sc->mp;94 95	if (!xfs_has_ftype(mp)) {96		if (ftype != XFS_DIR3_FT_UNKNOWN && ftype != XFS_DIR3_FT_DIR)97			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);98		return;99	}100 101	if (xfs_mode_to_ftype(VFS_I(ip)->i_mode) != ftype)102		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);103}104 105/*106 * Try to lock a child file for checking parent pointers.  Returns the inode107 * flags for the locks we now hold, or zero if we failed.108 */109STATIC unsigned int110xchk_dir_lock_child(111	struct xfs_scrub	*sc,112	struct xfs_inode	*ip)113{114	if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED))115		return 0;116 117	if (!xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) {118		xfs_iunlock(ip, XFS_IOLOCK_SHARED);119		return 0;120	}121 122	if (!xfs_inode_has_attr_fork(ip) || !xfs_need_iread_extents(&ip->i_af))123		return XFS_IOLOCK_SHARED | XFS_ILOCK_SHARED;124 125	xfs_iunlock(ip, XFS_ILOCK_SHARED);126 127	if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) {128		xfs_iunlock(ip, XFS_IOLOCK_SHARED);129		return 0;130	}131 132	return XFS_IOLOCK_SHARED | XFS_ILOCK_EXCL;133}134 135/* Check the backwards link (parent pointer) associated with this dirent. */136STATIC int137xchk_dir_parent_pointer(138	struct xchk_dir		*sd,139	const struct xfs_name	*name,140	struct xfs_inode	*ip)141{142	struct xfs_scrub	*sc = sd->sc;143	int			error;144 145	xfs_inode_to_parent_rec(&sd->pptr_rec, sc->ip);146	error = xfs_parent_lookup(sc->tp, ip, name, &sd->pptr_rec,147			&sd->pptr_args);148	if (error == -ENOATTR)149		xchk_fblock_xref_set_corrupt(sc, XFS_DATA_FORK, 0);150 151	return 0;152}153 154/* Look for a parent pointer matching this dirent, if the child isn't busy. */155STATIC int156xchk_dir_check_pptr_fast(157	struct xchk_dir		*sd,158	xfs_dir2_dataptr_t	dapos,159	const struct xfs_name	*name,160	struct xfs_inode	*ip)161{162	struct xfs_scrub	*sc = sd->sc;163	unsigned int		lockmode;164	int			error;165 166	/* dot and dotdot entries do not have parent pointers */167	if (xfs_dir2_samename(name, &xfs_name_dot) ||168	    xfs_dir2_samename(name, &xfs_name_dotdot))169		return 0;170 171	/* No self-referential non-dot or dotdot dirents. */172	if (ip == sc->ip) {173		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);174		return -ECANCELED;175	}176 177	/* Try to lock the inode. */178	lockmode = xchk_dir_lock_child(sc, ip);179	if (!lockmode) {180		struct xchk_dirent	save_de = {181			.namelen	= name->len,182			.ino		= ip->i_ino,183		};184 185		/* Couldn't lock the inode, so save the dirent for later. */186		trace_xchk_dir_defer(sc->ip, name, ip->i_ino);187 188		error = xfblob_storename(sd->dir_names, &save_de.name_cookie,189				name);190		if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0,191					&error))192			return error;193 194		error = xfarray_append(sd->dir_entries, &save_de);195		if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0,196					&error))197			return error;198 199		return 0;200	}201 202	error = xchk_dir_parent_pointer(sd, name, ip);203	xfs_iunlock(ip, lockmode);204	return error;205}206 207/*208 * Scrub a single directory entry.209 *210 * Check the inode number to make sure it's sane, then we check that we can211 * look up this filename.  Finally, we check the ftype.212 */213STATIC int214xchk_dir_actor(215	struct xfs_scrub	*sc,216	struct xfs_inode	*dp,217	xfs_dir2_dataptr_t	dapos,218	const struct xfs_name	*name,219	xfs_ino_t		ino,220	void			*priv)221{222	struct xfs_mount	*mp = dp->i_mount;223	struct xfs_inode	*ip;224	struct xchk_dir		*sd = priv;225	xfs_ino_t		lookup_ino;226	xfs_dablk_t		offset;227	int			error = 0;228 229	offset = xfs_dir2_db_to_da(mp->m_dir_geo,230			xfs_dir2_dataptr_to_db(mp->m_dir_geo, dapos));231 232	if (xchk_should_terminate(sc, &error))233		return error;234 235	/* Does this inode number make sense? */236	if (!xfs_verify_dir_ino(mp, ino)) {237		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);238		return -ECANCELED;239	}240 241	/* Does this name make sense? */242	if (!xfs_dir2_namecheck(name->name, name->len)) {243		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);244		return -ECANCELED;245	}246 247	if (xfs_dir2_samename(name, &xfs_name_dot)) {248		/* If this is "." then check that the inum matches the dir. */249		if (ino != dp->i_ino)250			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);251	} else if (xfs_dir2_samename(name, &xfs_name_dotdot)) {252		/*253		 * If this is ".." in the root inode, check that the inum254		 * matches this dir.255		 */256		if (dp->i_ino == mp->m_sb.sb_rootino && ino != dp->i_ino)257			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);258	}259 260	/* Verify that we can look up this name by hash. */261	error = xchk_dir_lookup(sc, dp, name, &lookup_ino);262	/* ENOENT means the hash lookup failed and the dir is corrupt */263	if (error == -ENOENT)264		error = -EFSCORRUPTED;265	if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, offset, &error))266		goto out;267	if (lookup_ino != ino) {268		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);269		return -ECANCELED;270	}271 272	/*273	 * Grab the inode pointed to by the dirent.  We release the inode274	 * before we cancel the scrub transaction.275	 *276	 * If _iget returns -EINVAL or -ENOENT then the child inode number is277	 * garbage and the directory is corrupt.  If the _iget returns278	 * -EFSCORRUPTED or -EFSBADCRC then the child is corrupt which is a279	 *  cross referencing error.  Any other error is an operational error.280	 */281	error = xchk_iget(sc, ino, &ip);282	if (error == -EINVAL || error == -ENOENT) {283		error = -EFSCORRUPTED;284		xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error);285		goto out;286	}287	if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, offset, &error))288		goto out;289 290	xchk_dir_check_ftype(sc, offset, ip, name->type);291 292	if (xfs_has_parent(mp)) {293		error = xchk_dir_check_pptr_fast(sd, dapos, name, ip);294		if (error)295			goto out_rele;296	}297 298out_rele:299	xchk_irele(sc, ip);300out:301	if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)302		return -ECANCELED;303	return error;304}305 306/* Scrub a directory btree record. */307STATIC int308xchk_dir_rec(309	struct xchk_da_btree		*ds,310	int				level)311{312	struct xfs_name			dname = { };313	struct xfs_da_state_blk		*blk = &ds->state->path.blk[level];314	struct xfs_mount		*mp = ds->state->mp;315	struct xfs_inode		*dp = ds->dargs.dp;316	struct xfs_da_geometry		*geo = mp->m_dir_geo;317	struct xfs_dir2_data_entry	*dent;318	struct xfs_buf			*bp;319	struct xfs_dir2_leaf_entry	*ent;320	unsigned int			end;321	unsigned int			iter_off;322	xfs_ino_t			ino;323	xfs_dablk_t			rec_bno;324	xfs_dir2_db_t			db;325	xfs_dir2_data_aoff_t		off;326	xfs_dir2_dataptr_t		ptr;327	xfs_dahash_t			calc_hash;328	xfs_dahash_t			hash;329	struct xfs_dir3_icleaf_hdr	hdr;330	unsigned int			tag;331	int				error;332 333	ASSERT(blk->magic == XFS_DIR2_LEAF1_MAGIC ||334	       blk->magic == XFS_DIR2_LEAFN_MAGIC);335 336	xfs_dir2_leaf_hdr_from_disk(mp, &hdr, blk->bp->b_addr);337	ent = hdr.ents + blk->index;338 339	/* Check the hash of the entry. */340	error = xchk_da_btree_hash(ds, level, &ent->hashval);341	if (error)342		goto out;343 344	/* Valid hash pointer? */345	ptr = be32_to_cpu(ent->address);346	if (ptr == 0)347		return 0;348 349	/* Find the directory entry's location. */350	db = xfs_dir2_dataptr_to_db(geo, ptr);351	off = xfs_dir2_dataptr_to_off(geo, ptr);352	rec_bno = xfs_dir2_db_to_da(geo, db);353 354	if (rec_bno >= geo->leafblk) {355		xchk_da_set_corrupt(ds, level);356		goto out;357	}358	error = xfs_dir3_data_read(ds->dargs.trans, dp, ds->dargs.owner,359			rec_bno, XFS_DABUF_MAP_HOLE_OK, &bp);360	if (!xchk_fblock_process_error(ds->sc, XFS_DATA_FORK, rec_bno,361			&error))362		goto out;363	if (!bp) {364		xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno);365		goto out;366	}367	xchk_buffer_recheck(ds->sc, bp);368 369	if (ds->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)370		goto out_relse;371 372	dent = bp->b_addr + off;373 374	/* Make sure we got a real directory entry. */375	iter_off = geo->data_entry_offset;376	end = xfs_dir3_data_end_offset(geo, bp->b_addr);377	if (!end) {378		xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno);379		goto out_relse;380	}381	for (;;) {382		struct xfs_dir2_data_entry	*dep = bp->b_addr + iter_off;383		struct xfs_dir2_data_unused	*dup = bp->b_addr + iter_off;384 385		if (iter_off >= end) {386			xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno);387			goto out_relse;388		}389 390		if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {391			iter_off += be16_to_cpu(dup->length);392			continue;393		}394		if (dep == dent)395			break;396		iter_off += xfs_dir2_data_entsize(mp, dep->namelen);397	}398 399	/* Retrieve the entry, sanity check it, and compare hashes. */400	ino = be64_to_cpu(dent->inumber);401	hash = be32_to_cpu(ent->hashval);402	tag = be16_to_cpup(xfs_dir2_data_entry_tag_p(mp, dent));403	if (!xfs_verify_dir_ino(mp, ino) || tag != off)404		xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno);405	if (dent->namelen == 0) {406		xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno);407		goto out_relse;408	}409 410	/* Does the directory hash match? */411	dname.name = dent->name;412	dname.len = dent->namelen;413	calc_hash = xfs_dir2_hashname(mp, &dname);414	if (calc_hash != hash)415		xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno);416 417out_relse:418	xfs_trans_brelse(ds->dargs.trans, bp);419out:420	return error;421}422 423/*424 * Is this unused entry either in the bestfree or smaller than all of425 * them?  We've already checked that the bestfrees are sorted longest to426 * shortest, and that there aren't any bogus entries.427 */428STATIC void429xchk_directory_check_free_entry(430	struct xfs_scrub		*sc,431	xfs_dablk_t			lblk,432	struct xfs_dir2_data_free	*bf,433	struct xfs_dir2_data_unused	*dup)434{435	struct xfs_dir2_data_free	*dfp;436	unsigned int			dup_length;437 438	dup_length = be16_to_cpu(dup->length);439 440	/* Unused entry is shorter than any of the bestfrees */441	if (dup_length < be16_to_cpu(bf[XFS_DIR2_DATA_FD_COUNT - 1].length))442		return;443 444	for (dfp = &bf[XFS_DIR2_DATA_FD_COUNT - 1]; dfp >= bf; dfp--)445		if (dup_length == be16_to_cpu(dfp->length))446			return;447 448	/* Unused entry should be in the bestfrees but wasn't found. */449	xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);450}451 452/* Check free space info in a directory data block. */453STATIC int454xchk_directory_data_bestfree(455	struct xfs_scrub		*sc,456	xfs_dablk_t			lblk,457	bool				is_block)458{459	struct xfs_dir2_data_unused	*dup;460	struct xfs_dir2_data_free	*dfp;461	struct xfs_buf			*bp;462	struct xfs_dir2_data_free	*bf;463	struct xfs_mount		*mp = sc->mp;464	u16				tag;465	unsigned int			nr_bestfrees = 0;466	unsigned int			nr_frees = 0;467	unsigned int			smallest_bestfree;468	int				newlen;469	unsigned int			offset;470	unsigned int			end;471	int				error;472 473	if (is_block) {474		/* dir block format */475		if (lblk != XFS_B_TO_FSBT(mp, XFS_DIR2_DATA_OFFSET))476			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);477		error = xfs_dir3_block_read(sc->tp, sc->ip, sc->ip->i_ino, &bp);478	} else {479		/* dir data format */480		error = xfs_dir3_data_read(sc->tp, sc->ip, sc->ip->i_ino, lblk,481				0, &bp);482	}483	if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error))484		goto out;485	xchk_buffer_recheck(sc, bp);486 487	/* XXX: Check xfs_dir3_data_hdr.pad is zero once we start setting it. */488 489	if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)490		goto out_buf;491 492	/* Do the bestfrees correspond to actual free space? */493	bf = xfs_dir2_data_bestfree_p(mp, bp->b_addr);494	smallest_bestfree = UINT_MAX;495	for (dfp = &bf[0]; dfp < &bf[XFS_DIR2_DATA_FD_COUNT]; dfp++) {496		offset = be16_to_cpu(dfp->offset);497		if (offset == 0)498			continue;499		if (offset >= mp->m_dir_geo->blksize) {500			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);501			goto out_buf;502		}503		dup = bp->b_addr + offset;504		tag = be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup));505 506		/* bestfree doesn't match the entry it points at? */507		if (dup->freetag != cpu_to_be16(XFS_DIR2_DATA_FREE_TAG) ||508		    be16_to_cpu(dup->length) != be16_to_cpu(dfp->length) ||509		    tag != offset) {510			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);511			goto out_buf;512		}513 514		/* bestfree records should be ordered largest to smallest */515		if (smallest_bestfree < be16_to_cpu(dfp->length)) {516			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);517			goto out_buf;518		}519 520		smallest_bestfree = be16_to_cpu(dfp->length);521		nr_bestfrees++;522	}523 524	/* Make sure the bestfrees are actually the best free spaces. */525	offset = mp->m_dir_geo->data_entry_offset;526	end = xfs_dir3_data_end_offset(mp->m_dir_geo, bp->b_addr);527 528	/* Iterate the entries, stopping when we hit or go past the end. */529	while (offset < end) {530		dup = bp->b_addr + offset;531 532		/* Skip real entries */533		if (dup->freetag != cpu_to_be16(XFS_DIR2_DATA_FREE_TAG)) {534			struct xfs_dir2_data_entry *dep = bp->b_addr + offset;535 536			newlen = xfs_dir2_data_entsize(mp, dep->namelen);537			if (newlen <= 0) {538				xchk_fblock_set_corrupt(sc, XFS_DATA_FORK,539						lblk);540				goto out_buf;541			}542			offset += newlen;543			continue;544		}545 546		/* Spot check this free entry */547		tag = be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup));548		if (tag != offset) {549			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);550			goto out_buf;551		}552 553		/*554		 * Either this entry is a bestfree or it's smaller than555		 * any of the bestfrees.556		 */557		xchk_directory_check_free_entry(sc, lblk, bf, dup);558		if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)559			goto out_buf;560 561		/* Move on. */562		newlen = be16_to_cpu(dup->length);563		if (newlen <= 0) {564			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);565			goto out_buf;566		}567		offset += newlen;568		if (offset <= end)569			nr_frees++;570	}571 572	/* We're required to fill all the space. */573	if (offset != end)574		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);575 576	/* Did we see at least as many free slots as there are bestfrees? */577	if (nr_frees < nr_bestfrees)578		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);579out_buf:580	xfs_trans_brelse(sc->tp, bp);581out:582	return error;583}584 585/*586 * Does the free space length in the free space index block ($len) match587 * the longest length in the directory data block's bestfree array?588 * Assume that we've already checked that the data block's bestfree589 * array is in order.590 */591STATIC void592xchk_directory_check_freesp(593	struct xfs_scrub		*sc,594	xfs_dablk_t			lblk,595	struct xfs_buf			*dbp,596	unsigned int			len)597{598	struct xfs_dir2_data_free	*dfp;599 600	dfp = xfs_dir2_data_bestfree_p(sc->mp, dbp->b_addr);601 602	if (len != be16_to_cpu(dfp->length))603		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);604 605	if (len > 0 && be16_to_cpu(dfp->offset) == 0)606		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);607}608 609/* Check free space info in a directory leaf1 block. */610STATIC int611xchk_directory_leaf1_bestfree(612	struct xfs_scrub		*sc,613	struct xfs_da_args		*args,614	xfs_dir2_db_t			last_data_db,615	xfs_dablk_t			lblk)616{617	struct xfs_dir3_icleaf_hdr	leafhdr;618	struct xfs_dir2_leaf_tail	*ltp;619	struct xfs_dir2_leaf		*leaf;620	struct xfs_buf			*dbp;621	struct xfs_buf			*bp;622	struct xfs_da_geometry		*geo = sc->mp->m_dir_geo;623	__be16				*bestp;624	__u16				best;625	__u32				hash;626	__u32				lasthash = 0;627	__u32				bestcount;628	unsigned int			stale = 0;629	int				i;630	int				error;631 632	/* Read the free space block. */633	error = xfs_dir3_leaf_read(sc->tp, sc->ip, sc->ip->i_ino, lblk, &bp);634	if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error))635		return error;636	xchk_buffer_recheck(sc, bp);637 638	leaf = bp->b_addr;639	xfs_dir2_leaf_hdr_from_disk(sc->ip->i_mount, &leafhdr, leaf);640	ltp = xfs_dir2_leaf_tail_p(geo, leaf);641	bestcount = be32_to_cpu(ltp->bestcount);642	bestp = xfs_dir2_leaf_bests_p(ltp);643 644	if (xfs_has_crc(sc->mp)) {645		struct xfs_dir3_leaf_hdr	*hdr3 = bp->b_addr;646 647		if (hdr3->pad != cpu_to_be32(0))648			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);649	}650 651	/*652	 * There must be enough bestfree slots to cover all the directory data653	 * blocks that we scanned.  It is possible for there to be a hole654	 * between the last data block and i_disk_size.  This seems like an655	 * oversight to the scrub author, but as we have been writing out656	 * directories like this (and xfs_repair doesn't mind them) for years,657	 * that's what we have to check.658	 */659	if (bestcount != last_data_db + 1) {660		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);661		goto out;662	}663 664	/* Is the leaf count even remotely sane? */665	if (leafhdr.count > geo->leaf_max_ents) {666		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);667		goto out;668	}669 670	/* Leaves and bests don't overlap in leaf format. */671	if ((char *)&leafhdr.ents[leafhdr.count] > (char *)bestp) {672		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);673		goto out;674	}675 676	/* Check hash value order, count stale entries.  */677	for (i = 0; i < leafhdr.count; i++) {678		hash = be32_to_cpu(leafhdr.ents[i].hashval);679		if (i > 0 && lasthash > hash)680			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);681		lasthash = hash;682		if (leafhdr.ents[i].address ==683		    cpu_to_be32(XFS_DIR2_NULL_DATAPTR))684			stale++;685	}686	if (leafhdr.stale != stale)687		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);688	if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)689		goto out;690 691	/* Check all the bestfree entries. */692	for (i = 0; i < bestcount; i++, bestp++) {693		best = be16_to_cpu(*bestp);694		error = xfs_dir3_data_read(sc->tp, sc->ip, args->owner,695				xfs_dir2_db_to_da(args->geo, i),696				XFS_DABUF_MAP_HOLE_OK, &dbp);697		if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk,698				&error))699			break;700 701		if (!dbp) {702			if (best != NULLDATAOFF) {703				xchk_fblock_set_corrupt(sc, XFS_DATA_FORK,704						lblk);705				break;706			}707			continue;708		}709 710		if (best == NULLDATAOFF)711			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);712		else713			xchk_directory_check_freesp(sc, lblk, dbp, best);714		xfs_trans_brelse(sc->tp, dbp);715		if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)716			break;717	}718out:719	xfs_trans_brelse(sc->tp, bp);720	return error;721}722 723/* Check free space info in a directory freespace block. */724STATIC int725xchk_directory_free_bestfree(726	struct xfs_scrub		*sc,727	struct xfs_da_args		*args,728	xfs_dablk_t			lblk)729{730	struct xfs_dir3_icfree_hdr	freehdr;731	struct xfs_buf			*dbp;732	struct xfs_buf			*bp;733	__u16				best;734	unsigned int			stale = 0;735	int				i;736	int				error;737 738	/* Read the free space block */739	error = xfs_dir2_free_read(sc->tp, sc->ip, sc->ip->i_ino, lblk, &bp);740	if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error))741		return error;742	xchk_buffer_recheck(sc, bp);743 744	if (xfs_has_crc(sc->mp)) {745		struct xfs_dir3_free_hdr	*hdr3 = bp->b_addr;746 747		if (hdr3->pad != cpu_to_be32(0))748			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);749	}750 751	/* Check all the entries. */752	xfs_dir2_free_hdr_from_disk(sc->ip->i_mount, &freehdr, bp->b_addr);753	for (i = 0; i < freehdr.nvalid; i++) {754		best = be16_to_cpu(freehdr.bests[i]);755		if (best == NULLDATAOFF) {756			stale++;757			continue;758		}759		error = xfs_dir3_data_read(sc->tp, sc->ip, args->owner,760				(freehdr.firstdb + i) * args->geo->fsbcount,761				0, &dbp);762		if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk,763				&error))764			goto out;765		xchk_directory_check_freesp(sc, lblk, dbp, best);766		xfs_trans_brelse(sc->tp, dbp);767	}768 769	if (freehdr.nused + stale != freehdr.nvalid)770		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);771out:772	xfs_trans_brelse(sc->tp, bp);773	return error;774}775 776/* Check free space information in directories. */777STATIC int778xchk_directory_blocks(779	struct xfs_scrub	*sc)780{781	struct xfs_bmbt_irec	got;782	struct xfs_da_args	args = {783		.dp		= sc->ip,784		.whichfork	= XFS_DATA_FORK,785		.geo		= sc->mp->m_dir_geo,786		.trans		= sc->tp,787		.owner		= sc->ip->i_ino,788	};789	struct xfs_ifork	*ifp = xfs_ifork_ptr(sc->ip, XFS_DATA_FORK);790	struct xfs_mount	*mp = sc->mp;791	xfs_fileoff_t		leaf_lblk;792	xfs_fileoff_t		free_lblk;793	xfs_fileoff_t		lblk;794	struct xfs_iext_cursor	icur;795	xfs_dablk_t		dabno;796	xfs_dir2_db_t		last_data_db = 0;797	bool			found;798	bool			is_block = false;799	int			error;800 801	/* Ignore local format directories. */802	if (ifp->if_format != XFS_DINODE_FMT_EXTENTS &&803	    ifp->if_format != XFS_DINODE_FMT_BTREE)804		return 0;805 806	lblk = XFS_B_TO_FSB(mp, XFS_DIR2_DATA_OFFSET);807	leaf_lblk = XFS_B_TO_FSB(mp, XFS_DIR2_LEAF_OFFSET);808	free_lblk = XFS_B_TO_FSB(mp, XFS_DIR2_FREE_OFFSET);809 810	/* Is this a block dir? */811	if (xfs_dir2_format(&args, &error) == XFS_DIR2_FMT_BLOCK)812		is_block = true;813	if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error))814		goto out;815 816	/* Iterate all the data extents in the directory... */817	found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got);818	while (found && !(sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) {819		/* No more data blocks... */820		if (got.br_startoff >= leaf_lblk)821			break;822 823		/*824		 * Check each data block's bestfree data.825		 *826		 * Iterate all the fsbcount-aligned block offsets in827		 * this directory.  The directory block reading code is828		 * smart enough to do its own bmap lookups to handle829		 * discontiguous directory blocks.  When we're done830		 * with the extent record, re-query the bmap at the831		 * next fsbcount-aligned offset to avoid redundant832		 * block checks.833		 */834		for (lblk = roundup((xfs_dablk_t)got.br_startoff,835				args.geo->fsbcount);836		     lblk < got.br_startoff + got.br_blockcount;837		     lblk += args.geo->fsbcount) {838			last_data_db = xfs_dir2_da_to_db(args.geo, lblk);839			error = xchk_directory_data_bestfree(sc, lblk,840					is_block);841			if (error)842				goto out;843		}844		dabno = got.br_startoff + got.br_blockcount;845		lblk = roundup(dabno, args.geo->fsbcount);846		found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got);847	}848 849	if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)850		goto out;851 852	/* Look for a leaf1 block, which has free info. */853	if (xfs_iext_lookup_extent(sc->ip, ifp, leaf_lblk, &icur, &got) &&854	    got.br_startoff == leaf_lblk &&855	    got.br_blockcount == args.geo->fsbcount &&856	    !xfs_iext_next_extent(ifp, &icur, &got)) {857		if (is_block) {858			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);859			goto out;860		}861		error = xchk_directory_leaf1_bestfree(sc, &args, last_data_db,862				leaf_lblk);863		if (error)864			goto out;865	}866 867	if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)868		goto out;869 870	/* Scan for free blocks */871	lblk = free_lblk;872	found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got);873	while (found && !(sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) {874		/*875		 * Dirs can't have blocks mapped above 2^32.876		 * Single-block dirs shouldn't even be here.877		 */878		lblk = got.br_startoff;879		if (lblk & ~0xFFFFFFFFULL) {880			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);881			goto out;882		}883		if (is_block) {884			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);885			goto out;886		}887 888		/*889		 * Check each dir free block's bestfree data.890		 *891		 * Iterate all the fsbcount-aligned block offsets in892		 * this directory.  The directory block reading code is893		 * smart enough to do its own bmap lookups to handle894		 * discontiguous directory blocks.  When we're done895		 * with the extent record, re-query the bmap at the896		 * next fsbcount-aligned offset to avoid redundant897		 * block checks.898		 */899		for (lblk = roundup((xfs_dablk_t)got.br_startoff,900				args.geo->fsbcount);901		     lblk < got.br_startoff + got.br_blockcount;902		     lblk += args.geo->fsbcount) {903			error = xchk_directory_free_bestfree(sc, &args,904					lblk);905			if (error)906				goto out;907		}908		dabno = got.br_startoff + got.br_blockcount;909		lblk = roundup(dabno, args.geo->fsbcount);910		found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got);911	}912out:913	return error;914}915 916/*917 * Revalidate a dirent that we collected in the past but couldn't check because918 * of lock contention.  Returns 0 if the dirent is still valid, -ENOENT if it919 * has gone away on us, or a negative errno.920 */921STATIC int922xchk_dir_revalidate_dirent(923	struct xchk_dir		*sd,924	const struct xfs_name	*xname,925	xfs_ino_t		ino)926{927	struct xfs_scrub	*sc = sd->sc;928	xfs_ino_t		child_ino;929	int			error;930 931	/*932	 * Look up the directory entry.  If we get -ENOENT, the directory entry933	 * went away and there's nothing to revalidate.  Return any other934	 * error.935	 */936	error = xchk_dir_lookup(sc, sc->ip, xname, &child_ino);937	if (error)938		return error;939 940	/* The inode number changed, nothing to revalidate. */941	if (ino != child_ino)942		return -ENOENT;943 944	return 0;945}946 947/*948 * Check a directory entry's parent pointers the slow way, which means we cycle949 * locks a bunch and put up with revalidation until we get it done.950 */951STATIC int952xchk_dir_slow_dirent(953	struct xchk_dir		*sd,954	struct xchk_dirent	*dirent,955	const struct xfs_name	*xname)956{957	struct xfs_scrub	*sc = sd->sc;958	struct xfs_inode	*ip;959	unsigned int		lockmode;960	int			error;961 962	/* Check that the deferred dirent still exists. */963	if (sd->need_revalidate) {964		error = xchk_dir_revalidate_dirent(sd, xname, dirent->ino);965		if (error == -ENOENT)966			return 0;967		if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0,968					&error))969			return error;970	}971 972	error = xchk_iget(sc, dirent->ino, &ip);973	if (error == -EINVAL || error == -ENOENT) {974		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);975		return 0;976	}977	if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0, &error))978		return error;979 980	/*981	 * If we can grab both IOLOCK and ILOCK of the alleged child, we can982	 * proceed with the validation.983	 */984	lockmode = xchk_dir_lock_child(sc, ip);985	if (lockmode) {986		trace_xchk_dir_slowpath(sc->ip, xname, ip->i_ino);987		goto check_pptr;988	}989 990	/*991	 * We couldn't lock the child file.  Drop all the locks and try to992	 * get them again, one at a time.993	 */994	xchk_iunlock(sc, sc->ilock_flags);995	sd->need_revalidate = true;996 997	trace_xchk_dir_ultraslowpath(sc->ip, xname, ip->i_ino);998 999	error = xchk_dir_trylock_for_pptrs(sc, ip, &lockmode);1000	if (error)1001		goto out_rele;1002 1003	/* Revalidate, since we just cycled the locks. */1004	error = xchk_dir_revalidate_dirent(sd, xname, dirent->ino);1005	if (error == -ENOENT) {1006		error = 0;1007		goto out_unlock;1008	}1009	if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0, &error))1010		goto out_unlock;1011 1012check_pptr:1013	error = xchk_dir_parent_pointer(sd, xname, ip);1014out_unlock:1015	xfs_iunlock(ip, lockmode);1016out_rele:1017	xchk_irele(sc, ip);1018	return error;1019}1020 1021/* Check all the dirents that we deferred the first time around. */1022STATIC int1023xchk_dir_finish_slow_dirents(1024	struct xchk_dir		*sd)1025{1026	xfarray_idx_t		array_cur;1027	int			error;1028 1029	foreach_xfarray_idx(sd->dir_entries, array_cur) {1030		struct xchk_dirent	dirent;1031 1032		if (sd->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)1033			return 0;1034 1035		error = xfarray_load(sd->dir_entries, array_cur, &dirent);1036		if (error)1037			return error;1038 1039		error = xfblob_loadname(sd->dir_names, dirent.name_cookie,1040				&sd->xname, dirent.namelen);1041		if (error)1042			return error;1043 1044		error = xchk_dir_slow_dirent(sd, &dirent, &sd->xname);1045		if (error)1046			return error;1047	}1048 1049	return 0;1050}1051 1052/* Scrub a whole directory. */1053int1054xchk_directory(1055	struct xfs_scrub	*sc)1056{1057	struct xchk_dir		*sd;1058	int			error;1059 1060	if (!S_ISDIR(VFS_I(sc->ip)->i_mode))1061		return -ENOENT;1062 1063	if (xchk_file_looks_zapped(sc, XFS_SICK_INO_DIR_ZAPPED)) {1064		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);1065		return 0;1066	}1067 1068	/* Plausible size? */1069	if (sc->ip->i_disk_size < xfs_dir2_sf_hdr_size(0)) {1070		xchk_ino_set_corrupt(sc, sc->ip->i_ino);1071		return 0;1072	}1073 1074	/* Check directory tree structure */1075	error = xchk_da_btree(sc, XFS_DATA_FORK, xchk_dir_rec, NULL);1076	if (error)1077		return error;1078 1079	if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)1080		return 0;1081 1082	/* Check the freespace. */1083	error = xchk_directory_blocks(sc);1084	if (error)1085		return error;1086 1087	if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)1088		return 0;1089 1090	sd = kvzalloc(sizeof(struct xchk_dir), XCHK_GFP_FLAGS);1091	if (!sd)1092		return -ENOMEM;1093	sd->sc = sc;1094	sd->xname.name = sd->namebuf;1095 1096	if (xfs_has_parent(sc->mp)) {1097		char		*descr;1098 1099		/*1100		 * Set up some staging memory for dirents that we can't check1101		 * due to locking contention.1102		 */1103		descr = xchk_xfile_ino_descr(sc, "slow directory entries");1104		error = xfarray_create(descr, 0, sizeof(struct xchk_dirent),1105				&sd->dir_entries);1106		kfree(descr);1107		if (error)1108			goto out_sd;1109 1110		descr = xchk_xfile_ino_descr(sc, "slow directory entry names");1111		error = xfblob_create(descr, &sd->dir_names);1112		kfree(descr);1113		if (error)1114			goto out_entries;1115	}1116 1117	/* Look up every name in this directory by hash. */1118	error = xchk_dir_walk(sc, sc->ip, xchk_dir_actor, sd);1119	if (error == -ECANCELED)1120		error = 0;1121	if (error)1122		goto out_names;1123 1124	if (xfs_has_parent(sc->mp)) {1125		error = xchk_dir_finish_slow_dirents(sd);1126		if (error == -ETIMEDOUT) {1127			/* Couldn't grab a lock, scrub was marked incomplete */1128			error = 0;1129			goto out_names;1130		}1131		if (error)1132			goto out_names;1133	}1134 1135out_names:1136	if (sd->dir_names)1137		xfblob_destroy(sd->dir_names);1138out_entries:1139	if (sd->dir_entries)1140		xfarray_destroy(sd->dir_entries);1141out_sd:1142	kvfree(sd);1143	if (error)1144		return error;1145 1146	/* If the dir is clean, it is clearly not zapped. */1147	xchk_mark_healthy_if_clean(sc, XFS_SICK_INO_DIR_ZAPPED);1148	return 0;1149}1150 1151/*1152 * Decide if this directory has been zapped to satisfy the inode and ifork1153 * verifiers.  Checking and repairing should be postponed until the directory1154 * is fixed.1155 */1156bool1157xchk_dir_looks_zapped(1158	struct xfs_inode	*dp)1159{1160	/* Repair zapped this dir's data fork a short time ago */1161	if (xfs_ifork_zapped(dp, XFS_DATA_FORK))1162		return true;1163 1164	/*1165	 * If the dinode repair found a bad data fork, it will reset the fork1166	 * to extents format with zero records and wait for the bmapbtd1167	 * scrubber to reconstruct the block mappings.  Directories always1168	 * contain some content, so this is a clear sign of a zapped directory.1169	 * The state checked by xfs_ifork_zapped is not persisted, so this is1170	 * the secondary strategy if repairs are interrupted by a crash or an1171	 * unmount.1172	 */1173	return dp->i_df.if_format == XFS_DINODE_FMT_EXTENTS &&1174	       dp->i_df.if_nextents == 0;1175}1176