summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2022-07-14 11:06:56 -0700
committerDarrick J. Wong <djwong@kernel.org>2022-11-09 19:07:43 -0800
commit3be5338a72ec543d93a528f576bcf21701e663e5 (patch)
tree8f022d9d5cef68e008aef4a53b669cdc6a8f96bf
parent6a74f77f01266ec7f78dd54892059263645a5dad (diff)
xfs: online repair of parent pointers
Teach the online repair code to fix directory '..' entries (aka directory parent pointers). Since this requires us to know how to scan every dirent in every directory on the filesystem, we can reuse the parent scanner components to validate (or find!) the correct parent entry when rebuilding directories too. Signed-off-by: Darrick J. Wong <djwong@kernel.org>
-rw-r--r--fs/xfs/Makefile1
-rw-r--r--fs/xfs/scrub/dir_repair.c60
-rw-r--r--fs/xfs/scrub/iscan.c7
-rw-r--r--fs/xfs/scrub/iscan.h3
-rw-r--r--fs/xfs/scrub/parent.c3
-rw-r--r--fs/xfs/scrub/parent.h16
-rw-r--r--fs/xfs/scrub/parent_repair.c413
-rw-r--r--fs/xfs/scrub/repair.h2
-rw-r--r--fs/xfs/scrub/scrub.c2
-rw-r--r--fs/xfs/scrub/trace.h2
10 files changed, 476 insertions, 33 deletions
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile
index f39f46d83485..9c21df34b392 100644
--- a/fs/xfs/Makefile
+++ b/fs/xfs/Makefile
@@ -197,6 +197,7 @@ xfs-y += $(addprefix scrub/, \
inode_repair.o \
newbt.o \
nlinks_repair.o \
+ parent_repair.o \
reap.o \
refcount_repair.o \
repair.o \
diff --git a/fs/xfs/scrub/dir_repair.c b/fs/xfs/scrub/dir_repair.c
index 2c58d971be52..6644b0e32369 100644
--- a/fs/xfs/scrub/dir_repair.c
+++ b/fs/xfs/scrub/dir_repair.c
@@ -38,6 +38,7 @@
#include "scrub/xfblob.h"
#include "scrub/readdir.h"
#include "scrub/reap.h"
+#include "scrub/parent.h"
/*
* Directory Repair
@@ -1017,50 +1018,36 @@ xrep_dir_rebuild_tree(
}
/*
- * If we're the root of a directory tree, we are our own parent. If we're an
- * unlinked directory, the parent /won't/ have a link to us. Set the parent
- * directory to the root for both cases. Returns NULLFSINO if we don't know
- * what to do.
+ * Look up the dotdot entry and confirm that it's really the parent.
+ * Returns NULLFSINO if we don't know what to do.
*/
static inline xfs_ino_t
-xrep_dir_self_parent(
+xrep_dir_lookup_parent(
struct xrep_dir *rd)
{
struct xfs_scrub *sc = rd->sc;
+ xfs_ino_t parent_ino;
+ int error;
- if (sc->ip->i_ino == sc->mp->m_sb.sb_rootino)
- return sc->mp->m_sb.sb_rootino;
+ parent_ino = xrep_dotdot_lookup(sc);
+ if (parent_ino == NULLFSINO)
+ return parent_ino;
- if (VFS_I(sc->ip)->i_nlink == 0)
- return sc->mp->m_sb.sb_rootino;
+ error = xrep_parent_confirm(sc, &parent_ino);
+ if (error)
+ return NULLFSINO;
- return NULLFSINO;
+ return parent_ino;
}
-/*
- * Look up the dotdot entry. Returns NULLFSINO if we don't know what to do.
- * The next patch will check this more carefully.
- */
-static inline xfs_ino_t
-xrep_dir_lookup_parent(
- struct xrep_dir *rd)
-{
- return xrep_dotdot_lookup(rd->sc);
-}
-
-/*
- * Try to find the parent of the directory being repaired.
- *
- * NOTE: This function will someday be augmented by the directory parent repair
- * code, which will know how to check the parent and scan the filesystem if
- * we cannot find anything. Inode scans will have to be done before we start
- * salvaging directory entries, so we do this now.
- */
+/* Try to find the parent of the directory being repaired. */
STATIC int
xrep_dir_find_parent(
struct xrep_dir *rd)
{
- rd->parent_ino = xrep_dir_self_parent(rd);
+ int error;
+
+ rd->parent_ino = xrep_parent_self_reference(rd->sc);
if (rd->parent_ino != NULLFSINO)
return 0;
@@ -1068,6 +1055,19 @@ xrep_dir_find_parent(
if (rd->parent_ino != NULLFSINO)
return 0;
+ /*
+ * A full filesystem scan is the last resort. On a busy filesystem,
+ * the scan can fail with -EBUSY if we cannot grab IOLOCKs. That means
+ * that we don't know what who the parent is, so we should return to
+ * userspace.
+ */
+ error = xrep_parent_scan(rd->sc, &rd->parent_ino);
+ if (error)
+ return error;
+
+ if (rd->parent_ino != NULLFSINO)
+ return 0;
+
/* NOTE: A future patch will deal with moving orphans. */
return -EFSCORRUPTED;
}
diff --git a/fs/xfs/scrub/iscan.c b/fs/xfs/scrub/iscan.c
index 29ab56927d8a..cc3bc098818b 100644
--- a/fs/xfs/scrub/iscan.c
+++ b/fs/xfs/scrub/iscan.c
@@ -342,8 +342,13 @@ xchk_iscan_iget(
* It's possible that this inode has lost all of its links but
* hasn't yet been inactivated. If we don't have a transaction
* or it's not writable, flush the inodegc workers and wait.
+ * Otherwise, we have a dirty transaction in progress and the
+ * best we can do is to queue the inodegc workers.
*/
- xfs_inodegc_flush(mp);
+ if (!iscan->iget_nowait)
+ xfs_inodegc_flush(mp);
+ else
+ xfs_inodegc_push(mp);
return xchk_iscan_iget_retry(mp, iscan, true);
}
diff --git a/fs/xfs/scrub/iscan.h b/fs/xfs/scrub/iscan.h
index 947176620bc3..f10b71d9cec4 100644
--- a/fs/xfs/scrub/iscan.h
+++ b/fs/xfs/scrub/iscan.h
@@ -32,6 +32,9 @@ struct xchk_iscan {
/* Wait this many ms to retry an iget. */
unsigned int iget_retry_delay;
+
+ /* True if we cannot allow iget to wait indefinitely. */
+ bool iget_nowait:1;
};
/* Set if the scan has been aborted due to some event in the fs. */
diff --git a/fs/xfs/scrub/parent.c b/fs/xfs/scrub/parent.c
index 9ca8cfe3d3d3..120e3be383fe 100644
--- a/fs/xfs/scrub/parent.c
+++ b/fs/xfs/scrub/parent.c
@@ -17,6 +17,7 @@
#include "scrub/scrub.h"
#include "scrub/common.h"
#include "scrub/readdir.h"
+#include "scrub/parent.h"
/* Set us up to scrub parents. */
int
@@ -68,7 +69,7 @@ xchk_parent_actor(
* Try to iolock the parent dir @dp in shared mode and the child dir @sc->ip
* exclusively.
*/
-STATIC int
+int
xchk_parent_lock_two_dirs(
struct xfs_scrub *sc,
struct xfs_inode *dp)
diff --git a/fs/xfs/scrub/parent.h b/fs/xfs/scrub/parent.h
new file mode 100644
index 000000000000..e1979f5bb001
--- /dev/null
+++ b/fs/xfs/scrub/parent.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2022 Oracle. All Rights Reserved.
+ * Author: Darrick J. Wong <djwong@kernel.org>
+ */
+#ifndef __XFS_SCRUB_PARENT_H__
+#define __XFS_SCRUB_PARENT_H__
+
+int xchk_parent_lock_two_dirs(struct xfs_scrub *sc, struct xfs_inode *dp);
+
+int xrep_parent_confirm(struct xfs_scrub *sc, xfs_ino_t *parent_ino);
+int xrep_parent_scan(struct xfs_scrub *sc, xfs_ino_t *parent_ino);
+
+xfs_ino_t xrep_parent_self_reference(struct xfs_scrub *sc);
+
+#endif /* __XFS_SCRUB_PARENT_H__ */
diff --git a/fs/xfs/scrub/parent_repair.c b/fs/xfs/scrub/parent_repair.c
new file mode 100644
index 000000000000..1d01d00a1501
--- /dev/null
+++ b/fs/xfs/scrub/parent_repair.c
@@ -0,0 +1,413 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2022 Oracle. All Rights Reserved.
+ * Author: Darrick J. Wong <djwong@kernel.org>
+ */
+#include "xfs.h"
+#include "xfs_fs.h"
+#include "xfs_shared.h"
+#include "xfs_format.h"
+#include "xfs_trans_resv.h"
+#include "xfs_mount.h"
+#include "xfs_defer.h"
+#include "xfs_bit.h"
+#include "xfs_log_format.h"
+#include "xfs_trans.h"
+#include "xfs_sb.h"
+#include "xfs_inode.h"
+#include "xfs_icache.h"
+#include "xfs_da_format.h"
+#include "xfs_da_btree.h"
+#include "xfs_dir2.h"
+#include "xfs_bmap_btree.h"
+#include "xfs_dir2_priv.h"
+#include "xfs_trans_space.h"
+#include "xfs_health.h"
+#include "xfs_swapext.h"
+#include "scrub/xfs_scrub.h"
+#include "scrub/scrub.h"
+#include "scrub/common.h"
+#include "scrub/trace.h"
+#include "scrub/repair.h"
+#include "scrub/iscan.h"
+#include "scrub/parent.h"
+#include "scrub/readdir.h"
+#include "scrub/tempfile.h"
+
+struct xrep_findparent_info {
+ /* The directory currently being scanned. */
+ struct xfs_inode *dp;
+
+ /*
+ * Scrub context. We're looking for a @dp containing a directory
+ * entry pointing to sc->ip->i_ino.
+ */
+ struct xfs_scrub *sc;
+
+ /*
+ * Parent that we've found for sc->ip. If we're scanning the entire
+ * directory tree, we need this to ensure that we only find /one/
+ * parent directory.
+ */
+ xfs_ino_t found_parent;
+
+ /*
+ * This is set to true if @found_parent was not observed directly from
+ * the directory scan but by noticing a change in dotdot entries after
+ * cycling the sc->ip IOLOCK.
+ */
+ bool parent_tentative;
+};
+
+/*
+ * If this directory entry points to the scrub target inode, then the directory
+ * we're scanning is the parent of the scrub target inode.
+ */
+STATIC int
+xrep_findparent_dirent(
+ struct xfs_scrub *sc,
+ struct xfs_inode *dp,
+ xfs_dir2_dataptr_t dapos,
+ const struct xfs_name *name,
+ xfs_ino_t ino,
+ void *priv)
+{
+ struct xrep_findparent_info *fpi = priv;
+ int error = 0;
+
+ if (xchk_should_terminate(fpi->sc, &error))
+ return error;
+
+ if (ino != fpi->sc->ip->i_ino)
+ return 0;
+
+ /* Ignore garbage directory entry names. */
+ if (name->len == 0 || !xfs_dir2_namecheck(name->name, name->len))
+ return -EFSCORRUPTED;
+
+ /*
+ * Ignore dotdot and dot entries -- we're looking for parent -> child
+ * links only.
+ */
+ if (name->name[0] == '.' && (name->len == 1 ||
+ (name->len == 2 && name->name[1] == '.')))
+ return 0;
+
+ /* Uhoh, more than one parent for a dir? */
+ if (fpi->found_parent != NULLFSINO &&
+ !(fpi->parent_tentative && fpi->found_parent == fpi->dp->i_ino)) {
+ trace_xrep_findparent_dirent(fpi->sc->ip, 0);
+ return -EFSCORRUPTED;
+ }
+
+ /* We found a potential parent; remember this. */
+ trace_xrep_findparent_dirent(fpi->sc->ip, fpi->dp->i_ino);
+ fpi->found_parent = fpi->dp->i_ino;
+ fpi->parent_tentative = false;
+ return 0;
+}
+
+/*
+ * If this is a directory, walk the dirents looking for any that point to the
+ * scrub target inode.
+ */
+STATIC int
+xrep_findparent_walk_directory(
+ struct xrep_findparent_info *fpi)
+{
+ struct xfs_scrub *sc = fpi->sc;
+ struct xfs_inode *dp = fpi->dp;
+ unsigned int lock_mode;
+ int error = 0;
+
+ /*
+ * The inode being scanned cannot be its own parent, nor can any
+ * temporary directory we created to stage this repair.
+ */
+ if (dp == sc->ip || dp == sc->tempip)
+ return 0;
+
+ /*
+ * Similarly, temporary files created to stage a repair cannot be the
+ * parent of this inode.
+ */
+ if (xrep_is_tempfile(dp))
+ return 0;
+
+ /* Try to lock dp; if we can, we're ready to scan! */
+ if (!xfs_ilock_nowait(dp, XFS_IOLOCK_SHARED)) {
+ xfs_ino_t orig_parent, new_parent;
+
+ /*
+ * We may have to drop the lock on sc->ip to try to lock dp.
+ * Therefore, look up the old dotdot entry for sc->ip so that
+ * we can compare it after we re-lock sc->ip.
+ */
+ orig_parent = xrep_dotdot_lookup(sc);
+
+ error = xchk_parent_lock_two_dirs(sc, dp);
+ if (error)
+ return error;
+
+ /*
+ * It is possible that sc->ip got moved elsewhere in the
+ * directory tree if we dropped sc->ip to grab dp. Note that
+ * rename operations replace the dotdot entry without checking
+ * the old value.
+ *
+ * If the dotdot entry was wrong but there really was only one
+ * parent of sc->ip, then the dotdot entry could now be
+ * correct. Record this new parent as a tentative parent and
+ * keep scanning. If there are more parents of this directory,
+ * we must not touch anything.
+ */
+ new_parent = xrep_dotdot_lookup(sc);
+
+ if (orig_parent != new_parent || VFS_I(sc->ip)->i_nlink == 0) {
+ fpi->found_parent = new_parent;
+ fpi->parent_tentative = true;
+ }
+ }
+
+ /*
+ * If this directory is known to be sick, we cannot scan it reliably
+ * and must abort.
+ */
+ if (xfs_inode_has_sickness(dp, XFS_SICK_INO_CORE |
+ XFS_SICK_INO_BMBTD |
+ XFS_SICK_INO_DIR)) {
+ error = -EFSCORRUPTED;
+ goto out_unlock;
+ }
+
+ /*
+ * Scan the directory to see if there it contains an entry pointing to
+ * the directory that we are repairing.
+ */
+ lock_mode = xfs_ilock_data_map_shared(dp);
+ error = xchk_dir_walk(sc, dp, xrep_findparent_dirent, fpi);
+ xfs_iunlock(dp, lock_mode);
+ if (error)
+ goto out_unlock;
+
+out_unlock:
+ xfs_iunlock(dp, XFS_IOLOCK_SHARED);
+ return error;
+}
+
+/*
+ * Confirm that the directory @parent_ino actually contains a directory entry
+ * pointing to the child @sc->ip->ino. This function returns one of several
+ * ways:
+ *
+ * Returns 0 with @parent_ino unchanged if the parent was confirmed.
+ * Returns 0 with a different @parent_ino if we had to cycle inode locks to
+ * walk the alleged parent and the child's '..' entry was changed in the mean
+ * time.
+ * Returns 0 with @parent_ino set to NULLFSINO if the parent was not valid.
+ * Returns the usual negative errno if something else happened.
+ */
+int
+xrep_parent_confirm(
+ struct xfs_scrub *sc,
+ xfs_ino_t *parent_ino)
+{
+ struct xrep_findparent_info fpi = {
+ .sc = sc,
+ .found_parent = NULLFSINO,
+ };
+ int error;
+
+ /*
+ * The root directory always points to itself. Unlinked dirs can point
+ * anywhere, so we point them at the root dir too.
+ */
+ if (sc->ip == sc->mp->m_rootip || VFS_I(sc->ip)->i_nlink == 0) {
+ *parent_ino = sc->mp->m_sb.sb_rootino;
+ return 0;
+ }
+
+ /* Reject garbage parent inode numbers and self-referential parents. */
+ if (*parent_ino == NULLFSINO)
+ return 0;
+ if (!xfs_verify_dir_ino(sc->mp, *parent_ino) ||
+ *parent_ino == sc->ip->i_ino) {
+ *parent_ino = NULLFSINO;
+ return 0;
+ }
+
+ error = xchk_iget(sc, *parent_ino, &fpi.dp);
+ if (error)
+ return error;
+
+ if (!S_ISDIR(VFS_I(fpi.dp)->i_mode)) {
+ *parent_ino = NULLFSINO;
+ goto out_rele;
+ }
+
+ error = xrep_findparent_walk_directory(&fpi);
+ if (error)
+ goto out_rele;
+
+ *parent_ino = fpi.found_parent;
+out_rele:
+ xchk_irele(sc, fpi.dp);
+ return error;
+}
+
+/*
+ * Scan the entire filesystem looking for a parent inode for the inode being
+ * scrubbed. @sc->ip must not be the root of a directory tree.
+ *
+ * Returns 0 with @parent_ino set to the parent that we found, or the current
+ * value of the child's '..' entry, if it changed when we had to drop the
+ * child's IOLOCK.
+ * Returns 0 with @parent_ino set to NULLFSINO if we didn't find anything.
+ * Returns the usual negative errno if something else happened.
+ */
+int
+xrep_parent_scan(
+ struct xfs_scrub *sc,
+ xfs_ino_t *parent_ino)
+{
+ struct xrep_findparent_info fpi = {
+ .sc = sc,
+ .found_parent = NULLFSINO,
+ };
+ struct xchk_iscan iscan = { };
+ int ret;
+
+ /*
+ * The caller holds a non-empty transaction and a directory ILOCK.
+ * Hence we cannot block the system indefinitely in iget, so we will
+ * retry rapidly for up to five seconds before aborting the operation.
+ */
+ iscan.iget_nowait = true;
+ xchk_iscan_start(&iscan, 5000, 1);
+
+ while ((ret = xchk_iscan_iter(sc, &iscan, &fpi.dp)) == 1) {
+ if (S_ISDIR(VFS_I(fpi.dp)->i_mode))
+ ret = xrep_findparent_walk_directory(&fpi);
+ else
+ ret = 0;
+ xchk_iscan_mark_visited(&iscan, fpi.dp);
+ xchk_irele(sc, fpi.dp);
+ if (ret)
+ break;
+
+ if (xchk_should_terminate(sc, &ret))
+ break;
+ }
+ xchk_iscan_finish(&iscan);
+ if (ret)
+ return ret;
+
+ *parent_ino = fpi.found_parent;
+ return 0;
+}
+
+/*
+ * If we're the root of a directory tree, we are our own parent. If we're an
+ * unlinked directory, the parent /won't/ have a link to us. Set the parent
+ * directory to the root for both cases. Returns NULLFSINO if we don't know
+ * what to do.
+ */
+xfs_ino_t
+xrep_parent_self_reference(
+ struct xfs_scrub *sc)
+{
+ if (sc->ip->i_ino == sc->mp->m_sb.sb_rootino)
+ return sc->mp->m_sb.sb_rootino;
+
+ if (VFS_I(sc->ip)->i_nlink == 0)
+ return sc->mp->m_sb.sb_rootino;
+
+ return NULLFSINO;
+}
+
+/*
+ * Repairing The Directory Parent Pointer
+ * ======================================
+ *
+ * Currently, only directories support parent pointers (in the form of '..'
+ * entries), so we simply scan the filesystem and update the '..' entry.
+ *
+ * Note that because the only parent pointer is the dotdot entry, we won't
+ * touch an unhealthy directory, since the directory repair code is perfectly
+ * capable of rebuilding a directory with the proper parent inode.
+ */
+
+/* Replace a directory's parent '..' pointer. */
+STATIC int
+xrep_parent_reset_dir(
+ struct xfs_scrub *sc,
+ xfs_ino_t parent_ino)
+{
+ unsigned int spaceres;
+ int error;
+
+ trace_xrep_parent_reset_dir(sc->ip, parent_ino);
+
+ /*
+ * Reserve more space just in case we have to expand the dir. We're
+ * allowed to exceed quota to repair inconsistent metadata.
+ */
+ spaceres = XFS_RENAME_SPACE_RES(sc->mp, 2);
+ error = xfs_trans_reserve_more_inode(sc->tp, sc->ip, spaceres, 0,
+ true);
+ if (error)
+ return error;
+
+ /* Replace the dotdot entry. */
+ return xfs_dir_replace(sc->tp, sc->ip, &xfs_name_dotdot, parent_ino,
+ spaceres);
+}
+
+int
+xrep_parent(
+ struct xfs_scrub *sc)
+{
+ xfs_ino_t parent_ino, curr_parent;
+ unsigned int sick, checked;
+ int error;
+
+ /*
+ * Avoid sick directories. The parent pointer scrubber dropped the
+ * ILOCK and MMAPLOCK, but we still hold IOLOCK_EXCL on the directory.
+ * There shouldn't be anyone else clearing the directory's sick status.
+ */
+ xfs_inode_measure_sickness(sc->ip, &sick, &checked);
+ if (sick & XFS_SICK_INO_DIR)
+ return -EFSCORRUPTED;
+
+ parent_ino = xrep_parent_self_reference(sc);
+ if (parent_ino != NULLFSINO)
+ goto reset_parent;
+
+ /* Scan the entire filesystem for a parent. */
+ error = xrep_parent_scan(sc, &parent_ino);
+ if (error)
+ return error;
+ if (parent_ino == NULLFSINO)
+ return -EFSCORRUPTED;
+
+reset_parent:
+ /* If the '..' entry is already set to the parent inode, we're done. */
+ curr_parent = xrep_dotdot_lookup(sc);
+ if (curr_parent != NULLFSINO && curr_parent == parent_ino)
+ return 0;
+
+ /* Last chance to abort before we start committing fixes. */
+ if (xchk_should_terminate(sc, &error))
+ return error;
+
+ /* Re-take the ILOCK, we're going to need it to modify the dir. */
+ xchk_ilock(sc, XFS_ILOCK_EXCL);
+ xfs_trans_ijoin(sc->tp, sc->ip, 0);
+
+ error = xrep_ino_dqattach(sc);
+ if (error)
+ return error;
+
+ return xrep_parent_reset_dir(sc, parent_ino);
+}
diff --git a/fs/xfs/scrub/repair.h b/fs/xfs/scrub/repair.h
index bc0ce5a4b414..d1a5faafcee0 100644
--- a/fs/xfs/scrub/repair.h
+++ b/fs/xfs/scrub/repair.h
@@ -119,6 +119,7 @@ int xrep_nlinks(struct xfs_scrub *sc);
int xrep_fscounters(struct xfs_scrub *sc);
int xrep_xattr(struct xfs_scrub *sc);
int xrep_directory(struct xfs_scrub *sc);
+int xrep_parent(struct xfs_scrub *sc);
#ifdef CONFIG_XFS_RT
int xrep_rtbitmap(struct xfs_scrub *sc);
@@ -229,6 +230,7 @@ xrep_setup_rtsummary(
#define xrep_rtsummary xrep_notsupported
#define xrep_xattr xrep_notsupported
#define xrep_directory xrep_notsupported
+#define xrep_parent xrep_notsupported
#endif /* CONFIG_XFS_ONLINE_REPAIR */
diff --git a/fs/xfs/scrub/scrub.c b/fs/xfs/scrub/scrub.c
index 1695e9d2f104..39ad06e6b2d0 100644
--- a/fs/xfs/scrub/scrub.c
+++ b/fs/xfs/scrub/scrub.c
@@ -345,7 +345,7 @@ static const struct xchk_meta_ops meta_scrub_ops[] = {
.type = ST_INODE,
.setup = xchk_setup_parent,
.scrub = xchk_parent,
- .repair = xrep_notsupported,
+ .repair = xrep_parent,
},
[XFS_SCRUB_TYPE_RTBITMAP] = { /* realtime bitmap */
.type = ST_FS,
diff --git a/fs/xfs/scrub/trace.h b/fs/xfs/scrub/trace.h
index 45ea4c87380b..62ef5f431f93 100644
--- a/fs/xfs/scrub/trace.h
+++ b/fs/xfs/scrub/trace.h
@@ -2478,6 +2478,7 @@ DEFINE_EVENT(xrep_dir_class, name, \
TP_ARGS(dp, parent_ino))
DEFINE_XREP_DIR_CLASS(xrep_dir_rebuild_tree);
DEFINE_XREP_DIR_CLASS(xrep_dir_reset_fork);
+DEFINE_XREP_DIR_CLASS(xrep_parent_reset_dir);
DECLARE_EVENT_CLASS(xrep_dirent_class,
TP_PROTO(struct xfs_inode *dp, struct xfs_name *name, xfs_ino_t ino),
@@ -2535,6 +2536,7 @@ DEFINE_EVENT(xrep_parent_salvage_class, name, \
TP_PROTO(struct xfs_inode *dp, xfs_ino_t ino), \
TP_ARGS(dp, ino))
DEFINE_XREP_PARENT_SALVAGE_CLASS(xrep_dir_salvaged_parent);
+DEFINE_XREP_PARENT_SALVAGE_CLASS(xrep_findparent_dirent);
#endif /* IS_ENABLED(CONFIG_XFS_ONLINE_REPAIR) */