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