]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
xfs: allow setting errortags at mount time
authorChristoph Hellwig <hch@lst.de>
Fri, 30 Jan 2026 05:19:21 +0000 (06:19 +0100)
committerCarlos Maiolino <cem@kernel.org>
Fri, 30 Jan 2026 09:41:42 +0000 (10:41 +0100)
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: Christoph Hellwig <hch@lst.de>
Reviewed-by: Hans Holmberg <hans.holmberg@wdc.com>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
Documentation/admin-guide/xfs.rst
fs/xfs/xfs_error.c
fs/xfs/xfs_error.h
fs/xfs/xfs_super.c

index c85cd327af284de8b434abe62e14fcb31aa8f01e..746ea60eed3fa841583d61b438207bb4109745d9 100644 (file)
@@ -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
 ========================
 
index 53704f1ed7910b56f3afd862afe22021e328f90e..d652240a1dcacaeff82e03b006536ef8871a2c7e 100644 (file)
 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)
index b40e7c671d2a0ca8c0c681eef836b21e1c86ee79..05fc1d1cf5213b78cbbcf4c7c9dc87640f7a9579 100644 (file)
@@ -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 */
 
index 5029bf63b87d460d0f88872acb4539b23dc082c9..1dcbad1c5d685f3dcda2f875dff81dec4cca6796 100644 (file)
@@ -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,