Commit 2d263deb authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Carlos Maiolino
Browse files

xfs: allow setting errortags at mount time



Add an errortag mount option that enables an errortag with the default
injection frequency.  This allows injecting errors into the mount
process instead of just on live file systems, and thus test mount
error handling.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarHans Holmberg <hans.holmberg@wdc.com>
Reviewed-by: default avatarCarlos Maiolino <cmaiolino@redhat.com>
Signed-off-by: default avatarCarlos Maiolino <cem@kernel.org>
parent 4d8f4246
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -215,6 +215,14 @@ When mounting an XFS filesystem, the following options are accepted.
	inconsistent namespace presentation during or after a
	failover event.

  errortag=tagname
	When specified, enables the error inject tag named "tagname" with the
	default frequency.  Can be specified multiple times to enable multiple
	errortags.  Specifying this option on remount will reset the error tag
	to the default value if it was set to any other value before.
	This option is only supported when CONFIG_XFS_DEBUG is enabled, and
	will not be reflected in /proc/self/mounts.

Deprecation of V4 Format
========================

+36 −0
Original line number Diff line number Diff line
@@ -22,6 +22,12 @@
static const unsigned int xfs_errortag_random_default[] = { XFS_ERRTAGS };
#undef XFS_ERRTAG

#define XFS_ERRTAG(_tag, _name, _default) \
        [XFS_ERRTAG_##_tag]	=  __stringify(_name),
#include "xfs_errortag.h"
static const char *xfs_errortag_names[] = { XFS_ERRTAGS };
#undef XFS_ERRTAG

struct xfs_errortag_attr {
	struct attribute	attr;
	unsigned int		tag;
@@ -189,6 +195,36 @@ xfs_errortag_add(
	return 0;
}

int
xfs_errortag_add_name(
	struct xfs_mount	*mp,
	const char		*tag_name)
{
	unsigned int		i;

	for (i = 0; i < XFS_ERRTAG_MAX; i++) {
		if (xfs_errortag_names[i] &&
		    !strcmp(xfs_errortag_names[i], tag_name))
			return xfs_errortag_add(mp, i);
	}

	return -EINVAL;
}

void
xfs_errortag_copy(
	struct xfs_mount	*dst_mp,
	struct xfs_mount	*src_mp)
{
	unsigned int		val, i;

	for (i = 0; i < XFS_ERRTAG_MAX; i++) {
		val = READ_ONCE(src_mp->m_errortag[i]);
		if (val)
			WRITE_ONCE(dst_mp->m_errortag[i], val);
	}
}

int
xfs_errortag_clearall(
	struct xfs_mount	*mp)
+4 −0
Original line number Diff line number Diff line
@@ -45,6 +45,8 @@ void xfs_errortag_delay(struct xfs_mount *mp, const char *file, int line,
#define XFS_ERRORTAG_DELAY(mp, tag)		\
	xfs_errortag_delay((mp), __FILE__, __LINE__, (tag))
int xfs_errortag_add(struct xfs_mount *mp, unsigned int error_tag);
int xfs_errortag_add_name(struct xfs_mount *mp, const char *tag_name);
void xfs_errortag_copy(struct xfs_mount *dst_mp, struct xfs_mount *src_mp);
int xfs_errortag_clearall(struct xfs_mount *mp);
#else
#define xfs_errortag_init(mp)			(0)
@@ -52,6 +54,8 @@ int xfs_errortag_clearall(struct xfs_mount *mp);
#define XFS_TEST_ERROR(mp, tag)			(false)
#define XFS_ERRORTAG_DELAY(mp, tag)		((void)0)
#define xfs_errortag_add(mp, tag)		(-ENOSYS)
#define xfs_errortag_copy(dst_mp, src_mp)	((void)0)
#define xfs_errortag_add_name(mp, tag_name)	(-ENOSYS)
#define xfs_errortag_clearall(mp)		(-ENOSYS)
#endif /* DEBUG */

+7 −1
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@
#include "xfs_defer.h"
#include "xfs_attr_item.h"
#include "xfs_xattr.h"
#include "xfs_error.h"
#include "xfs_errortag.h"
#include "xfs_iunlink_item.h"
#include "xfs_dahash_test.h"
@@ -114,7 +115,7 @@ enum {
	Opt_prjquota, Opt_uquota, Opt_gquota, Opt_pquota,
	Opt_uqnoenforce, Opt_gqnoenforce, Opt_pqnoenforce, Opt_qnoenforce,
	Opt_discard, Opt_nodiscard, Opt_dax, Opt_dax_enum, Opt_max_open_zones,
	Opt_lifetime, Opt_nolifetime, Opt_max_atomic_write,
	Opt_lifetime, Opt_nolifetime, Opt_max_atomic_write, Opt_errortag,
};

#define fsparam_dead(NAME) \
@@ -173,6 +174,7 @@ static const struct fs_parameter_spec xfs_fs_parameters[] = {
	fsparam_flag("lifetime",	Opt_lifetime),
	fsparam_flag("nolifetime",	Opt_nolifetime),
	fsparam_string("max_atomic_write",	Opt_max_atomic_write),
	fsparam_string("errortag",	Opt_errortag),
	{}
};

@@ -1593,6 +1595,8 @@ xfs_fs_parse_param(
			return -EINVAL;
		}
		return 0;
	case Opt_errortag:
		return xfs_errortag_add_name(parsing_mp, param->string);
	default:
		xfs_warn(parsing_mp, "unknown mount option [%s].", param->key);
		return -EINVAL;
@@ -2184,6 +2188,8 @@ xfs_fs_reconfigure(
	if (error)
		return error;

	xfs_errortag_copy(mp, new_mp);

	/* Validate new max_atomic_write option before making other changes */
	if (mp->m_awu_max_bytes != new_mp->m_awu_max_bytes) {
		error = xfs_set_max_atomic_write_opt(mp,