xref: /linux/fs/xfs/scrub/parent.c (revision 3fd6c59042dbba50391e30862beac979491145fe)
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
xchk_setup_parent(struct xfs_scrub * sc)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
xchk_parent_actor(struct xfs_scrub * sc,struct xfs_inode * dp,xfs_dir2_dataptr_t dapos,const struct xfs_name * name,xfs_ino_t ino,void * priv)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
xchk_parent_ilock_dir(struct xfs_inode * dp)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
xchk_parent_validate(struct xfs_scrub * sc,xfs_ino_t parent_ino)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 	/* 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 
214 out_unlock:
215 	xfs_iunlock(dp, lock_mode);
216 out_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. */
232 struct 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 
243 struct 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? */
270 STATIC int
xchk_parent_scan_dotdot(struct xfs_scrub * sc,struct xfs_inode * ip,unsigned int attr_flags,const unsigned char * name,unsigned int namelen,const void * value,unsigned int valuelen,void * priv)271 xchk_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. */
300 STATIC int
xchk_parent_pptr_and_dotdot(struct xchk_pptrs * pp)301 xchk_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  */
351 STATIC unsigned int
xchk_parent_lock_dir(struct xfs_scrub * sc,struct xfs_inode * dp)352 xchk_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. */
378 STATIC int
xchk_parent_dirent(struct xchk_pptrs * pp,const struct xfs_name * xname,struct xfs_inode * dp)379 xchk_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. */
410 STATIC int
xchk_parent_iget(struct xchk_pptrs * pp,const struct xfs_parent_rec * pptr,struct xfs_inode ** dpp)411 xchk_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;
450 out_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  */
460 STATIC int
xchk_parent_scan_attr(struct xfs_scrub * sc,struct xfs_inode * ip,unsigned int attr_flags,const unsigned char * name,unsigned int namelen,const void * value,unsigned int valuelen,void * priv)461 xchk_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 
535 out_unlock:
536 	xfs_iunlock(dp, lockmode);
537 out_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  */
547 STATIC int
xchk_parent_revalidate_pptr(struct xchk_pptrs * pp,const struct xfs_name * xname,struct xfs_parent_rec * pptr)548 xchk_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  */
569 STATIC int
xchk_parent_slow_pptr(struct xchk_pptrs * pp,const struct xfs_name * xname,struct xfs_parent_rec * pptr)570 xchk_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 
628 check_dirent:
629 	error = xchk_parent_dirent(pp, xname, dp);
630 out_unlock:
631 	xfs_iunlock(dp, lockmode);
632 out_rele:
633 	xchk_irele(sc, dp);
634 	return error;
635 }
636 
637 /* Check all the parent pointers that we deferred the first time around. */
638 STATIC int
xchk_parent_finish_slow_pptrs(struct xchk_pptrs * pp)639 xchk_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. */
672 STATIC int
xchk_parent_count_pptr(struct xfs_scrub * sc,struct xfs_inode * ip,unsigned int attr_flags,const unsigned char * name,unsigned int namelen,const void * value,unsigned int valuelen,void * priv)673 xchk_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  */
703 STATIC int
xchk_parent_count_pptrs(struct xchk_pptrs * pp)704 xchk_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. */
753 STATIC int
xchk_parent_pptr(struct xfs_scrub * sc)754 xchk_parent_pptr(
755 	struct xfs_scrub	*sc)
756 {
757 	struct xchk_pptrs	*pp;
758 	char			*descr;
759 	int			error;
760 
761 	pp = kvzalloc(sizeof(struct xchk_pptrs), XCHK_GFP_FLAGS);
762 	if (!pp)
763 		return -ENOMEM;
764 	pp->sc = sc;
765 	pp->xname.name = pp->namebuf;
766 
767 	/*
768 	 * Set up some staging memory for parent pointers that we can't check
769 	 * due to locking contention.
770 	 */
771 	descr = xchk_xfile_ino_descr(sc, "slow parent pointer entries");
772 	error = xfarray_create(descr, 0, sizeof(struct xchk_pptr),
773 			&pp->pptr_entries);
774 	kfree(descr);
775 	if (error)
776 		goto out_pp;
777 
778 	descr = xchk_xfile_ino_descr(sc, "slow parent pointer names");
779 	error = xfblob_create(descr, &pp->pptr_names);
780 	kfree(descr);
781 	if (error)
782 		goto out_entries;
783 
784 	error = xchk_xattr_walk(sc, sc->ip, xchk_parent_scan_attr, NULL, pp);
785 	if (error == -ECANCELED) {
786 		error = 0;
787 		goto out_names;
788 	}
789 	if (error)
790 		goto out_names;
791 
792 	error = xchk_parent_finish_slow_pptrs(pp);
793 	if (error == -ETIMEDOUT) {
794 		/* Couldn't grab a lock, scrub was marked incomplete */
795 		error = 0;
796 		goto out_names;
797 	}
798 	if (error)
799 		goto out_names;
800 
801 	if (pp->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
802 		goto out_names;
803 
804 	/*
805 	 * For subdirectories, make sure the dotdot entry references the same
806 	 * inode as the parent pointers.
807 	 *
808 	 * If we're scanning a /consistent/ directory, there should only be
809 	 * one parent pointer, and it should point to the same directory as
810 	 * the dotdot entry.
811 	 *
812 	 * However, a corrupt directory tree might feature a subdirectory with
813 	 * multiple parents.  The directory loop scanner is responsible for
814 	 * correcting that kind of problem, so for now we only validate that
815 	 * the dotdot entry matches /one/ of the parents.
816 	 */
817 	if (S_ISDIR(VFS_I(sc->ip)->i_mode)) {
818 		error = xchk_parent_pptr_and_dotdot(pp);
819 		if (error)
820 			goto out_names;
821 	}
822 
823 	if (pp->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
824 		goto out_names;
825 
826 	/*
827 	 * Complain if the number of parent pointers doesn't match the link
828 	 * count.  This could be a sign of missing parent pointers (or an
829 	 * incorrect link count).
830 	 */
831 	error = xchk_parent_count_pptrs(pp);
832 	if (error)
833 		goto out_names;
834 
835 out_names:
836 	xfblob_destroy(pp->pptr_names);
837 out_entries:
838 	xfarray_destroy(pp->pptr_entries);
839 out_pp:
840 	kvfree(pp);
841 	return error;
842 }
843 
844 /* Scrub a parent pointer. */
845 int
xchk_parent(struct xfs_scrub * sc)846 xchk_parent(
847 	struct xfs_scrub	*sc)
848 {
849 	struct xfs_mount	*mp = sc->mp;
850 	xfs_ino_t		parent_ino;
851 	int			error = 0;
852 
853 	if (xfs_has_parent(mp))
854 		return xchk_parent_pptr(sc);
855 
856 	/*
857 	 * If we're a directory, check that the '..' link points up to
858 	 * a directory that has one entry pointing to us.
859 	 */
860 	if (!S_ISDIR(VFS_I(sc->ip)->i_mode))
861 		return -ENOENT;
862 
863 	/* We're not a special inode, are we? */
864 	if (!xfs_verify_dir_ino(mp, sc->ip->i_ino)) {
865 		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
866 		return 0;
867 	}
868 
869 	do {
870 		if (xchk_should_terminate(sc, &error))
871 			break;
872 
873 		/* Look up '..' */
874 		error = xchk_dir_lookup(sc, sc->ip, &xfs_name_dotdot,
875 				&parent_ino);
876 		if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error))
877 			return error;
878 		if (!xfs_verify_dir_ino(mp, parent_ino)) {
879 			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
880 			return 0;
881 		}
882 
883 		/*
884 		 * Check that the dotdot entry points to a parent directory
885 		 * containing a dirent pointing to this subdirectory.
886 		 */
887 		error = xchk_parent_validate(sc, parent_ino);
888 	} while (error == -EAGAIN);
889 	if (error == -EBUSY) {
890 		/*
891 		 * We could not scan a directory, so we marked the check
892 		 * incomplete.  No further error return is necessary.
893 		 */
894 		return 0;
895 	}
896 
897 	return error;
898 }
899 
900 /*
901  * Decide if this file's extended attributes (and therefore its parent
902  * pointers) have been zapped to satisfy the inode and ifork verifiers.
903  * Checking and repairing should be postponed until the extended attribute
904  * structure is fixed.
905  */
906 bool
xchk_pptr_looks_zapped(struct xfs_inode * ip)907 xchk_pptr_looks_zapped(
908 	struct xfs_inode	*ip)
909 {
910 	struct inode		*inode = VFS_I(ip);
911 
912 	ASSERT(xfs_has_parent(ip->i_mount));
913 
914 	/*
915 	 * Temporary files that cannot be linked into the directory tree do not
916 	 * have attr forks because they cannot ever have parents.
917 	 */
918 	if (inode->i_nlink == 0 && !(inode->i_state & I_LINKABLE))
919 		return false;
920 
921 	/*
922 	 * Directory tree roots do not have parents, so the expected outcome
923 	 * of a parent pointer scan is always the empty set.  It's safe to scan
924 	 * them even if the attr fork was zapped.
925 	 */
926 	if (xchk_inode_is_dirtree_root(ip))
927 		return false;
928 
929 	/*
930 	 * Metadata inodes that are rooted in the superblock do not have any
931 	 * parents.  Hence the attr fork will not be initialized, but there are
932 	 * no parent pointers that might have been zapped.
933 	 */
934 	if (xchk_inode_is_sb_rooted(ip))
935 		return false;
936 
937 	/*
938 	 * Linked and linkable non-rootdir files should always have an
939 	 * attribute fork because that is where parent pointers are
940 	 * stored.  If the fork is absent, something is amiss.
941 	 */
942 	if (!xfs_inode_has_attr_fork(ip))
943 		return true;
944 
945 	/* Repair zapped this file's attr fork a short time ago */
946 	if (xfs_ifork_zapped(ip, XFS_ATTR_FORK))
947 		return true;
948 
949 	/*
950 	 * If the dinode repair found a bad attr fork, it will reset the fork
951 	 * to extents format with zero records and wait for the bmapbta
952 	 * scrubber to reconstruct the block mappings.  The extended attribute
953 	 * structure always contain some content when parent pointers are
954 	 * enabled, so this is a clear sign of a zapped attr fork.
955 	 */
956 	return ip->i_af.if_format == XFS_DINODE_FMT_EXTENTS &&
957 	       ip->i_af.if_nextents == 0;
958 }
959