summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/admin-guide/xfs.rst8
-rw-r--r--fs/xfs/xfs_error.c36
-rw-r--r--fs/xfs/xfs_error.h4
-rw-r--r--fs/xfs/xfs_super.c8
4 files changed, 55 insertions, 1 deletions
diff --git a/Documentation/admin-guide/xfs.rst b/Documentation/admin-guide/xfs.rst
index c85cd327af28..746ea60eed3f 100644
--- a/Documentation/admin-guide/xfs.rst
+++ b/Documentation/admin-guide/xfs.rst
@@ -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
========================
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c
index 53704f1ed791..d652240a1dca 100644
--- a/fs/xfs/xfs_error.c
+++ b/fs/xfs/xfs_error.c
@@ -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;
@@ -190,6 +196,36 @@ xfs_errortag_add(
}
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)
{
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h
index b40e7c671d2a..05fc1d1cf521 100644
--- a/fs/xfs/xfs_error.h
+++ b/fs/xfs/xfs_error.h
@@ -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 */
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 5029bf63b87d..1dcbad1c5d68 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -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,