File Index
Files and directories
Sign in
FILE

parent.c

File preview with syntax highlighting.

linux-6.19.14/fs/xfs/scrub/parent.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  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_attr.h"
 19#include "xfs_parent.h"
 20#include "scrub/scrub.h"
 21#include "scrub/common.h"
 22#include "scrub/readdir.h"
 23#include "scrub/tempfile.h"
 24#include "scrub/repair.h"
 25#include "scrub/listxattr.h"
 26#include "scrub/xfile.h"
 27#include "scrub/xfarray.h"
 28#include "scrub/xfblob.h"
 29#include "scrub/trace.h"
 30
 31/* Set us up to scrub parents. */
 32int
 33xchk_setup_parent(
 34	struct xfs_scrub	*sc)
 35{
 36	int			error;
 37
 38	if (xchk_could_repair(sc)) {
 39		error = xrep_setup_parent(sc);
 40		if (error)
 41			return error;
 42	}
 43
 44	return xchk_setup_inode_contents(sc, 0);
 45}
 46
 47/* Parent pointers */
 48
 49/* Look for an entry in a parent pointing to this inode. */
 50
 51struct xchk_parent_ctx {
 52	struct xfs_scrub	*sc;
 53	xfs_nlink_t		nlink;
 54};
 55
 56/* Look for a single entry in a directory pointing to an inode. */
 57STATIC int
 58xchk_parent_actor(
 59	struct xfs_scrub	*sc,
 60	struct xfs_inode	*dp,
 61	xfs_dir2_dataptr_t	dapos,
 62	const struct xfs_name	*name,
 63	xfs_ino_t		ino,
 64	void			*priv)
 65{
 66	struct xchk_parent_ctx	*spc = priv;
 67	int			error = 0;
 68
 69	/* Does this name make sense? */
 70	if (!xfs_dir2_namecheck(name->name, name->len))
 71		error = -EFSCORRUPTED;
 72	if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0, &error))
 73		return error;
 74
 75	if (sc->ip->i_ino == ino)
 76		spc->nlink++;
 77
 78	if (xchk_should_terminate(spc->sc, &error))
 79		return error;
 80
 81	return 0;
 82}
 83
 84/*
 85 * Try to lock a parent directory for checking dirents.  Returns the inode
 86 * flags for the locks we now hold, or zero if we failed.
 87 */
 88STATIC unsigned int
 89xchk_parent_ilock_dir(
 90	struct xfs_inode	*dp)
 91{
 92	if (!xfs_ilock_nowait(dp, XFS_ILOCK_SHARED))
 93		return 0;
 94
 95	if (!xfs_need_iread_extents(&dp->i_df))
 96		return XFS_ILOCK_SHARED;
 97
 98	xfs_iunlock(dp, XFS_ILOCK_SHARED);
 99
100	if (!xfs_ilock_nowait(dp, XFS_ILOCK_EXCL))
101		return 0;
102
103	return XFS_ILOCK_EXCL;
104}
105
106/*
107 * Given the inode number of the alleged parent of the inode being scrubbed,
108 * try to validate that the parent has exactly one directory entry pointing
109 * back to the inode being scrubbed.  Returns -EAGAIN if we need to revalidate
110 * the dotdot entry.
111 */
112STATIC int
113xchk_parent_validate(
114	struct xfs_scrub	*sc,
115	xfs_ino_t		parent_ino)
116{
117	struct xchk_parent_ctx	spc = {
118		.sc		= sc,
119		.nlink		= 0,
120	};
121	struct xfs_mount	*mp = sc->mp;
122	struct xfs_inode	*dp = NULL;
123	xfs_nlink_t		expected_nlink;
124	unsigned int		lock_mode;
125	int			error = 0;
126
127	/* Is this the root dir?  Then '..' must point to itself. */
128	if (sc->ip == mp->m_rootip) {
129		if (sc->ip->i_ino != mp->m_sb.sb_rootino ||
130		    sc->ip->i_ino != parent_ino)
131			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
132		return 0;
133	}
134
135	/* Is this the metadata root dir?  Then '..' must point to itself. */
136	if (sc->ip == mp->m_metadirip) {
137		if (sc->ip->i_ino != mp->m_sb.sb_metadirino ||
138		    sc->ip->i_ino != parent_ino)
139			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
140		return 0;
141	}
142
143	/* '..' must not point to ourselves. */
144	if (sc->ip->i_ino == parent_ino) {
145		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
146		return 0;
147	}
148
149	/*
150	 * If we're an unlinked directory, the parent /won't/ have a link
151	 * to us.  Otherwise, it should have one link.
152	 */
153	expected_nlink = VFS_I(sc->ip)->i_nlink == 0 ? 0 : 1;
154
155	/*
156	 * Grab the parent directory inode.  This must be released before we
157	 * cancel the scrub transaction.
158	 *
159	 * If _iget returns -EINVAL or -ENOENT then the parent inode number is
160	 * garbage and the directory is corrupt.  If the _iget returns
161	 * -EFSCORRUPTED or -EFSBADCRC then the parent is corrupt which is a
162	 *  cross referencing error.  Any other error is an operational error.
163	 */
164	error = xchk_iget(sc, parent_ino, &dp);
165	if (error == -EINVAL || error == -ENOENT) {
166		error = -EFSCORRUPTED;
167		xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error);
168		return error;
169	}
170	if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0, &error))
171		return error;
172	if (dp == sc->ip || xrep_is_tempfile(dp) ||
173	    !S_ISDIR(VFS_I(dp)->i_mode)) {
174		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
175		goto out_rele;
176	}
177
178	lock_mode = xchk_parent_ilock_dir(dp);
179	if (!lock_mode) {
180		xchk_iunlock(sc, XFS_ILOCK_EXCL);
181		xchk_ilock(sc, XFS_ILOCK_EXCL);
182		error = -EAGAIN;
183		goto out_rele;
184	}
185
186	/*
187	 * We cannot yet validate this parent pointer if the directory looks as
188	 * though it has been zapped by the inode record repair code.
189	 */
190	if (xchk_dir_looks_zapped(dp)) {
191		error = -EBUSY;
192		xchk_set_incomplete(sc);
193		goto out_unlock;
194	}
195
196	/* Metadata and regular inodes cannot cross trees. */
197	if (xfs_is_metadir_inode(dp) != xfs_is_metadir_inode(sc->ip)) {
198		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
199		goto out_unlock;
200	}
201
202	/* Look for a directory entry in the parent pointing to the child. */
203	error = xchk_dir_walk(sc, dp, xchk_parent_actor, &spc);
204	if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0, &error))
205		goto out_unlock;
206
207	/*
208	 * Ensure that the parent has as many links to the child as the child
209	 * thinks it has to the parent.
210	 */
211	if (spc.nlink != expected_nlink)
212		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
213
214out_unlock:
215	xfs_iunlock(dp, lock_mode);
216out_rele:
217	xchk_irele(sc, dp);
218	return error;
219}
220
221/*
222 * Checking of Parent Pointers
223 * ===========================
224 *
225 * On filesystems with directory parent pointers, we check the referential
226 * integrity by visiting each parent pointer of a child file and checking that
227 * the directory referenced by the pointer actually has a dirent pointing
228 * forward to the child file.
229 */
230
231/* Deferred parent pointer entry that we saved for later. */
232struct xchk_pptr {
233	/* Cookie for retrieval of the pptr name. */
234	xfblob_cookie		name_cookie;
235
236	/* Parent pointer record. */
237	struct xfs_parent_rec	pptr_rec;
238
239	/* Length of the pptr name. */
240	uint8_t			namelen;
241};
242
243struct xchk_pptrs {
244	struct xfs_scrub	*sc;
245
246	/* How many parent pointers did we find at the end? */
247	unsigned long long	pptrs_found;
248
249	/* Parent of this directory. */
250	xfs_ino_t		parent_ino;
251
252	/* Fixed-size array of xchk_pptr structures. */
253	struct xfarray		*pptr_entries;
254
255	/* Blobs containing parent pointer names. */
256	struct xfblob		*pptr_names;
257
258	/* Scratch buffer for scanning pptr xattrs */
259	struct xfs_da_args	pptr_args;
260
261	/* If we've cycled the ILOCK, we must revalidate all deferred pptrs. */
262	bool			need_revalidate;
263
264	/* Name buffer */
265	struct xfs_name		xname;
266	char			namebuf[MAXNAMELEN];
267};
268
269/* Does this parent pointer match the dotdot entry? */
270STATIC int
271xchk_parent_scan_dotdot(
272	struct xfs_scrub		*sc,
273	struct xfs_inode		*ip,
274	unsigned int			attr_flags,
275	const unsigned char		*name,
276	unsigned int			namelen,
277	const void			*value,
278	unsigned int			valuelen,
279	void				*priv)
280{
281	struct xchk_pptrs		*pp = priv;
282	xfs_ino_t			parent_ino;
283	int				error;
284
285	if (!(attr_flags & XFS_ATTR_PARENT))
286		return 0;
287
288	error = xfs_parent_from_attr(sc->mp, attr_flags, name, namelen, value,
289			valuelen, &parent_ino, NULL);
290	if (error)
291		return error;
292
293	if (pp->parent_ino == parent_ino)
294		return -ECANCELED;
295
296	return 0;
297}
298
299/* Look up the dotdot entry so that we can check it as we walk the pptrs. */
300STATIC int
301xchk_parent_pptr_and_dotdot(
302	struct xchk_pptrs	*pp)
303{
304	struct xfs_scrub	*sc = pp->sc;
305	int			error;
306
307	/* Look up '..' */
308	error = xchk_dir_lookup(sc, sc->ip, &xfs_name_dotdot, &pp->parent_ino);
309	if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error))
310		return error;
311	if (!xfs_verify_dir_ino(sc->mp, pp->parent_ino)) {
312		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
313		return 0;
314	}
315
316	/* Is this the root dir?  Then '..' must point to itself. */
317	if (xchk_inode_is_dirtree_root(sc->ip)) {
318		if (sc->ip->i_ino != pp->parent_ino)
319			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
320		return 0;
321	}
322
323	/*
324	 * If this is now an unlinked directory, the dotdot value is
325	 * meaningless as long as it points to a valid inode.
326	 */
327	if (VFS_I(sc->ip)->i_nlink == 0)
328		return 0;
329
330	if (pp->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
331		return 0;
332
333	/* Otherwise, walk the pptrs again, and check. */
334	error = xchk_xattr_walk(sc, sc->ip, xchk_parent_scan_dotdot, NULL, pp);
335	if (error == -ECANCELED) {
336		/* Found a parent pointer that matches dotdot. */
337		return 0;
338	}
339	if (!error || error == -EFSCORRUPTED) {
340		/* Found a broken parent pointer or no match. */
341		xchk_fblock_set_corrupt(sc, XFS_ATTR_FORK, 0);
342		return 0;
343	}
344	return error;
345}
346
347/*
348 * Try to lock a parent directory for checking dirents.  Returns the inode
349 * flags for the locks we now hold, or zero if we failed.
350 */
351STATIC unsigned int
352xchk_parent_lock_dir(
353	struct xfs_scrub	*sc,
354	struct xfs_inode	*dp)
355{
356	if (!xfs_ilock_nowait(dp, XFS_IOLOCK_SHARED))
357		return 0;
358
359	if (!xfs_ilock_nowait(dp, XFS_ILOCK_SHARED)) {
360		xfs_iunlock(dp, XFS_IOLOCK_SHARED);
361		return 0;
362	}
363
364	if (!xfs_need_iread_extents(&dp->i_df))
365		return XFS_IOLOCK_SHARED | XFS_ILOCK_SHARED;
366
367	xfs_iunlock(dp, XFS_ILOCK_SHARED);
368
369	if (!xfs_ilock_nowait(dp, XFS_ILOCK_EXCL)) {
370		xfs_iunlock(dp, XFS_IOLOCK_SHARED);
371		return 0;
372	}
373
374	return XFS_IOLOCK_SHARED | XFS_ILOCK_EXCL;
375}
376
377/* Check the forward link (dirent) associated with this parent pointer. */
378STATIC int
379xchk_parent_dirent(
380	struct xchk_pptrs	*pp,
381	const struct xfs_name	*xname,
382	struct xfs_inode	*dp)
383{
384	struct xfs_scrub	*sc = pp->sc;
385	xfs_ino_t		child_ino;
386	int			error;
387
388	/*
389	 * Use the name attached to this parent pointer to look up the
390	 * directory entry in the alleged parent.
391	 */
392	error = xchk_dir_lookup(sc, dp, xname, &child_ino);
393	if (error == -ENOENT) {
394		xchk_fblock_xref_set_corrupt(sc, XFS_ATTR_FORK, 0);
395		return 0;
396	}
397	if (!xchk_fblock_xref_process_error(sc, XFS_ATTR_FORK, 0, &error))
398		return error;
399
400	/* Does the inode number match? */
401	if (child_ino != sc->ip->i_ino) {
402		xchk_fblock_xref_set_corrupt(sc, XFS_ATTR_FORK, 0);
403		return 0;
404	}
405
406	return 0;
407}
408
409/* Try to grab a parent directory. */
410STATIC int
411xchk_parent_iget(
412	struct xchk_pptrs	*pp,
413	const struct xfs_parent_rec	*pptr,
414	struct xfs_inode	**dpp)
415{
416	struct xfs_scrub	*sc = pp->sc;
417	struct xfs_inode	*ip;
418	xfs_ino_t		parent_ino = be64_to_cpu(pptr->p_ino);
419	int			error;
420
421	/* Validate inode number. */
422	error = xfs_dir_ino_validate(sc->mp, parent_ino);
423	if (error) {
424		xchk_fblock_set_corrupt(sc, XFS_ATTR_FORK, 0);
425		return -ECANCELED;
426	}
427
428	error = xchk_iget(sc, parent_ino, &ip);
429	if (error == -EINVAL || error == -ENOENT) {
430		xchk_fblock_set_corrupt(sc, XFS_ATTR_FORK, 0);
431		return -ECANCELED;
432	}
433	if (!xchk_fblock_xref_process_error(sc, XFS_ATTR_FORK, 0, &error))
434		return error;
435
436	/* The parent must be a directory. */
437	if (!S_ISDIR(VFS_I(ip)->i_mode)) {
438		xchk_fblock_xref_set_corrupt(sc, XFS_ATTR_FORK, 0);
439		goto out_rele;
440	}
441
442	/* Validate generation number. */
443	if (VFS_I(ip)->i_generation != be32_to_cpu(pptr->p_gen)) {
444		xchk_fblock_xref_set_corrupt(sc, XFS_ATTR_FORK, 0);
445		goto out_rele;
446	}
447
448	*dpp = ip;
449	return 0;
450out_rele:
451	xchk_irele(sc, ip);
452	return 0;
453}
454
455/*
456 * Walk an xattr of a file.  If this xattr is a parent pointer, follow it up
457 * to a parent directory and check that the parent has a dirent pointing back
458 * to us.
459 */
460STATIC int
461xchk_parent_scan_attr(
462	struct xfs_scrub	*sc,
463	struct xfs_inode	*ip,
464	unsigned int		attr_flags,
465	const unsigned char	*name,
466	unsigned int		namelen,
467	const void		*value,
468	unsigned int		valuelen,
469	void			*priv)
470{
471	struct xfs_name		xname = {
472		.name		= name,
473		.len		= namelen,
474	};
475	struct xchk_pptrs	*pp = priv;
476	struct xfs_inode	*dp = NULL;
477	const struct xfs_parent_rec *pptr_rec = value;
478	xfs_ino_t		parent_ino;
479	unsigned int		lockmode;
480	int			error;
481
482	if (!(attr_flags & XFS_ATTR_PARENT))
483		return 0;
484
485	error = xfs_parent_from_attr(sc->mp, attr_flags, name, namelen, value,
486			valuelen, &parent_ino, NULL);
487	if (error) {
488		xchk_fblock_set_corrupt(sc, XFS_ATTR_FORK, 0);
489		return error;
490	}
491
492	/* No self-referential parent pointers. */
493	if (parent_ino == sc->ip->i_ino) {
494		xchk_fblock_set_corrupt(sc, XFS_ATTR_FORK, 0);
495		return -ECANCELED;
496	}
497
498	pp->pptrs_found++;
499
500	error = xchk_parent_iget(pp, pptr_rec, &dp);
501	if (error)
502		return error;
503	if (!dp)
504		return 0;
505
506	/* Try to lock the inode. */
507	lockmode = xchk_parent_lock_dir(sc, dp);
508	if (!lockmode) {
509		struct xchk_pptr	save_pp = {
510			.pptr_rec	= *pptr_rec, /* struct copy */
511			.namelen	= namelen,
512		};
513
514		/* Couldn't lock the inode, so save the pptr for later. */
515		trace_xchk_parent_defer(sc->ip, &xname, dp->i_ino);
516
517		error = xfblob_storename(pp->pptr_names, &save_pp.name_cookie,
518				&xname);
519		if (!xchk_fblock_xref_process_error(sc, XFS_ATTR_FORK, 0,
520					&error))
521			goto out_rele;
522
523		error = xfarray_append(pp->pptr_entries, &save_pp);
524		if (!xchk_fblock_xref_process_error(sc, XFS_ATTR_FORK, 0,
525					&error))
526			goto out_rele;
527
528		goto out_rele;
529	}
530
531	error = xchk_parent_dirent(pp, &xname, dp);
532	if (error)
533		goto out_unlock;
534
535out_unlock:
536	xfs_iunlock(dp, lockmode);
537out_rele:
538	xchk_irele(sc, dp);
539	return error;
540}
541
542/*
543 * Revalidate a parent pointer that we collected in the past but couldn't check
544 * because of lock contention.  Returns 0 if the parent pointer is still valid,
545 * -ENOENT if it has gone away on us, or a negative errno.
546 */
547STATIC int
548xchk_parent_revalidate_pptr(
549	struct xchk_pptrs		*pp,
550	const struct xfs_name		*xname,
551	struct xfs_parent_rec		*pptr)
552{
553	struct xfs_scrub		*sc = pp->sc;
554	int				error;
555
556	error = xfs_parent_lookup(sc->tp, sc->ip, xname, pptr, &pp->pptr_args);
557	if (error == -ENOATTR) {
558		/* Parent pointer went away, nothing to revalidate. */
559		return -ENOENT;
560	}
561
562	return error;
563}
564
565/*
566 * Check a parent pointer the slow way, which means we cycle locks a bunch
567 * and put up with revalidation until we get it done.
568 */
569STATIC int
570xchk_parent_slow_pptr(
571	struct xchk_pptrs	*pp,
572	const struct xfs_name	*xname,
573	struct xfs_parent_rec	*pptr)
574{
575	struct xfs_scrub	*sc = pp->sc;
576	struct xfs_inode	*dp = NULL;
577	unsigned int		lockmode;
578	int			error;
579
580	/* Check that the deferred parent pointer still exists. */
581	if (pp->need_revalidate) {
582		error = xchk_parent_revalidate_pptr(pp, xname, pptr);
583		if (error == -ENOENT)
584			return 0;
585		if (!xchk_fblock_xref_process_error(sc, XFS_ATTR_FORK, 0,
586					&error))
587			return error;
588	}
589
590	error = xchk_parent_iget(pp, pptr, &dp);
591	if (error)
592		return error;
593	if (!dp)
594		return 0;
595
596	/*
597	 * If we can grab both IOLOCK and ILOCK of the alleged parent, we
598	 * can proceed with the validation.
599	 */
600	lockmode = xchk_parent_lock_dir(sc, dp);
601	if (lockmode) {
602		trace_xchk_parent_slowpath(sc->ip, xname, dp->i_ino);
603		goto check_dirent;
604	}
605
606	/*
607	 * We couldn't lock the parent dir.  Drop all the locks and try to
608	 * get them again, one at a time.
609	 */
610	xchk_iunlock(sc, sc->ilock_flags);
611	pp->need_revalidate = true;
612
613	trace_xchk_parent_ultraslowpath(sc->ip, xname, dp->i_ino);
614
615	error = xchk_dir_trylock_for_pptrs(sc, dp, &lockmode);
616	if (error)
617		goto out_rele;
618
619	/* Revalidate the parent pointer now that we cycled locks. */
620	error = xchk_parent_revalidate_pptr(pp, xname, pptr);
621	if (error == -ENOENT) {
622		error = 0;
623		goto out_unlock;
624	}
625	if (!xchk_fblock_xref_process_error(sc, XFS_ATTR_FORK, 0, &error))
626		goto out_unlock;
627
628check_dirent:
629	error = xchk_parent_dirent(pp, xname, dp);
630out_unlock:
631	xfs_iunlock(dp, lockmode);
632out_rele:
633	xchk_irele(sc, dp);
634	return error;
635}
636
637/* Check all the parent pointers that we deferred the first time around. */
638STATIC int
639xchk_parent_finish_slow_pptrs(
640	struct xchk_pptrs	*pp)
641{
642	xfarray_idx_t		array_cur;
643	int			error;
644
645	foreach_xfarray_idx(pp->pptr_entries, array_cur) {
646		struct xchk_pptr	pptr;
647
648		if (pp->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
649			return 0;
650
651		error = xfarray_load(pp->pptr_entries, array_cur, &pptr);
652		if (error)
653			return error;
654
655		error = xfblob_loadname(pp->pptr_names, pptr.name_cookie,
656				&pp->xname, pptr.namelen);
657		if (error)
658			return error;
659
660		error = xchk_parent_slow_pptr(pp, &pp->xname, &pptr.pptr_rec);
661		if (error)
662			return error;
663	}
664
665	/* Empty out both xfiles now that we've checked everything. */
666	xfarray_truncate(pp->pptr_entries);
667	xfblob_truncate(pp->pptr_names);
668	return 0;
669}
670
671/* Count the number of parent pointers. */
672STATIC int
673xchk_parent_count_pptr(
674	struct xfs_scrub		*sc,
675	struct xfs_inode		*ip,
676	unsigned int			attr_flags,
677	const unsigned char		*name,
678	unsigned int			namelen,
679	const void			*value,
680	unsigned int			valuelen,
681	void				*priv)
682{
683	struct xchk_pptrs		*pp = priv;
684	int				error;
685
686	if (!(attr_flags & XFS_ATTR_PARENT))
687		return 0;
688
689	error = xfs_parent_from_attr(sc->mp, attr_flags, name, namelen, value,
690			valuelen, NULL, NULL);
691	if (error)
692		return error;
693
694	pp->pptrs_found++;
695	return 0;
696}
697
698/*
699 * Compare the number of parent pointers to the link count.  For
700 * non-directories these should be the same.  For unlinked directories the
701 * count should be zero; for linked directories, it should be nonzero.
702 */
703STATIC int
704xchk_parent_count_pptrs(
705	struct xchk_pptrs	*pp)
706{
707	struct xfs_scrub	*sc = pp->sc;
708	int			error;
709
710	/*
711	 * If we cycled the ILOCK while cross-checking parent pointers with
712	 * dirents, then we need to recalculate the number of parent pointers.
713	 */
714	if (pp->need_revalidate) {
715		pp->pptrs_found = 0;
716		error = xchk_xattr_walk(sc, sc->ip, xchk_parent_count_pptr,
717				NULL, pp);
718		if (error == -EFSCORRUPTED) {
719			/* Found a bad parent pointer */
720			xchk_fblock_set_corrupt(sc, XFS_ATTR_FORK, 0);
721			return 0;
722		}
723		if (error)
724			return error;
725	}
726
727	if (S_ISDIR(VFS_I(sc->ip)->i_mode)) {
728		if (xchk_inode_is_dirtree_root(sc->ip))
729			pp->pptrs_found++;
730
731		if (VFS_I(sc->ip)->i_nlink == 0 && pp->pptrs_found > 0)
732			xchk_ino_set_corrupt(sc, sc->ip->i_ino);
733		else if (VFS_I(sc->ip)->i_nlink > 0 &&
734			 pp->pptrs_found == 0)
735			xchk_ino_set_corrupt(sc, sc->ip->i_ino);
736	} else {
737		/*
738		 * Starting with metadir, we allow checking of parent pointers
739		 * of non-directory files that are children of the superblock.
740		 * Pretend that we found a parent pointer attr.
741		 */
742		if (xfs_has_metadir(sc->mp) && xchk_inode_is_sb_rooted(sc->ip))
743			pp->pptrs_found++;
744
745		if (VFS_I(sc->ip)->i_nlink != pp->pptrs_found)
746			xchk_ino_set_corrupt(sc, sc->ip->i_ino);
747	}
748
749	return 0;
750}
751
752/* Check parent pointers of a file. */
753STATIC int
754xchk_parent_pptr(
755	struct xfs_scrub	*sc)
756{
757	struct xchk_pptrs	*pp;
758	int			error;
759
760	pp = kvzalloc(sizeof(struct xchk_pptrs), XCHK_GFP_FLAGS);
761	if (!pp)
762		return -ENOMEM;
763	pp->sc = sc;
764	pp->xname.name = pp->namebuf;
765
766	/*
767	 * Set up some staging memory for parent pointers that we can't check
768	 * due to locking contention.
769	 */
770	error = xfarray_create("slow parent pointer entries", 0,
771			sizeof(struct xchk_pptr), &pp->pptr_entries);
772	if (error)
773		goto out_pp;
774
775	error = xfblob_create("slow parent pointer names", &pp->pptr_names);
776	if (error)
777		goto out_entries;
778
779	error = xchk_xattr_walk(sc, sc->ip, xchk_parent_scan_attr, NULL, pp);
780	if (error == -ECANCELED) {
781		error = 0;
782		goto out_names;
783	}
784	if (error)
785		goto out_names;
786
787	error = xchk_parent_finish_slow_pptrs(pp);
788	if (error == -ETIMEDOUT) {
789		/* Couldn't grab a lock, scrub was marked incomplete */
790		error = 0;
791		goto out_names;
792	}
793	if (error)
794		goto out_names;
795
796	if (pp->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
797		goto out_names;
798
799	/*
800	 * For subdirectories, make sure the dotdot entry references the same
801	 * inode as the parent pointers.
802	 *
803	 * If we're scanning a /consistent/ directory, there should only be
804	 * one parent pointer, and it should point to the same directory as
805	 * the dotdot entry.
806	 *
807	 * However, a corrupt directory tree might feature a subdirectory with
808	 * multiple parents.  The directory loop scanner is responsible for
809	 * correcting that kind of problem, so for now we only validate that
810	 * the dotdot entry matches /one/ of the parents.
811	 */
812	if (S_ISDIR(VFS_I(sc->ip)->i_mode)) {
813		error = xchk_parent_pptr_and_dotdot(pp);
814		if (error)
815			goto out_names;
816	}
817
818	if (pp->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
819		goto out_names;
820
821	/*
822	 * Complain if the number of parent pointers doesn't match the link
823	 * count.  This could be a sign of missing parent pointers (or an
824	 * incorrect link count).
825	 */
826	error = xchk_parent_count_pptrs(pp);
827	if (error)
828		goto out_names;
829
830out_names:
831	xfblob_destroy(pp->pptr_names);
832out_entries:
833	xfarray_destroy(pp->pptr_entries);
834out_pp:
835	kvfree(pp);
836	return error;
837}
838
839/* Scrub a parent pointer. */
840int
841xchk_parent(
842	struct xfs_scrub	*sc)
843{
844	struct xfs_mount	*mp = sc->mp;
845	xfs_ino_t		parent_ino;
846	int			error = 0;
847
848	if (xfs_has_parent(mp))
849		return xchk_parent_pptr(sc);
850
851	/*
852	 * If we're a directory, check that the '..' link points up to
853	 * a directory that has one entry pointing to us.
854	 */
855	if (!S_ISDIR(VFS_I(sc->ip)->i_mode))
856		return -ENOENT;
857
858	/* We're not a special inode, are we? */
859	if (!xfs_verify_dir_ino(mp, sc->ip->i_ino)) {
860		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
861		return 0;
862	}
863
864	do {
865		if (xchk_should_terminate(sc, &error))
866			break;
867
868		/* Look up '..' */
869		error = xchk_dir_lookup(sc, sc->ip, &xfs_name_dotdot,
870				&parent_ino);
871		if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error))
872			return error;
873		if (!xfs_verify_dir_ino(mp, parent_ino)) {
874			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
875			return 0;
876		}
877
878		/*
879		 * Check that the dotdot entry points to a parent directory
880		 * containing a dirent pointing to this subdirectory.
881		 */
882		error = xchk_parent_validate(sc, parent_ino);
883	} while (error == -EAGAIN);
884	if (error == -EBUSY) {
885		/*
886		 * We could not scan a directory, so we marked the check
887		 * incomplete.  No further error return is necessary.
888		 */
889		return 0;
890	}
891
892	return error;
893}
894
895/*
896 * Decide if this file's extended attributes (and therefore its parent
897 * pointers) have been zapped to satisfy the inode and ifork verifiers.
898 * Checking and repairing should be postponed until the extended attribute
899 * structure is fixed.
900 */
901bool
902xchk_pptr_looks_zapped(
903	struct xfs_inode	*ip)
904{
905	struct inode		*inode = VFS_I(ip);
906
907	ASSERT(xfs_has_parent(ip->i_mount));
908
909	/*
910	 * Temporary files that cannot be linked into the directory tree do not
911	 * have attr forks because they cannot ever have parents.
912	 */
913	if (inode->i_nlink == 0 && !(inode_state_read_once(inode) & I_LINKABLE))
914		return false;
915
916	/*
917	 * Directory tree roots do not have parents, so the expected outcome
918	 * of a parent pointer scan is always the empty set.  It's safe to scan
919	 * them even if the attr fork was zapped.
920	 */
921	if (xchk_inode_is_dirtree_root(ip))
922		return false;
923
924	/*
925	 * Metadata inodes that are rooted in the superblock do not have any
926	 * parents.  Hence the attr fork will not be initialized, but there are
927	 * no parent pointers that might have been zapped.
928	 */
929	if (xchk_inode_is_sb_rooted(ip))
930		return false;
931
932	/*
933	 * Linked and linkable non-rootdir files should always have an
934	 * attribute fork because that is where parent pointers are
935	 * stored.  If the fork is absent, something is amiss.
936	 */
937	if (!xfs_inode_has_attr_fork(ip))
938		return true;
939
940	/* Repair zapped this file's attr fork a short time ago */
941	if (xfs_ifork_zapped(ip, XFS_ATTR_FORK))
942		return true;
943
944	/*
945	 * If the dinode repair found a bad attr fork, it will reset the fork
946	 * to extents format with zero records and wait for the bmapbta
947	 * scrubber to reconstruct the block mappings.  The extended attribute
948	 * structure always contain some content when parent pointers are
949	 * enabled, so this is a clear sign of a zapped attr fork.
950	 */
951	return ip->i_af.if_format == XFS_DINODE_FMT_EXTENTS &&
952	       ip->i_af.if_nextents == 0;
953}
~/ Read-only file preview.