1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (c) 2023-2024 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <djwong@kernel.org>
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_metafile.h"
16 #include "xfs_quota.h"
19 #include "xfs_parent.h"
20 #include "xfs_bmap_btree.h"
21 #include "xfs_trans_space.h"
23 #include "xfs_rtgroup.h"
24 #include "scrub/scrub.h"
25 #include "scrub/common.h"
26 #include "scrub/trace.h"
27 #include "scrub/readdir.h"
28 #include "scrub/repair.h"
31 * Metadata Directory Tree Paths
32 * =============================
34 * A filesystem with metadir enabled expects to find metadata structures
35 * attached to files that are accessible by walking a path down the metadata
36 * directory tree. Given the metadir path and the incore inode storing the
37 * metadata, this scrubber ensures that the ondisk metadir path points to the
38 * ondisk inode represented by the incore inode.
41 struct xchk_metapath
{
45 struct xfs_name xname
;
47 /* Directory update for repairs */
48 struct xfs_dir_update du
;
50 /* Path down to this metadata file from the parent directory */
53 /* Directory parent of the metadata file. */
56 /* Locks held on dp */
57 unsigned int dp_ilock_flags
;
59 /* Transaction block reservations */
60 unsigned int link_resblks
;
61 unsigned int unlink_resblks
;
63 /* Parent pointer updates */
64 struct xfs_parent_args link_ppargs
;
65 struct xfs_parent_args unlink_ppargs
;
67 /* Scratchpads for removing links */
68 struct xfs_da_args pptr_args
;
71 /* Release resources tracked in the buffer. */
73 xchk_metapath_cleanup(
76 struct xchk_metapath
*mpath
= buf
;
78 if (mpath
->dp_ilock_flags
)
79 xfs_iunlock(mpath
->dp
, mpath
->dp_ilock_flags
);
83 /* Set up a metadir path scan. @path must be dynamically allocated. */
85 xchk_setup_metapath_scan(
91 struct xchk_metapath
*mpath
;
97 error
= xchk_install_live_inode(sc
, ip
);
103 mpath
= kzalloc(sizeof(struct xchk_metapath
), XCHK_GFP_FLAGS
);
111 sc
->buf_cleanup
= xchk_metapath_cleanup
;
114 mpath
->path
= path
; /* path is now owned by mpath */
116 mpath
->xname
.name
= mpath
->path
;
117 mpath
->xname
.len
= strlen(mpath
->path
);
118 mpath
->xname
.type
= xfs_mode_to_ftype(VFS_I(ip
)->i_mode
);
124 /* Scan the /rtgroups directory itself. */
126 xchk_setup_metapath_rtdir(
127 struct xfs_scrub
*sc
)
129 if (!sc
->mp
->m_rtdirip
)
132 return xchk_setup_metapath_scan(sc
, sc
->mp
->m_metadirip
,
133 kasprintf(GFP_KERNEL
, "rtgroups"), sc
->mp
->m_rtdirip
);
136 /* Scan a rtgroup inode under the /rtgroups directory. */
138 xchk_setup_metapath_rtginode(
139 struct xfs_scrub
*sc
,
140 enum xfs_rtg_inodes type
)
142 struct xfs_rtgroup
*rtg
;
143 struct xfs_inode
*ip
;
146 rtg
= xfs_rtgroup_get(sc
->mp
, sc
->sm
->sm_agno
);
150 ip
= rtg
->rtg_inodes
[type
];
156 error
= xchk_setup_metapath_scan(sc
, sc
->mp
->m_rtdirip
,
157 xfs_rtginode_path(rtg_rgno(rtg
), type
), ip
);
160 xfs_rtgroup_put(rtg
);
164 # define xchk_setup_metapath_rtdir(...) (-ENOENT)
165 # define xchk_setup_metapath_rtginode(...) (-ENOENT)
166 #endif /* CONFIG_XFS_RT */
168 #ifdef CONFIG_XFS_QUOTA
169 /* Scan the /quota directory itself. */
171 xchk_setup_metapath_quotadir(
172 struct xfs_scrub
*sc
)
174 struct xfs_trans
*tp
;
175 struct xfs_inode
*dp
= NULL
;
178 error
= xfs_trans_alloc_empty(sc
->mp
, &tp
);
182 error
= xfs_dqinode_load_parent(tp
, &dp
);
183 xfs_trans_cancel(tp
);
187 error
= xchk_setup_metapath_scan(sc
, sc
->mp
->m_metadirip
,
188 kasprintf(GFP_KERNEL
, "quota"), dp
);
193 /* Scan a quota inode under the /quota directory. */
195 xchk_setup_metapath_dqinode(
196 struct xfs_scrub
*sc
,
199 struct xfs_trans
*tp
= NULL
;
200 struct xfs_inode
*dp
= NULL
;
201 struct xfs_inode
*ip
= NULL
;
205 error
= xfs_trans_alloc_empty(sc
->mp
, &tp
);
209 error
= xfs_dqinode_load_parent(tp
, &dp
);
213 error
= xfs_dqinode_load(tp
, dp
, type
, &ip
);
217 xfs_trans_cancel(tp
);
220 path
= kasprintf(GFP_KERNEL
, "%s", xfs_dqinode_path(type
));
221 error
= xchk_setup_metapath_scan(sc
, dp
, path
, ip
);
228 xfs_trans_cancel(tp
);
232 # define xchk_setup_metapath_quotadir(...) (-ENOENT)
233 # define xchk_setup_metapath_dqinode(...) (-ENOENT)
234 #endif /* CONFIG_XFS_QUOTA */
238 struct xfs_scrub
*sc
)
240 if (!xfs_has_metadir(sc
->mp
))
245 switch (sc
->sm
->sm_ino
) {
246 case XFS_SCRUB_METAPATH_PROBE
:
247 /* Just probing, nothing else to do. */
251 case XFS_SCRUB_METAPATH_RTDIR
:
252 return xchk_setup_metapath_rtdir(sc
);
253 case XFS_SCRUB_METAPATH_RTBITMAP
:
254 return xchk_setup_metapath_rtginode(sc
, XFS_RTGI_BITMAP
);
255 case XFS_SCRUB_METAPATH_RTSUMMARY
:
256 return xchk_setup_metapath_rtginode(sc
, XFS_RTGI_SUMMARY
);
257 case XFS_SCRUB_METAPATH_QUOTADIR
:
258 return xchk_setup_metapath_quotadir(sc
);
259 case XFS_SCRUB_METAPATH_USRQUOTA
:
260 return xchk_setup_metapath_dqinode(sc
, XFS_DQTYPE_USER
);
261 case XFS_SCRUB_METAPATH_GRPQUOTA
:
262 return xchk_setup_metapath_dqinode(sc
, XFS_DQTYPE_GROUP
);
263 case XFS_SCRUB_METAPATH_PRJQUOTA
:
264 return xchk_setup_metapath_dqinode(sc
, XFS_DQTYPE_PROJ
);
271 * Take the ILOCK on the metadata directory parent and child. We do not know
272 * that the metadata directory is not corrupt, so we lock the parent and try
273 * to lock the child. Returns 0 if successful, or -EINTR to abort the scrub.
276 xchk_metapath_ilock_both(
277 struct xchk_metapath
*mpath
)
279 struct xfs_scrub
*sc
= mpath
->sc
;
283 xfs_ilock(mpath
->dp
, XFS_ILOCK_EXCL
);
284 if (xchk_ilock_nowait(sc
, XFS_ILOCK_EXCL
)) {
285 mpath
->dp_ilock_flags
|= XFS_ILOCK_EXCL
;
288 xfs_iunlock(mpath
->dp
, XFS_ILOCK_EXCL
);
290 if (xchk_should_terminate(sc
, &error
))
300 /* Unlock parent and child inodes. */
302 xchk_metapath_iunlock(
303 struct xchk_metapath
*mpath
)
305 struct xfs_scrub
*sc
= mpath
->sc
;
307 xchk_iunlock(sc
, XFS_ILOCK_EXCL
);
309 mpath
->dp_ilock_flags
&= ~XFS_ILOCK_EXCL
;
310 xfs_iunlock(mpath
->dp
, XFS_ILOCK_EXCL
);
315 struct xfs_scrub
*sc
)
317 struct xchk_metapath
*mpath
= sc
->buf
;
318 xfs_ino_t ino
= NULLFSINO
;
321 /* Just probing, nothing else to do. */
322 if (sc
->sm
->sm_ino
== XFS_SCRUB_METAPATH_PROBE
)
325 /* Parent required to do anything else. */
326 if (mpath
->dp
== NULL
) {
327 xchk_ino_set_corrupt(sc
, sc
->ip
->i_ino
);
331 error
= xchk_trans_alloc_empty(sc
);
335 error
= xchk_metapath_ilock_both(mpath
);
339 /* Make sure the parent dir has a dirent pointing to this file. */
340 error
= xchk_dir_lookup(sc
, mpath
->dp
, &mpath
->xname
, &ino
);
341 trace_xchk_metapath_lookup(sc
, mpath
->path
, mpath
->dp
, ino
);
342 if (error
== -ENOENT
) {
343 /* No directory entry at all */
344 xchk_ino_set_corrupt(sc
, sc
->ip
->i_ino
);
348 if (!xchk_fblock_xref_process_error(sc
, XFS_DATA_FORK
, 0, &error
))
350 if (ino
!= sc
->ip
->i_ino
) {
351 /* Pointing to wrong inode */
352 xchk_ino_set_corrupt(sc
, sc
->ip
->i_ino
);
356 xchk_metapath_iunlock(mpath
);
358 xchk_trans_cancel(sc
);
362 #ifdef CONFIG_XFS_ONLINE_REPAIR
363 /* Create the dirent represented by the final component of the path. */
366 struct xchk_metapath
*mpath
)
368 struct xfs_scrub
*sc
= mpath
->sc
;
370 mpath
->du
.dp
= mpath
->dp
;
371 mpath
->du
.name
= &mpath
->xname
;
372 mpath
->du
.ip
= sc
->ip
;
374 if (xfs_has_parent(sc
->mp
))
375 mpath
->du
.ppargs
= &mpath
->link_ppargs
;
377 mpath
->du
.ppargs
= NULL
;
379 trace_xrep_metapath_link(sc
, mpath
->path
, mpath
->dp
, sc
->ip
->i_ino
);
381 return xfs_dir_add_child(sc
->tp
, mpath
->link_resblks
, &mpath
->du
);
384 /* Remove the dirent at the final component of the path. */
386 xrep_metapath_unlink(
387 struct xchk_metapath
*mpath
,
389 struct xfs_inode
*ip
)
391 struct xfs_parent_rec rec
;
392 struct xfs_scrub
*sc
= mpath
->sc
;
393 struct xfs_mount
*mp
= sc
->mp
;
396 trace_xrep_metapath_unlink(sc
, mpath
->path
, mpath
->dp
, ino
);
399 /* The child inode isn't allocated. Junk the dirent. */
400 xfs_trans_log_inode(sc
->tp
, mpath
->dp
, XFS_ILOG_CORE
);
401 return xfs_dir_removename(sc
->tp
, mpath
->dp
, &mpath
->xname
,
402 ino
, mpath
->unlink_resblks
);
405 mpath
->du
.dp
= mpath
->dp
;
406 mpath
->du
.name
= &mpath
->xname
;
408 mpath
->du
.ppargs
= NULL
;
410 /* Figure out if we're removing a parent pointer too. */
411 if (xfs_has_parent(mp
)) {
412 xfs_inode_to_parent_rec(&rec
, ip
);
413 error
= xfs_parent_lookup(sc
->tp
, ip
, &mpath
->xname
, &rec
,
419 mpath
->du
.ppargs
= &mpath
->unlink_ppargs
;
426 return xfs_dir_remove_child(sc
->tp
, mpath
->unlink_resblks
, &mpath
->du
);
430 * Try to create a dirent in @mpath->dp with the name @mpath->xname that points
431 * to @sc->ip. Returns:
433 * -EEXIST and an @alleged_child if the dirent that points to the wrong inode;
434 * 0 if there is now a dirent pointing to @sc->ip; or
435 * A negative errno on error.
438 xrep_metapath_try_link(
439 struct xchk_metapath
*mpath
,
440 xfs_ino_t
*alleged_child
)
442 struct xfs_scrub
*sc
= mpath
->sc
;
446 /* Allocate transaction, lock inodes, join to transaction. */
447 error
= xchk_trans_alloc(sc
, mpath
->link_resblks
);
451 error
= xchk_metapath_ilock_both(mpath
);
453 xchk_trans_cancel(sc
);
456 xfs_trans_ijoin(sc
->tp
, mpath
->dp
, 0);
457 xfs_trans_ijoin(sc
->tp
, sc
->ip
, 0);
459 error
= xchk_dir_lookup(sc
, mpath
->dp
, &mpath
->xname
, &ino
);
460 trace_xrep_metapath_lookup(sc
, mpath
->path
, mpath
->dp
, ino
);
461 if (error
== -ENOENT
) {
463 * There is no dirent in the directory. Create an entry
464 * pointing to @sc->ip.
466 error
= xrep_metapath_link(mpath
);
470 error
= xrep_trans_commit(sc
);
471 xchk_metapath_iunlock(mpath
);
477 if (ino
== sc
->ip
->i_ino
) {
478 /* The dirent already points to @sc->ip; we're done. */
484 * The dirent points elsewhere; pass that back so that the caller
485 * can try to remove the dirent.
487 *alleged_child
= ino
;
491 xchk_trans_cancel(sc
);
492 xchk_metapath_iunlock(mpath
);
497 * Take the ILOCK on the metadata directory parent and a bad child, if one is
498 * supplied. We do not know that the metadata directory is not corrupt, so we
499 * lock the parent and try to lock the child. Returns 0 if successful, or
500 * -EINTR to abort the repair. The lock state of @dp is not recorded in @mpath.
503 xchk_metapath_ilock_parent_and_child(
504 struct xchk_metapath
*mpath
,
505 struct xfs_inode
*ip
)
507 struct xfs_scrub
*sc
= mpath
->sc
;
511 xfs_ilock(mpath
->dp
, XFS_ILOCK_EXCL
);
512 if (!ip
|| xfs_ilock_nowait(ip
, XFS_ILOCK_EXCL
))
514 xfs_iunlock(mpath
->dp
, XFS_ILOCK_EXCL
);
516 if (xchk_should_terminate(sc
, &error
))
527 * Try to remove a dirent in @mpath->dp with the name @mpath->xname that points
528 * to @alleged_child. Returns:
530 * 0 if there is no longer a dirent;
531 * -EEXIST if the dirent points to @sc->ip;
532 * -EAGAIN and an updated @alleged_child if the dirent points elsewhere; or
533 * A negative errno for any other error.
536 xrep_metapath_try_unlink(
537 struct xchk_metapath
*mpath
,
538 xfs_ino_t
*alleged_child
)
540 struct xfs_scrub
*sc
= mpath
->sc
;
541 struct xfs_inode
*ip
= NULL
;
545 ASSERT(*alleged_child
!= sc
->ip
->i_ino
);
547 trace_xrep_metapath_try_unlink(sc
, mpath
->path
, mpath
->dp
,
551 * Allocate transaction, grab the alleged child inode, lock inodes,
552 * join to transaction.
554 error
= xchk_trans_alloc(sc
, mpath
->unlink_resblks
);
558 error
= xchk_iget(sc
, *alleged_child
, &ip
);
559 if (error
== -EINVAL
|| error
== -ENOENT
) {
560 /* inode number is bogus, junk the dirent */
564 xchk_trans_cancel(sc
);
568 error
= xchk_metapath_ilock_parent_and_child(mpath
, ip
);
570 xchk_trans_cancel(sc
);
573 xfs_trans_ijoin(sc
->tp
, mpath
->dp
, 0);
575 xfs_trans_ijoin(sc
->tp
, ip
, 0);
577 error
= xchk_dir_lookup(sc
, mpath
->dp
, &mpath
->xname
, &ino
);
578 trace_xrep_metapath_lookup(sc
, mpath
->path
, mpath
->dp
, ino
);
579 if (error
== -ENOENT
) {
581 * There is no dirent in the directory anymore. We're ready to
582 * try the link operation again.
590 if (ino
== sc
->ip
->i_ino
) {
591 /* The dirent already points to @sc->ip; we're done. */
597 * The dirent does not point to the alleged child. Update the caller
598 * and signal that we want to be called again.
600 if (ino
!= *alleged_child
) {
601 *alleged_child
= ino
;
606 /* Remove the link to the child. */
607 error
= xrep_metapath_unlink(mpath
, ino
, ip
);
611 error
= xrep_trans_commit(sc
);
615 xchk_trans_cancel(sc
);
617 xfs_iunlock(mpath
->dp
, XFS_ILOCK_EXCL
);
619 xfs_iunlock(ip
, XFS_ILOCK_EXCL
);
626 * Make sure the metadata directory path points to the child being examined.
628 * Repair needs to be able to create a directory structure, create its own
629 * transactions, and take ILOCKs. This function /must/ be called after all
630 * other repairs have completed.
634 struct xfs_scrub
*sc
)
636 struct xchk_metapath
*mpath
= sc
->buf
;
637 struct xfs_mount
*mp
= sc
->mp
;
640 /* Just probing, nothing to repair. */
641 if (sc
->sm
->sm_ino
== XFS_SCRUB_METAPATH_PROBE
)
644 /* Parent required to do anything else. */
645 if (mpath
->dp
== NULL
)
646 return -EFSCORRUPTED
;
649 * Make sure the child file actually has an attr fork to receive a new
650 * parent pointer if the fs has parent pointers.
652 if (xfs_has_parent(mp
)) {
653 error
= xfs_attr_add_fork(sc
->ip
,
654 sizeof(struct xfs_attr_sf_hdr
), 1);
659 /* Compute block reservation required to unlink and link a file. */
660 mpath
->unlink_resblks
= xfs_remove_space_res(mp
, MAXNAMELEN
);
661 mpath
->link_resblks
= xfs_link_space_res(mp
, MAXNAMELEN
);
664 xfs_ino_t alleged_child
;
666 /* Re-establish the link, or tell us which inode to remove. */
667 error
= xrep_metapath_try_link(mpath
, &alleged_child
);
670 if (error
!= -EEXIST
)
674 * Remove an incorrect link to an alleged child, or tell us
675 * which inode to remove.
678 error
= xrep_metapath_try_unlink(mpath
, &alleged_child
);
679 } while (error
== -EAGAIN
);
680 if (error
== -EEXIST
) {
681 /* Link established; we're done. */
689 #endif /* CONFIG_XFS_ONLINE_REPAIR */