Commit e47dcf11 authored by Darrick J. Wong's avatar Darrick J. Wong
Browse files

xfs: repair extended attributes



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: default avatarDarrick J. Wong <djwong@kernel.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
parent 629fdaf5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -194,6 +194,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 \
+1 −1
Original line number Diff line number Diff line
@@ -1055,7 +1055,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_sf_hdr *sf = dp->i_af.if_data;

+2 −0
Original line number Diff line number Diff line
@@ -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__ */
+5 −0
Original line number Diff line number Diff line
@@ -721,6 +721,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)
+18 −2
Original line number Diff line number Diff line
@@ -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,
Loading