All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <djwong@kernel.org>
To: djwong@kernel.org
Cc: linux-xfs@vger.kernel.org
Subject: [PATCH 3/5] xfs: repair extended attributes
Date: Thu, 25 May 2023 18:33:28 -0700	[thread overview]
Message-ID: <168506066867.3737146.16409002171766831567.stgit@frogsfrogsfrogs> (raw)
In-Reply-To: <168506066818.3737146.14391441616329630322.stgit@frogsfrogsfrogs>

From: Darrick J. Wong <djwong@kernel.org>

If the extended attributes look bad, try to sift through the rubble to
find whatever keys/values we can, stage a new attribute structure in a
temporary file and use the atomic extent swapping mechanism to commit
the results in bulk.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
 fs/xfs/Makefile               |    1 
 fs/xfs/libxfs/xfs_attr.c      |    2 
 fs/xfs/libxfs/xfs_attr.h      |    2 
 fs/xfs/libxfs/xfs_da_format.h |    5 
 fs/xfs/scrub/attr.c           |   20 +
 fs/xfs/scrub/attr.h           |    7 
 fs/xfs/scrub/attr_repair.c    | 1190 +++++++++++++++++++++++++++++++++++++++++
 fs/xfs/scrub/attr_repair.h    |   11 
 fs/xfs/scrub/repair.c         |   46 ++
 fs/xfs/scrub/repair.h         |    6 
 fs/xfs/scrub/scrub.c          |    2 
 fs/xfs/scrub/trace.h          |   83 +++
 fs/xfs/scrub/xfarray.c        |   17 +
 fs/xfs/scrub/xfarray.h        |    2 
 fs/xfs/scrub/xfblob.c         |   17 +
 fs/xfs/scrub/xfblob.h         |    2 
 fs/xfs/scrub/xfile.h          |   12 
 fs/xfs/xfs_buf.c              |    3 
 fs/xfs/xfs_trace.h            |    2 
 19 files changed, 1426 insertions(+), 4 deletions(-)
 create mode 100644 fs/xfs/scrub/attr_repair.c
 create mode 100644 fs/xfs/scrub/attr_repair.h


diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile
index 589e18e7886c..af49d5702377 100644
--- a/fs/xfs/Makefile
+++ b/fs/xfs/Makefile
@@ -190,6 +190,7 @@ ifeq ($(CONFIG_XFS_ONLINE_REPAIR),y)
 xfs-y				+= $(addprefix scrub/, \
 				   agheader_repair.o \
 				   alloc_repair.o \
+				   attr_repair.o \
 				   bmap_repair.o \
 				   cow_repair.o \
 				   fscounters_repair.o \
diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
index 564345a17119..d38a4c42a912 100644
--- a/fs/xfs/libxfs/xfs_attr.c
+++ b/fs/xfs/libxfs/xfs_attr.c
@@ -1095,7 +1095,7 @@ xfs_attr_set(
  * External routines when attribute list is inside the inode
  *========================================================================*/
 
-static inline int xfs_attr_sf_totsize(struct xfs_inode *dp)
+int xfs_attr_sf_totsize(struct xfs_inode *dp)
 {
 	struct xfs_attr_shortform *sf;
 
diff --git a/fs/xfs/libxfs/xfs_attr.h b/fs/xfs/libxfs/xfs_attr.h
index 81be9b3e4004..e4f55008552b 100644
--- a/fs/xfs/libxfs/xfs_attr.h
+++ b/fs/xfs/libxfs/xfs_attr.h
@@ -618,4 +618,6 @@ extern struct kmem_cache *xfs_attr_intent_cache;
 int __init xfs_attr_intent_init_cache(void);
 void xfs_attr_intent_destroy_cache(void);
 
+int xfs_attr_sf_totsize(struct xfs_inode *dp);
+
 #endif	/* __XFS_ATTR_H__ */
diff --git a/fs/xfs/libxfs/xfs_da_format.h b/fs/xfs/libxfs/xfs_da_format.h
index 9d332415e0b6..e37de511bc2f 100644
--- a/fs/xfs/libxfs/xfs_da_format.h
+++ b/fs/xfs/libxfs/xfs_da_format.h
@@ -706,6 +706,11 @@ struct xfs_attr3_leafblock {
 #define XFS_ATTR_INCOMPLETE	(1u << XFS_ATTR_INCOMPLETE_BIT)
 #define XFS_ATTR_NSP_ONDISK_MASK	(XFS_ATTR_ROOT | XFS_ATTR_SECURE)
 
+#define XFS_ATTR_NAMESPACE_STR \
+	{ XFS_ATTR_LOCAL,	"local" }, \
+	{ XFS_ATTR_ROOT,	"root" }, \
+	{ XFS_ATTR_SECURE,	"secure" }
+
 /*
  * Alignment for namelist and valuelist entries (since they are mixed
  * there can be only one alignment value)
diff --git a/fs/xfs/scrub/attr.c b/fs/xfs/scrub/attr.c
index 40a59b24c209..692e1b2837bb 100644
--- a/fs/xfs/scrub/attr.c
+++ b/fs/xfs/scrub/attr.c
@@ -10,6 +10,7 @@
 #include "xfs_trans_resv.h"
 #include "xfs_mount.h"
 #include "xfs_log_format.h"
+#include "xfs_trans.h"
 #include "xfs_inode.h"
 #include "xfs_da_format.h"
 #include "xfs_da_btree.h"
@@ -20,6 +21,7 @@
 #include "scrub/common.h"
 #include "scrub/dabtree.h"
 #include "scrub/attr.h"
+#include "scrub/repair.h"
 
 /* Free the buffers linked from the xattr buffer. */
 static void
@@ -35,6 +37,8 @@ xchk_xattr_buf_cleanup(
 	kvfree(ab->value);
 	ab->value = NULL;
 	ab->value_sz = 0;
+	kvfree(ab->name);
+	ab->name = NULL;
 }
 
 /*
@@ -65,7 +69,7 @@ xchk_xattr_want_freemap(
  * reallocating the buffer if necessary.  Buffer contents are not preserved
  * across a reallocation.
  */
-static int
+int
 xchk_setup_xattr_buf(
 	struct xfs_scrub	*sc,
 	size_t			value_size)
@@ -95,6 +99,12 @@ xchk_setup_xattr_buf(
 			return -ENOMEM;
 	}
 
+	if (xchk_could_repair(sc)) {
+		ab->name = kvmalloc(XATTR_NAME_MAX + 1, XCHK_GFP_FLAGS);
+		if (!ab->name)
+			return -ENOMEM;
+	}
+
 resize_value:
 	if (ab->value_sz >= value_size)
 		return 0;
@@ -121,6 +131,12 @@ xchk_setup_xattr(
 {
 	int			error;
 
+	if (xchk_could_repair(sc)) {
+		error = xrep_setup_xattr(sc);
+		if (error)
+			return error;
+	}
+
 	/*
 	 * We failed to get memory while checking attrs, so this time try to
 	 * get all the memory we're ever going to need.  Allocate the buffer
@@ -247,7 +263,7 @@ xchk_xattr_listent(
  * Within a char, the lowest bit of the char represents the byte with
  * the smallest address
  */
-STATIC bool
+bool
 xchk_xattr_set_map(
 	struct xfs_scrub	*sc,
 	unsigned long		*map,
diff --git a/fs/xfs/scrub/attr.h b/fs/xfs/scrub/attr.h
index 48fd9402c432..7db58af56646 100644
--- a/fs/xfs/scrub/attr.h
+++ b/fs/xfs/scrub/attr.h
@@ -16,9 +16,16 @@ struct xchk_xattr_buf {
 	/* Bitmap of free space in xattr leaf blocks. */
 	unsigned long		*freemap;
 
+	/* Memory buffer used to hold salvaged xattr names. */
+	unsigned char		*name;
+
 	/* Memory buffer used to extract xattr values. */
 	void			*value;
 	size_t			value_sz;
 };
 
+bool xchk_xattr_set_map(struct xfs_scrub *sc, unsigned long *map,
+		unsigned int start, unsigned int len);
+int xchk_setup_xattr_buf(struct xfs_scrub *sc, size_t value_size);
+
 #endif	/* __XFS_SCRUB_ATTR_H__ */
diff --git a/fs/xfs/scrub/attr_repair.c b/fs/xfs/scrub/attr_repair.c
new file mode 100644
index 000000000000..1d5bacbe1b81
--- /dev/null
+++ b/fs/xfs/scrub/attr_repair.c
@@ -0,0 +1,1190 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2018-2023 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_btree.h"
+#include "xfs_bit.h"
+#include "xfs_log_format.h"
+#include "xfs_trans.h"
+#include "xfs_sb.h"
+#include "xfs_inode.h"
+#include "xfs_da_format.h"
+#include "xfs_da_btree.h"
+#include "xfs_dir2.h"
+#include "xfs_attr.h"
+#include "xfs_attr_leaf.h"
+#include "xfs_attr_sf.h"
+#include "xfs_attr_remote.h"
+#include "xfs_bmap.h"
+#include "xfs_bmap_util.h"
+#include "xfs_swapext.h"
+#include "xfs_xchgrange.h"
+#include "xfs_acl.h"
+#include "scrub/xfs_scrub.h"
+#include "scrub/scrub.h"
+#include "scrub/common.h"
+#include "scrub/trace.h"
+#include "scrub/repair.h"
+#include "scrub/tempfile.h"
+#include "scrub/tempswap.h"
+#include "scrub/xfile.h"
+#include "scrub/xfarray.h"
+#include "scrub/xfblob.h"
+#include "scrub/attr.h"
+#include "scrub/reap.h"
+#include "scrub/attr_repair.h"
+
+/*
+ * Extended Attribute Repair
+ * =========================
+ *
+ * We repair extended attributes by reading the attr leaf blocks looking for
+ * attributes entries that look salvageable (name passes verifiers, value can
+ * be retrieved, etc).  Each extended attribute worth salvaging is stashed in
+ * memory, and the stashed entries are periodically replayed into a temporary
+ * file to constrain memory use.  Batching the construction of the temporary
+ * extended attribute structure in this fashion reduces lock cycling of the
+ * file being repaired and the temporary file.
+ *
+ * When salvaging completes, the remaining stashed attributes are replayed to
+ * the temporary file.  An atomic extent swap is used to commit the new xattr
+ * blocks to the file being repaired.  This will disrupt attrmulti cursors.
+ */
+
+struct xrep_xattr_key {
+	/* 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_XATTR_MAX_STASH_BYTES	(PAGE_SIZE * 8)
+
+struct xrep_xattr {
+	struct xfs_scrub	*sc;
+
+	/* Information for swapping attr forks at the end. */
+	struct xrep_tempswap	tx;
+
+	/* xattr keys */
+	struct xfarray		*xattr_records;
+
+	/* xattr values */
+	struct xfblob		*xattr_blobs;
+
+	/* Number of attributes that we are salvaging. */
+	unsigned long long	attrs_found;
+};
+
+/* Set up to recreate the extended attributes. */
+int
+xrep_setup_xattr(
+	struct xfs_scrub	*sc)
+{
+	return xrep_tempfile_create(sc, S_IFREG);
+}
+
+/*
+ * Decide if we want to salvage this attribute.  We don't bother with
+ * incomplete or oversized keys or values.  The @value parameter can be null
+ * for remote attrs.
+ */
+STATIC int
+xrep_xattr_want_salvage(
+	struct xrep_xattr	*rx,
+	unsigned int		attr_flags,
+	const void		*name,
+	int			namelen,
+	const void		*value,
+	int			valuelen)
+{
+	if (attr_flags & XFS_ATTR_INCOMPLETE)
+		return false;
+	if (namelen > XATTR_NAME_MAX || namelen <= 0)
+		return false;
+	if (valuelen > XATTR_SIZE_MAX || valuelen < 0)
+		return false;
+	return true;
+}
+
+/* Allocate an in-core record to hold xattrs while we rebuild the xattr data. */
+STATIC int
+xrep_xattr_salvage_key(
+	struct xrep_xattr	*rx,
+	int			flags,
+	unsigned char		*name,
+	int			namelen,
+	unsigned char		*value,
+	int			valuelen)
+{
+	struct xrep_xattr_key	key = {
+		.valuelen	= valuelen,
+		.flags		= flags & XFS_ATTR_NSP_ONDISK_MASK,
+	};
+	unsigned int		i = 0;
+	int			error = 0;
+
+	if (xchk_should_terminate(rx->sc, &error))
+		return error;
+
+	/*
+	 * Truncate the name to the first character that would trip namecheck.
+	 * If we no longer have a name after that, ignore this attribute.
+	 */
+	while (i < namelen && name[i] != 0)
+		i++;
+	if (i == 0)
+		return 0;
+	key.namelen = i;
+
+	trace_xrep_xattr_salvage_rec(rx->sc->ip, flags, name, key.namelen,
+			valuelen);
+
+	error = xfblob_store(rx->xattr_blobs, &key.name_cookie, name,
+			key.namelen);
+	if (error)
+		return error;
+
+	error = xfblob_store(rx->xattr_blobs, &key.value_cookie, value,
+			key.valuelen);
+	if (error)
+		return error;
+
+	error = xfarray_append(rx->xattr_records, &key);
+	if (error)
+		return error;
+
+	rx->attrs_found++;
+	return 0;
+}
+
+/*
+ * Record a shortform extended attribute key & value for later reinsertion
+ * into the inode.
+ */
+STATIC int
+xrep_xattr_salvage_sf_attr(
+	struct xrep_xattr		*rx,
+	struct xfs_attr_shortform	*sf,
+	struct xfs_attr_sf_entry	*sfe)
+{
+	struct xfs_scrub		*sc = rx->sc;
+	struct xchk_xattr_buf		*ab = sc->buf;
+	unsigned char			*name = sfe->nameval;
+	unsigned char			*value = &sfe->nameval[sfe->namelen];
+
+	if (!xchk_xattr_set_map(sc, ab->usedmap, (char *)name - (char *)sf,
+			sfe->namelen))
+		return 0;
+
+	if (!xchk_xattr_set_map(sc, ab->usedmap, (char *)value - (char *)sf,
+			sfe->valuelen))
+		return 0;
+
+	if (!xrep_xattr_want_salvage(rx, sfe->flags, sfe->nameval,
+			sfe->namelen, value, sfe->valuelen))
+		return 0;
+
+	return xrep_xattr_salvage_key(rx, sfe->flags, sfe->nameval,
+			sfe->namelen, value, sfe->valuelen);
+}
+
+/*
+ * Record a local format extended attribute key & value for later reinsertion
+ * into the inode.
+ */
+STATIC int
+xrep_xattr_salvage_local_attr(
+	struct xrep_xattr		*rx,
+	struct xfs_attr_leaf_entry	*ent,
+	unsigned int			nameidx,
+	const char			*buf_end,
+	struct xfs_attr_leaf_name_local	*lentry)
+{
+	struct xchk_xattr_buf		*ab = rx->sc->buf;
+	unsigned char			*value;
+	unsigned int			valuelen;
+	unsigned int			namesize;
+
+	/*
+	 * Decode the leaf local entry format.  If something seems wrong, we
+	 * junk the attribute.
+	 */
+	value = &lentry->nameval[lentry->namelen];
+	valuelen = be16_to_cpu(lentry->valuelen);
+	namesize = xfs_attr_leaf_entsize_local(lentry->namelen, valuelen);
+	if ((char *)lentry + namesize > buf_end)
+		return 0;
+	if (!xrep_xattr_want_salvage(rx, ent->flags, lentry->nameval,
+			lentry->namelen, value, valuelen))
+		return 0;
+	if (!xchk_xattr_set_map(rx->sc, ab->usedmap, nameidx, namesize))
+		return 0;
+
+	/* Try to save this attribute. */
+	return xrep_xattr_salvage_key(rx, ent->flags, lentry->nameval,
+			lentry->namelen, value, valuelen);
+}
+
+/*
+ * Record a remote format extended attribute key & value for later reinsertion
+ * into the inode.
+ */
+STATIC int
+xrep_xattr_salvage_remote_attr(
+	struct xrep_xattr		*rx,
+	struct xfs_attr_leaf_entry	*ent,
+	unsigned int			nameidx,
+	const char			*buf_end,
+	struct xfs_attr_leaf_name_remote *rentry,
+	unsigned int			ent_idx,
+	struct xfs_buf			*leaf_bp)
+{
+	struct xfs_da_args		args = {
+		.trans			= rx->sc->tp,
+		.dp			= rx->sc->ip,
+		.index			= ent_idx,
+		.geo			= rx->sc->mp->m_attr_geo,
+		.owner			= rx->sc->ip->i_ino,
+	};
+	struct xchk_xattr_buf		*ab = rx->sc->buf;
+	unsigned int			valuelen;
+	unsigned int			namesize;
+	int				error;
+
+	/*
+	 * Decode the leaf remote entry format.  If something seems wrong, we
+	 * junk the attribute.  Note that we should never find a zero-length
+	 * remote attribute value.
+	 */
+	valuelen = be32_to_cpu(rentry->valuelen);
+	namesize = xfs_attr_leaf_entsize_remote(rentry->namelen);
+	if ((char *)rentry + namesize > buf_end)
+		return 0;
+	if (valuelen == 0 ||
+	    !xrep_xattr_want_salvage(rx, ent->flags, rentry->name,
+			rentry->namelen, NULL, valuelen))
+		return 0;
+	if (!xchk_xattr_set_map(rx->sc, ab->usedmap, nameidx, namesize))
+		return 0;
+
+	/*
+	 * Enlarge the buffer (if needed) to hold the value that we're trying
+	 * to salvage from the old extended attribute data.
+	 */
+	error = xchk_setup_xattr_buf(rx->sc, valuelen);
+	if (error == -ENOMEM)
+		error = -EDEADLOCK;
+	if (error)
+		return error;
+
+	/* Look up the remote value and stash it for reconstruction. */
+	args.valuelen = valuelen;
+	args.namelen = rentry->namelen;
+	args.name = rentry->name;
+	args.value = ab->value;
+	error = xfs_attr3_leaf_getvalue(leaf_bp, &args);
+	if (error || args.rmtblkno == 0)
+		goto err_free;
+
+	error = xfs_attr_rmtval_get(&args);
+	if (error)
+		goto err_free;
+
+	/* Try to save this attribute. */
+	error = xrep_xattr_salvage_key(rx, ent->flags, rentry->name,
+			rentry->namelen, ab->value, valuelen);
+err_free:
+	/* remote value was garbage, junk it */
+	if (error == -EFSBADCRC || error == -EFSCORRUPTED)
+		error = 0;
+	return error;
+}
+
+/* Extract every xattr key that we can from this attr fork block. */
+STATIC int
+xrep_xattr_recover_leaf(
+	struct xrep_xattr		*rx,
+	struct xfs_buf			*bp)
+{
+	struct xfs_attr3_icleaf_hdr	leafhdr;
+	struct xfs_scrub		*sc = rx->sc;
+	struct xfs_mount		*mp = sc->mp;
+	struct xfs_attr_leafblock	*leaf;
+	struct xfs_attr_leaf_name_local	*lentry;
+	struct xfs_attr_leaf_name_remote *rentry;
+	struct xfs_attr_leaf_entry	*ent;
+	struct xfs_attr_leaf_entry	*entries;
+	struct xchk_xattr_buf		*ab = rx->sc->buf;
+	char				*buf_end;
+	size_t				off;
+	unsigned int			nameidx;
+	unsigned int			hdrsize;
+	int				i;
+	int				error = 0;
+
+	bitmap_zero(ab->usedmap, mp->m_attr_geo->blksize);
+
+	/* Check the leaf header */
+	leaf = bp->b_addr;
+	xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf);
+	hdrsize = xfs_attr3_leaf_hdr_size(leaf);
+	xchk_xattr_set_map(sc, ab->usedmap, 0, hdrsize);
+	entries = xfs_attr3_leaf_entryp(leaf);
+
+	buf_end = (char *)bp->b_addr + mp->m_attr_geo->blksize;
+	for (i = 0, ent = entries; i < leafhdr.count; ent++, i++) {
+		if (xchk_should_terminate(sc, &error))
+			return error;
+
+		/* Skip key if it conflicts with something else? */
+		off = (char *)ent - (char *)leaf;
+		if (!xchk_xattr_set_map(sc, ab->usedmap, off,
+				sizeof(xfs_attr_leaf_entry_t)))
+			continue;
+
+		/* Check the name information. */
+		nameidx = be16_to_cpu(ent->nameidx);
+		if (nameidx < leafhdr.firstused ||
+		    nameidx >= mp->m_attr_geo->blksize)
+			continue;
+
+		if (ent->flags & XFS_ATTR_LOCAL) {
+			lentry = xfs_attr3_leaf_name_local(leaf, i);
+			error = xrep_xattr_salvage_local_attr(rx, ent, nameidx,
+					buf_end, lentry);
+		} else {
+			rentry = xfs_attr3_leaf_name_remote(leaf, i);
+			error = xrep_xattr_salvage_remote_attr(rx, ent, nameidx,
+					buf_end, rentry, i, bp);
+		}
+		if (error)
+			return error;
+	}
+
+	return 0;
+}
+
+/* Try to recover shortform attrs. */
+STATIC int
+xrep_xattr_recover_sf(
+	struct xrep_xattr		*rx)
+{
+	struct xfs_scrub		*sc = rx->sc;
+	struct xchk_xattr_buf		*ab = sc->buf;
+	struct xfs_attr_shortform	*sf;
+	struct xfs_attr_sf_entry	*sfe;
+	struct xfs_attr_sf_entry	*next;
+	struct xfs_ifork		*ifp;
+	unsigned char			*end;
+	int				i;
+	int				error = 0;
+
+	ifp = xfs_ifork_ptr(rx->sc->ip, XFS_ATTR_FORK);
+
+	bitmap_zero(ab->usedmap, ifp->if_bytes);
+	sf = (struct xfs_attr_shortform *)rx->sc->ip->i_af.if_u1.if_data;
+	end = (unsigned char *)ifp->if_u1.if_data + ifp->if_bytes;
+	xchk_xattr_set_map(sc, ab->usedmap, 0, sizeof(sf->hdr));
+
+	sfe = &sf->list[0];
+	if ((unsigned char *)sfe > end)
+		return 0;
+
+	for (i = 0; i < sf->hdr.count; i++) {
+		if (xchk_should_terminate(sc, &error))
+			return error;
+
+		next = xfs_attr_sf_nextentry(sfe);
+		if ((unsigned char *)next > end)
+			break;
+
+		if (xchk_xattr_set_map(sc, ab->usedmap,
+				(char *)sfe - (char *)sf,
+				sizeof(struct xfs_attr_sf_entry))) {
+			/*
+			 * No conflicts with the sf entry; let's save this
+			 * attribute.
+			 */
+			error = xrep_xattr_salvage_sf_attr(rx, sf, sfe);
+			if (error)
+				return error;
+		}
+
+		sfe = next;
+	}
+
+	return 0;
+}
+
+/*
+ * Try to return a buffer of xattr data for a given physical extent.
+ *
+ * Because the buffer cache get function complains if it finds a buffer
+ * matching the block number but not matching the length, we must be careful to
+ * look for incore buffers (up to the maximum length of a remote value) that
+ * could be hiding anywhere in the physical range.  If we find an incore
+ * buffer, we can pass that to the caller.  Optionally, read a single block and
+ * pass that back.
+ *
+ * Note the subtlety that remote attr value blocks for which there is no incore
+ * buffer will be passed to the callback one block at a time.  These buffers
+ * will not have any ops attached and must be staled to prevent aliasing with
+ * multiblock buffers once we drop the ILOCK.
+ */
+STATIC int
+xrep_xattr_find_buf(
+	struct xfs_mount	*mp,
+	xfs_fsblock_t		fsbno,
+	xfs_extlen_t		max_len,
+	bool			can_read,
+	struct xfs_buf		**bpp)
+{
+	struct xrep_bufscan	scan = {
+		.daddr		= XFS_FSB_TO_DADDR(mp, fsbno),
+		.max_sectors	= xrep_bufscan_max_sectors(mp, max_len),
+		.daddr_step	= XFS_FSB_TO_BB(mp, 1),
+	};
+	struct xfs_buf		*bp;
+
+	while ((bp = xrep_bufscan_advance(mp, &scan)) != NULL) {
+		*bpp = bp;
+		return 0;
+	}
+
+	if (!can_read) {
+		*bpp = NULL;
+		return 0;
+	}
+
+	return xfs_buf_read(mp->m_ddev_targp, scan.daddr, XFS_FSB_TO_BB(mp, 1),
+			XBF_TRYLOCK, bpp, NULL);
+}
+
+/*
+ * Deal with a buffer that we found during our walk of the attr fork.
+ *
+ * Attribute leaf and node blocks are simple -- they're a single block, so we
+ * can walk them one at a time and we never have to worry about discontiguous
+ * multiblock buffers like we do for directories.
+ *
+ * Unfortunately, remote attr blocks add a lot of complexity here.  Each disk
+ * block is totally self contained, in the sense that the v5 header provides no
+ * indication that there could be more data in the next block.  The incore
+ * buffers can span multiple blocks, though they never cross extent records.
+ * However, they don't necessarily start or end on an extent record boundary.
+ * Therefore, we need a special buffer find function to walk the buffer cache
+ * for us.
+ *
+ * The caller must hold the ILOCK on the file being repaired.  We use
+ * XBF_TRYLOCK here to skip any locked buffer on the assumption that we don't
+ * own the block and don't want to hang the system on a potentially garbage
+ * buffer.
+ */
+STATIC int
+xrep_xattr_recover_block(
+	struct xrep_xattr	*rx,
+	xfs_dablk_t		dabno,
+	xfs_fsblock_t		fsbno,
+	xfs_extlen_t		max_len,
+	xfs_extlen_t		*actual_len)
+{
+	struct xfs_da_blkinfo	*info;
+	struct xfs_buf		*bp;
+	int			error;
+
+	error = xrep_xattr_find_buf(rx->sc->mp, fsbno, max_len, true, &bp);
+	if (error)
+		return error;
+	info = bp->b_addr;
+	*actual_len = XFS_BB_TO_FSB(rx->sc->mp, bp->b_length);
+
+	trace_xrep_xattr_recover_leafblock(rx->sc->ip, dabno,
+			be16_to_cpu(info->magic));
+
+	/*
+	 * If the buffer has the right magic number for an attr leaf block and
+	 * passes a structure check (we don't care about checksums), salvage
+	 * as much as we can from the block. */
+	if (info->magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC) &&
+	    xrep_buf_verify_struct(bp, &xfs_attr3_leaf_buf_ops) &&
+	    xfs_attr3_leaf_header_check(bp, rx->sc->ip->i_ino) == NULL)
+		error = xrep_xattr_recover_leaf(rx, bp);
+
+	/*
+	 * If the buffer didn't already have buffer ops set, it was read in by
+	 * the _find_buf function and could very well be /part/ of a multiblock
+	 * remote block.  Mark it stale so that it doesn't hang around in
+	 * memory to cause problems.
+	 */
+	if (bp->b_ops == NULL)
+		xfs_buf_stale(bp);
+
+	xfs_buf_relse(bp);
+	return error;
+}
+
+/* Insert one xattr key/value. */
+STATIC int
+xrep_xattr_insert_rec(
+	struct xrep_xattr		*rx,
+	const struct xrep_xattr_key	*key)
+{
+	struct xfs_da_args		args = {
+		.dp			= rx->sc->tempip,
+		.attr_filter		= key->flags,
+		.attr_flags		= XATTR_CREATE,
+		.namelen		= key->namelen,
+		.valuelen		= key->valuelen,
+		.op_flags		= XFS_DA_OP_NOTIME,
+		.owner			= rx->sc->ip->i_ino,
+	};
+	struct xchk_xattr_buf		*ab = rx->sc->buf;
+	int				error;
+
+	/*
+	 * Grab pointers to the scrub buffer so that we can use them to insert
+	 * attrs into the temp file.
+	 */
+	args.name = ab->name;
+	args.value = ab->value;
+
+	/*
+	 * The attribute name is stored near the end of the in-core buffer,
+	 * though we reserve one more byte to ensure null termination.
+	 */
+	ab->name[XATTR_NAME_MAX] = 0;
+
+	error = xfblob_load(rx->xattr_blobs, key->name_cookie, ab->name,
+			key->namelen);
+	if (error)
+		return error;
+
+	error = xfblob_free(rx->xattr_blobs, key->name_cookie);
+	if (error)
+		return error;
+
+	error = xfblob_load(rx->xattr_blobs, key->value_cookie, args.value,
+			key->valuelen);
+	if (error)
+		return error;
+
+	error = xfblob_free(rx->xattr_blobs, key->value_cookie);
+	if (error)
+		return error;
+
+	ab->name[key->namelen] = 0;
+
+	trace_xrep_xattr_insert_rec(rx->sc->tempip, key->flags, ab->name,
+			key->namelen, key->valuelen);
+
+	/*
+	 * xfs_attr_set creates and commits its own transaction.  If the attr
+	 * already exists, we'll just drop it during the rebuild.
+	 */
+	error = xfs_attr_set(&args);
+	if (error == -EEXIST)
+		error = 0;
+
+	return error;
+}
+
+/*
+ * 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_xattr_flush_stashed(
+	struct xrep_xattr	*rx)
+{
+	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 a scrub transaction
+	 * that we use during xattr salvaging to avoid livelocking if there
+	 * are cycles in the xattr structures.  We hold ILOCK_EXCL on both
+	 * the inode being repaired, though it is not ijoined to the scrub
+	 * transaction.
+	 *
+	 * To constrain kernel memory use, we occasionally flush salvaged
+	 * xattrs from the xfarray and xfblob structures into the temporary
+	 * file in preparation for swapping the xattr structures at the end.
+	 * Updating the temporary file requires a transaction, so we commit the
+	 * scrub transaction and drop the two ILOCKs 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 accessing the damaged xattr data while we
+	 * repair it.
+	 */
+	error = xrep_trans_commit(rx->sc);
+	if (error)
+		return error;
+	xchk_iunlock(rx->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(rx->sc);
+	if (error)
+		return error;
+
+	/* Add all the salvaged attrs to the temporary file. */
+	foreach_xfarray_idx(rx->xattr_records, array_cur) {
+		struct xrep_xattr_key	key;
+
+		error = xfarray_load(rx->xattr_records, array_cur, &key);
+		if (error)
+			return error;
+
+		error = xrep_xattr_insert_rec(rx, &key);
+		if (error)
+			return error;
+	}
+
+	/* Empty out both arrays now that we've added the entries. */
+	xfarray_truncate(rx->xattr_records);
+	xfblob_truncate(rx->xattr_blobs);
+
+	xrep_tempfile_iounlock(rx->sc);
+
+	/* Recreate the salvage transaction and relock the inode. */
+	error = xchk_trans_alloc(rx->sc, 0);
+	if (error)
+		return error;
+	xchk_ilock(rx->sc, XFS_ILOCK_EXCL);
+	return 0;
+}
+
+/* Decide if we've stashed too much xattr data in memory. */
+static inline bool
+xrep_xattr_want_flush_stashed(
+	struct xrep_xattr	*rx)
+{
+	unsigned long long	bytes;
+
+	bytes = xfarray_bytes(rx->xattr_records) +
+		xfblob_bytes(rx->xattr_blobs);
+	return bytes > XREP_XATTR_MAX_STASH_BYTES;
+}
+
+/* Extract as many attribute keys and values as we can. */
+STATIC int
+xrep_xattr_recover(
+	struct xrep_xattr	*rx)
+{
+	struct xfs_bmbt_irec	got;
+	struct xfs_scrub	*sc = rx->sc;
+	struct xfs_da_geometry	*geo = sc->mp->m_attr_geo;
+	xfs_fileoff_t		offset;
+	xfs_extlen_t		len;
+	xfs_dablk_t		dabno;
+	int			nmap;
+	int			error;
+
+	/*
+	 * Iterate each xattr leaf block in the attr fork to scan them for any
+	 * attributes that we might salvage.
+	 */
+	for (offset = 0;
+	     offset < XFS_MAX_FILEOFF;
+	     offset = got.br_startoff + got.br_blockcount) {
+		nmap = 1;
+		error = xfs_bmapi_read(sc->ip, offset, XFS_MAX_FILEOFF - offset,
+				&got, &nmap, XFS_BMAPI_ATTRFORK);
+		if (error)
+			return error;
+		if (nmap != 1)
+			return -EFSCORRUPTED;
+		if (!xfs_bmap_is_written_extent(&got))
+			continue;
+
+		for (dabno = round_up(got.br_startoff, geo->fsbcount);
+		     dabno < got.br_startoff + got.br_blockcount;
+		     dabno += len) {
+			xfs_fileoff_t	curr_offset = dabno - got.br_startoff;
+			xfs_extlen_t	maxlen;
+
+			if (xchk_should_terminate(rx->sc, &error))
+				return error;
+
+			maxlen = min_t(xfs_filblks_t, INT_MAX,
+					got.br_blockcount - curr_offset);
+			error = xrep_xattr_recover_block(rx, dabno,
+					curr_offset + got.br_startblock,
+					maxlen, &len);
+			if (error)
+				return error;
+
+			if (xrep_xattr_want_flush_stashed(rx)) {
+				error = xrep_xattr_flush_stashed(rx);
+				if (error)
+					return error;
+			}
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Reset the extended attribute fork to a state where we can start re-adding
+ * the salvaged attributes.
+ */
+STATIC int
+xrep_xattr_fork_remove(
+	struct xfs_scrub	*sc,
+	struct xfs_inode	*ip)
+{
+	struct xfs_attr_sf_hdr	*hdr;
+	struct xfs_ifork	*ifp = xfs_ifork_ptr(ip, XFS_ATTR_FORK);
+
+	/*
+	 * If the data fork is in btree format, we can't change di_forkoff
+	 * because we could run afoul of the rule that the data fork isn't
+	 * supposed to be in btree format if there's enough space in the fork
+	 * that it could have used extents format.  Instead, reinitialize the
+	 * attr fork to have a shortform structure with zero attributes.
+	 */
+	if (ip->i_df.if_format == XFS_DINODE_FMT_BTREE) {
+		ifp->if_format = XFS_DINODE_FMT_LOCAL;
+		xfs_idata_realloc(ip, (int)sizeof(*hdr) - ifp->if_bytes,
+				XFS_ATTR_FORK);
+		hdr = (struct xfs_attr_sf_hdr *)ifp->if_u1.if_data;
+		hdr->count = 0;
+		hdr->totsize = cpu_to_be16(sizeof(*hdr));
+		xfs_trans_log_inode(sc->tp, ip,
+				XFS_ILOG_CORE | XFS_ILOG_ADATA);
+		return 0;
+	}
+
+	/* If we still have attr fork extents, something's wrong. */
+	if (ifp->if_nextents != 0) {
+		struct xfs_iext_cursor	icur;
+		struct xfs_bmbt_irec	irec;
+		unsigned int		i = 0;
+
+		xfs_emerg(sc->mp,
+	"inode 0x%llx attr fork still has %llu attr extents, format %d?!",
+				ip->i_ino, ifp->if_nextents, ifp->if_format);
+		for_each_xfs_iext(ifp, &icur, &irec) {
+			xfs_err(sc->mp,
+	"[%u]: startoff %llu startblock %llu blockcount %llu state %u",
+					i++, irec.br_startoff,
+					irec.br_startblock, irec.br_blockcount,
+					irec.br_state);
+		}
+		ASSERT(0);
+		return -EFSCORRUPTED;
+	}
+
+	xfs_attr_fork_remove(ip, sc->tp);
+	return 0;
+}
+
+/*
+ * Free all the attribute fork blocks of the file being repaired and delete the
+ * fork.  The caller must ILOCK the scrub file and join it to the transaction.
+ * This function returns with the inode joined to a clean transaction.
+ */
+int
+xrep_xattr_reset_fork(
+	struct xfs_scrub	*sc)
+{
+	int			error;
+
+	trace_xrep_xattr_reset_fork(sc->ip, sc->ip);
+
+	/* Unmap all the attr blocks. */
+	if (xfs_ifork_has_extents(&sc->ip->i_af)) {
+		error = xrep_reap_ifork(sc, sc->ip, XFS_ATTR_FORK);
+		if (error)
+			return error;
+	}
+
+	error = xrep_xattr_fork_remove(sc, sc->ip);
+	if (error)
+		return error;
+
+	return xfs_trans_roll_inode(&sc->tp, sc->ip);
+}
+
+/*
+ * Free all the attribute fork blocks of the temporary file and delete the attr
+ * 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
+xrep_xattr_reset_tempfile_fork(
+	struct xfs_scrub	*sc)
+{
+	int			error;
+
+	trace_xrep_xattr_reset_fork(sc->ip, sc->tempip);
+
+	/*
+	 * Wipe out the attr fork of the temp file so that regular inode
+	 * inactivation won't trip over the corrupt attr fork.
+	 */
+	if (xfs_ifork_has_extents(&sc->tempip->i_af)) {
+		error = xrep_reap_ifork(sc, sc->tempip, XFS_ATTR_FORK);
+		if (error)
+			return error;
+	}
+
+	error = xrep_xattr_fork_remove(sc, sc->tempip);
+	if (error)
+		return error;
+
+	return xrep_tempfile_roll_trans(sc);
+}
+
+/*
+ * Find all the extended attributes for this inode by scraping them out of the
+ * attribute key blocks by hand, and flushing them into the temp file.
+ * When we're done, free the staging memory before swapping the xattr
+ * structures to reduce memory usage.
+ */
+STATIC int
+xrep_xattr_salvage_attributes(
+	struct xrep_xattr	*rx)
+{
+	struct xfs_inode	*ip = rx->sc->ip;
+	int			error;
+
+	/* Short format xattrs are easy! */
+	if (rx->sc->ip->i_af.if_format == XFS_DINODE_FMT_LOCAL) {
+		error = xrep_xattr_recover_sf(rx);
+		if (error)
+			return error;
+
+		return xrep_xattr_flush_stashed(rx);
+	}
+
+	/*
+	 * For non-inline xattr structures, the salvage function scans the
+	 * buffer cache looking for potential attr leaf blocks.  The scan
+	 * requires the ability to lock any buffer found and runs independently
+	 * of any transaction <-> buffer item <-> buffer linkage.  Therefore,
+	 * roll the transaction to ensure there are no buffers joined.  We hold
+	 * the ILOCK independently of the transaction.
+	 */
+	error = xfs_trans_roll(&rx->sc->tp);
+	if (error)
+		return error;
+
+	error = xfs_iread_extents(rx->sc->tp, ip, XFS_ATTR_FORK);
+	if (error)
+		return error;
+
+	error = xrep_xattr_recover(rx);
+	if (error)
+		return error;
+
+	return xrep_xattr_flush_stashed(rx);
+}
+
+/*
+ * Prepare both inodes' attribute forks for extent swapping.  Promote the
+ * tempfile from short format to leaf format, and if the file being repaired
+ * has a short format attr fork, turn it into an empty extent list.
+ */
+STATIC int
+xrep_xattr_swap_prep(
+	struct xfs_scrub	*sc,
+	bool			temp_local,
+	bool			ip_local)
+{
+	int			error;
+
+	/*
+	 * If the tempfile's attributes are in shortform format, convert that
+	 * to a single leaf extent so that we can use the atomic extent swap.
+	 */
+	if (temp_local) {
+		struct xfs_da_args	args = {
+			.dp		= sc->tempip,
+			.geo		= sc->mp->m_attr_geo,
+			.whichfork	= XFS_ATTR_FORK,
+			.trans		= sc->tp,
+			.total		= 1,
+			.owner		= sc->ip->i_ino,
+		};
+
+		error = xfs_attr_shortform_to_leaf(&args);
+		if (error)
+			return error;
+
+		/*
+		 * Roll the deferred log items to get us back to a clean
+		 * transaction.
+		 */
+		error = xfs_defer_finish(&sc->tp);
+		if (error)
+			return error;
+	}
+
+	/*
+	 * If the file being repaired had a shortform attribute fork, convert
+	 * that to an empty extent list in preparation for the atomic extent
+	 * swap.
+	 */
+	if (ip_local) {
+		struct xfs_ifork	*ifp;
+
+		ifp = xfs_ifork_ptr(sc->ip, XFS_ATTR_FORK);
+
+		xfs_idestroy_fork(ifp);
+		ifp->if_format = XFS_DINODE_FMT_EXTENTS;
+		ifp->if_nextents = 0;
+		ifp->if_bytes = 0;
+		ifp->if_u1.if_root = NULL;
+		ifp->if_height = 0;
+
+		xfs_trans_log_inode(sc->tp, sc->ip,
+				XFS_ILOG_CORE | XFS_ILOG_ADATA);
+	}
+
+	return 0;
+}
+
+/* Swap the temporary file's attribute fork with the one being repaired. */
+STATIC int
+xrep_xattr_swap(
+	struct xfs_scrub	*sc,
+	struct xrep_tempswap	*tx)
+{
+	bool			ip_local, temp_local;
+	int			error = 0;
+
+	ip_local = sc->ip->i_af.if_format == XFS_DINODE_FMT_LOCAL;
+	temp_local = sc->tempip->i_af.if_format == XFS_DINODE_FMT_LOCAL;
+
+	/*
+	 * If the both files have a local format attr fork and the rebuilt
+	 * xattr data would fit in the repaired file's attr fork, just copy
+	 * the contents from the tempfile and declare ourselves done.
+	 */
+	if (ip_local && temp_local) {
+		int	forkoff;
+		int	newsize;
+
+		newsize = xfs_attr_sf_totsize(sc->tempip);
+		forkoff = xfs_attr_shortform_bytesfit(sc->ip, newsize);
+		if (forkoff > 0) {
+			sc->ip->i_forkoff = forkoff;
+			xrep_tempfile_copyout_local(sc, XFS_ATTR_FORK);
+			return 0;
+		}
+	}
+
+	/* Otherwise, make sure both attr forks are in block-mapping mode. */
+	error = xrep_xattr_swap_prep(sc, temp_local, ip_local);
+	if (error)
+		return error;
+
+	return xrep_tempswap_contents(sc, tx);
+}
+
+/*
+ * Swap the new extended attribute data (which we created in the tempfile) into
+ * the file being repaired.
+ */
+STATIC int
+xrep_xattr_rebuild_tree(
+	struct xrep_xattr	*rx)
+{
+	struct xfs_scrub	*sc = rx->sc;
+	int			error;
+
+	/*
+	 * If we didn't find any attributes to salvage, repair the file by
+	 * zapping its attr fork.
+	 */
+	if (rx->attrs_found == 0) {
+		xfs_trans_ijoin(sc->tp, sc->ip, 0);
+		error = xrep_xattr_reset_fork(sc);
+		if (error)
+			return error;
+
+		goto forget_acls;
+	}
+
+	trace_xrep_xattr_rebuild_tree(sc->ip, sc->tempip);
+
+	/*
+	 * Commit the repair transaction and drop the ILOCKs so that we can use
+	 * the atomic extent swap helper functions to compute the correct
+	 * resource reservations.
+	 *
+	 * We still hold IOLOCK_EXCL (aka i_rwsem) which will prevent xattr
+	 * modifications, but there's nothing to prevent userspace from reading
+	 * the attributes until we're ready for the swap operation.  Reads will
+	 * return -EIO without shutting down the fs, so we're ok with that.
+	 */
+	error = xrep_trans_commit(sc);
+	if (error)
+		return error;
+
+	xchk_iunlock(sc, XFS_ILOCK_EXCL);
+
+	/*
+	 * Take the IOLOCK on the temporary file so that we can run xattr
+	 * operations with the same locks held as we would for a normal file.
+	 * We still hold sc->ip's IOLOCK.
+	 */
+	error = xrep_tempfile_iolock_polled(rx->sc);
+	if (error)
+		return error;
+
+	/* Allocate swapext transaction and lock both inodes. */
+	error = xrep_tempswap_trans_alloc(rx->sc, XFS_ATTR_FORK, &rx->tx);
+	if (error)
+		return error;
+
+	/*
+	 * Exchange the blocks mapped by the tempfile's attr fork with the file
+	 * being repaired.  The old attr blocks will then be attached to the
+	 * tempfile, so reap its attr fork.
+	 */
+	error = xrep_xattr_swap(sc, &rx->tx);
+	if (error)
+		return error;
+
+	error = xrep_xattr_reset_tempfile_fork(sc);
+	if (error)
+		return error;
+
+forget_acls:
+	/* Invalidate cached ACLs now that we've reloaded all the xattrs. */
+	xfs_forget_acl(VFS_I(sc->ip), SGI_ACL_FILE);
+	xfs_forget_acl(VFS_I(sc->ip), SGI_ACL_DEFAULT);
+	return 0;
+}
+
+/* Tear down all the incore scan stuff we created. */
+STATIC void
+xrep_xattr_teardown(
+	struct xrep_xattr	*rx)
+{
+	xfblob_destroy(rx->xattr_blobs);
+	xfarray_destroy(rx->xattr_records);
+	kfree(rx);
+}
+
+/* Set up the filesystem scan so we can regenerate extended attributes. */
+STATIC int
+xrep_xattr_setup_scan(
+	struct xfs_scrub	*sc,
+	struct xrep_xattr	**rxp)
+{
+	struct xrep_xattr	*rx;
+	int			max_len;
+	int			error;
+
+	rx = kzalloc(sizeof(struct xrep_xattr), XCHK_GFP_FLAGS);
+	if (!rx)
+		return -ENOMEM;
+	rx->sc = sc;
+
+	/*
+	 * 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.
+	 */
+	max_len = xfs_attr_leaf_entsize_local_max(sc->mp->m_attr_geo->blksize);
+	error = xchk_setup_xattr_buf(rx->sc, max_len);
+	if (error == -ENOMEM)
+		error = -EDEADLOCK;
+	if (error)
+		goto out_rx;
+
+	/* Set up some staging for salvaged attribute keys and values */
+	error = xfarray_create(sc->mp, "xattr keys", 0,
+			sizeof(struct xrep_xattr_key), &rx->xattr_records);
+	if (error)
+		goto out_rx;
+
+	error = xfblob_create(sc->mp, "xattr values", &rx->xattr_blobs);
+	if (error)
+		goto out_keys;
+
+	*rxp = rx;
+	return 0;
+out_keys:
+	xfarray_destroy(rx->xattr_records);
+out_rx:
+	kfree(rx);
+	return error;
+}
+
+/*
+ * Repair the extended attribute metadata.
+ *
+ * XXX: Remote attribute value buffers encompass the entire (up to 64k) buffer.
+ * The buffer cache in XFS can't handle aliased multiblock buffers, so this
+ * might misbehave if the attr fork is crosslinked with other filesystem
+ * metadata.
+ */
+int
+xrep_xattr(
+	struct xfs_scrub	*sc)
+{
+	struct xrep_xattr	*rx = NULL;
+	int			error;
+
+	if (!xfs_inode_hasattr(sc->ip))
+		return -ENOENT;
+
+	/* We require the rmapbt to rebuild anything. */
+	if (!xfs_has_rmapbt(sc->mp))
+		return -EOPNOTSUPP;
+
+	error = xrep_xattr_setup_scan(sc, &rx);
+	if (error)
+		return error;
+
+	ASSERT(sc->ilock_flags & XFS_ILOCK_EXCL);
+
+	error = xrep_xattr_salvage_attributes(rx);
+	if (error)
+		goto out_scan;
+
+	/* Last chance to abort before we start committing fixes. */
+	if (xchk_should_terminate(sc, &error))
+		goto out_scan;
+
+	error = xrep_xattr_rebuild_tree(rx);
+	if (error)
+		goto out_scan;
+
+out_scan:
+	xrep_xattr_teardown(rx);
+	return error;
+}
diff --git a/fs/xfs/scrub/attr_repair.h b/fs/xfs/scrub/attr_repair.h
new file mode 100644
index 000000000000..372c2d0eff68
--- /dev/null
+++ b/fs/xfs/scrub/attr_repair.h
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2018-2023 Oracle.  All Rights Reserved.
+ * Author: Darrick J. Wong <djwong@kernel.org>
+ */
+#ifndef __XFS_SCRUB_ATTR_REPAIR_H__
+#define __XFS_SCRUB_ATTR_REPAIR_H__
+
+int xrep_xattr_reset_fork(struct xfs_scrub *sc);
+
+#endif /* __XFS_SCRUB_ATTR_REPAIR_H__ */
diff --git a/fs/xfs/scrub/repair.c b/fs/xfs/scrub/repair.c
index ce5540d53062..e63b2b1d9662 100644
--- a/fs/xfs/scrub/repair.c
+++ b/fs/xfs/scrub/repair.c
@@ -32,12 +32,16 @@
 #include "xfs_reflink.h"
 #include "xfs_health.h"
 #include "xfs_buf_xfile.h"
+#include "xfs_da_format.h"
+#include "xfs_da_btree.h"
+#include "xfs_attr.h"
 #include "scrub/scrub.h"
 #include "scrub/common.h"
 #include "scrub/trace.h"
 #include "scrub/repair.h"
 #include "scrub/bitmap.h"
 #include "scrub/xfile.h"
+#include "scrub/attr_repair.h"
 
 /*
  * Attempt to repair some metadata, if the metadata is corrupt and userspace
@@ -1122,6 +1126,17 @@ xrep_metadata_inode_forks(
 			return error;
 	}
 
+	/* Clear the attr forks since metadata shouldn't have that. */
+	if (xfs_inode_hasattr(sc->ip)) {
+		if (!dirty) {
+			dirty = true;
+			xfs_trans_ijoin(sc->tp, sc->ip, 0);
+		}
+		error = xrep_xattr_reset_fork(sc);
+		if (error)
+			return error;
+	}
+
 	/*
 	 * If we modified the inode, roll the transaction but don't rejoin the
 	 * inode to the new transaction because xrep_bmap_data can do that.
@@ -1224,3 +1239,34 @@ xrep_trans_cancel_hook_dummy(
 	current->journal_info = *cookiep;
 	*cookiep = NULL;
 }
+
+/*
+ * See if this buffer can pass the given ->verify_struct() function.
+ *
+ * If the buffer already has ops attached and they're not the ones that were
+ * passed in, we reject the buffer.  Otherwise, we perform the structure test
+ * (note that we do not check CRCs) and return the outcome of the test.  The
+ * buffer ops and error state are left unchanged.
+ */
+bool
+xrep_buf_verify_struct(
+	struct xfs_buf			*bp,
+	const struct xfs_buf_ops	*ops)
+{
+	const struct xfs_buf_ops	*old_ops = bp->b_ops;
+	xfs_failaddr_t			fa;
+	int				old_error;
+
+	if (old_ops) {
+		if (old_ops != ops)
+			return false;
+	}
+
+	old_error = bp->b_error;
+	bp->b_ops = ops;
+	fa = bp->b_ops->verify_struct(bp);
+	bp->b_ops = old_ops;
+	bp->b_error = old_error;
+
+	return fa == NULL;
+}
diff --git a/fs/xfs/scrub/repair.h b/fs/xfs/scrub/repair.h
index 2af25ad31fc7..52c278d50068 100644
--- a/fs/xfs/scrub/repair.h
+++ b/fs/xfs/scrub/repair.h
@@ -83,6 +83,7 @@ int xrep_setup_ag_rmapbt(struct xfs_scrub *sc);
 int xrep_setup_ag_refcountbt(struct xfs_scrub *sc);
 int xrep_setup_rtsummary(struct xfs_scrub *sc, unsigned int *resblks,
 		size_t *bufsize);
+int xrep_setup_xattr(struct xfs_scrub *sc);
 
 /* Repair setup functions */
 int xrep_setup_ag_allocbt(struct xfs_scrub *sc);
@@ -117,6 +118,7 @@ int xrep_bmap_attr(struct xfs_scrub *sc);
 int xrep_bmap_cow(struct xfs_scrub *sc);
 int xrep_nlinks(struct xfs_scrub *sc);
 int xrep_fscounters(struct xfs_scrub *sc);
+int xrep_xattr(struct xfs_scrub *sc);
 
 #ifdef CONFIG_XFS_RT
 int xrep_rtbitmap(struct xfs_scrub *sc);
@@ -141,6 +143,8 @@ int xrep_trans_alloc_hook_dummy(struct xfs_mount *mp, void **cookiep,
 		struct xfs_trans **tpp);
 void xrep_trans_cancel_hook_dummy(void **cookiep, struct xfs_trans *tp);
 
+bool xrep_buf_verify_struct(struct xfs_buf *bp, const struct xfs_buf_ops *ops);
+
 #else
 
 #define xrep_ino_dqattach(sc)	(0)
@@ -183,6 +187,7 @@ xrep_setup_nothing(
 #define xrep_setup_ag_allocbt		xrep_setup_nothing
 #define xrep_setup_ag_rmapbt		xrep_setup_nothing
 #define xrep_setup_ag_refcountbt	xrep_setup_nothing
+#define xrep_setup_xattr		xrep_setup_nothing
 
 #define xrep_setup_inode(sc, imap)	((void)0)
 
@@ -222,6 +227,7 @@ xrep_setup_rtsummary(
 #define xrep_nlinks			xrep_notsupported
 #define xrep_fscounters			xrep_notsupported
 #define xrep_rtsummary			xrep_notsupported
+#define xrep_xattr			xrep_notsupported
 
 #endif /* CONFIG_XFS_ONLINE_REPAIR */
 
diff --git a/fs/xfs/scrub/scrub.c b/fs/xfs/scrub/scrub.c
index 17d93bea6d64..461f3f1bd72c 100644
--- a/fs/xfs/scrub/scrub.c
+++ b/fs/xfs/scrub/scrub.c
@@ -335,7 +335,7 @@ static const struct xchk_meta_ops meta_scrub_ops[] = {
 		.type	= ST_INODE,
 		.setup	= xchk_setup_xattr,
 		.scrub	= xchk_xattr,
-		.repair	= xrep_notsupported,
+		.repair	= xrep_xattr,
 	},
 	[XFS_SCRUB_TYPE_SYMLINK] = {	/* symbolic link */
 		.type	= ST_INODE,
diff --git a/fs/xfs/scrub/trace.h b/fs/xfs/scrub/trace.h
index cc4027435992..51855452b16b 100644
--- a/fs/xfs/scrub/trace.h
+++ b/fs/xfs/scrub/trace.h
@@ -2345,6 +2345,89 @@ TRACE_EVENT(xreap_bmapi_binval_scan,
 		  __entry->scan_blocks)
 );
 
+TRACE_EVENT(xrep_xattr_recover_leafblock,
+	TP_PROTO(struct xfs_inode *ip, xfs_dablk_t dabno, uint16_t magic),
+	TP_ARGS(ip, dabno, magic),
+	TP_STRUCT__entry(
+		__field(dev_t, dev)
+		__field(xfs_ino_t, ino)
+		__field(xfs_dablk_t, dabno)
+		__field(uint16_t, magic)
+	),
+	TP_fast_assign(
+		__entry->dev = ip->i_mount->m_super->s_dev;
+		__entry->ino = ip->i_ino;
+		__entry->dabno = dabno;
+		__entry->magic = magic;
+	),
+	TP_printk("dev %d:%d ino 0x%llx dablk 0x%x magic 0x%x",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  __entry->ino,
+		  __entry->dabno,
+		  __entry->magic)
+);
+
+DECLARE_EVENT_CLASS(xrep_xattr_salvage_class,
+	TP_PROTO(struct xfs_inode *ip, unsigned int flags, char *name,
+		 unsigned int namelen, unsigned int valuelen),
+	TP_ARGS(ip, flags, name, namelen, valuelen),
+	TP_STRUCT__entry(
+		__field(dev_t, dev)
+		__field(xfs_ino_t, ino)
+		__field(unsigned int, flags)
+		__field(unsigned int, namelen)
+		__dynamic_array(char, name, namelen)
+		__field(unsigned int, valuelen)
+	),
+	TP_fast_assign(
+		__entry->dev = ip->i_mount->m_super->s_dev;
+		__entry->ino = ip->i_ino;
+		__entry->flags = flags;
+		__entry->namelen = namelen;
+		memcpy(__get_str(name), name, namelen);
+		__entry->valuelen = valuelen;
+	),
+	TP_printk("dev %d:%d ino 0x%llx flags %s name '%.*s' valuelen 0x%x",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  __entry->ino,
+		   __print_flags(__entry->flags, "|", XFS_ATTR_NAMESPACE_STR),
+		  __entry->namelen,
+		  __get_str(name),
+		  __entry->valuelen)
+);
+#define DEFINE_XREP_XATTR_SALVAGE_EVENT(name) \
+DEFINE_EVENT(xrep_xattr_salvage_class, name, \
+	TP_PROTO(struct xfs_inode *ip, unsigned int flags, char *name, \
+		 unsigned int namelen, unsigned int valuelen), \
+	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);
+
+TRACE_EVENT(xrep_xattr_class,
+	TP_PROTO(struct xfs_inode *ip, struct xfs_inode *arg_ip),
+	TP_ARGS(ip, arg_ip),
+	TP_STRUCT__entry(
+		__field(dev_t, dev)
+		__field(xfs_ino_t, ino)
+		__field(xfs_ino_t, src_ino)
+	),
+	TP_fast_assign(
+		__entry->dev = ip->i_mount->m_super->s_dev;
+		__entry->ino = ip->i_ino;
+		__entry->src_ino = arg_ip->i_ino;
+	),
+	TP_printk("dev %d:%d ino 0x%llx src 0x%llx",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  __entry->ino,
+		  __entry->src_ino)
+)
+#define DEFINE_XREP_XATTR_CLASS(name) \
+DEFINE_EVENT(xrep_xattr_class, name, \
+	TP_PROTO(struct xfs_inode *ip, struct xfs_inode *arg_ip), \
+	TP_ARGS(ip, arg_ip))
+DEFINE_XREP_XATTR_CLASS(xrep_xattr_rebuild_tree);
+DEFINE_XREP_XATTR_CLASS(xrep_xattr_reset_fork);
+
 #endif /* IS_ENABLED(CONFIG_XFS_ONLINE_REPAIR) */
 
 
diff --git a/fs/xfs/scrub/xfarray.c b/fs/xfs/scrub/xfarray.c
index 54e9c61d36f6..f9a5f890ea3e 100644
--- a/fs/xfs/scrub/xfarray.c
+++ b/fs/xfs/scrub/xfarray.c
@@ -1082,3 +1082,20 @@ xfarray_sort(
 	kvfree(si);
 	return error;
 }
+
+/* How many bytes is this array consuming? */
+unsigned long long
+xfarray_bytes(
+	struct xfarray		*array)
+{
+	return xfile_bytes(array->xfile);
+}
+
+/* Empty the entire array. */
+void
+xfarray_truncate(
+	struct xfarray	*array)
+{
+	xfile_discard(array->xfile, 0, MAX_LFS_FILESIZE);
+	array->nr = 0;
+}
diff --git a/fs/xfs/scrub/xfarray.h b/fs/xfs/scrub/xfarray.h
index e5a8aab9fad5..4cff6f6ba1d1 100644
--- a/fs/xfs/scrub/xfarray.h
+++ b/fs/xfs/scrub/xfarray.h
@@ -45,6 +45,8 @@ int xfarray_unset(struct xfarray *array, xfarray_idx_t idx);
 int xfarray_store(struct xfarray *array, xfarray_idx_t idx, const void *ptr);
 int xfarray_store_anywhere(struct xfarray *array, const void *ptr);
 bool xfarray_element_is_null(struct xfarray *array, const void *ptr);
+void xfarray_truncate(struct xfarray *array);
+unsigned long long xfarray_bytes(struct xfarray *array);
 
 /*
  * Load an array element, but zero the buffer if there's no data because we
diff --git a/fs/xfs/scrub/xfblob.c b/fs/xfs/scrub/xfblob.c
index b0d253bbbaa6..efcbc8aedf2a 100644
--- a/fs/xfs/scrub/xfblob.c
+++ b/fs/xfs/scrub/xfblob.c
@@ -150,3 +150,20 @@ xfblob_free(
 	xfile_discard(blob->xfile, cookie, sizeof(key) + key.xb_size);
 	return 0;
 }
+
+/* How many bytes is this blob storage object consuming? */
+unsigned long long
+xfblob_bytes(
+	struct xfblob		*blob)
+{
+	return xfile_bytes(blob->xfile);
+}
+
+/* Drop all the blobs. */
+void
+xfblob_truncate(
+	struct xfblob	*blob)
+{
+	xfile_discard(blob->xfile, PAGE_SIZE, MAX_LFS_FILESIZE - PAGE_SIZE);
+	blob->last_offset = PAGE_SIZE;
+}
diff --git a/fs/xfs/scrub/xfblob.h b/fs/xfs/scrub/xfblob.h
index 874ce350b38c..076f2ea8bcd3 100644
--- a/fs/xfs/scrub/xfblob.h
+++ b/fs/xfs/scrub/xfblob.h
@@ -21,5 +21,7 @@ int xfblob_load(struct xfblob *blob, xfblob_cookie cookie, void *ptr,
 int xfblob_store(struct xfblob *blob, xfblob_cookie *cookie, const void *ptr,
 		uint32_t size);
 int xfblob_free(struct xfblob *blob, xfblob_cookie cookie);
+unsigned long long xfblob_bytes(struct xfblob *blob);
+void xfblob_truncate(struct xfblob *blob);
 
 #endif /* __XFS_SCRUB_XFBLOB_H__ */
diff --git a/fs/xfs/scrub/xfile.h b/fs/xfs/scrub/xfile.h
index d3b52f8069f2..1bfcefdae58e 100644
--- a/fs/xfs/scrub/xfile.h
+++ b/fs/xfs/scrub/xfile.h
@@ -87,6 +87,18 @@ static inline loff_t xfile_size(struct xfile *xf)
 	return i_size_read(file_inode(xf->file));
 }
 
+static inline unsigned long long xfile_bytes(struct xfile *xf)
+{
+	struct xfile_stat	xs;
+	int			ret;
+
+	ret = xfile_stat(xf, &xs);
+	if (ret)
+		return 0;
+
+	return xs.bytes;
+}
+
 /* file block (aka system page size) to basic block conversions. */
 typedef unsigned long long	xfileoff_t;
 #define XFB_BLOCKSIZE		(PAGE_SIZE)
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
index 2d717808ef7a..524a4434116d 100644
--- a/fs/xfs/xfs_buf.c
+++ b/fs/xfs/xfs_buf.c
@@ -481,6 +481,9 @@ _xfs_buf_obj_cmp(
 		 * it stale has not yet committed. i.e. we are
 		 * reallocating a busy extent. Skip this buffer and
 		 * continue searching for an exact match.
+		 *
+		 * Note: If we're scanning for incore buffers to stale, don't
+		 * complain if we find non-stale buffers.
 		 */
 		if (!(map->bm_flags & XBM_IGNORE_LENGTH_MISMATCH))
 			ASSERT(bp->b_flags & XBF_STALE);
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index ecc2d4a8ce38..26d6e9694c2e 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -31,6 +31,8 @@
  * pos: file offset, in bytes
  * bytecount: number of bytes
  *
+ * dablk: directory or xattr block offset, in filesystem blocks
+ *
  * disize: ondisk file size, in bytes
  * isize: incore file size, in bytes
  *


  parent reply	other threads:[~2023-05-26  1:33 UTC|newest]

Thread overview: 383+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-05-26  0:00 [MEGAPATCHSET v25 1/2] xfs: online repair, part 1 Darrick J. Wong
2023-05-26  0:28 ` [PATCHSET 0/7] xfs: fix ranged queries and integer overflows in GETFSMAP Darrick J. Wong
2023-05-26  0:41   ` [PATCH 1/7] xfs: fix interval filtering in multi-step fsmap queries Darrick J. Wong
2023-05-26  0:41   ` [PATCH 2/7] xfs: fix integer overflows in the fsmap rtbitmap and logdev backends Darrick J. Wong
2023-05-26  0:41   ` [PATCH 3/7] xfs: fix getfsmap reporting past the last rt extent Darrick J. Wong
2023-05-26  0:42   ` [PATCH 4/7] xfs: clean up the rtbitmap fsmap backend Darrick J. Wong
2023-05-26  0:42   ` [PATCH 5/7] xfs: fix logdev fsmap query result filtering Darrick J. Wong
2023-05-26  0:42   ` [PATCH 6/7] xfs: validate fsmap offsets specified in the query keys Darrick J. Wong
2023-05-26  0:42   ` [PATCH 7/7] xfs: fix xfs_btree_query_range callers to initialize btree rec fully Darrick J. Wong
2023-06-04 17:56   ` [PATCHSET 0/7] xfs: fix ranged queries and integer overflows in GETFSMAP Darrick J. Wong
2023-06-04 23:02     ` Dave Chinner
2023-06-20  2:09   ` Dave Chinner
2023-06-30  0:00     ` Darrick J. Wong
2023-05-26  0:28 ` [PATCHSET v25.0 0/9] xfs: fix online repair block reaping Darrick J. Wong
2023-05-26  0:43   ` [PATCH 1/9] xfs: cull repair code that will never get used Darrick J. Wong
2023-05-26  0:43   ` [PATCH 2/9] xfs: move the post-repair block reaping code to a separate file Darrick J. Wong
2023-05-26  0:43   ` [PATCH 3/9] xfs: only invalidate blocks if we're going to free them Darrick J. Wong
2023-05-26  0:44   ` [PATCH 4/9] xfs: only allow reaping of per-AG blocks in xrep_reap_extents Darrick J. Wong
2023-05-26  0:44   ` [PATCH 5/9] xfs: use deferred frees to reap old btree blocks Darrick J. Wong
2023-06-20  3:08     ` Dave Chinner
2023-06-20  4:27       ` Darrick J. Wong
2023-05-26  0:44   ` [PATCH 6/9] xfs: rearrange xrep_reap_block to make future code flow easier Darrick J. Wong
2023-05-26  0:44   ` [PATCH 7/9] xfs: ignore stale buffers when scanning the buffer cache Darrick J. Wong
2023-06-20  3:24     ` Dave Chinner
2023-06-20  4:44       ` Darrick J. Wong
2023-06-20  6:01         ` Dave Chinner
2023-07-05 23:17           ` Darrick J. Wong
2023-07-09 23:15             ` Dave Chinner
2023-07-09 23:32               ` Darrick J. Wong
2023-07-10 22:07                 ` Dave Chinner
2023-05-26  0:45   ` [PATCH 8/9] xfs: reap large AG metadata extents when possible Darrick J. Wong
2023-06-20  5:47     ` Dave Chinner
2023-07-07 21:50       ` Darrick J. Wong
2023-05-26  0:45   ` [PATCH 9/9] xfs: use per-AG bitmaps to reap unused AG metadata blocks during repair Darrick J. Wong
2023-05-26  0:28 ` [PATCHSET v25.0 0/6] xfs: prepare repair for bulk loading Darrick J. Wong
2023-05-26  0:45   ` [PATCH 1/6] xfs: force all buffers to be written during btree bulk load Darrick J. Wong
2023-06-21  2:05     ` Dave Chinner
2023-07-05 23:37       ` Darrick J. Wong
2023-05-26  0:45   ` [PATCH 2/6] xfs: implement block reservation accounting for btrees we're staging Darrick J. Wong
2023-05-26  0:46   ` [PATCH 3/6] xfs: log EFIs for all btree blocks being used to stage a btree Darrick J. Wong
2023-05-26  0:46   ` [PATCH 4/6] xfs: add debug knobs to control btree bulk load slack factors Darrick J. Wong
2023-05-26  0:46   ` [PATCH 5/6] xfs: move btree bulkload record initialization to ->get_record implementations Darrick J. Wong
2023-05-26  0:46   ` [PATCH 6/6] xfs: constrain dirty buffers while formatting a staged btree Darrick J. Wong
2023-05-26  0:28 ` [PATCHSET v25.0 0/7] xfs: stage repair information in pageable memory Darrick J. Wong
2023-05-26  0:47   ` [PATCH 1/7] xfs: create a big array data structure Darrick J. Wong
2023-05-26  1:34     ` Kent Overstreet
2023-05-26  3:19       ` Darrick J. Wong
2023-06-22  2:55     ` Dave Chinner
2023-07-05 23:48       ` Darrick J. Wong
2023-05-26  0:47   ` [PATCH 2/7] xfs: enable sorting of xfile-backed arrays Darrick J. Wong
2023-05-26  0:47   ` [PATCH 3/7] xfs: convert xfarray insertion sort to heapsort using scratchpad memory Darrick J. Wong
2023-05-26  0:47   ` [PATCH 4/7] xfs: teach xfile to pass back direct-map pages to caller Darrick J. Wong
2023-05-26  0:48   ` [PATCH 5/7] xfs: speed up xfarray sort by sorting xfile page contents directly Darrick J. Wong
2023-05-26  0:48   ` [PATCH 6/7] xfs: cache pages used for xfarray quicksort convergence Darrick J. Wong
2023-05-26  0:48   ` [PATCH 7/7] xfs: improve xfarray quicksort pivot Darrick J. Wong
2023-06-22  2:58   ` [PATCHSET v25.0 0/7] xfs: stage repair information in pageable memory Dave Chinner
2023-05-26  0:29 ` [PATCHSET v25.0 0/4] xfs: online scrubbing of realtime summary files Darrick J. Wong
2023-05-26  0:48   ` [PATCH 1/4] xfs: get our own reference to inodes that we want to scrub Darrick J. Wong
2023-05-26  0:49   ` [PATCH 2/4] xfs: wrap ilock/iunlock operations on sc->ip Darrick J. Wong
2023-05-26  0:49   ` [PATCH 3/4] xfs: move the realtime summary file scrubber to a separate source file Darrick J. Wong
2023-05-26  0:49   ` [PATCH 4/4] xfs: implement online scrubbing of rtsummary info Darrick J. Wong
2023-06-22  3:11   ` [PATCHSET v25.0 0/4] xfs: online scrubbing of realtime summary files Dave Chinner
2023-05-26  0:29 ` [PATCHSET v25.0 0/2] xfs: miscellaneous repair tweaks Darrick J. Wong
2023-05-26  0:50   ` [PATCH 1/2] xfs: always rescan allegedly healthy per-ag metadata after repair Darrick J. Wong
2023-05-26  0:50   ` [PATCH 2/2] xfs: allow the user to cancel repairs before we start writing Darrick J. Wong
2023-06-22  3:13   ` [PATCHSET v25.0 0/2] xfs: miscellaneous repair tweaks Dave Chinner
2023-05-26  0:29 ` [PATCHSET v25.0 0/2] xfs: force rebuilding of metadata Darrick J. Wong
2023-05-26  0:50   ` [PATCH 1/2] xfs: don't complain about unfixed metadata when repairs were injected Darrick J. Wong
2023-05-26  0:50   ` [PATCH 2/2] xfs: allow userspace to rebuild metadata structures Darrick J. Wong
2023-06-22  3:17     ` Dave Chinner
2023-07-05 23:52       ` Darrick J. Wong
2023-06-22  3:18   ` [PATCHSET v25.0 0/2] xfs: force rebuilding of metadata Dave Chinner
2023-05-26  0:29 ` [PATCHSET v25.0 0/5] xfs: online repair of AG btrees Darrick J. Wong
2023-05-26  0:51   ` [PATCH 1/5] xfs: clear pagf_agflreset when repairing the AGFL Darrick J. Wong
2023-05-26  0:51   ` [PATCH 2/5] xfs: repair free space btrees Darrick J. Wong
2023-05-26  0:51   ` [PATCH 3/5] xfs: rewrite xfs_icache_inode_is_allocated Darrick J. Wong
2023-06-22  4:04     ` Dave Chinner
2023-07-06  0:37       ` Darrick J. Wong
2023-07-09 23:05         ` Dave Chinner
2023-07-09 23:23           ` Darrick J. Wong
2023-05-26  0:51   ` [PATCH 4/5] xfs: repair inode btrees Darrick J. Wong
2023-05-26  0:52   ` [PATCH 5/5] xfs: repair refcount btrees Darrick J. Wong
2023-06-28  0:08   ` [PATCHSET v25.0 0/5] xfs: online repair of AG btrees Dave Chinner
2023-05-26  0:30 ` [PATCHSET v25.0 0/6] xfs: online repair of inodes and forks Darrick J. Wong
2023-05-26  0:52   ` [PATCH 1/6] xfs: disable online repair quota helpers when quota not enabled Darrick J. Wong
2023-05-26  0:52   ` [PATCH 2/6] xfs: try to attach dquots to files before repairing them Darrick J. Wong
2023-05-26  0:52   ` [PATCH 3/6] xfs: repair inode records Darrick J. Wong
2023-05-26  0:53   ` [PATCH 4/6] xfs: zap broken inode forks Darrick J. Wong
2023-05-26  0:53   ` [PATCH 5/6] xfs: abort directory parent scrub scans if we encounter a zapped directory Darrick J. Wong
2023-05-26  0:53   ` [PATCH 6/6] xfs: repair obviously broken inode modes Darrick J. Wong
2023-05-26  0:30 ` [PATCHSET v25.0 0/5] xfs: online repair of file fork mappings Darrick J. Wong
2023-05-26  0:53   ` [PATCH 1/5] xfs: reintroduce reaping of file metadata blocks to xrep_reap_extents Darrick J. Wong
2023-05-26  0:54   ` [PATCH 2/5] xfs: repair inode fork block mapping data structures Darrick J. Wong
2023-05-26  0:54   ` [PATCH 3/5] xfs: refactor repair forcing tests into a repair.c helper Darrick J. Wong
2023-05-26  0:54   ` [PATCH 4/5] xfs: create a ranged query function for refcount btrees Darrick J. Wong
2023-05-26  0:54   ` [PATCH 5/5] xfs: repair problems in CoW forks Darrick J. Wong
2023-05-26  0:30 ` [PATCHSET v25.0 0/4] xfs: online repair of quota and rt metadata files Darrick J. Wong
2023-05-26  0:55   ` [PATCH 1/4] xfs: repair the inode core and forks of a metadata inode Darrick J. Wong
2023-05-26  0:55   ` [PATCH 2/4] xfs: create a new inode fork block unmap helper Darrick J. Wong
2023-05-26  0:55   ` [PATCH 3/4] xfs: online repair of realtime bitmaps Darrick J. Wong
2023-05-26  0:56   ` [PATCH 4/4] xfs: repair quotas Darrick J. Wong
2023-05-26  0:31 ` [PATCHSET v25.0 0/4] xfs: live inode scans for online fsck Darrick J. Wong
2023-05-26  0:56   ` [PATCH 1/4] xfs: speed up xfs_iwalk_adjust_start a little bit Darrick J. Wong
2023-05-26  0:56   ` [PATCH 2/4] xfs: implement live inode scan for scrub Darrick J. Wong
2023-05-26  0:56   ` [PATCH 3/4] xfs: allow scrub to hook metadata updates in other writers Darrick J. Wong
2023-05-26  0:57   ` [PATCH 4/4] xfs: allow blocking notifier chains with filesystem hooks Darrick J. Wong
2023-05-26  0:31 ` [PATCHSET v25.0 0/7] xfs: online repair of quota counters Darrick J. Wong
2023-05-26  0:57   ` [PATCH 1/7] xfs: stagger the starting AG of scrub iscans to reduce contention Darrick J. Wong
2023-05-26  0:57   ` [PATCH 2/7] xfs: cache a bunch of inodes for repair scans Darrick J. Wong
2023-05-26  0:57   ` [PATCH 3/7] xfs: report the health of quota counts Darrick J. Wong
2023-05-26  0:58   ` [PATCH 4/7] xfs: implement live quotacheck inode scan Darrick J. Wong
2023-05-26  0:58   ` [PATCH 5/7] xfs: track quota updates during live quotacheck Darrick J. Wong
2023-05-26  0:58   ` [PATCH 6/7] xfs: repair cannot update the summary counters when logging quota flags Darrick J. Wong
2023-05-26  0:58   ` [PATCH 7/7] xfs: repair dquots based on live quotacheck results Darrick J. Wong
2023-05-26  0:31 ` [PATCHSET v25.0 0/5] xfs: online repair of file link counts Darrick J. Wong
2023-05-26  0:59   ` [PATCH 1/5] xfs: report health of inode " Darrick J. Wong
2023-05-26  0:59   ` [PATCH 2/5] xfs: teach scrub to check file nlinks Darrick J. Wong
2023-05-26  0:59   ` [PATCH 3/5] xfs: track directory entry updates during live nlinks fsck Darrick J. Wong
2023-05-26  0:59   ` [PATCH 4/5] xfs: create a predicate to determine if two xfs_names are the same Darrick J. Wong
2023-05-26  1:00   ` [PATCH 5/5] xfs: teach repair to fix file nlinks Darrick J. Wong
2023-05-26  0:31 ` [PATCHSET v25.0 00/11] xfs: report corruption to the health trackers Darrick J. Wong
2023-05-26  1:00   ` [PATCH 01/11] xfs: separate the marking of sick and checked metadata Darrick J. Wong
2023-05-26  1:00   ` [PATCH 02/11] xfs: report fs corruption errors to the health tracking system Darrick J. Wong
2023-05-26  1:00   ` [PATCH 03/11] xfs: report ag header " Darrick J. Wong
2023-05-26  1:01   ` [PATCH 04/11] xfs: report block map " Darrick J. Wong
2023-05-26  1:01   ` [PATCH 05/11] xfs: report btree block corruption errors to the health system Darrick J. Wong
2023-05-26  1:01   ` [PATCH 06/11] xfs: report dir/attr " Darrick J. Wong
2023-05-26  1:01   ` [PATCH 07/11] xfs: report symlink " Darrick J. Wong
2023-05-26  1:02   ` [PATCH 08/11] xfs: report inode " Darrick J. Wong
2023-05-26  1:02   ` [PATCH 09/11] xfs: report quota block " Darrick J. Wong
2023-05-26  1:02   ` [PATCH 10/11] xfs: report realtime metadata " Darrick J. Wong
2023-05-26  1:03   ` [PATCH 11/11] xfs: report XFS_IS_CORRUPT " Darrick J. Wong
2023-05-26  0:32 ` [PATCHSET v25.0 0/3] xfs: indirect health reporting Darrick J. Wong
2023-05-26  1:03   ` [PATCH 1/3] xfs: add secondary and indirect classes to the health tracking system Darrick J. Wong
2023-05-26  1:03   ` [PATCH 2/3] xfs: remember sick inodes that get inactivated Darrick J. Wong
2023-05-26  1:03   ` [PATCH 3/3] xfs: update health status if we get a clean bill of health Darrick J. Wong
2023-05-26  0:32 ` [PATCHSET v25.0 0/3] xfs: online repair for fs summary counters Darrick J. Wong
2023-05-26  1:04   ` [PATCH 1/3] fs: distinguish between user initiated freeze and kernel initiated freeze Darrick J. Wong
2023-05-26  1:04   ` [PATCH 2/3] xfs: stabilize fs summary counters for online fsck Darrick J. Wong
2023-05-26  1:04   ` [PATCH 3/3] xfs: repair summary counters Darrick J. Wong
2023-05-26  0:32 ` [PATCHSET v25.0 0/9] xfs: support in-memory btrees Darrick J. Wong
2023-05-26  1:04   ` [PATCH 1/9] xfs: dump xfiles for debugging purposes Darrick J. Wong
2023-05-26  1:05   ` [PATCH 2/9] xfs: teach buftargs to maintain their own buffer hashtable Darrick J. Wong
2023-05-26  1:05   ` [PATCH 3/9] xfs: create buftarg helpers to abstract block_device operations Darrick J. Wong
2023-05-26  1:05   ` [PATCH 4/9] xfs: make GFP_ usage consistent when allocating buftargs Darrick J. Wong
2023-05-26  1:05   ` [PATCH 5/9] xfs: support in-memory buffer cache targets Darrick J. Wong
2023-05-26  1:06   ` [PATCH 6/9] xfs: consolidate btree block freeing tracepoints Darrick J. Wong
2023-05-26  1:06   ` [PATCH 7/9] xfs: consolidate btree block allocation tracepoints Darrick J. Wong
2023-05-26  1:06   ` [PATCH 8/9] xfs: support in-memory btrees Darrick J. Wong
2023-05-26  1:06   ` [PATCH 9/9] xfs: connect in-memory btrees to xfiles Darrick J. Wong
2023-05-26  0:32 ` [PATCHSET v25.0 0/4] xfs: online repair of rmap btrees Darrick J. Wong
2023-05-26  1:07   ` [PATCH 1/4] xfs: create a helper to decide if a file mapping targets the rt volume Darrick J. Wong
2023-05-26  1:07   ` [PATCH 2/4] xfs: repair the rmapbt Darrick J. Wong
2023-05-26  1:07   ` [PATCH 3/4] xfs: create a shadow rmap btree during rmap repair Darrick J. Wong
2023-05-26  1:07   ` [PATCH 4/4] xfs: hook live rmap operations during a repair operation Darrick J. Wong
2023-05-26  0:33 ` [PATCHSET v25.0 0/9] xfs: move btree geometry to ops struct Darrick J. Wong
2023-05-26  1:08   ` [PATCH 1/9] xfs: set the btree cursor bc_ops in xfs_btree_alloc_cursor Darrick J. Wong
2023-05-26  1:08   ` [PATCH 2/9] xfs: encode the default bc_flags in the btree ops structure Darrick J. Wong
2023-05-26  1:08   ` [PATCH 3/9] xfs: export some of the btree ops structures Darrick J. Wong
2023-05-26  1:09   ` [PATCH 4/9] xfs: initialize btree blocks using btree_ops structure Darrick J. Wong
2023-05-26  1:09   ` [PATCH 5/9] xfs: rename btree block/buffer init functions Darrick J. Wong
2023-05-26  1:09   ` [PATCH 6/9] xfs: btree convert xfs_btree_init_block to xfs_btree_init_buf calls Darrick J. Wong
2023-05-26  1:09   ` [PATCH 7/9] xfs: remove the unnecessary daddr paramter to _init_block Darrick J. Wong
2023-05-26  1:10   ` [PATCH 8/9] xfs: set btree block buffer ops in _init_buf Darrick J. Wong
2023-05-26  1:10   ` [PATCH 9/9] xfs: remove unnecessary fields in xfbtree_config Darrick J. Wong
2023-05-26  0:33 ` [PATCHSET v25.0 0/4] xfs: reduce refcount repair memory usage Darrick J. Wong
2023-05-26  1:10   ` [PATCH 1/4] xfs: move lru refs to the btree ops structure Darrick J. Wong
2023-05-26  1:10   ` [PATCH 2/4] xfs: define an in-memory btree for storing refcount bag info during repairs Darrick J. Wong
2023-05-26  1:11   ` [PATCH 3/4] xfs: create refcount bag structure for btree repairs Darrick J. Wong
2023-05-26  1:11   ` [PATCH 4/4] xfs: port refcount repair to the new refcount bag structure Darrick J. Wong
2023-05-26  0:33 ` [PATCHSET v25.0 0/3] xfs: bmap log intent cleanups Darrick J. Wong
2023-05-26  1:11   ` [PATCH 1/3] xfs: split tracepoint classes for deferred items Darrick J. Wong
2023-05-26  1:11   ` [PATCH 2/3] xfs: clean up bmap log intent item tracepoint callsites Darrick J. Wong
2023-05-26  1:12   ` [PATCH 3/3] xfs: remove xfs_trans_set_bmap_flags Darrick J. Wong
2023-05-26  0:33 ` [PATCHSET v25.0 0/4] xfs: widen BUI formats to support realtime Darrick J. Wong
2023-05-26  1:12   ` [PATCH 1/4] xfs: fix xfs_bunmapi to allow unmapping of partial rt extents Darrick J. Wong
2023-05-26  1:12   ` [PATCH 2/4] xfs: hoist freeing of rt data fork extent mappings Darrick J. Wong
2023-05-26  1:12   ` [PATCH 3/4] xfs: add a realtime flag to the bmap update log redo items Darrick J. Wong
2023-05-26  1:13   ` [PATCH 4/4] xfs: support recovering bmap intent items targetting realtime extents Darrick J. Wong
2023-05-26  0:34 ` [PATCHSET v25.0 0/2] xfs: support attrfork and unwritten BUIs Darrick J. Wong
2023-05-26  1:13   ` [PATCH 1/2] xfs: support deferred bmap updates on the attr fork Darrick J. Wong
2023-05-26  1:13   ` [PATCH 2/2] xfs: xfs_bmap_finish_one should map unwritten extents properly Darrick J. Wong
2023-05-26  0:34 ` [PATCHSET v25.0 0/3] xfs: clean up symbolic link code Darrick J. Wong
2023-05-26  1:13   ` [PATCH 1/3] xfs: move xfs_symlink_remote.c declarations to xfs_symlink_remote.h Darrick J. Wong
2023-05-26  1:14   ` [PATCH 2/3] xfs: move remote symlink target read function to libxfs Darrick J. Wong
2023-05-26  1:14   ` [PATCH 3/3] xfs: move symlink target write " Darrick J. Wong
2023-05-26  0:34 ` [PATCHSET v25.0 00/25] xfs: atomic file updates Darrick J. Wong
2023-05-26  1:14   ` [PATCH 01/25] xfs: add a libxfs header file for staging new ioctls Darrick J. Wong
2023-05-26  1:14   ` [PATCH 02/25] xfs: introduce new file range exchange ioctl Darrick J. Wong
2023-05-26  1:15   ` [PATCH 03/25] xfs: move inode lease breaking functions to xfs_inode.c Darrick J. Wong
2023-05-26  1:15   ` [PATCH 04/25] xfs: move xfs_iops.c declarations out of xfs_inode.h Darrick J. Wong
2023-05-26  1:15   ` [PATCH 05/25] xfs: declare xfs_file.c symbols in xfs_file.h Darrick J. Wong
2023-05-26  1:16   ` [PATCH 06/25] xfs: create a new helper to return a file's allocation unit Darrick J. Wong
2023-05-26  1:16   ` [PATCH 07/25] xfs: refactor non-power-of-two alignment checks Darrick J. Wong
2023-05-26  1:16   ` [PATCH 08/25] xfs: parameterize all the incompat log feature helpers Darrick J. Wong
2023-05-26  1:16   ` [PATCH 09/25] xfs: create a log incompat flag for atomic extent swapping Darrick J. Wong
2023-05-26  1:17   ` [PATCH 10/25] xfs: introduce a swap-extent log intent item Darrick J. Wong
2023-05-26  1:17   ` [PATCH 11/25] xfs: create deferred log items for extent swapping Darrick J. Wong
2023-05-26  1:17   ` [PATCH 12/25] xfs: enable xlog users to toggle atomic " Darrick J. Wong
2023-05-26  1:17   ` [PATCH 13/25] xfs: bind the xfs-specific extent swape code to the vfs-generic file exchange code Darrick J. Wong
2023-05-26  1:18   ` [PATCH 14/25] xfs: add error injection to test swapext recovery Darrick J. Wong
2023-05-26  1:18   ` [PATCH 15/25] xfs: port xfs_swap_extents_rmap to our new code Darrick J. Wong
2023-05-26  1:18   ` [PATCH 16/25] xfs: consolidate all of the xfs_swap_extent_forks code Darrick J. Wong
2023-05-26  1:19   ` [PATCH 17/25] xfs: port xfs_swap_extent_forks to use xfs_swapext_req Darrick J. Wong
2023-05-26  1:26   ` [PATCH 18/25] xfs: allow xfs_swap_range to use older extent swap algorithms Darrick J. Wong
2023-05-26  1:26   ` [PATCH 19/25] xfs: remove old swap extents implementation Darrick J. Wong
2023-05-26  1:27   ` [PATCH 20/25] xfs: condense extended attributes after an atomic swap Darrick J. Wong
2023-05-26  1:27   ` [PATCH 21/25] xfs: condense directories " Darrick J. Wong
2023-05-26  1:27   ` [PATCH 22/25] xfs: condense symbolic links " Darrick J. Wong
2023-05-26  1:28   ` [PATCH 23/25] xfs: make atomic extent swapping support realtime files Darrick J. Wong
2023-05-26  1:28   ` [PATCH 24/25] xfs: support non-power-of-two rtextsize with exchange-range Darrick J. Wong
2023-05-26  1:28   ` [PATCH 25/25] xfs: enable atomic swapext feature Darrick J. Wong
2023-05-26  0:34 ` [PATCHSET v25.0 0/4] xfs: create temporary files for online repair Darrick J. Wong
2023-05-26  1:28   ` [PATCH 1/4] xfs: hide private inodes from bulkstat and handle functions Darrick J. Wong
2023-05-26  1:29   ` [PATCH 2/4] xfs: create temporary files and directories for online repair Darrick J. Wong
2023-05-26  1:29   ` [PATCH 3/4] xfs: refactor stale buffer scanning for repairs Darrick J. Wong
2023-05-26  1:29   ` [PATCH 4/4] xfs: add the ability to reap entire inode forks Darrick J. Wong
2023-05-26  0:35 ` [PATCHSET v25.0 0/3] xfs: online repair of realtime summaries Darrick J. Wong
2023-05-26  1:29   ` [PATCH 1/3] xfs: support preallocating and copying content into temporary files Darrick J. Wong
2023-05-26  1:30   ` [PATCH 2/3] xfs: teach the tempfile to support atomic extent swapping Darrick J. Wong
2023-05-26  1:30   ` [PATCH 3/3] xfs: online repair of realtime summaries Darrick J. Wong
2023-05-26  0:35 ` [PATCHSET v25.0 0/9] xfs: set and validate dir/attr block owners Darrick J. Wong
2023-05-26  1:30   ` [PATCH 1/9] xfs: add an explicit owner field to xfs_da_args Darrick J. Wong
2023-05-26  1:30   ` [PATCH 2/9] xfs: use the xfs_da_args owner field to set new dir/attr block owner Darrick J. Wong
2023-05-26  1:31   ` [PATCH 3/9] xfs: validate attr leaf buffer owners Darrick J. Wong
2023-05-26  1:31   ` [PATCH 4/9] xfs: validate attr remote value " Darrick J. Wong
2023-05-26  1:31   ` [PATCH 5/9] xfs: validate dabtree node " Darrick J. Wong
2023-05-26  1:31   ` [PATCH 6/9] xfs: validate directory leaf " Darrick J. Wong
2023-05-26  1:32   ` [PATCH 7/9] xfs: validate explicit directory data " Darrick J. Wong
2023-05-26  1:32   ` [PATCH 8/9] xfs: validate explicit directory block " Darrick J. Wong
2023-05-26  1:32   ` [PATCH 9/9] xfs: validate explicit directory free block owners Darrick J. Wong
2023-05-26  0:35 ` [PATCHSET v25.0 0/5] xfs: online repair of extended attributes Darrick J. Wong
2023-05-26  1:32   ` [PATCH 1/5] xfs: create a blob array data structure Darrick J. Wong
2023-05-26  1:33   ` [PATCH 2/5] xfs: use atomic extent swapping to fix user file fork data Darrick J. Wong
2023-05-26  1:33   ` Darrick J. Wong [this message]
2023-05-26  1:33   ` [PATCH 4/5] xfs: scrub should set preen if attr leaf has holes Darrick J. Wong
2023-05-26  1:33   ` [PATCH 5/5] xfs: flag empty xattr leaf blocks for optimization Darrick J. Wong
2023-05-26  0:35 ` [PATCHSET v25.0 0/7] xfs: online repair of directories Darrick J. Wong
2023-05-26  1:34   ` [PATCH 1/7] xfs: use i_prev_unlinked to distinguish inodes that are not on the unlinked list Darrick J. Wong
2023-05-26  1:34   ` [PATCH 2/7] xfs: ensure unlinked list state is consistent with nlink during scrub Darrick J. Wong
2023-05-26  1:34   ` [PATCH 3/7] xfs: update the unlinked list when repairing link counts Darrick J. Wong
2023-05-26  1:35   ` [PATCH 4/7] xfs: online repair of directories Darrick J. Wong
2023-05-26  1:35   ` [PATCH 5/7] xfs: scan the filesystem to repair a directory dotdot entry Darrick J. Wong
2023-05-26  1:35   ` [PATCH 6/7] xfs: online repair of parent pointers Darrick J. Wong
2023-05-26  1:35   ` [PATCH 7/7] xfs: ask the dentry cache if it knows the parent of a directory Darrick J. Wong
2023-05-26  0:36 ` [PATCHSET v25.0 0/3] xfs: move orphan files to lost and found Darrick J. Wong
2023-05-26  1:36   ` [PATCH 1/3] xfs: move orphan files to the orphanage Darrick J. Wong
2023-05-26  1:36   ` [PATCH 2/3] xfs: move files to orphanage instead of letting nlinks drop to zero Darrick J. Wong
2023-05-26  1:36   ` [PATCH 3/3] xfs: ensure dentry consistency when the orphanage adopts a file Darrick J. Wong
2023-05-26  0:36 ` [PATCHSET v25.0 0/1] xfs: online repair of symbolic links Darrick J. Wong
2023-05-26  1:36   ` [PATCH 1/1] " Darrick J. Wong
2023-05-26  0:36 ` [PATCHSET v25.0 0/1] xfs: online repair of parent pointers Darrick J. Wong
2023-05-26  1:37   ` [PATCH 1/1] xfs: create an xattr iteration function for scrub Darrick J. Wong
2023-05-26  0:36 ` [PATCHSET v25.0 0/3] xfs: online fsck of iunlink buckets Darrick J. Wong
2023-05-26  1:37   ` [PATCH 1/3] xfs: check AGI unlinked inode buckets Darrick J. Wong
2023-05-26  1:37   ` [PATCH 2/3] xfs: hoist AGI repair context to a heap object Darrick J. Wong
2023-05-26  1:37   ` [PATCH 3/3] xfs: repair AGI unlinked inode bucket lists Darrick J. Wong
2023-05-26  0:37 ` [PATCHSET v25.0 0/3] xfs: cache xfile pages for better performance Darrick J. Wong
2023-05-26  1:38   ` [PATCH 1/3] xfs: map xfile pages directly into xfs_buf Darrick J. Wong
2023-05-26  1:38   ` [PATCH 2/3] xfs: use b_offset to support direct-mapping pages when blocksize < pagesize Darrick J. Wong
2023-05-26  1:38   ` [PATCH 3/3] xfile: implement write caching Darrick J. Wong
2023-05-26  0:37 ` [PATCHSET v25.0 0/3] xfs: inode-related repair fixes Darrick J. Wong
2023-05-26  1:38   ` [PATCH 1/3] xfs: check unused nlink fields in the ondisk inode Darrick J. Wong
2023-05-26  1:39   ` [PATCH 2/3] xfs: try to avoid allocating from sick inode clusters Darrick J. Wong
2023-05-26  1:39   ` [PATCH 3/3] xfs: pin inodes that would otherwise overflow link count Darrick J. Wong
2023-05-26  0:37 ` [PATCHSET v25.0 0/4] xfs: relax AGF locks during fstrim Darrick J. Wong
2023-05-26  1:39   ` [PATCH 1/4] xfs: hoist data device FITRIM AG iteration to a separate function Darrick J. Wong
2023-05-26  1:39   ` [PATCH 2/4] xfs: separate the xfs_trim_perag looping code Darrick J. Wong
2023-05-26  1:40   ` [PATCH 3/4] xfs: fix severe performance problems when fstrimming a subset of an AG Darrick J. Wong
2023-05-26  1:40   ` [PATCH 4/4] xfs: relax the AGF lock while we're doing a large fstrim Darrick J. Wong
2023-05-26  0:38 ` [PATCHSET v25.0 0/7] xfs_scrub: fixes to the repair code Darrick J. Wong
2023-05-26  1:40   ` [PATCH 1/7] xfs_scrub: flush stdout after printing to it Darrick J. Wong
2023-05-26  1:41   ` [PATCH 2/7] xfs_scrub: don't report media errors for space with unknowable owner Darrick J. Wong
2023-05-26  1:41   ` [PATCH 3/7] xfs_scrub: remove ALP_* flags namespace Darrick J. Wong
2023-05-26  1:41   ` [PATCH 4/7] xfs_scrub: move repair functions to repair.c Darrick J. Wong
2023-05-26  1:41   ` [PATCH 5/7] xfs_scrub: log when a repair was unnecessary Darrick J. Wong
2023-05-26  1:42   ` [PATCH 6/7] xfs_scrub: require primary superblock repairs to complete before proceeding Darrick J. Wong
2023-05-26  1:42   ` [PATCH 7/7] xfs_scrub: actually try to fix summary counters ahead of repairs Darrick J. Wong
2023-06-08 13:22   ` [PATCHSET v25.0 0/7] xfs_scrub: fixes to the repair code Shiyang Ruan
2023-06-08 14:56     ` Darrick J. Wong
2023-06-09  3:22       ` Shiyang Ruan
2023-07-13  5:12         ` Darrick J. Wong
2023-05-26  0:38 ` [PATCHSET v25.0 0/6] xfs_scrub: improve warnings about difficult repairs Darrick J. Wong
2023-05-26  1:42   ` [PATCH 1/6] xfs_scrub: collapse trivial superblock scrub helpers Darrick J. Wong
2023-05-26  1:42   ` [PATCH 2/6] xfs_scrub: get rid of trivial fs metadata scanner helpers Darrick J. Wong
2023-05-26  1:43   ` [PATCH 3/6] xfs_scrub: split up the mustfix repairs and difficulty assessment functions Darrick J. Wong
2023-05-26  1:43   ` [PATCH 4/6] xfs_scrub: add missing repair types to the mustfix and difficulty assessment Darrick J. Wong
2023-05-26  1:43   ` [PATCH 5/6] xfs_scrub: any inconsistency in metadata should trigger difficulty warnings Darrick J. Wong
2023-05-26  1:43   ` [PATCH 6/6] xfs_scrub: warn about difficult repairs to rt and quota metadata Darrick J. Wong
2023-05-26  0:38 ` [PATCHSET v25.0 0/9] xfs_scrub: track data dependencies for repairs Darrick J. Wong
2023-05-26  1:44   ` [PATCH 1/9] xfs_scrub: track repair items by principal, not by individual repairs Darrick J. Wong
2023-05-26  1:44   ` [PATCH 2/9] xfs_scrub: use repair_item to direct repair activities Darrick J. Wong
2023-05-26  1:44   ` [PATCH 3/9] xfs_scrub: remove action lists from phaseX code Darrick J. Wong
2023-05-26  1:44   ` [PATCH 4/9] xfs_scrub: remove scrub_metadata_file Darrick J. Wong
2023-05-26  1:45   ` [PATCH 5/9] xfs_scrub: boost the repair priority of dependencies of damaged items Darrick J. Wong
2023-05-26  1:45   ` [PATCH 6/9] xfs_scrub: clean up repair_item_difficulty a little Darrick J. Wong
2023-05-26  1:45   ` [PATCH 7/9] xfs_scrub: check dependencies of a scrub type before repairing Darrick J. Wong
2023-05-26  1:45   ` [PATCH 8/9] xfs_scrub: retry incomplete repairs Darrick J. Wong
2023-05-26  1:46   ` [PATCH 9/9] xfs_scrub: remove unused action_list fields Darrick J. Wong
2023-05-26  0:38 ` [PATCHSET v25.0 0/5] xfs_scrub: use scrub_item to track check progress Darrick J. Wong
2023-05-26  1:46   ` [PATCH 1/5] xfs_scrub: start tracking scrub state in scrub_item Darrick J. Wong
2023-05-26  1:46   ` [PATCH 2/5] xfs_scrub: remove enum check_outcome Darrick J. Wong
2023-05-26  1:46   ` [PATCH 3/5] xfs_scrub: refactor scrub_meta_type out of existence Darrick J. Wong
2023-05-26  1:47   ` [PATCH 4/5] xfs_scrub: hoist repair retry loop to repair_item_class Darrick J. Wong
2023-05-26  1:47   ` [PATCH 5/5] xfs_scrub: hoist scrub retry loop to scrub_item_check_file Darrick J. Wong
2023-05-26  0:39 ` [PATCHSET v25.0 0/4] xfs_scrub: improve scheduling of repair items Darrick J. Wong
2023-05-26  1:47   ` [PATCH 1/4] libfrog: enhance ptvar to support initializer functions Darrick J. Wong
2023-05-26  1:48   ` [PATCH 2/4] xfs_scrub: improve thread scheduling repair items during phase 4 Darrick J. Wong
2023-05-26  1:48   ` [PATCH 3/4] xfs_scrub: recheck entire metadata objects after corruption repairs Darrick J. Wong
2023-05-26  1:48   ` [PATCH 4/4] xfs_scrub: try to repair space metadata before file metadata Darrick J. Wong
2023-05-26  0:39 ` [PATCHSET v25.0 0/8] xfs_scrub: move fstrim to a separate phase Darrick J. Wong
2023-05-26  1:48   ` [PATCH 1/8] xfs_scrub: move FITRIM to phase 8 Darrick J. Wong
2023-05-26  1:49   ` [PATCH 2/8] xfs_scrub: ignore phase 8 if the user disabled fstrim Darrick J. Wong
2023-05-26  1:49   ` [PATCH 3/8] xfs_scrub: collapse trim_filesystem Darrick J. Wong
2023-05-26  1:49   ` [PATCH 4/8] xfs_scrub: fix the work estimation for phase 8 Darrick J. Wong
2023-05-26  1:49   ` [PATCH 5/8] xfs_scrub: report FITRIM errors properly Darrick J. Wong
2023-05-26  1:50   ` [PATCH 6/8] xfs_scrub: don't call FITRIM after runtime errors Darrick J. Wong
2023-05-26  1:50   ` [PATCH 7/8] xfs_scrub: don't trim the first agbno of each AG for better performance Darrick J. Wong
2023-05-26  1:50   ` [PATCH 8/8] xfs_scrub: improve progress meter for phase 8 fstrimming Darrick J. Wong
2023-05-26  0:39 ` [PATCHSET v25.0 0/7] xfs_scrub: use free space histograms to reduce fstrim runtime Darrick J. Wong
2023-05-26  1:50   ` [PATCH 1/7] libfrog: hoist free space histogram code Darrick J. Wong
2023-05-26  1:51   ` [PATCH 2/7] libfrog: print wider columns for free space histogram Darrick J. Wong
2023-05-26  1:51   ` [PATCH 3/7] libfrog: print cdf of free space buckets Darrick J. Wong
2023-05-26  1:51   ` [PATCH 4/7] xfs_scrub: don't close stdout when closing the progress bar Darrick J. Wong
2023-05-26  1:51   ` [PATCH 5/7] xfs_scrub: remove pointless spacemap.c arguments Darrick J. Wong
2023-05-26  1:52   ` [PATCH 6/7] xfs_scrub: collect free space histograms during phase 7 Darrick J. Wong
2023-05-26  1:52   ` [PATCH 7/7] xfs_scrub: tune fstrim minlen parameter based on free space histograms Darrick J. Wong
2023-05-26  0:39 ` [PATCHSET v25.0 0/5] xfs_scrub: fixes for systemd services Darrick J. Wong
2023-05-26  1:52   ` [PATCH 1/5] debian: install scrub services with dh_installsystemd Darrick J. Wong
2023-11-07  8:35     ` Christoph Hellwig
2023-05-26  1:52   ` [PATCH 2/5] xfs_scrub_all: escape service names consistently Darrick J. Wong
2023-11-07  8:37     ` Christoph Hellwig
2023-05-26  1:53   ` [PATCH 3/5] xfs_scrub: fix pathname escaping across all service definitions Darrick J. Wong
2023-11-07  8:38     ` Christoph Hellwig
2023-05-26  1:53   ` [PATCH 4/5] xfs_scrub_fail: fix sendmail detection Darrick J. Wong
2023-11-07  8:39     ` Christoph Hellwig
2023-05-26  1:53   ` [PATCH 5/5] xfs_scrub_fail: return the failure status of the mailer program Darrick J. Wong
2023-11-07  8:39     ` Christoph Hellwig
2023-05-26  0:40 ` [PATCHSET v25.0 0/4] xfs_scrub_all: fixes for systemd services Darrick J. Wong
2023-05-26  1:54   ` [PATCH 1/4] xfs_scrub_all: fix argument passing when invoking xfs_scrub manually Darrick J. Wong
2023-11-07  8:39     ` Christoph Hellwig
2023-05-26  1:54   ` [PATCH 2/4] xfs_scrub_all: survive systemd restarts when waiting for services Darrick J. Wong
2023-11-07  8:40     ` Christoph Hellwig
2023-05-26  1:54   ` [PATCH 3/4] xfs_scrub_all: simplify cleanup of run_killable Darrick J. Wong
2023-11-07  8:41     ` Christoph Hellwig
2023-05-26  1:54   ` [PATCH 4/4] xfs_scrub_all: fix termination signal handling Darrick J. Wong
2023-11-07  8:41     ` Christoph Hellwig
2023-05-26  0:40 ` [PATCHSET v25.0 0/5] xfs_scrub: tighten security of systemd services Darrick J. Wong
2023-05-26  1:55   ` [PATCH 1/5] xfs_scrub: allow auxiliary pathnames for sandboxing Darrick J. Wong
2023-11-07  8:48     ` Christoph Hellwig
2023-11-07 18:35       ` Darrick J. Wong
2023-11-08  7:22         ` Christoph Hellwig
2023-11-08  7:24           ` Christoph Hellwig
2023-11-08  7:44           ` Darrick J. Wong
2023-11-08  7:46             ` Darrick J. Wong
2023-11-08  7:49             ` Christoph Hellwig
2023-11-09  0:50               ` Darrick J. Wong
2023-05-26  1:55   ` [PATCH 2/5] xfs_scrub.service: reduce CPU usage to 60% when possible Darrick J. Wong
2023-11-07  8:50     ` Christoph Hellwig
2023-11-07 17:00       ` Darrick J. Wong
2023-05-26  1:55   ` [PATCH 3/5] xfs_scrub: tighten up the security on the background systemd service Darrick J. Wong
2023-11-07  8:52     ` Christoph Hellwig
2023-11-09  0:32       ` Darrick J. Wong
2023-05-26  1:55   ` [PATCH 4/5] xfs_scrub_fail: " Darrick J. Wong
2023-05-26  1:56   ` [PATCH 5/5] xfs_scrub_all: " Darrick J. Wong
2023-05-26  0:40 ` [PATCHSET v25.0 0/6] xfs_scrub_all: automatic media scan service Darrick J. Wong
2023-05-26  1:56   ` [PATCH 1/6] xfs_scrub_all: only use the xfs_scrub@ systemd services in service mode Darrick J. Wong
2023-05-26  1:56   ` [PATCH 2/6] xfs_scrub_all: remove journalctl background process Darrick J. Wong
2023-05-26  1:56   ` [PATCH 3/6] xfs_scrub_all: support metadata+media scans of all filesystems Darrick J. Wong
2023-05-26  1:57   ` [PATCH 4/6] xfs_scrub_all: enable periodic file data scrubs automatically Darrick J. Wong
2023-05-26  1:57   ` [PATCH 5/6] xfs_scrub_all: trigger automatic media scans once per month Darrick J. Wong
2023-05-26  1:57   ` [PATCH 6/6] xfs_scrub_all: failure reporting for the xfs_scrub_all job Darrick J. Wong
2023-05-26  0:40 ` [PATCHSET v25.0 0/5] xfs_scrub_all: improve systemd handling Darrick J. Wong
2023-05-26  1:57   ` [PATCH 1/5] xfs_scrub_all: encapsulate all the subprocess code in an object Darrick J. Wong
2023-05-26  1:58   ` [PATCH 2/5] xfs_scrub_all: encapsulate all the systemctl " Darrick J. Wong
2023-05-26  1:58   ` [PATCH 3/5] xfs_scrub_all: add CLI option for easier debugging Darrick J. Wong
2023-05-26  1:58   ` [PATCH 4/5] xfs_scrub_all: convert systemctl calls to dbus Darrick J. Wong
2023-05-26  1:58   ` [PATCH 5/5] xfs_scrub_all: implement retry and backoff for dbus calls Darrick J. Wong
2023-05-26  0:41 ` [PATCHSET v25.0 0/3] xfs_scrub: automatic optimization by default Darrick J. Wong
2023-05-26  1:59   ` [PATCH 1/3] xfs_scrub: automatic downgrades to dry-run mode in service mode Darrick J. Wong
2023-05-26  1:59   ` [PATCH 2/3] xfs_scrub: add an optimization-only mode Darrick J. Wong
2023-05-26  1:59   ` [PATCH 3/3] debian: enable xfs_scrub systemd services by default Darrick J. Wong
  -- strict thread matches above, loose matches on Subject: below --
2022-12-30 22:14 [PATCHSET v24.0 0/5] xfs: online repair of extended attributes Darrick J. Wong
2022-12-30 22:14 ` [PATCH 3/5] xfs: repair " 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=168506066867.3737146.16409002171766831567.stgit@frogsfrogsfrogs \
    --to=djwong@kernel.org \
    --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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.