@@ -19,6 +19,8 @@
#include "xfs_icache.h"
#include "xfs_bmap.h"
#include "xfs_bmap_btree.h"
+#include "xfs_parent.h"
+#include "xfs_attr_sf.h"
#include "scrub/scrub.h"
#include "scrub/common.h"
#include "scrub/repair.h"
@@ -330,8 +332,12 @@ xrep_adoption_trans_alloc(
if (S_ISDIR(VFS_I(sc->ip)->i_mode))
child_blkres = xfs_rename_space_res(mp, 0, false,
xfs_name_dotdot.len, false);
+ if (xfs_has_parent(mp))
+ child_blkres += XFS_ADDAFORK_SPACE_RES(mp);
adopt->child_blkres = child_blkres;
+ xfs_parent_args_init(mp, &adopt->ppargs);
+
/*
* Allocate a transaction to link the child into the parent, along with
* enough disk space to handle expansion of both the orphanage and the
@@ -500,6 +506,21 @@ xrep_adoption_zap_dcache(
dput(d_orphanage);
}
+/*
+ * If we have to add an attr fork ahead of a parent pointer update, how much
+ * space should we ask for?
+ */
+static inline int
+xrep_adoption_attr_sizeof(
+ const struct xrep_adoption *adopt)
+{
+ size_t res = sizeof(struct xfs_attr_sf_hdr);
+
+ res += xfs_attr_sf_entsize_byname(sizeof(struct xfs_parent_name_rec),
+ adopt->xname.len);
+ return res;
+}
+
/*
* Move the current file to the orphanage under the computed name.
*
@@ -522,6 +543,19 @@ xrep_adoption_move(
if (error)
return error;
+ /*
+ * If this filesystem has parent pointers, ensure that the file being
+ * moved to the orphanage has an attribute fork. This is required
+ * because the parent pointer code does not itself add attr forks.
+ */
+ if (!xfs_inode_has_attr_fork(sc->ip) && xfs_has_parent(sc->mp)) {
+ int sf_size = xrep_adoption_attr_sizeof(adopt);
+
+ error = xfs_bmap_add_attrfork(sc->tp, sc->ip, sf_size, true);
+ if (error)
+ return error;
+ }
+
/* Create the new name in the orphanage. */
error = xfs_dir_createname(sc->tp, sc->orphanage, xname, sc->ip->i_ino,
adopt->orphanage_blkres);
@@ -546,6 +580,14 @@ xrep_adoption_move(
return error;
}
+ /* Add a parent pointer from the file back to the lost+found. */
+ if (xfs_has_parent(sc->mp)) {
+ error = xfs_parent_addname(sc->tp, &adopt->ppargs,
+ sc->orphanage, xname, sc->ip);
+ if (error)
+ return error;
+ }
+
/*
* Notify dirent hooks that we moved the file to /lost+found, and
* finish all the deferred work so that we know the adoption is fully
@@ -54,6 +54,9 @@ struct xrep_adoption {
struct xfs_scrub *sc;
+ /* Parent pointer context tracking */
+ struct xfs_parent_args ppargs;
+
/* Block reservations for orphanage and child (if directory). */
unsigned int orphanage_blkres;
unsigned int child_blkres;
@@ -19,6 +19,8 @@
#include "xfs_rmap.h"
#include "xfs_xchgrange.h"
#include "xfs_swapext.h"
+#include "xfs_dir2.h"
+#include "xfs_parent.h"
#include "scrub/scrub.h"
#include "scrub/common.h"
#include "scrub/trace.h"