summaryrefslogtreecommitdiff
path: root/fs/xfs/scrub/dir_repair.c
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2021-01-05 17:45:19 -0800
committerDarrick J. Wong <djwong@kernel.org>2021-03-25 17:08:30 -0700
commitd026ac578ed111d462ead9df92f1676c3c4fb2d0 (patch)
treeb2fe6e532c5f97e51107e2e0e021c8c5909fbb3c /fs/xfs/scrub/dir_repair.c
parent72c0b9dbb97568b0c49d2bbf85fa6eadf74f63be (diff)
xfs: move orphan files to the orphanagerepair-dirs_2021-03-25
If we can't find a parent for a file, move it to the orphanage. Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Diffstat (limited to 'fs/xfs/scrub/dir_repair.c')
-rw-r--r--fs/xfs/scrub/dir_repair.c29
1 files changed, 26 insertions, 3 deletions
diff --git a/fs/xfs/scrub/dir_repair.c b/fs/xfs/scrub/dir_repair.c
index e6b66daae289..942ae7e15165 100644
--- a/fs/xfs/scrub/dir_repair.c
+++ b/fs/xfs/scrub/dir_repair.c
@@ -1081,6 +1081,7 @@ xrep_dir(
.parent_ino = NULLFSINO,
.new_nlink = 2,
};
+ bool move_orphanage = false;
int error;
/* Set up some storage */
@@ -1138,15 +1139,37 @@ xrep_dir(
/*
* Validate the parent pointer that we observed while salvaging the
* directory; or scan the filesystem to find one. If we can't find
- * one, we'll set a bogus parent and let the parent pointer repair
- * fix it.
+ * one, we'll recreate the dir with the dotdot entry pointing to the
+ * root directory and then move it to the orphanage.
*/
error = xrep_dir_parent_find(rd.sc, &rd.parent_ino);
if (error)
return error;
+ if (rd.parent_ino == NULLFSINO) {
+ rd.parent_ino = sc->mp->m_sb.sb_rootino;
+ move_orphanage = true;
+ }
/* Now rebuild the directory information. */
- return xrep_dir_rebuild_tree(&rd);
+ error = xrep_dir_rebuild_tree(&rd);
+ if (error || !move_orphanage)
+ return error;
+
+ /*
+ * Before we can move the directory to the orphanage, we must roll to a
+ * clean unjoined transaction and drop the ILOCKs on the dir and the
+ * temp dir. We still hold IOLOCK_EXCL on the dir, so nobody will be
+ * able to access it in the mean time.
+ */
+ error = xfs_trans_roll(&sc->tp);
+ if (error)
+ return error;
+ xfs_iunlock(sc->tempip, XFS_ILOCK_EXCL);
+ sc->temp_ilock_flags &= ~XFS_ILOCK_EXCL;
+ xfs_iunlock(sc->ip, XFS_ILOCK_EXCL);
+ sc->ilock_flags &= ~XFS_ILOCK_EXCL;
+
+ return xrep_move_to_orphanage(sc);
out_names:
xblob_destroy(rd.dir_names);