From: "Darrick J. Wong" <djwong@kernel.org>
To: djwong@kernel.org
Cc: catherine.hoang@oracle.com, hch@lst.de,
allison.henderson@oracle.com, linux-xfs@vger.kernel.org
Subject: [PATCH 11/14] xfs: actually rebuild the parent pointer xattrs
Date: Tue, 09 Apr 2024 18:06:33 -0700 [thread overview]
Message-ID: <171270971170.3632937.9669548372844049712.stgit@frogsfrogsfrogs> (raw)
In-Reply-To: <171270970952.3632937.3716036526502072405.stgit@frogsfrogsfrogs>
From: Darrick J. Wong <djwong@kernel.org>
Once we've assembled all the parent pointers for a file, we need to
commit the new dataset atomically to that file. Parent pointer records
are embedded in the xattr structure, which means that we must write a
new extended attribute structure, again, atomically. Therefore, we must
copy the non-parent-pointer attributes from the file being repaired into
the temporary file's extended attributes and then call the atomic extent
swap mechanism to exchange the blocks.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
fs/xfs/libxfs/xfs_attr.c | 2
fs/xfs/libxfs/xfs_attr.h | 1
fs/xfs/scrub/attr_repair.c | 4
fs/xfs/scrub/attr_repair.h | 4
fs/xfs/scrub/findparent.c | 2
fs/xfs/scrub/parent_repair.c | 706 +++++++++++++++++++++++++++++++++++++++++-
fs/xfs/scrub/trace.h | 2
7 files changed, 698 insertions(+), 23 deletions(-)
diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
index 94f5acaad6e09..76d40daa02cff 100644
--- a/fs/xfs/libxfs/xfs_attr.c
+++ b/fs/xfs/libxfs/xfs_attr.c
@@ -950,7 +950,7 @@ xfs_attr_lookup(
return error;
}
-STATIC int
+int
xfs_attr_add_fork(
struct xfs_inode *ip, /* incore inode pointer */
int size, /* space new attribute needs */
diff --git a/fs/xfs/libxfs/xfs_attr.h b/fs/xfs/libxfs/xfs_attr.h
index d51001c5809fe..2a0ef4f633e2d 100644
--- a/fs/xfs/libxfs/xfs_attr.h
+++ b/fs/xfs/libxfs/xfs_attr.h
@@ -643,5 +643,6 @@ int __init xfs_attr_intent_init_cache(void);
void xfs_attr_intent_destroy_cache(void);
int xfs_attr_sf_totsize(struct xfs_inode *dp);
+int xfs_attr_add_fork(struct xfs_inode *ip, int size, int rsvd);
#endif /* __XFS_ATTR_H__ */
diff --git a/fs/xfs/scrub/attr_repair.c b/fs/xfs/scrub/attr_repair.c
index 9cf002bc18042..e06d00ea828b3 100644
--- a/fs/xfs/scrub/attr_repair.c
+++ b/fs/xfs/scrub/attr_repair.c
@@ -1032,7 +1032,7 @@ xrep_xattr_reset_fork(
* fork. The caller must ILOCK the tempfile and join it to the transaction.
* This function returns with the inode joined to a clean scrub transaction.
*/
-STATIC int
+int
xrep_xattr_reset_tempfile_fork(
struct xfs_scrub *sc)
{
@@ -1338,7 +1338,7 @@ xrep_xattr_swap_prep(
}
/* Exchange the temporary file's attribute fork with the one being repaired. */
-STATIC int
+int
xrep_xattr_swap(
struct xfs_scrub *sc,
struct xrep_tempexch *tx)
diff --git a/fs/xfs/scrub/attr_repair.h b/fs/xfs/scrub/attr_repair.h
index 0a9ffa7cfa906..979729bd4a5f8 100644
--- a/fs/xfs/scrub/attr_repair.h
+++ b/fs/xfs/scrub/attr_repair.h
@@ -6,6 +6,10 @@
#ifndef __XFS_SCRUB_ATTR_REPAIR_H__
#define __XFS_SCRUB_ATTR_REPAIR_H__
+struct xrep_tempexch;
+
+int xrep_xattr_swap(struct xfs_scrub *sc, struct xrep_tempexch *tx);
int xrep_xattr_reset_fork(struct xfs_scrub *sc);
+int xrep_xattr_reset_tempfile_fork(struct xfs_scrub *sc);
#endif /* __XFS_SCRUB_ATTR_REPAIR_H__ */
diff --git a/fs/xfs/scrub/findparent.c b/fs/xfs/scrub/findparent.c
index c78422ad757bf..01766041ba2cd 100644
--- a/fs/xfs/scrub/findparent.c
+++ b/fs/xfs/scrub/findparent.c
@@ -24,6 +24,7 @@
#include "xfs_trans_space.h"
#include "xfs_health.h"
#include "xfs_exchmaps.h"
+#include "xfs_parent.h"
#include "scrub/xfs_scrub.h"
#include "scrub/scrub.h"
#include "scrub/common.h"
@@ -33,6 +34,7 @@
#include "scrub/findparent.h"
#include "scrub/readdir.h"
#include "scrub/tempfile.h"
+#include "scrub/listxattr.h"
/*
* Finding the Parent of a Directory
diff --git a/fs/xfs/scrub/parent_repair.c b/fs/xfs/scrub/parent_repair.c
index 311bc7990d7c7..02554c99d231f 100644
--- a/fs/xfs/scrub/parent_repair.c
+++ b/fs/xfs/scrub/parent_repair.c
@@ -25,6 +25,8 @@
#include "xfs_health.h"
#include "xfs_exchmaps.h"
#include "xfs_parent.h"
+#include "xfs_attr.h"
+#include "xfs_bmap.h"
#include "scrub/xfs_scrub.h"
#include "scrub/scrub.h"
#include "scrub/common.h"
@@ -34,10 +36,13 @@
#include "scrub/findparent.h"
#include "scrub/readdir.h"
#include "scrub/tempfile.h"
+#include "scrub/tempexch.h"
#include "scrub/orphanage.h"
#include "scrub/xfile.h"
#include "scrub/xfarray.h"
#include "scrub/xfblob.h"
+#include "scrub/attr_repair.h"
+#include "scrub/listxattr.h"
/*
* Repairing The Directory Parent Pointer
@@ -65,9 +70,9 @@
*
* When salvaging completes, the remaining stashed entries are replayed to the
* temporary file. All non-parent pointer extended attributes are copied to
- * the temporary file's extended attributes. An atomic extent swap is used to
- * commit the new directory blocks to the directory being repaired. This will
- * disrupt attrmulti cursors.
+ * the temporary file's extended attributes. An atomic file mapping exchange
+ * is used to commit the new xattr blocks to the file being repaired. This
+ * will disrupt attrmulti cursors.
*/
/* Create a parent pointer in the tempfile. */
@@ -106,6 +111,23 @@ struct xrep_parent {
/* Blobs containing parent pointer names. */
struct xfblob *pptr_names;
+ /* xattr keys */
+ struct xfarray *xattr_records;
+
+ /* xattr values */
+ struct xfblob *xattr_blobs;
+
+ /* Scratch buffers for saving extended attributes */
+ unsigned char *xattr_name;
+ void *xattr_value;
+ unsigned int xattr_value_sz;
+
+ /*
+ * Information used to exchange the attr fork mappings, if the fs
+ * supports parent pointers.
+ */
+ struct xrep_tempexch tx;
+
/*
* Information used to scan the filesystem to find the inumber of the
* dotdot entry for this directory. On filesystems without parent
@@ -117,6 +139,8 @@ struct xrep_parent {
* @pscan.lock coordinates access to pptr_recs, pptr_names, pptr, and
* pptr_scratch. This reduces the memory requirements of this
* structure.
+ *
+ * The lock also controls access to xattr_records and xattr_blobs(?)
*/
struct xrep_parent_scan_info pscan;
@@ -129,14 +153,48 @@ struct xrep_parent {
/* Scratch buffer for scanning pptr xattrs */
struct xfs_da_args pptr_args;
+
+ /* Have we seen any live updates of parent pointers recently? */
+ bool saw_pptr_updates;
};
+struct xrep_parent_xattr {
+ /* Cookie for retrieval of the xattr name. */
+ xfblob_cookie name_cookie;
+
+ /* Cookie for retrieval of the xattr value. */
+ xfblob_cookie value_cookie;
+
+ /* XFS_ATTR_* flags */
+ int flags;
+
+ /* Length of the value and name. */
+ uint32_t valuelen;
+ uint16_t namelen;
+};
+
+/*
+ * Stash up to 8 pages of attrs in xattr_records/xattr_blobs before we write
+ * them to the temp file.
+ */
+#define XREP_PARENT_XATTR_MAX_STASH_BYTES (PAGE_SIZE * 8)
+
/* Tear down all the incore stuff we created. */
static void
xrep_parent_teardown(
struct xrep_parent *rp)
{
xrep_findparent_scan_teardown(&rp->pscan);
+ kvfree(rp->xattr_name);
+ rp->xattr_name = NULL;
+ kvfree(rp->xattr_value);
+ rp->xattr_value = NULL;
+ if (rp->xattr_blobs)
+ xfblob_destroy(rp->xattr_blobs);
+ rp->xattr_blobs = NULL;
+ if (rp->xattr_records)
+ xfarray_destroy(rp->xattr_records);
+ rp->xattr_records = NULL;
if (rp->pptr_names)
xfblob_destroy(rp->pptr_names);
rp->pptr_names = NULL;
@@ -556,10 +614,11 @@ xrep_parent_scan_dirtree(
}
/*
- * Cancel the empty transaction so that we can (later) use the atomic
- * extent swap helpers to lock files and commit the new directory.
+ * Retake sc->ip's ILOCK now that we're done flushing stashed parent
+ * pointers. We end this function with an empty transaction and the
+ * ILOCK.
*/
- xchk_trans_cancel(rp->sc);
+ xchk_ilock(rp->sc, XFS_ILOCK_EXCL);
return 0;
}
@@ -594,6 +653,8 @@ xrep_parent_live_update(
else
error = xrep_parent_stash_parentremove(rp, p->name,
p->dp);
+ if (!error)
+ rp->saw_pptr_updates = true;
mutex_unlock(&rp->pscan.lock);
if (error)
goto out_abort;
@@ -648,6 +709,52 @@ xrep_parent_reset_dotdot(
return xfs_trans_roll(&sc->tp);
}
+/* Pass back the parent inumber if this a parent pointer */
+STATIC int
+xrep_parent_lookup_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)
+{
+ xfs_ino_t *inop = priv;
+ xfs_ino_t parent_ino;
+ int ret;
+
+ ret = xfs_parent_from_xattr(sc->mp, attr_flags, name, namelen,
+ value, valuelen, &parent_ino, NULL);
+ if (ret != 1)
+ return ret;
+
+ *inop = parent_ino;
+ return -ECANCELED;
+}
+
+/*
+ * Find the first parent of the scrub target by walking parent pointers for
+ * the purpose of deciding if we're going to move it to the orphanage.
+ * We don't care if the attr fork is zapped.
+ */
+STATIC int
+xrep_parent_lookup_pptrs(
+ struct xfs_scrub *sc,
+ xfs_ino_t *inop)
+{
+ int error;
+
+ *inop = NULLFSINO;
+
+ error = xchk_xattr_walk(sc, sc->ip, xrep_parent_lookup_pptr, NULL,
+ inop);
+ if (error && error != -ECANCELED)
+ return error;
+ return 0;
+}
+
/*
* Move the current file to the orphanage.
*
@@ -664,14 +771,26 @@ xrep_parent_move_to_orphanage(
xfs_ino_t orig_parent, new_parent;
int error;
- /*
- * We are about to drop the ILOCK on sc->ip to lock the orphanage and
- * prepare for the adoption. Therefore, look up the old dotdot entry
- * for sc->ip so that we can compare it after we re-lock sc->ip.
- */
- error = xchk_dir_lookup(sc, sc->ip, &xfs_name_dotdot, &orig_parent);
- if (error)
- return error;
+ if (S_ISDIR(VFS_I(sc->ip)->i_mode)) {
+ /*
+ * We are about to drop the ILOCK on sc->ip to lock the
+ * orphanage and prepare for the adoption. Therefore, look up
+ * the old dotdot entry for sc->ip so that we can compare it
+ * after we re-lock sc->ip.
+ */
+ error = xchk_dir_lookup(sc, sc->ip, &xfs_name_dotdot,
+ &orig_parent);
+ if (error)
+ return error;
+ } else {
+ /*
+ * We haven't dropped the ILOCK since we committed the new
+ * xattr structure (and hence the new parent pointer records),
+ * which means that the file cannot have been moved in the
+ * directory tree, and there are no parents.
+ */
+ orig_parent = NULLFSINO;
+ }
/*
* Drop the ILOCK on the scrub target and commit the transaction.
@@ -704,9 +823,14 @@ xrep_parent_move_to_orphanage(
* Now that we've reacquired the ILOCK on sc->ip, look up the dotdot
* entry again. If the parent changed or the child was unlinked while
* the child directory was unlocked, we don't need to move the child to
- * the orphanage after all.
+ * the orphanage after all. For a non-directory, we have to scan for
+ * the first parent pointer to see if one has been added.
*/
- error = xchk_dir_lookup(sc, sc->ip, &xfs_name_dotdot, &new_parent);
+ if (S_ISDIR(VFS_I(sc->ip)->i_mode))
+ error = xchk_dir_lookup(sc, sc->ip, &xfs_name_dotdot,
+ &new_parent);
+ else
+ error = xrep_parent_lookup_pptrs(sc, &new_parent);
if (error)
return error;
@@ -733,6 +857,488 @@ xrep_parent_move_to_orphanage(
return 0;
}
+/* Ensure that the xattr value buffer is large enough. */
+STATIC int
+xrep_parent_alloc_xattr_value(
+ struct xrep_parent *rp,
+ size_t bufsize)
+{
+ void *new_val;
+
+ if (rp->xattr_value_sz >= bufsize)
+ return 0;
+
+ if (rp->xattr_value) {
+ kvfree(rp->xattr_value);
+ rp->xattr_value = NULL;
+ rp->xattr_value_sz = 0;
+ }
+
+ new_val = kvmalloc(bufsize, XCHK_GFP_FLAGS);
+ if (!new_val)
+ return -ENOMEM;
+
+ rp->xattr_value = new_val;
+ rp->xattr_value_sz = bufsize;
+ return 0;
+}
+
+/* Retrieve the (remote) value of a non-pptr xattr. */
+STATIC int
+xrep_parent_fetch_xattr_remote(
+ struct xrep_parent *rp,
+ struct xfs_inode *ip,
+ unsigned int attr_flags,
+ const unsigned char *name,
+ unsigned int namelen,
+ unsigned int valuelen)
+{
+ struct xfs_scrub *sc = rp->sc;
+ struct xfs_da_args args = {
+ .attr_filter = attr_flags & XFS_ATTR_NSP_ONDISK_MASK,
+ .geo = sc->mp->m_attr_geo,
+ .whichfork = XFS_ATTR_FORK,
+ .dp = ip,
+ .name = name,
+ .namelen = namelen,
+ .trans = sc->tp,
+ .valuelen = valuelen,
+ .owner = ip->i_ino,
+ };
+ int error;
+
+ /*
+ * If we need a larger value buffer, try to allocate one. If that
+ * fails, return with -EDEADLOCK to try harder.
+ */
+ error = xrep_parent_alloc_xattr_value(rp, valuelen);
+ if (error == -ENOMEM)
+ return -EDEADLOCK;
+ if (error)
+ return error;
+
+ args.value = rp->xattr_value;
+ xfs_attr_sethash(&args);
+ return xfs_attr_get_ilocked(&args);
+}
+
+/* Stash non-pptr attributes for later replay into the temporary file. */
+STATIC int
+xrep_parent_stash_xattr(
+ 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)
+{
+ struct xrep_parent_xattr key = {
+ .valuelen = valuelen,
+ .namelen = namelen,
+ .flags = attr_flags & XFS_ATTR_NSP_ONDISK_MASK,
+ };
+ struct xrep_parent *rp = priv;
+ int error;
+
+ if (attr_flags & (XFS_ATTR_INCOMPLETE | XFS_ATTR_PARENT))
+ return 0;
+
+ if (!value) {
+ error = xrep_parent_fetch_xattr_remote(rp, ip, attr_flags,
+ name, namelen, valuelen);
+ if (error)
+ return error;
+
+ value = rp->xattr_value;
+ }
+
+ trace_xrep_parent_stash_xattr(rp->sc->tempip, key.flags, (void *)name,
+ key.namelen, key.valuelen);
+
+ error = xfblob_store(rp->xattr_blobs, &key.name_cookie, name,
+ key.namelen);
+ if (error)
+ return error;
+
+ error = xfblob_store(rp->xattr_blobs, &key.value_cookie, value,
+ key.valuelen);
+ if (error)
+ return error;
+
+ return xfarray_append(rp->xattr_records, &key);
+}
+
+/* Insert one xattr key/value. */
+STATIC int
+xrep_parent_insert_xattr(
+ struct xrep_parent *rp,
+ const struct xrep_parent_xattr *key)
+{
+ struct xfs_da_args args = {
+ .dp = rp->sc->tempip,
+ .attr_filter = key->flags,
+ .namelen = key->namelen,
+ .valuelen = key->valuelen,
+ .owner = rp->sc->ip->i_ino,
+ .geo = rp->sc->mp->m_attr_geo,
+ .whichfork = XFS_ATTR_FORK,
+ .op_flags = XFS_DA_OP_OKNOENT,
+ };
+ int error;
+
+ ASSERT(!(key->flags & XFS_ATTR_PARENT));
+
+ /*
+ * Grab pointers to the scrub buffer so that we can use them to insert
+ * attrs into the temp file.
+ */
+ args.name = rp->xattr_name;
+ args.value = rp->xattr_value;
+
+ /*
+ * The attribute name is stored near the end of the in-core buffer,
+ * though we reserve one more byte to ensure null termination.
+ */
+ rp->xattr_name[XATTR_NAME_MAX] = 0;
+
+ error = xfblob_load(rp->xattr_blobs, key->name_cookie, rp->xattr_name,
+ key->namelen);
+ if (error)
+ return error;
+
+ error = xfblob_free(rp->xattr_blobs, key->name_cookie);
+ if (error)
+ return error;
+
+ error = xfblob_load(rp->xattr_blobs, key->value_cookie, args.value,
+ key->valuelen);
+ if (error)
+ return error;
+
+ error = xfblob_free(rp->xattr_blobs, key->value_cookie);
+ if (error)
+ return error;
+
+ rp->xattr_name[key->namelen] = 0;
+
+ trace_xrep_parent_insert_xattr(rp->sc->tempip, key->flags,
+ rp->xattr_name, key->namelen, key->valuelen);
+
+ xfs_attr_sethash(&args);
+ return xfs_attr_setname(&args, false);
+}
+
+/*
+ * Periodically flush salvaged attributes to the temporary file. This is done
+ * to reduce the memory requirements of the xattr rebuild because files can
+ * contain millions of attributes.
+ */
+STATIC int
+xrep_parent_flush_xattrs(
+ struct xrep_parent *rp)
+{
+ xfarray_idx_t array_cur;
+ int error;
+
+ /*
+ * Entering this function, the scrub context has a reference to the
+ * inode being repaired, the temporary file, and the empty scrub
+ * transaction that we created for the xattr scan. We hold ILOCK_EXCL
+ * on the inode being repaired.
+ *
+ * To constrain kernel memory use, we occasionally flush salvaged
+ * xattrs from the xfarray and xfblob structures into the temporary
+ * file in preparation for exchanging the xattr structures at the end.
+ * Updating the temporary file requires a transaction, so we commit the
+ * scrub transaction and drop the ILOCK so that xfs_attr_set can
+ * allocate whatever transaction it wants.
+ *
+ * We still hold IOLOCK_EXCL on the inode being repaired, which
+ * prevents anyone from adding xattrs (or parent pointers) while we're
+ * flushing.
+ */
+ xchk_trans_cancel(rp->sc);
+ xchk_iunlock(rp->sc, XFS_ILOCK_EXCL);
+
+ /*
+ * Take the IOLOCK of the temporary file while we modify xattrs. This
+ * isn't strictly required because the temporary file is never revealed
+ * to userspace, but we follow the same locking rules. We still hold
+ * sc->ip's IOLOCK.
+ */
+ error = xrep_tempfile_iolock_polled(rp->sc);
+ if (error)
+ return error;
+
+ /* Add all the salvaged attrs to the temporary file. */
+ foreach_xfarray_idx(rp->xattr_records, array_cur) {
+ struct xrep_parent_xattr key;
+
+ error = xfarray_load(rp->xattr_records, array_cur, &key);
+ if (error)
+ return error;
+
+ error = xrep_parent_insert_xattr(rp, &key);
+ if (error)
+ return error;
+ }
+
+ /* Empty out both arrays now that we've added the entries. */
+ xfarray_truncate(rp->xattr_records);
+ xfblob_truncate(rp->xattr_blobs);
+
+ xrep_tempfile_iounlock(rp->sc);
+
+ /* Recreate the empty transaction and relock the inode. */
+ error = xchk_trans_alloc_empty(rp->sc);
+ if (error)
+ return error;
+ xchk_ilock(rp->sc, XFS_ILOCK_EXCL);
+ return 0;
+}
+
+/* Decide if we've stashed too much xattr data in memory. */
+static inline bool
+xrep_parent_want_flush_xattrs(
+ struct xrep_parent *rp)
+{
+ unsigned long long bytes;
+
+ bytes = xfarray_bytes(rp->xattr_records) +
+ xfblob_bytes(rp->xattr_blobs);
+ return bytes > XREP_PARENT_XATTR_MAX_STASH_BYTES;
+}
+
+/* Flush staged attributes to the temporary file if we're over the limit. */
+STATIC int
+xrep_parent_try_flush_xattrs(
+ struct xfs_scrub *sc,
+ void *priv)
+{
+ struct xrep_parent *rp = priv;
+ int error;
+
+ if (!xrep_parent_want_flush_xattrs(rp))
+ return 0;
+
+ error = xrep_parent_flush_xattrs(rp);
+ if (error)
+ return error;
+
+ /*
+ * If there were any parent pointer updates to the xattr structure
+ * while we dropped the ILOCK, the xattr structure is now stale.
+ * Signal to the attr copy process that we need to start over, but
+ * this time without opportunistic attr flushing.
+ *
+ * This is unlikely to happen, so we're ok with restarting the copy.
+ */
+ mutex_lock(&rp->pscan.lock);
+ if (rp->saw_pptr_updates)
+ error = -ESTALE;
+ mutex_unlock(&rp->pscan.lock);
+ return error;
+}
+
+/* Copy all the non-pptr extended attributes into the temporary file. */
+STATIC int
+xrep_parent_copy_xattrs(
+ struct xrep_parent *rp)
+{
+ struct xfs_scrub *sc = rp->sc;
+ int error;
+
+ /*
+ * Clear the pptr updates flag. We hold sc->ip ILOCKed, so there
+ * can't be any parent pointer updates in progress.
+ */
+ mutex_lock(&rp->pscan.lock);
+ rp->saw_pptr_updates = false;
+ mutex_unlock(&rp->pscan.lock);
+
+ /* Copy xattrs, stopping periodically to flush the incore buffers. */
+ error = xchk_xattr_walk(sc, sc->ip, xrep_parent_stash_xattr,
+ xrep_parent_try_flush_xattrs, rp);
+ if (error && error != -ESTALE)
+ return error;
+
+ if (error == -ESTALE) {
+ /*
+ * The xattr copy collided with a parent pointer update.
+ * Restart the copy, but this time hold the ILOCK all the way
+ * to the end to lock out any directory parent pointer updates.
+ */
+ error = xchk_xattr_walk(sc, sc->ip, xrep_parent_stash_xattr,
+ NULL, rp);
+ if (error)
+ return error;
+ }
+
+ /* Flush any remaining stashed xattrs to the temporary file. */
+ if (xfarray_bytes(rp->xattr_records) == 0)
+ return 0;
+
+ return xrep_parent_flush_xattrs(rp);
+}
+
+/*
+ * Ensure that @sc->ip and @sc->tempip both have attribute forks before we head
+ * into the attr fork exchange transaction. All files on a filesystem with
+ * parent pointers must have an attr fork because the parent pointer code does
+ * not itself add attribute forks.
+ *
+ * Note: Unlinkable unlinked files don't need one, but the overhead of having
+ * an unnecessary attr fork is not justified by the additional code complexity
+ * that would be needed to track that state correctly.
+ */
+STATIC int
+xrep_parent_ensure_attr_fork(
+ struct xrep_parent *rp)
+{
+ struct xfs_scrub *sc = rp->sc;
+ int error;
+
+ error = xfs_attr_add_fork(sc->tempip,
+ sizeof(struct xfs_attr_sf_hdr), 1);
+ if (error)
+ return error;
+ return xfs_attr_add_fork(sc->ip, sizeof(struct xfs_attr_sf_hdr), 1);
+}
+
+/*
+ * Finish replaying stashed parent pointer updates, allocate a transaction for
+ * exchanging extent mappings, and take the ILOCKs of both files before we
+ * commit the new attribute structure.
+ */
+STATIC int
+xrep_parent_finalize_tempfile(
+ struct xrep_parent *rp)
+{
+ struct xfs_scrub *sc = rp->sc;
+ int error;
+
+ /*
+ * Repair relies on the ILOCK to quiesce all possible xattr updates.
+ * Replay all queued parent pointer updates into the tempfile before
+ * exchanging the contents, even if that means dropping the ILOCKs and
+ * the transaction.
+ */
+ do {
+ error = xrep_parent_replay_updates(rp);
+ if (error)
+ return error;
+
+ error = xrep_parent_ensure_attr_fork(rp);
+ if (error)
+ return error;
+
+ error = xrep_tempexch_trans_alloc(sc, XFS_ATTR_FORK, &rp->tx);
+ if (error)
+ return error;
+
+ if (xfarray_length(rp->pptr_recs) == 0)
+ break;
+
+ xchk_trans_cancel(sc);
+ xrep_tempfile_iunlock_both(sc);
+ } while (!xchk_should_terminate(sc, &error));
+ return error;
+}
+
+/*
+ * Replay all the stashed parent pointers into the temporary file, copy all
+ * the non-pptr xattrs from the file being repaired into the temporary file,
+ * and exchange the attr fork contents atomically.
+ */
+STATIC int
+xrep_parent_rebuild_pptrs(
+ struct xrep_parent *rp)
+{
+ struct xfs_scrub *sc = rp->sc;
+ xfs_ino_t parent_ino = NULLFSINO;
+ int error;
+
+ /*
+ * Copy non-ppttr xattrs from the file being repaired into the
+ * temporary file's xattr structure. We hold sc->ip's IOLOCK, which
+ * prevents setxattr/removexattr calls from occurring, but renames
+ * update the parent pointers without holding IOLOCK. If we detect
+ * stale attr structures, we restart the scan but only flush at the
+ * end.
+ */
+ error = xrep_parent_copy_xattrs(rp);
+ if (error)
+ return error;
+
+ /*
+ * Cancel the empty transaction that we used to walk and copy attrs,
+ * and drop the ILOCK so that we can take the IOLOCK on the temporary
+ * file. We still hold sc->ip's IOLOCK.
+ */
+ xchk_trans_cancel(sc);
+ xchk_iunlock(sc, XFS_ILOCK_EXCL);
+
+ error = xrep_tempfile_iolock_polled(sc);
+ if (error)
+ return error;
+
+ /*
+ * Allocate transaction, lock inodes, and make sure that we've replayed
+ * all the stashed pptr updates to the tempdir. After this point,
+ * we're ready to exchange the attr fork mappings.
+ */
+ error = xrep_parent_finalize_tempfile(rp);
+ if (error)
+ return error;
+
+ /* Last chance to abort before we start committing pptr fixes. */
+ if (xchk_should_terminate(sc, &error))
+ return error;
+
+ if (xchk_iscan_aborted(&rp->pscan.iscan))
+ return -ECANCELED;
+
+ /*
+ * Exchange the attr fork contents and junk the old attr fork contents,
+ * which are now in the tempfile.
+ */
+ error = xrep_xattr_swap(sc, &rp->tx);
+ if (error)
+ return error;
+ error = xrep_xattr_reset_tempfile_fork(sc);
+ if (error)
+ return error;
+
+ /*
+ * Roll to get a transaction without any inodes joined to it. Then we
+ * can drop the tempfile's ILOCK and IOLOCK before doing more work on
+ * the scrub target file.
+ */
+ error = xfs_trans_roll(&sc->tp);
+ if (error)
+ return error;
+ xrep_tempfile_iunlock(sc);
+ xrep_tempfile_iounlock(sc);
+
+ /*
+ * We've committed the new parent pointers. Find at least one parent
+ * so that we can decide if we're moving this file to the orphanage.
+ * For this purpose, root directories are their own parents.
+ */
+ if (sc->ip == sc->mp->m_rootip) {
+ xrep_findparent_scan_found(&rp->pscan, sc->ip->i_ino);
+ } else {
+ error = xrep_parent_lookup_pptrs(sc, &parent_ino);
+ if (error)
+ return error;
+ if (parent_ino != NULLFSINO)
+ xrep_findparent_scan_found(&rp->pscan, parent_ino);
+ }
+ return 0;
+}
+
/*
* Commit the new parent pointer structure (currently only the dotdot entry) to
* the file that we're repairing.
@@ -741,13 +1347,24 @@ STATIC int
xrep_parent_rebuild_tree(
struct xrep_parent *rp)
{
+ int error;
+
+ if (xfs_has_parent(rp->sc->mp)) {
+ error = xrep_parent_rebuild_pptrs(rp);
+ if (error)
+ return error;
+ }
+
if (rp->pscan.parent_ino == NULLFSINO) {
if (xrep_orphanage_can_adopt(rp->sc))
return xrep_parent_move_to_orphanage(rp);
return -EFSCORRUPTED;
}
- return xrep_parent_reset_dotdot(rp);
+ if (S_ISDIR(VFS_I(rp->sc->ip)->i_mode))
+ return xrep_parent_reset_dotdot(rp);
+
+ return 0;
}
/* Set up the filesystem scan so we can look for parents. */
@@ -757,18 +1374,39 @@ xrep_parent_setup_scan(
{
struct xfs_scrub *sc = rp->sc;
char *descr;
+ struct xfs_da_geometry *geo = sc->mp->m_attr_geo;
+ int max_len;
int error;
if (!xfs_has_parent(sc->mp))
return xrep_findparent_scan_start(sc, &rp->pscan);
+ /* Buffers for copying non-pptr attrs to the tempfile */
+ rp->xattr_name = kvmalloc(XATTR_NAME_MAX + 1, XCHK_GFP_FLAGS);
+ if (!rp->xattr_name)
+ return -ENOMEM;
+
+ /*
+ * Allocate enough memory to handle loading local attr values from the
+ * xfblob data while flushing stashed attrs to the temporary file.
+ * We only realloc the buffer when salvaging remote attr values, so
+ * TRY_HARDER means we allocate the maximal attr value size.
+ */
+ if (sc->flags & XCHK_TRY_HARDER)
+ max_len = XATTR_SIZE_MAX;
+ else
+ max_len = xfs_attr_leaf_entsize_local_max(geo->blksize);
+ error = xrep_parent_alloc_xattr_value(rp, max_len);
+ if (error)
+ goto out_xattr_name;
+
/* Set up some staging memory for logging parent pointer updates. */
descr = xchk_xfile_ino_descr(sc, "parent pointer entries");
error = xfarray_create(descr, 0, sizeof(struct xrep_pptr),
&rp->pptr_recs);
kfree(descr);
if (error)
- return error;
+ goto out_xattr_value;
descr = xchk_xfile_ino_descr(sc, "parent pointer names");
error = xfblob_create(descr, &rp->pptr_names);
@@ -776,19 +1414,47 @@ xrep_parent_setup_scan(
if (error)
goto out_recs;
+ /* Set up some storage for copying attrs before the mapping exchange */
+ descr = xchk_xfile_ino_descr(sc,
+ "parent pointer retained xattr entries");
+ error = xfarray_create(descr, 0, sizeof(struct xrep_parent_xattr),
+ &rp->xattr_records);
+ kfree(descr);
+ if (error)
+ goto out_names;
+
+ descr = xchk_xfile_ino_descr(sc,
+ "parent pointer retained xattr values");
+ error = xfblob_create(descr, &rp->xattr_blobs);
+ kfree(descr);
+ if (error)
+ goto out_attr_keys;
+
error = __xrep_findparent_scan_start(sc, &rp->pscan,
xrep_parent_live_update);
if (error)
- goto out_names;
+ goto out_attr_values;
return 0;
+out_attr_values:
+ xfblob_destroy(rp->xattr_blobs);
+ rp->xattr_blobs = NULL;
+out_attr_keys:
+ xfarray_destroy(rp->xattr_records);
+ rp->xattr_records = NULL;
out_names:
xfblob_destroy(rp->pptr_names);
rp->pptr_names = NULL;
out_recs:
xfarray_destroy(rp->pptr_recs);
rp->pptr_recs = NULL;
+out_xattr_value:
+ kvfree(rp->xattr_value);
+ rp->xattr_value = NULL;
+out_xattr_name:
+ kvfree(rp->xattr_name);
+ rp->xattr_name = NULL;
return error;
}
@@ -818,7 +1484,7 @@ xrep_parent(
if (error)
goto out_teardown;
- /* Last chance to abort before we start committing fixes. */
+ /* Last chance to abort before we start committing dotdot fixes. */
if (xchk_should_terminate(sc, &error))
goto out_teardown;
diff --git a/fs/xfs/scrub/trace.h b/fs/xfs/scrub/trace.h
index 3e0cd482379c6..ecfaa4b88910f 100644
--- a/fs/xfs/scrub/trace.h
+++ b/fs/xfs/scrub/trace.h
@@ -2539,6 +2539,8 @@ DEFINE_EVENT(xrep_xattr_salvage_class, name, \
TP_ARGS(ip, flags, name, namelen, valuelen))
DEFINE_XREP_XATTR_SALVAGE_EVENT(xrep_xattr_salvage_rec);
DEFINE_XREP_XATTR_SALVAGE_EVENT(xrep_xattr_insert_rec);
+DEFINE_XREP_XATTR_SALVAGE_EVENT(xrep_parent_stash_xattr);
+DEFINE_XREP_XATTR_SALVAGE_EVENT(xrep_parent_insert_xattr);
DECLARE_EVENT_CLASS(xrep_pptr_salvage_class,
TP_PROTO(struct xfs_inode *ip, unsigned int flags, const void *name,
next prev parent reply other threads:[~2024-04-10 1:06 UTC|newest]
Thread overview: 234+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-04-10 0:36 [PATCHBOMB v13.1] xfs: directory parent pointers Darrick J. Wong
2024-04-10 0:44 ` [PATCHSET v13.1 1/9] xfs: design documentation for online fsck, part 2 Darrick J. Wong
2024-04-10 0:46 ` [PATCH 1/4] docs: update the parent pointers documentation to the final version Darrick J. Wong
2024-04-10 4:40 ` Christoph Hellwig
2024-04-10 0:46 ` [PATCH 2/4] docs: update online directory and parent pointer repair sections Darrick J. Wong
2024-04-10 4:40 ` Christoph Hellwig
2024-04-10 0:47 ` [PATCH 3/4] docs: update offline parent pointer repair strategy Darrick J. Wong
2024-04-10 4:40 ` Christoph Hellwig
2024-04-10 0:47 ` [PATCH 4/4] docs: describe xfs directory tree online fsck Darrick J. Wong
2024-04-10 4:40 ` Christoph Hellwig
2024-04-10 0:44 ` [PATCHSET v13.1 2/9] xfs: retain ILOCK during directory updates Darrick J. Wong
2024-04-10 0:47 ` [PATCH 1/7] xfs: Increase XFS_DEFER_OPS_NR_INODES to 5 Darrick J. Wong
2024-04-10 4:41 ` Christoph Hellwig
2024-04-10 0:48 ` [PATCH 2/7] xfs: Increase XFS_QM_TRANS_MAXDQS " Darrick J. Wong
2024-04-10 4:41 ` Christoph Hellwig
2024-04-10 0:48 ` [PATCH 3/7] xfs: Hold inode locks in xfs_ialloc Darrick J. Wong
2024-04-10 4:41 ` Christoph Hellwig
2024-04-10 0:48 ` [PATCH 4/7] xfs: Hold inode locks in xfs_trans_alloc_dir Darrick J. Wong
2024-04-10 4:41 ` Christoph Hellwig
2024-04-10 0:48 ` [PATCH 5/7] xfs: Hold inode locks in xfs_rename Darrick J. Wong
2024-04-10 4:42 ` Christoph Hellwig
2024-04-10 0:49 ` [PATCH 6/7] xfs: don't pick up IOLOCK during rmapbt repair scan Darrick J. Wong
2024-04-10 4:42 ` Christoph Hellwig
2024-04-10 0:49 ` [PATCH 7/7] xfs: unlock new repair tempfiles after creation Darrick J. Wong
2024-04-10 4:42 ` Christoph Hellwig
2024-04-10 0:44 ` [PATCHSET v13.1 3/9] xfs: shrink struct xfs_da_args Darrick J. Wong
2024-04-10 0:49 ` [PATCH 1/4] xfs: remove XFS_DA_OP_REMOVE Darrick J. Wong
2024-04-10 4:43 ` Christoph Hellwig
2024-04-10 0:49 ` [PATCH 2/4] xfs: remove XFS_DA_OP_NOTIME Darrick J. Wong
2024-04-10 4:44 ` Christoph Hellwig
2024-04-10 0:50 ` [PATCH 3/4] xfs: rename xfs_da_args.attr_flags Darrick J. Wong
2024-04-10 5:01 ` Christoph Hellwig
2024-04-10 20:55 ` Darrick J. Wong
2024-04-11 0:00 ` Darrick J. Wong
2024-04-11 3:26 ` Christoph Hellwig
2024-04-11 4:15 ` Darrick J. Wong
2024-04-10 0:50 ` [PATCH 4/4] xfs: rearrange xfs_da_args a bit to use less space Darrick J. Wong
2024-04-10 5:02 ` Christoph Hellwig
2024-04-10 20:56 ` Darrick J. Wong
2024-04-10 0:45 ` [PATCHSET v13.1 4/9] xfs: improve extended attribute validation Darrick J. Wong
2024-04-10 0:50 ` [PATCH 01/12] xfs: attr fork iext must be loaded before calling xfs_attr_is_leaf Darrick J. Wong
2024-04-10 5:04 ` Christoph Hellwig
2024-04-10 20:58 ` Darrick J. Wong
2024-04-10 0:50 ` [PATCH 02/12] xfs: require XFS_SB_FEAT_INCOMPAT_LOG_XATTRS for attr log intent item recovery Darrick J. Wong
2024-04-10 5:04 ` Christoph Hellwig
2024-04-10 0:51 ` [PATCH 03/12] xfs: use an XFS_OPSTATE_ flag for detecting if logged xattrs are available Darrick J. Wong
2024-04-10 5:05 ` Christoph Hellwig
2024-04-10 0:51 ` [PATCH 04/12] xfs: check opcode and iovec count match in xlog_recover_attri_commit_pass2 Darrick J. Wong
2024-04-10 5:05 ` Christoph Hellwig
2024-04-10 0:51 ` [PATCH 05/12] xfs: fix missing check for invalid attr flags Darrick J. Wong
2024-04-10 5:07 ` Christoph Hellwig
2024-04-10 21:04 ` Darrick J. Wong
2024-04-10 0:51 ` [PATCH 06/12] xfs: restructure xfs_attr_complete_op a bit Darrick J. Wong
2024-04-10 5:07 ` Christoph Hellwig
2024-04-10 0:52 ` [PATCH 07/12] xfs: use helpers to extract xattr op from opflags Darrick J. Wong
2024-04-10 5:07 ` Christoph Hellwig
2024-04-10 0:52 ` [PATCH 08/12] xfs: validate recovered name buffers when recovering xattr items Darrick J. Wong
2024-04-10 5:08 ` Christoph Hellwig
2024-04-10 0:52 ` [PATCH 09/12] xfs: always set args->value in xfs_attri_item_recover Darrick J. Wong
2024-04-10 5:08 ` Christoph Hellwig
2024-04-10 0:52 ` [PATCH 10/12] xfs: use local variables for name and value length in _attri_commit_pass2 Darrick J. Wong
2024-04-10 5:08 ` Christoph Hellwig
2024-04-10 0:53 ` [PATCH 11/12] xfs: refactor name/length checks in xfs_attri_validate Darrick J. Wong
2024-04-10 5:09 ` Christoph Hellwig
2024-04-10 0:53 ` [PATCH 12/12] xfs: enforce one namespace per attribute Darrick J. Wong
2024-04-10 5:09 ` Christoph Hellwig
2024-04-10 0:45 ` [PATCHSET v13.1 5/9] xfs: Parent Pointers Darrick J. Wong
2024-04-10 0:53 ` [PATCH 01/32] xfs: rearrange xfs_attr_match parameters Darrick J. Wong
2024-04-10 5:10 ` Christoph Hellwig
2024-04-10 0:54 ` [PATCH 02/32] xfs: check the flags earlier in xfs_attr_match Darrick J. Wong
2024-04-10 0:54 ` [PATCH 03/32] xfs: move xfs_attr_defer_add to xfs_attr_item.c Darrick J. Wong
2024-04-10 5:11 ` Christoph Hellwig
2024-04-10 0:54 ` [PATCH 04/32] xfs: create a separate hashname function for extended attributes Darrick J. Wong
2024-04-10 5:11 ` Christoph Hellwig
2024-04-10 0:54 ` [PATCH 05/32] xfs: add parent pointer support to attribute code Darrick J. Wong
2024-04-10 5:11 ` Christoph Hellwig
2024-04-10 0:55 ` [PATCH 06/32] xfs: define parent pointer ondisk extended attribute format Darrick J. Wong
2024-04-10 5:12 ` Christoph Hellwig
2024-04-10 0:55 ` [PATCH 07/32] xfs: allow xattr matching on name and value for local/sf attrs Darrick J. Wong
2024-04-10 5:16 ` Christoph Hellwig
2024-04-10 21:13 ` Darrick J. Wong
2024-04-11 3:28 ` Christoph Hellwig
2024-04-10 0:55 ` [PATCH 08/32] xfs: allow logged xattr operations if parent pointers are enabled Darrick J. Wong
2024-04-10 5:18 ` Christoph Hellwig
2024-04-10 21:18 ` Darrick J. Wong
2024-04-10 0:55 ` [PATCH 09/32] xfs: log parent pointer xattr removal operations Darrick J. Wong
2024-04-10 5:18 ` Christoph Hellwig
2024-04-10 0:56 ` [PATCH 10/32] xfs: log parent pointer xattr setting operations Darrick J. Wong
2024-04-10 0:56 ` [PATCH 11/32] xfs: log parent pointer xattr replace operations Darrick J. Wong
2024-04-10 5:26 ` Christoph Hellwig
2024-04-10 23:07 ` Darrick J. Wong
2024-04-11 3:35 ` Christoph Hellwig
2024-04-10 0:56 ` [PATCH 12/32] xfs: record inode generation in xattr update log intent items Darrick J. Wong
2024-04-10 5:27 ` Christoph Hellwig
2024-04-10 0:56 ` [PATCH 13/32] xfs: Expose init_xattrs in xfs_create_tmpfile Darrick J. Wong
2024-04-10 5:28 ` Christoph Hellwig
2024-04-10 0:57 ` [PATCH 14/32] xfs: add parent pointer validator functions Darrick J. Wong
2024-04-10 5:31 ` Christoph Hellwig
2024-04-10 18:53 ` Darrick J. Wong
2024-04-11 3:25 ` Christoph Hellwig
2024-04-10 0:57 ` [PATCH 15/32] xfs: extend transaction reservations for parent attributes Darrick J. Wong
2024-04-10 5:31 ` Christoph Hellwig
2024-04-10 0:57 ` [PATCH 16/32] xfs: create a hashname function for parent pointers Darrick J. Wong
2024-04-10 5:33 ` Christoph Hellwig
2024-04-10 21:39 ` Darrick J. Wong
2024-04-10 0:57 ` [PATCH 17/32] xfs: parent pointer attribute creation Darrick J. Wong
2024-04-10 5:44 ` Christoph Hellwig
2024-04-10 21:50 ` Darrick J. Wong
2024-04-10 0:58 ` [PATCH 18/32] xfs: add parent attributes to link Darrick J. Wong
2024-04-10 5:45 ` Christoph Hellwig
2024-04-10 0:58 ` [PATCH 19/32] xfs: add parent attributes to symlink Darrick J. Wong
2024-04-10 5:45 ` Christoph Hellwig
2024-04-10 0:58 ` [PATCH 20/32] xfs: remove parent pointers in unlink Darrick J. Wong
2024-04-10 5:45 ` Christoph Hellwig
2024-04-10 0:58 ` [PATCH 21/32] xfs: Add parent pointers to rename Darrick J. Wong
2024-04-10 5:46 ` Christoph Hellwig
2024-04-10 0:59 ` [PATCH 22/32] xfs: Add parent pointers to xfs_cross_rename Darrick J. Wong
2024-04-10 5:46 ` Christoph Hellwig
2024-04-10 0:59 ` [PATCH 23/32] xfs: Filter XFS_ATTR_PARENT for getfattr Darrick J. Wong
2024-04-10 5:51 ` Christoph Hellwig
2024-04-10 21:58 ` Darrick J. Wong
2024-04-11 3:29 ` Christoph Hellwig
2024-04-10 0:59 ` [PATCH 24/32] xfs: pass the attr value to put_listent when possible Darrick J. Wong
2024-04-10 5:51 ` Christoph Hellwig
2024-04-10 1:00 ` [PATCH 25/32] xfs: move handle ioctl code to xfs_handle.c Darrick J. Wong
2024-04-10 5:52 ` Christoph Hellwig
2024-04-10 1:00 ` [PATCH 26/32] xfs: split out handle management helpers a bit Darrick J. Wong
2024-04-10 5:56 ` Christoph Hellwig
2024-04-10 22:01 ` Darrick J. Wong
2024-04-10 1:00 ` [PATCH 27/32] xfs: Add parent pointer ioctls Darrick J. Wong
2024-04-10 6:04 ` Christoph Hellwig
2024-04-10 23:34 ` Darrick J. Wong
2024-04-12 17:39 ` Darrick J. Wong
2024-04-14 5:18 ` Christoph Hellwig
2024-04-15 19:40 ` Darrick J. Wong
2024-04-16 4:47 ` Christoph Hellwig
2024-04-16 16:50 ` Darrick J. Wong
2024-04-16 16:54 ` Christoph Hellwig
2024-04-16 18:52 ` Darrick J. Wong
2024-04-16 19:01 ` Christoph Hellwig
2024-04-16 19:07 ` Darrick J. Wong
2024-04-16 19:14 ` Christoph Hellwig
2024-04-17 5:22 ` Darrick J. Wong
2024-04-17 5:29 ` Christoph Hellwig
2024-04-17 5:55 ` Darrick J. Wong
2024-04-10 1:00 ` [PATCH 28/32] xfs: don't remove the attr fork when parent pointers are enabled Darrick J. Wong
2024-04-10 6:04 ` Christoph Hellwig
2024-04-10 1:01 ` [PATCH 29/32] xfs: Add the parent pointer support to the superblock version 5 Darrick J. Wong
2024-04-10 6:05 ` Christoph Hellwig
2024-04-10 22:06 ` Darrick J. Wong
2024-04-10 1:01 ` [PATCH 30/32] xfs: fix unit conversion error in xfs_log_calc_max_attrsetm_res Darrick J. Wong
2024-04-10 6:05 ` Christoph Hellwig
2024-04-10 1:01 ` [PATCH 31/32] xfs: drop compatibility minimum log size computations for reflink Darrick J. Wong
2024-04-10 6:06 ` Christoph Hellwig
2024-04-10 1:01 ` [PATCH 32/32] xfs: enable parent pointers Darrick J. Wong
2024-04-10 6:06 ` Christoph Hellwig
2024-04-10 22:11 ` Darrick J. Wong
2024-04-10 0:45 ` [PATCHSET v13.1 6/9] xfs: scrubbing for " Darrick J. Wong
2024-04-10 1:02 ` [PATCH 1/7] xfs: check dirents have " Darrick J. Wong
2024-04-10 6:12 ` Christoph Hellwig
2024-04-10 1:02 ` [PATCH 2/7] xfs: deferred scrub of dirents Darrick J. Wong
2024-04-10 6:13 ` Christoph Hellwig
2024-04-10 1:02 ` [PATCH 3/7] xfs: scrub parent pointers Darrick J. Wong
2024-04-10 6:13 ` Christoph Hellwig
2024-04-10 1:02 ` [PATCH 4/7] xfs: deferred scrub of " Darrick J. Wong
2024-04-10 6:14 ` Christoph Hellwig
2024-04-10 1:03 ` [PATCH 5/7] xfs: walk directory parent pointers to determine backref count Darrick J. Wong
2024-04-10 6:14 ` Christoph Hellwig
2024-04-10 1:03 ` [PATCH 6/7] xfs: check parent pointer xattrs when scrubbing Darrick J. Wong
2024-04-10 6:14 ` Christoph Hellwig
2024-04-10 1:03 ` [PATCH 7/7] xfs: salvage parent pointers when rebuilding xattr structures Darrick J. Wong
2024-04-10 6:15 ` Christoph Hellwig
2024-04-10 0:45 ` [PATCHSET v13.1 7/9] xfs: online repair for parent pointers Darrick J. Wong
2024-04-10 1:03 ` [PATCH 01/14] xfs: add xattr setname and removename functions for internal users Darrick J. Wong
2024-04-10 6:18 ` Christoph Hellwig
2024-04-10 22:18 ` Darrick J. Wong
2024-04-11 3:32 ` Christoph Hellwig
2024-04-11 4:30 ` Darrick J. Wong
2024-04-11 4:50 ` Christoph Hellwig
2024-04-10 1:04 ` [PATCH 02/14] xfs: add raw parent pointer apis to support repair Darrick J. Wong
2024-04-10 6:18 ` Christoph Hellwig
2024-04-10 1:04 ` [PATCH 03/14] xfs: repair directories by scanning directory parent pointers Darrick J. Wong
2024-04-10 6:19 ` Christoph Hellwig
2024-04-10 1:04 ` [PATCH 04/14] xfs: implement live updates for directory repairs Darrick J. Wong
2024-04-10 6:19 ` Christoph Hellwig
2024-04-10 1:04 ` [PATCH 05/14] xfs: replay unlocked parent pointer updates that accrue during xattr repair Darrick J. Wong
2024-04-10 6:19 ` Christoph Hellwig
2024-04-10 1:05 ` [PATCH 06/14] xfs: repair directory parent pointers by scanning for dirents Darrick J. Wong
2024-04-10 6:20 ` Christoph Hellwig
2024-04-10 1:05 ` [PATCH 07/14] xfs: implement live updates for parent pointer repairs Darrick J. Wong
2024-04-10 6:20 ` Christoph Hellwig
2024-04-10 1:05 ` [PATCH 08/14] xfs: remove pointless unlocked assertion Darrick J. Wong
2024-04-10 6:20 ` Christoph Hellwig
2024-04-10 1:06 ` [PATCH 09/14] xfs: split xfs_bmap_add_attrfork into two pieces Darrick J. Wong
2024-04-10 6:21 ` Christoph Hellwig
2024-04-10 1:06 ` [PATCH 10/14] xfs: add a per-leaf block callback to xchk_xattr_walk Darrick J. Wong
2024-04-10 6:22 ` Christoph Hellwig
2024-04-10 1:06 ` Darrick J. Wong [this message]
2024-04-10 6:22 ` [PATCH 11/14] xfs: actually rebuild the parent pointer xattrs Christoph Hellwig
2024-04-10 1:06 ` [PATCH 12/14] xfs: adapt the orphanage code to handle parent pointers Darrick J. Wong
2024-04-10 6:23 ` Christoph Hellwig
2024-04-10 1:07 ` [PATCH 13/14] xfs: repair link count of nondirectories after rebuilding " Darrick J. Wong
2024-04-10 6:22 ` Christoph Hellwig
2024-04-10 1:07 ` [PATCH 14/14] xfs: inode repair should ensure there's an attr fork to store " Darrick J. Wong
2024-04-10 6:24 ` Christoph Hellwig
2024-04-10 0:46 ` [PATCHSET v13.1 8/9] xfs: detect and correct directory tree problems Darrick J. Wong
2024-04-10 1:07 ` [PATCH 1/4] xfs: teach online scrub to find directory tree structure problems Darrick J. Wong
2024-04-10 7:21 ` Christoph Hellwig
2024-04-10 1:07 ` [PATCH 2/4] xfs: invalidate dirloop scrub path data when concurrent updates happen Darrick J. Wong
2024-04-10 7:21 ` Christoph Hellwig
2024-04-10 1:08 ` [PATCH 3/4] xfs: report directory tree corruption in the health information Darrick J. Wong
2024-04-10 7:23 ` Christoph Hellwig
2024-04-10 1:08 ` [PATCH 4/4] xfs: fix corruptions in the directory tree Darrick J. Wong
2024-04-10 7:23 ` Christoph Hellwig
2024-04-10 0:46 ` [PATCHSET v13.1 9/9] xfs: vectorize scrub kernel calls Darrick J. Wong
2024-04-10 1:08 ` [PATCH 1/3] xfs: reduce the rate of cond_resched calls inside scrub Darrick J. Wong
2024-04-10 14:55 ` Christoph Hellwig
2024-04-10 22:19 ` Darrick J. Wong
2024-04-10 1:08 ` [PATCH 2/3] xfs: introduce vectored scrub mode Darrick J. Wong
2024-04-10 15:00 ` Christoph Hellwig
2024-04-11 0:59 ` Darrick J. Wong
2024-04-11 3:38 ` Christoph Hellwig
2024-04-11 4:31 ` Darrick J. Wong
2024-04-10 1:09 ` [PATCH 3/3] xfs: only iget the file once when doing vectored scrub-by-handle Darrick J. Wong
2024-04-10 15:12 ` Christoph Hellwig
2024-04-11 1:15 ` Darrick J. Wong
2024-04-11 3:49 ` Christoph Hellwig
2024-04-11 4:41 ` Darrick J. Wong
2024-04-11 4:52 ` Christoph Hellwig
2024-04-11 4:56 ` Darrick J. Wong
2024-04-11 5:02 ` Christoph Hellwig
2024-04-11 5:21 ` Darrick J. Wong
2024-04-11 14:02 ` Christoph Hellwig
2024-04-12 0:21 ` Darrick J. Wong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=171270971170.3632937.9669548372844049712.stgit@frogsfrogsfrogs \
--to=djwong@kernel.org \
--cc=allison.henderson@oracle.com \
--cc=catherine.hoang@oracle.com \
--cc=hch@lst.de \
--cc=linux-xfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).