brintos

brintos / linux-shallow public Read only

0
0
Text · 21.8 KiB · cf9d983 Raw
827 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (c) 2021-2024 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_btree.h"16#include "xfs_ialloc.h"17#include "xfs_ialloc_btree.h"18#include "xfs_ag.h"19#include "xfs_error.h"20#include "xfs_bit.h"21#include "xfs_icache.h"22#include "scrub/scrub.h"23#include "scrub/iscan.h"24#include "scrub/common.h"25#include "scrub/trace.h"26 27/*28 * Live File Scan29 * ==============30 *31 * Live file scans walk every inode in a live filesystem.  This is more or32 * less like a regular iwalk, except that when we're advancing the scan cursor,33 * we must ensure that inodes cannot be added or deleted anywhere between the34 * old cursor value and the new cursor value.  If we're advancing the cursor35 * by one inode, the caller must hold that inode; if we're finding the next36 * inode to scan, we must grab the AGI and hold it until we've updated the37 * scan cursor.38 *39 * Callers are expected to use this code to scan all files in the filesystem to40 * construct a new metadata index of some kind.  The scan races against other41 * live updates, which means there must be a provision to update the new index42 * when updates are made to inodes that already been scanned.  The iscan lock43 * can be used in live update hook code to stop the scan and protect this data44 * structure.45 *46 * To keep the new index up to date with other metadata updates being made to47 * the live filesystem, it is assumed that the caller will add hooks as needed48 * to be notified when a metadata update occurs.  The inode scanner must tell49 * the hook code when an inode has been visited with xchk_iscan_mark_visit.50 * Hook functions can use xchk_iscan_want_live_update to decide if the51 * scanner's observations must be updated.52 */53 54/*55 * If the inobt record @rec covers @iscan->skip_ino, mark the inode free so56 * that the scan ignores that inode.57 */58STATIC void59xchk_iscan_mask_skipino(60	struct xchk_iscan	*iscan,61	struct xfs_perag	*pag,62	struct xfs_inobt_rec_incore	*rec,63	xfs_agino_t		lastrecino)64{65	struct xfs_scrub	*sc = iscan->sc;66	struct xfs_mount	*mp = sc->mp;67	xfs_agnumber_t		skip_agno = XFS_INO_TO_AGNO(mp, iscan->skip_ino);68	xfs_agnumber_t		skip_agino = XFS_INO_TO_AGINO(mp, iscan->skip_ino);69 70	if (pag->pag_agno != skip_agno)71		return;72	if (skip_agino < rec->ir_startino)73		return;74	if (skip_agino > lastrecino)75		return;76 77	rec->ir_free |= xfs_inobt_maskn(skip_agino - rec->ir_startino, 1);78}79 80/*81 * Set *cursor to the next allocated inode after whatever it's set to now.82 * If there are no more inodes in this AG, cursor is set to NULLAGINO.83 */84STATIC int85xchk_iscan_find_next(86	struct xchk_iscan	*iscan,87	struct xfs_buf		*agi_bp,88	struct xfs_perag	*pag,89	xfs_inofree_t		*allocmaskp,90	xfs_agino_t		*cursor,91	uint8_t			*nr_inodesp)92{93	struct xfs_scrub	*sc = iscan->sc;94	struct xfs_inobt_rec_incore	rec;95	struct xfs_btree_cur	*cur;96	struct xfs_mount	*mp = sc->mp;97	struct xfs_trans	*tp = sc->tp;98	xfs_agnumber_t		agno = pag->pag_agno;99	xfs_agino_t		lastino = NULLAGINO;100	xfs_agino_t		first, last;101	xfs_agino_t		agino = *cursor;102	int			has_rec;103	int			error;104 105	/* If the cursor is beyond the end of this AG, move to the next one. */106	xfs_agino_range(mp, agno, &first, &last);107	if (agino > last) {108		*cursor = NULLAGINO;109		return 0;110	}111 112	/*113	 * Look up the inode chunk for the current cursor position.  If there114	 * is no chunk here, we want the next one.115	 */116	cur = xfs_inobt_init_cursor(pag, tp, agi_bp);117	error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &has_rec);118	if (!error && !has_rec)119		error = xfs_btree_increment(cur, 0, &has_rec);120	for (; !error; error = xfs_btree_increment(cur, 0, &has_rec)) {121		xfs_inofree_t	allocmask;122 123		/*124		 * If we've run out of inobt records in this AG, move the125		 * cursor on to the next AG and exit.  The caller can try126		 * again with the next AG.127		 */128		if (!has_rec) {129			*cursor = NULLAGINO;130			break;131		}132 133		error = xfs_inobt_get_rec(cur, &rec, &has_rec);134		if (error)135			break;136		if (!has_rec) {137			error = -EFSCORRUPTED;138			break;139		}140 141		/* Make sure that we always move forward. */142		if (lastino != NULLAGINO &&143		    XFS_IS_CORRUPT(mp, lastino >= rec.ir_startino)) {144			error = -EFSCORRUPTED;145			break;146		}147		lastino = rec.ir_startino + XFS_INODES_PER_CHUNK - 1;148 149		/*150		 * If this record only covers inodes that come before the151		 * cursor, advance to the next record.152		 */153		if (rec.ir_startino + XFS_INODES_PER_CHUNK <= agino)154			continue;155 156		if (iscan->skip_ino)157			xchk_iscan_mask_skipino(iscan, pag, &rec, lastino);158 159		/*160		 * If the incoming lookup put us in the middle of an inobt161		 * record, mark it and the previous inodes "free" so that the162		 * search for allocated inodes will start at the cursor.163		 * We don't care about ir_freecount here.164		 */165		if (agino >= rec.ir_startino)166			rec.ir_free |= xfs_inobt_maskn(0,167						agino + 1 - rec.ir_startino);168 169		/*170		 * If there are allocated inodes in this chunk, find them171		 * and update the scan cursor.172		 */173		allocmask = ~rec.ir_free;174		if (hweight64(allocmask) > 0) {175			int	next = xfs_lowbit64(allocmask);176 177			ASSERT(next >= 0);178			*cursor = rec.ir_startino + next;179			*allocmaskp = allocmask >> next;180			*nr_inodesp = XFS_INODES_PER_CHUNK - next;181			break;182		}183	}184 185	xfs_btree_del_cursor(cur, error);186	return error;187}188 189/*190 * Advance both the scan and the visited cursors.191 *192 * The inumber address space for a given filesystem is sparse, which means that193 * the scan cursor can jump a long ways in a single iter() call.  There are no194 * inodes in these sparse areas, so we must move the visited cursor forward at195 * the same time so that the scan user can receive live updates for inodes that196 * may get created once we release the AGI buffer.197 */198static inline void199xchk_iscan_move_cursor(200	struct xchk_iscan	*iscan,201	xfs_agnumber_t		agno,202	xfs_agino_t		agino)203{204	struct xfs_scrub	*sc = iscan->sc;205	struct xfs_mount	*mp = sc->mp;206	xfs_ino_t		cursor, visited;207 208	BUILD_BUG_ON(XFS_MAXINUMBER == NULLFSINO);209 210	/*211	 * Special-case ino == 0 here so that we never set visited_ino to212	 * NULLFSINO when wrapping around EOFS, for that will let through all213	 * live updates.214	 */215	cursor = XFS_AGINO_TO_INO(mp, agno, agino);216	if (cursor == 0)217		visited = XFS_MAXINUMBER;218	else219		visited = cursor - 1;220 221	mutex_lock(&iscan->lock);222	iscan->cursor_ino = cursor;223	iscan->__visited_ino = visited;224	trace_xchk_iscan_move_cursor(iscan);225	mutex_unlock(&iscan->lock);226}227 228/*229 * Prepare to return agno/agino to the iscan caller by moving the lastino230 * cursor to the previous inode.  Do this while we still hold the AGI so that231 * no other threads can create or delete inodes in this AG.232 */233static inline void234xchk_iscan_finish(235	struct xchk_iscan	*iscan)236{237	mutex_lock(&iscan->lock);238	iscan->cursor_ino = NULLFSINO;239 240	/* All live updates will be applied from now on */241	iscan->__visited_ino = NULLFSINO;242 243	mutex_unlock(&iscan->lock);244}245 246/* Mark an inode scan finished before we actually scan anything. */247void248xchk_iscan_finish_early(249	struct xchk_iscan	*iscan)250{251	ASSERT(iscan->cursor_ino == iscan->scan_start_ino);252	ASSERT(iscan->__visited_ino == iscan->scan_start_ino);253 254	xchk_iscan_finish(iscan);255}256 257/*258 * Grab the AGI to advance the inode scan.  Returns 0 if *agi_bpp is now set,259 * -ECANCELED if the live scan aborted, -EBUSY if the AGI could not be grabbed,260 * or the usual negative errno.261 */262STATIC int263xchk_iscan_read_agi(264	struct xchk_iscan	*iscan,265	struct xfs_perag	*pag,266	struct xfs_buf		**agi_bpp)267{268	struct xfs_scrub	*sc = iscan->sc;269	unsigned long		relax;270	int			ret;271 272	if (!xchk_iscan_agi_needs_trylock(iscan))273		return xfs_ialloc_read_agi(pag, sc->tp, 0, agi_bpp);274 275	relax = msecs_to_jiffies(iscan->iget_retry_delay);276	do {277		ret = xfs_ialloc_read_agi(pag, sc->tp, XFS_IALLOC_FLAG_TRYLOCK,278				agi_bpp);279		if (ret != -EAGAIN)280			return ret;281		if (!iscan->iget_timeout ||282		    time_is_before_jiffies(iscan->__iget_deadline))283			return -EBUSY;284 285		trace_xchk_iscan_agi_retry_wait(iscan);286	} while (!schedule_timeout_killable(relax) &&287		 !xchk_iscan_aborted(iscan));288	return -ECANCELED;289}290 291/*292 * Advance ino to the next inode that the inobt thinks is allocated, being293 * careful to jump to the next AG if we've reached the right end of this AG's294 * inode btree.  Advancing ino effectively means that we've pushed the inode295 * scan forward, so set the iscan cursor to (ino - 1) so that our live update296 * predicates will track inode allocations in that part of the inode number297 * key space once we release the AGI buffer.298 *299 * Returns 1 if there's a new inode to examine, 0 if we've run out of inodes,300 * -ECANCELED if the live scan aborted, or the usual negative errno.301 */302STATIC int303xchk_iscan_advance(304	struct xchk_iscan	*iscan,305	struct xfs_perag	**pagp,306	struct xfs_buf		**agi_bpp,307	xfs_inofree_t		*allocmaskp,308	uint8_t			*nr_inodesp)309{310	struct xfs_scrub	*sc = iscan->sc;311	struct xfs_mount	*mp = sc->mp;312	struct xfs_buf		*agi_bp;313	struct xfs_perag	*pag;314	xfs_agnumber_t		agno;315	xfs_agino_t		agino;316	int			ret;317 318	ASSERT(iscan->cursor_ino >= iscan->__visited_ino);319 320	do {321		if (xchk_iscan_aborted(iscan))322			return -ECANCELED;323 324		agno = XFS_INO_TO_AGNO(mp, iscan->cursor_ino);325		pag = xfs_perag_get(mp, agno);326		if (!pag)327			return -ECANCELED;328 329		ret = xchk_iscan_read_agi(iscan, pag, &agi_bp);330		if (ret)331			goto out_pag;332 333		agino = XFS_INO_TO_AGINO(mp, iscan->cursor_ino);334		ret = xchk_iscan_find_next(iscan, agi_bp, pag, allocmaskp,335				&agino, nr_inodesp);336		if (ret)337			goto out_buf;338 339		if (agino != NULLAGINO) {340			/*341			 * Found the next inode in this AG, so return it along342			 * with the AGI buffer and the perag structure to343			 * ensure it cannot go away.344			 */345			xchk_iscan_move_cursor(iscan, agno, agino);346			*agi_bpp = agi_bp;347			*pagp = pag;348			return 1;349		}350 351		/*352		 * Did not find any more inodes in this AG, move on to the next353		 * AG.354		 */355		agno = (agno + 1) % mp->m_sb.sb_agcount;356		xchk_iscan_move_cursor(iscan, agno, 0);357		xfs_trans_brelse(sc->tp, agi_bp);358		xfs_perag_put(pag);359 360		trace_xchk_iscan_advance_ag(iscan);361	} while (iscan->cursor_ino != iscan->scan_start_ino);362 363	xchk_iscan_finish(iscan);364	return 0;365 366out_buf:367	xfs_trans_brelse(sc->tp, agi_bp);368out_pag:369	xfs_perag_put(pag);370	return ret;371}372 373/*374 * Grabbing the inode failed, so we need to back up the scan and ask the caller375 * to try to _advance the scan again.  Returns -EBUSY if we've run out of retry376 * opportunities, -ECANCELED if the process has a fatal signal pending, or377 * -EAGAIN if we should try again.378 */379STATIC int380xchk_iscan_iget_retry(381	struct xchk_iscan	*iscan,382	bool			wait)383{384	ASSERT(iscan->cursor_ino == iscan->__visited_ino + 1);385 386	if (!iscan->iget_timeout ||387	    time_is_before_jiffies(iscan->__iget_deadline))388		return -EBUSY;389 390	if (wait) {391		unsigned long	relax;392 393		/*394		 * Sleep for a period of time to let the rest of the system395		 * catch up.  If we return early, someone sent a kill signal to396		 * the calling process.397		 */398		relax = msecs_to_jiffies(iscan->iget_retry_delay);399		trace_xchk_iscan_iget_retry_wait(iscan);400 401		if (schedule_timeout_killable(relax) ||402		    xchk_iscan_aborted(iscan))403			return -ECANCELED;404	}405 406	iscan->cursor_ino--;407	return -EAGAIN;408}409 410/*411 * For an inode scan, we hold the AGI and want to try to grab a batch of412 * inodes.  Holding the AGI prevents inodegc from clearing freed inodes,413 * so we must use noretry here.  For every inode after the first one in the414 * batch, we don't want to wait, so we use retry there too.  Finally, use415 * dontcache to avoid polluting the cache.416 */417#define ISCAN_IGET_FLAGS	(XFS_IGET_NORETRY | XFS_IGET_DONTCACHE)418 419/*420 * Grab an inode as part of an inode scan.  While scanning this inode, the421 * caller must ensure that no other threads can modify the inode until a call422 * to xchk_iscan_visit succeeds.423 *424 * Returns the number of incore inodes grabbed; -EAGAIN if the caller should425 * call again xchk_iscan_advance; -EBUSY if we couldn't grab an inode;426 * -ECANCELED if there's a fatal signal pending; or some other negative errno.427 */428STATIC int429xchk_iscan_iget(430	struct xchk_iscan	*iscan,431	struct xfs_perag	*pag,432	struct xfs_buf		*agi_bp,433	xfs_inofree_t		allocmask,434	uint8_t			nr_inodes)435{436	struct xfs_scrub	*sc = iscan->sc;437	struct xfs_mount	*mp = sc->mp;438	xfs_ino_t		ino = iscan->cursor_ino;439	unsigned int		idx = 0;440	unsigned int		i;441	int			error;442 443	ASSERT(iscan->__inodes[0] == NULL);444 445	/* Fill the first slot in the inode array. */446	error = xfs_iget(sc->mp, sc->tp, ino, ISCAN_IGET_FLAGS, 0,447			&iscan->__inodes[idx]);448 449	trace_xchk_iscan_iget(iscan, error);450 451	if (error == -ENOENT || error == -EAGAIN) {452		xfs_trans_brelse(sc->tp, agi_bp);453		xfs_perag_put(pag);454 455		/*456		 * It's possible that this inode has lost all of its links but457		 * hasn't yet been inactivated.  If we don't have a transaction458		 * or it's not writable, flush the inodegc workers and wait.459		 * If we have a non-empty transaction, we must not block on460		 * inodegc, which allocates its own transactions.461		 */462		if (sc->tp && !(sc->tp->t_flags & XFS_TRANS_NO_WRITECOUNT))463			xfs_inodegc_push(mp);464		else465			xfs_inodegc_flush(mp);466		return xchk_iscan_iget_retry(iscan, true);467	}468 469	if (error == -EINVAL) {470		xfs_trans_brelse(sc->tp, agi_bp);471		xfs_perag_put(pag);472 473		/*474		 * We thought the inode was allocated, but the inode btree475		 * lookup failed, which means that it was freed since the last476		 * time we advanced the cursor.  Back up and try again.  This477		 * should never happen since still hold the AGI buffer from the478		 * inobt check, but we need to be careful about infinite loops.479		 */480		return xchk_iscan_iget_retry(iscan, false);481	}482 483	if (error) {484		xfs_trans_brelse(sc->tp, agi_bp);485		xfs_perag_put(pag);486		return error;487	}488	idx++;489	ino++;490	allocmask >>= 1;491 492	/*493	 * Now that we've filled the first slot in __inodes, try to fill the494	 * rest of the batch with consecutively ordered inodes.  to reduce the495	 * number of _iter calls.  Make a bitmap of unallocated inodes from the496	 * zeroes in the inuse bitmap; these inodes will not be scanned, but497	 * the _want_live_update predicate will pass through all live updates.498	 *499	 * If we can't iget an allocated inode, stop and return what we have.500	 */501	mutex_lock(&iscan->lock);502	iscan->__batch_ino = ino - 1;503	iscan->__skipped_inomask = 0;504	mutex_unlock(&iscan->lock);505 506	for (i = 1; i < nr_inodes; i++, ino++, allocmask >>= 1) {507		if (!(allocmask & 1)) {508			ASSERT(!(iscan->__skipped_inomask & (1ULL << i)));509 510			mutex_lock(&iscan->lock);511			iscan->cursor_ino = ino;512			iscan->__skipped_inomask |= (1ULL << i);513			mutex_unlock(&iscan->lock);514			continue;515		}516 517		ASSERT(iscan->__inodes[idx] == NULL);518 519		error = xfs_iget(sc->mp, sc->tp, ino, ISCAN_IGET_FLAGS, 0,520				&iscan->__inodes[idx]);521		if (error)522			break;523 524		mutex_lock(&iscan->lock);525		iscan->cursor_ino = ino;526		mutex_unlock(&iscan->lock);527		idx++;528	}529 530	trace_xchk_iscan_iget_batch(sc->mp, iscan, nr_inodes, idx);531	xfs_trans_brelse(sc->tp, agi_bp);532	xfs_perag_put(pag);533	return idx;534}535 536/*537 * Advance the visit cursor to reflect skipped inodes beyond whatever we538 * scanned.539 */540STATIC void541xchk_iscan_finish_batch(542	struct xchk_iscan	*iscan)543{544	xfs_ino_t		highest_skipped;545 546	mutex_lock(&iscan->lock);547 548	if (iscan->__batch_ino != NULLFSINO) {549		highest_skipped = iscan->__batch_ino +550					xfs_highbit64(iscan->__skipped_inomask);551		iscan->__visited_ino = max(iscan->__visited_ino,552					   highest_skipped);553 554		trace_xchk_iscan_skip(iscan);555	}556 557	iscan->__batch_ino = NULLFSINO;558	iscan->__skipped_inomask = 0;559 560	mutex_unlock(&iscan->lock);561}562 563/*564 * Advance the inode scan cursor to the next allocated inode and return up to565 * 64 consecutive allocated inodes starting with the cursor position.566 */567STATIC int568xchk_iscan_iter_batch(569	struct xchk_iscan	*iscan)570{571	struct xfs_scrub	*sc = iscan->sc;572	int			ret;573 574	xchk_iscan_finish_batch(iscan);575 576	if (iscan->iget_timeout)577		iscan->__iget_deadline = jiffies +578					 msecs_to_jiffies(iscan->iget_timeout);579 580	do {581		struct xfs_buf	*agi_bp = NULL;582		struct xfs_perag *pag = NULL;583		xfs_inofree_t	allocmask = 0;584		uint8_t		nr_inodes = 0;585 586		ret = xchk_iscan_advance(iscan, &pag, &agi_bp, &allocmask,587				&nr_inodes);588		if (ret != 1)589			return ret;590 591		if (xchk_iscan_aborted(iscan)) {592			xfs_trans_brelse(sc->tp, agi_bp);593			xfs_perag_put(pag);594			ret = -ECANCELED;595			break;596		}597 598		ret = xchk_iscan_iget(iscan, pag, agi_bp, allocmask, nr_inodes);599	} while (ret == -EAGAIN);600 601	return ret;602}603 604/*605 * Advance the inode scan cursor to the next allocated inode and return the606 * incore inode structure associated with it.607 *608 * Returns 1 if there's a new inode to examine, 0 if we've run out of inodes,609 * -ECANCELED if the live scan aborted, -EBUSY if the incore inode could not be610 * grabbed, or the usual negative errno.611 *612 * If the function returns -EBUSY and the caller can handle skipping an inode,613 * it may call this function again to continue the scan with the next allocated614 * inode.615 */616int617xchk_iscan_iter(618	struct xchk_iscan	*iscan,619	struct xfs_inode	**ipp)620{621	unsigned int		i;622	int			error;623 624	/* Find a cached inode, or go get another batch. */625	for (i = 0; i < XFS_INODES_PER_CHUNK; i++) {626		if (iscan->__inodes[i])627			goto foundit;628	}629 630	error = xchk_iscan_iter_batch(iscan);631	if (error <= 0)632		return error;633 634	ASSERT(iscan->__inodes[0] != NULL);635	i = 0;636 637foundit:638	/* Give the caller our reference. */639	*ipp = iscan->__inodes[i];640	iscan->__inodes[i] = NULL;641	return 1;642}643 644/* Clean up an xfs_iscan_iter call by dropping any inodes that we still hold. */645void646xchk_iscan_iter_finish(647	struct xchk_iscan	*iscan)648{649	struct xfs_scrub	*sc = iscan->sc;650	unsigned int		i;651 652	for (i = 0; i < XFS_INODES_PER_CHUNK; i++) {653		if (iscan->__inodes[i]) {654			xchk_irele(sc, iscan->__inodes[i]);655			iscan->__inodes[i] = NULL;656		}657	}658}659 660/* Mark this inode scan finished and release resources. */661void662xchk_iscan_teardown(663	struct xchk_iscan	*iscan)664{665	xchk_iscan_iter_finish(iscan);666	xchk_iscan_finish(iscan);667	mutex_destroy(&iscan->lock);668}669 670/* Pick an AG from which to start a scan. */671static inline xfs_ino_t672xchk_iscan_rotor(673	struct xfs_mount	*mp)674{675	static atomic_t		agi_rotor;676	unsigned int		r = atomic_inc_return(&agi_rotor) - 1;677 678	/*679	 * Rotoring *backwards* through the AGs, so we add one here before680	 * subtracting from the agcount to arrive at an AG number.681	 */682	r = (r % mp->m_sb.sb_agcount) + 1;683 684	return XFS_AGINO_TO_INO(mp, mp->m_sb.sb_agcount - r, 0);685}686 687/*688 * Set ourselves up to start an inode scan.  If the @iget_timeout and689 * @iget_retry_delay parameters are set, the scan will try to iget each inode690 * for @iget_timeout milliseconds.  If an iget call indicates that the inode is691 * waiting to be inactivated, the CPU will relax for @iget_retry_delay692 * milliseconds after pushing the inactivation workers.693 */694void695xchk_iscan_start(696	struct xfs_scrub	*sc,697	unsigned int		iget_timeout,698	unsigned int		iget_retry_delay,699	struct xchk_iscan	*iscan)700{701	xfs_ino_t		start_ino;702 703	start_ino = xchk_iscan_rotor(sc->mp);704 705	iscan->__batch_ino = NULLFSINO;706	iscan->__skipped_inomask = 0;707 708	iscan->sc = sc;709	clear_bit(XCHK_ISCAN_OPSTATE_ABORTED, &iscan->__opstate);710	iscan->iget_timeout = iget_timeout;711	iscan->iget_retry_delay = iget_retry_delay;712	iscan->__visited_ino = start_ino;713	iscan->cursor_ino = start_ino;714	iscan->scan_start_ino = start_ino;715	mutex_init(&iscan->lock);716	memset(iscan->__inodes, 0, sizeof(iscan->__inodes));717 718	trace_xchk_iscan_start(iscan, start_ino);719}720 721/*722 * Mark this inode as having been visited.  Callers must hold a sufficiently723 * exclusive lock on the inode to prevent concurrent modifications.724 */725void726xchk_iscan_mark_visited(727	struct xchk_iscan	*iscan,728	struct xfs_inode	*ip)729{730	mutex_lock(&iscan->lock);731	iscan->__visited_ino = ip->i_ino;732	trace_xchk_iscan_visit(iscan);733	mutex_unlock(&iscan->lock);734}735 736/*737 * Did we skip this inode because it wasn't allocated when we loaded the batch?738 * If so, it is newly allocated and will not be scanned.  All live updates to739 * this inode must be passed to the caller to maintain scan correctness.740 */741static inline bool742xchk_iscan_skipped(743	const struct xchk_iscan	*iscan,744	xfs_ino_t		ino)745{746	if (iscan->__batch_ino == NULLFSINO)747		return false;748	if (ino < iscan->__batch_ino)749		return false;750	if (ino >= iscan->__batch_ino + XFS_INODES_PER_CHUNK)751		return false;752 753	return iscan->__skipped_inomask & (1ULL << (ino - iscan->__batch_ino));754}755 756/*757 * Do we need a live update for this inode?  This is true if the scanner thread758 * has visited this inode and the scan hasn't been aborted due to errors.759 * Callers must hold a sufficiently exclusive lock on the inode to prevent760 * scanners from reading any inode metadata.761 */762bool763xchk_iscan_want_live_update(764	struct xchk_iscan	*iscan,765	xfs_ino_t		ino)766{767	bool			ret = false;768 769	if (xchk_iscan_aborted(iscan))770		return false;771 772	mutex_lock(&iscan->lock);773 774	trace_xchk_iscan_want_live_update(iscan, ino);775 776	/* Scan is finished, caller should receive all updates. */777	if (iscan->__visited_ino == NULLFSINO) {778		ret = true;779		goto unlock;780	}781 782	/*783	 * No inodes have been visited yet, so the visited cursor points at the784	 * start of the scan range.  The caller should not receive any updates.785	 */786	if (iscan->scan_start_ino == iscan->__visited_ino) {787		ret = false;788		goto unlock;789	}790 791	/*792	 * This inode was not allocated at the time of the iscan batch.793	 * The caller should receive all updates.794	 */795	if (xchk_iscan_skipped(iscan, ino)) {796		ret = true;797		goto unlock;798	}799 800	/*801	 * The visited cursor hasn't yet wrapped around the end of the FS.  If802	 * @ino is inside the starred range, the caller should receive updates:803	 *804	 * 0 ------------ S ************ V ------------ EOFS805	 */806	if (iscan->scan_start_ino <= iscan->__visited_ino) {807		if (ino >= iscan->scan_start_ino &&808		    ino <= iscan->__visited_ino)809			ret = true;810 811		goto unlock;812	}813 814	/*815	 * The visited cursor wrapped around the end of the FS.  If @ino is816	 * inside the starred range, the caller should receive updates:817	 *818	 * 0 ************ V ------------ S ************ EOFS819	 */820	if (ino >= iscan->scan_start_ino || ino <= iscan->__visited_ino)821		ret = true;822 823unlock:824	mutex_unlock(&iscan->lock);825	return ret;826}827