XFS has a couple places where atypical behavior is randomized in DEBUG mode in order to facilitate testing and code coverage. For example, DEBUG kernels randomly drop into different block and inode allocation algorithms that on production kernels may only occur under certain circumstances. These hooks are essentially hardcoded errortags. Rather than add more of such logic for similar things in the future, introduce the ability to define errortags that are on by default. Since errortags are somewhat noisy, also introduce a quiet mode opstate flag to suppress logging warnings for such tags. Quiet mode is enabled when at least one tag is enabled by default at mount time and then disabled upon the first errortag configuration change from userspace. This generally mimics current XFS_DEBUG behavior with the exception that logging is enabled for all tags once any other tag is configured. This can be enhanced to support per-tag log state in the future if needed, but for now is probably unnecessary as only a handful of default enabled tags are expected. Signed-off-by: Brian Foster <bfoster@xxxxxxxxxx> --- fs/xfs/xfs_error.c | 42 ++++++++++++++++++++++++++++++++++++++++-- fs/xfs/xfs_mount.h | 3 +++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c index dbd87e137694..62ac6debcb5e 100644 --- a/fs/xfs/xfs_error.c +++ b/fs/xfs/xfs_error.c @@ -69,6 +69,7 @@ static unsigned int xfs_errortag_random_default[] = { struct xfs_errortag_attr { struct attribute attr; unsigned int tag; + bool enable_default; }; static inline struct xfs_errortag_attr * @@ -129,12 +130,15 @@ static const struct sysfs_ops xfs_errortag_sysfs_ops = { .store = xfs_errortag_attr_store, }; -#define XFS_ERRORTAG_ATTR_RW(_name, _tag) \ +#define __XFS_ERRORTAG_ATTR_RW(_name, _tag, enable) \ static struct xfs_errortag_attr xfs_errortag_attr_##_name = { \ .attr = {.name = __stringify(_name), \ .mode = VERIFY_OCTAL_PERMISSIONS(S_IWUSR | S_IRUGO) }, \ .tag = (_tag), \ + .enable_default = enable, \ } +#define XFS_ERRORTAG_ATTR_RW(_name, _tag) \ + __XFS_ERRORTAG_ATTR_RW(_name, _tag, false) #define XFS_ERRORTAG_ATTR_LIST(_name) &xfs_errortag_attr_##_name.attr @@ -240,6 +244,35 @@ static const struct kobj_type xfs_errortag_ktype = { .default_groups = xfs_errortag_groups, }; +/* + * Enable tags that are defined to be on by default. This is typically limited + * to tags that don't necessarily inject errors, but rather modify control paths + * for improved code coverage testing on DEBUG kernels. + */ +static void +xfs_errortag_enable_defaults( + struct xfs_mount *mp) +{ + int i; + + for (i = 0; xfs_errortag_attrs[i]; i++) { + struct xfs_errortag_attr *xfs_attr = + to_attr(xfs_errortag_attrs[i]); + + if (!xfs_attr->enable_default) + continue; + + /* + * Suppress log noise unless userspace makes configuration + * changes. Open code the assignment to avoid clearing the quiet + * flag. + */ + xfs_set_quiet_errtag(mp); + mp->m_errortag[xfs_attr->tag] = + xfs_errortag_random_default[xfs_attr->tag]; + } +} + int xfs_errortag_init( struct xfs_mount *mp) @@ -251,6 +284,8 @@ xfs_errortag_init( if (!mp->m_errortag) return -ENOMEM; + xfs_errortag_enable_defaults(mp); + ret = xfs_sysfs_init(&mp->m_errortag_kobj, &xfs_errortag_ktype, &mp->m_kobj, "errortag"); if (ret) @@ -320,9 +355,11 @@ xfs_errortag_test( if (!randfactor || get_random_u32_below(randfactor)) return false; - xfs_warn_ratelimited(mp, + if (!xfs_is_quiet_errtag(mp)) { + xfs_warn_ratelimited(mp, "Injecting error (%s) at file %s, line %d, on filesystem \"%s\"", expression, file, line, mp->m_super->s_id); + } return true; } @@ -346,6 +383,7 @@ xfs_errortag_set( if (!xfs_errortag_valid(error_tag)) return -EINVAL; + xfs_clear_quiet_errtag(mp); mp->m_errortag[error_tag] = tag_value; return 0; } diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index d85084f9f317..44b02728056f 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -558,6 +558,8 @@ __XFS_HAS_FEAT(nouuid, NOUUID) */ #define XFS_OPSTATE_BLOCKGC_ENABLED 6 +/* Debug kernel skips warning on errtag event triggers */ +#define XFS_OPSTATE_QUIET_ERRTAG 7 /* Kernel has logged a warning about shrink being used on this fs. */ #define XFS_OPSTATE_WARNED_SHRINK 9 /* Kernel has logged a warning about logged xattr updates being used. */ @@ -600,6 +602,7 @@ __XFS_IS_OPSTATE(inode32, INODE32) __XFS_IS_OPSTATE(readonly, READONLY) __XFS_IS_OPSTATE(inodegc_enabled, INODEGC_ENABLED) __XFS_IS_OPSTATE(blockgc_enabled, BLOCKGC_ENABLED) +__XFS_IS_OPSTATE(quiet_errtag, QUIET_ERRTAG) #ifdef CONFIG_XFS_QUOTA __XFS_IS_OPSTATE(quotacheck_running, QUOTACHECK_RUNNING) __XFS_IS_OPSTATE(resuming_quotaon, RESUMING_QUOTAON) -- 2.49.0