* [PATCH v1] ext4: add sysfs attribute err_report_sec to control s_err_report timer
@ 2025-12-09 9:52 Baolin Liu
[not found] ` <21af8d64.9c77.19b0296bb66.Coremail.liubaolin12138@163.com>
2025-12-09 14:31 ` [syzbot ci] " syzbot ci
0 siblings, 2 replies; 6+ messages in thread
From: Baolin Liu @ 2025-12-09 9:52 UTC (permalink / raw)
To: tytso, adilger.kernel; +Cc: linux-ext4, linux-kernel, Baolin Liu
From: Baolin Liu <liubaolin@kylinos.cn>
Add a new sysfs attribute "err_report_sec" to control the s_err_report
timer in ext4_sb_info. Writing '0' disables the timer, while writing
a non-zero value enables the timer and sets the timeout in seconds.
Signed-off-by: Baolin Liu <liubaolin@kylinos.cn>
---
fs/ext4/ext4.h | 4 +++-
fs/ext4/super.c | 31 ++++++++++++++++++++-----------
fs/ext4/sysfs.c | 36 ++++++++++++++++++++++++++++++++++++
3 files changed, 59 insertions(+), 12 deletions(-)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 57087da6c7be..9eb5bf2a237a 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1673,6 +1673,8 @@ struct ext4_sb_info {
/* timer for periodic error stats printing */
struct timer_list s_err_report;
+ /* timeout in seconds for s_err_report; 0 disables the timer. */
+ unsigned long s_err_report_sec;
/* Lazy inode table initialization info */
struct ext4_li_request *s_li_request;
@@ -2349,7 +2351,6 @@ static inline int ext4_emergency_state(struct super_block *sb)
#define EXT4_DEF_SB_UPDATE_INTERVAL_SEC (3600) /* seconds (1 hour) */
#define EXT4_DEF_SB_UPDATE_INTERVAL_KB (16384) /* kilobytes (16MB) */
-
/*
* Minimum number of groups in a flexgroup before we separate out
* directories into the first block group of a flexgroup
@@ -3187,6 +3188,7 @@ extern void ext4_mark_group_bitmap_corrupted(struct super_block *sb,
unsigned int flags);
extern unsigned int ext4_num_base_meta_blocks(struct super_block *sb,
ext4_group_t block_group);
+extern void print_daily_error_info(struct timer_list *t);
extern __printf(7, 8)
void __ext4_error(struct super_block *, const char *, unsigned int, bool,
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 33e7c08c9529..a692fe2be1de 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -3635,10 +3635,12 @@ int ext4_feature_set_ok(struct super_block *sb, int readonly)
}
/*
- * This function is called once a day if we have errors logged
- * on the file system
+ * This function is called once a day by default if we have errors logged
+ * on the file system.
+ * Use the err_report_sec sysfs attribute to disable or adjust its call
+ * freequency.
*/
-static void print_daily_error_info(struct timer_list *t)
+void print_daily_error_info(struct timer_list *t)
{
struct ext4_sb_info *sbi = timer_container_of(sbi, t, s_err_report);
struct super_block *sb = sbi->s_sb;
@@ -3678,7 +3680,9 @@ static void print_daily_error_info(struct timer_list *t)
le64_to_cpu(es->s_last_error_block));
printk(KERN_CONT "\n");
}
- mod_timer(&sbi->s_err_report, jiffies + 24*60*60*HZ); /* Once a day */
+
+ if (sbi->s_err_report_sec)
+ mod_timer(&sbi->s_err_report, jiffies + secs_to_jiffies(sbi->s_err_report_sec));
}
/* Find next suitable group and run ext4_init_inode_table */
@@ -5350,7 +5354,6 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
if (err)
goto failed_mount;
- timer_setup(&sbi->s_err_report, print_daily_error_info, 0);
spin_lock_init(&sbi->s_error_lock);
INIT_WORK(&sbi->s_sb_upd_work, update_super_work);
@@ -5637,8 +5640,13 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
clear_opt(sb, DISCARD);
}
- if (es->s_error_count)
- mod_timer(&sbi->s_err_report, jiffies + 300*HZ); /* 5 minutes */
+ timer_setup(&sbi->s_err_report, print_daily_error_info, 0);
+ if (es->s_error_count) {
+ sbi->s_err_report_sec = 5*60; /* first time 5 minutes */
+ mod_timer(&sbi->s_err_report,
+ jiffies + secs_to_jiffies(sbi->s_err_report_sec));
+ }
+ sbi->s_err_report_sec = 24*60*60; /* Once a day */
/* Enable message ratelimiting. Default is 10 messages per 5 secs. */
ratelimit_state_init(&sbi->s_err_ratelimit_state, 5 * HZ, 10);
@@ -5656,6 +5664,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
failed_mount9:
ext4_quotas_off(sb, EXT4_MAXQUOTAS);
+ timer_delete_sync(&sbi->s_err_report);
failed_mount8: __maybe_unused
ext4_release_orphan_info(sb);
failed_mount7:
@@ -5690,7 +5699,6 @@ failed_mount8: __maybe_unused
/* flush s_sb_upd_work before sbi destroy */
flush_work(&sbi->s_sb_upd_work);
ext4_stop_mmpd(sbi);
- timer_delete_sync(&sbi->s_err_report);
ext4_group_desc_free(sbi);
failed_mount:
#if IS_ENABLED(CONFIG_UNICODE)
@@ -6184,10 +6192,11 @@ static void ext4_update_super(struct super_block *sb)
ext4_errno_to_code(sbi->s_last_error_code);
/*
* Start the daily error reporting function if it hasn't been
- * started already
+ * started already and sbi->s_err_report_sec is not zero
*/
- if (!es->s_error_count)
- mod_timer(&sbi->s_err_report, jiffies + 24*60*60*HZ);
+ if (!es->s_error_count && !sbi->s_err_report_sec)
+ mod_timer(&sbi->s_err_report,
+ jiffies + secs_to_jiffies(sbi->s_err_report_sec));
le32_add_cpu(&es->s_error_count, sbi->s_add_error_count);
sbi->s_add_error_count = 0;
}
diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c
index 987bd00f916a..ce9c18f6ba26 100644
--- a/fs/ext4/sysfs.c
+++ b/fs/ext4/sysfs.c
@@ -40,6 +40,7 @@ typedef enum {
attr_pointer_string,
attr_pointer_atomic,
attr_journal_task,
+ attr_err_report_sec,
} attr_id_t;
typedef enum {
@@ -130,6 +131,36 @@ static ssize_t trigger_test_error(struct ext4_sb_info *sbi,
return count;
}
+static ssize_t err_report_sec_store(struct ext4_sb_info *sbi,
+ const char *buf, size_t count)
+{
+ unsigned long t;
+ int ret;
+
+ ret = kstrtoul(skip_spaces(buf), 0, &t);
+ if (ret)
+ return ret;
+
+ /*the maximum time interval must not exceed one year.*/
+ if (t > (365*24*60*60))
+ return -EINVAL;
+
+ if (sbi->s_err_report_sec == t) /*nothing to do*/
+ goto out;
+ else if (!sbi->s_err_report_sec && t) {
+ timer_setup(&sbi->s_err_report, print_daily_error_info, 0);
+ } else if (sbi->s_err_report_sec && !t) {
+ timer_delete_sync(&sbi->s_err_report);
+ goto out;
+ }
+
+ sbi->s_err_report_sec = t;
+ mod_timer(&sbi->s_err_report, jiffies + secs_to_jiffies(sbi->s_err_report_sec));
+
+out:
+ return count;
+}
+
static ssize_t journal_task_show(struct ext4_sb_info *sbi, char *buf)
{
if (!sbi->s_journal)
@@ -217,6 +248,7 @@ EXT4_ATTR_OFFSET(mb_group_prealloc, 0644, clusters_in_group,
ext4_sb_info, s_mb_group_prealloc);
EXT4_ATTR_OFFSET(mb_best_avail_max_trim_order, 0644, mb_order,
ext4_sb_info, s_mb_best_avail_max_trim_order);
+EXT4_ATTR_OFFSET(err_report_sec, 0644, err_report_sec, ext4_sb_info, s_err_report_sec);
EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal);
EXT4_RW_ATTR_SBI_UI(mb_stats, s_mb_stats);
EXT4_RW_ATTR_SBI_UI(mb_max_to_scan, s_mb_max_to_scan);
@@ -309,6 +341,7 @@ static struct attribute *ext4_attrs[] = {
ATTR_LIST(last_trim_minblks),
ATTR_LIST(sb_update_sec),
ATTR_LIST(sb_update_kb),
+ ATTR_LIST(err_report_sec),
NULL,
};
ATTRIBUTE_GROUPS(ext4);
@@ -396,6 +429,7 @@ static ssize_t ext4_generic_attr_show(struct ext4_attr *a,
return sysfs_emit(buf, "%u\n", le32_to_cpup(ptr));
return sysfs_emit(buf, "%u\n", *((unsigned int *) ptr));
case attr_pointer_ul:
+ case attr_err_report_sec:
return sysfs_emit(buf, "%lu\n", *((unsigned long *) ptr));
case attr_pointer_u8:
return sysfs_emit(buf, "%u\n", *((unsigned char *) ptr));
@@ -519,6 +553,8 @@ static ssize_t ext4_attr_store(struct kobject *kobj,
return inode_readahead_blks_store(sbi, buf, len);
case attr_trigger_test_error:
return trigger_test_error(sbi, buf, len);
+ case attr_err_report_sec:
+ return err_report_sec_store(sbi, buf, len);
default:
return ext4_generic_attr_store(a, sbi, buf, len);
}
--
2.39.2
^ permalink raw reply related [flat|nested] 6+ messages in thread[parent not found: <21af8d64.9c77.19b0296bb66.Coremail.liubaolin12138@163.com>]
* Re: [PATCH v1] ext4: add sysfs attribute err_report_sec to control s_err_report timer [not found] ` <21af8d64.9c77.19b0296bb66.Coremail.liubaolin12138@163.com> @ 2025-12-09 10:13 ` liubaolin 2025-12-16 9:04 ` Zhang Yi 0 siblings, 1 reply; 6+ messages in thread From: liubaolin @ 2025-12-09 10:13 UTC (permalink / raw) To: tytso, adilger.kernel; +Cc: linux-ext4, linux-kernel, Baolin Liu > Dear maintainers, > Several customers have requested the ability to disable or adjust the frequency of the print_daily_error_info messages. > The fields s_error_count, s_first_error_time, and s_last_error_time being non-zero only indicate that the filesystem has experienced errors in the past. > They do not mean an error is currently happening or has just occurred. > However, the presence of the word “error” in logs can confuse customers and trigger false alerts in their log monitoring systems. > > To address this, customers asked for a way to disable or tune the reporting interval. > Based on this requirement, I implemented this patch and verified its behavior. > Initially, the timer for s_err_report was set to five minutes during fill_super, and then adjusted to a default of one day. > The new sysfs attribute err_report_sec allows users to disable the timer, enable it, or set a custom timeout value. 在 2025/12/9 18:09, Baolin Liu 写道: > Add . > > > > > > > At 2025-12-09 17:52:54, "Baolin Liu" <liubaolin12138@163.com> wrote: >>From: Baolin Liu <liubaolin@kylinos.cn> >> >>Add a new sysfs attribute "err_report_sec" to control the s_err_report >>timer in ext4_sb_info. Writing '0' disables the timer, while writing >>a non-zero value enables the timer and sets the timeout in seconds. >> >>Signed-off-by: Baolin Liu <liubaolin@kylinos.cn> >>--- >> fs/ext4/ext4.h | 4 +++- >> fs/ext4/super.c | 31 ++++++++++++++++++++----------- >> fs/ext4/sysfs.c | 36 ++++++++++++++++++++++++++++++++++++ >> 3 files changed, 59 insertions(+), 12 deletions(-) >> >>diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h >>index 57087da6c7be..9eb5bf2a237a 100644 >>--- a/fs/ext4/ext4.h >>+++ b/fs/ext4/ext4.h >>@@ -1673,6 +1673,8 @@ struct ext4_sb_info { >> >> /* timer for periodic error stats printing */ >> struct timer_list s_err_report; >>+ /* timeout in seconds for s_err_report; 0 disables the timer. */ >>+ unsigned long s_err_report_sec; >> >> /* Lazy inode table initialization info */ >> struct ext4_li_request *s_li_request; >>@@ -2349,7 +2351,6 @@ static inline int ext4_emergency_state(struct super_block *sb) >> #define EXT4_DEF_SB_UPDATE_INTERVAL_SEC (3600) /* seconds (1 hour) */ >> #define EXT4_DEF_SB_UPDATE_INTERVAL_KB (16384) /* kilobytes (16MB) */ >> >>- >> /* >> * Minimum number of groups in a flexgroup before we separate out >> * directories into the first block group of a flexgroup >>@@ -3187,6 +3188,7 @@ extern void ext4_mark_group_bitmap_corrupted(struct super_block *sb, >> unsigned int flags); >> extern unsigned int ext4_num_base_meta_blocks(struct super_block *sb, >> ext4_group_t block_group); >>+extern void print_daily_error_info(struct timer_list *t); >> >> extern __printf(7, 8) >> void __ext4_error(struct super_block *, const char *, unsigned int, bool, >>diff --git a/fs/ext4/super.c b/fs/ext4/super.c >>index 33e7c08c9529..a692fe2be1de 100644 >>--- a/fs/ext4/super.c >>+++ b/fs/ext4/super.c >>@@ -3635,10 +3635,12 @@ int ext4_feature_set_ok(struct super_block *sb, int readonly) >> } >> >> /* >>- * This function is called once a day if we have errors logged >>- * on the file system >>+ * This function is called once a day by default if we have errors logged >>+ * on the file system. >>+ * Use the err_report_sec sysfs attribute to disable or adjust its call >>+ * freequency. >> */ >>-static void print_daily_error_info(struct timer_list *t) >>+void print_daily_error_info(struct timer_list *t) >> { >> struct ext4_sb_info *sbi = timer_container_of(sbi, t, s_err_report); >> struct super_block *sb = sbi->s_sb; >>@@ -3678,7 +3680,9 @@ static void print_daily_error_info(struct timer_list *t) >> le64_to_cpu(es->s_last_error_block)); >> printk(KERN_CONT "\n"); >> } >>- mod_timer(&sbi->s_err_report, jiffies + 24*60*60*HZ); /* Once a day */ >>+ >>+ if (sbi->s_err_report_sec) >>+ mod_timer(&sbi->s_err_report, jiffies + secs_to_jiffies(sbi->s_err_report_sec)); >> } >> >> /* Find next suitable group and run ext4_init_inode_table */ >>@@ -5350,7 +5354,6 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) >> if (err) >> goto failed_mount; >> >>- timer_setup(&sbi->s_err_report, print_daily_error_info, 0); >> spin_lock_init(&sbi->s_error_lock); >> INIT_WORK(&sbi->s_sb_upd_work, update_super_work); >> >>@@ -5637,8 +5640,13 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) >> clear_opt(sb, DISCARD); >> } >> >>- if (es->s_error_count) >>- mod_timer(&sbi->s_err_report, jiffies + 300*HZ); /* 5 minutes */ >>+ timer_setup(&sbi->s_err_report, print_daily_error_info, 0); >>+ if (es->s_error_count) { >>+ sbi->s_err_report_sec = 5*60; /* first time 5 minutes */ >>+ mod_timer(&sbi->s_err_report, >>+ jiffies + secs_to_jiffies(sbi->s_err_report_sec)); >>+ } >>+ sbi->s_err_report_sec = 24*60*60; /* Once a day */ >> >> /* Enable message ratelimiting. Default is 10 messages per 5 secs. */ >> ratelimit_state_init(&sbi->s_err_ratelimit_state, 5 * HZ, 10); >>@@ -5656,6 +5664,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) >> >> failed_mount9: >> ext4_quotas_off(sb, EXT4_MAXQUOTAS); >>+ timer_delete_sync(&sbi->s_err_report); >> failed_mount8: __maybe_unused >> ext4_release_orphan_info(sb); >> failed_mount7: >>@@ -5690,7 +5699,6 @@ failed_mount8: __maybe_unused >> /* flush s_sb_upd_work before sbi destroy */ >> flush_work(&sbi->s_sb_upd_work); >> ext4_stop_mmpd(sbi); >>- timer_delete_sync(&sbi->s_err_report); >> ext4_group_desc_free(sbi); >> failed_mount: >> #if IS_ENABLED(CONFIG_UNICODE) >>@@ -6184,10 +6192,11 @@ static void ext4_update_super(struct super_block *sb) >> ext4_errno_to_code(sbi->s_last_error_code); >> /* >> * Start the daily error reporting function if it hasn't been >>- * started already >>+ * started already and sbi->s_err_report_sec is not zero >> */ >>- if (!es->s_error_count) >>- mod_timer(&sbi->s_err_report, jiffies + 24*60*60*HZ); >>+ if (!es->s_error_count && !sbi->s_err_report_sec) >>+ mod_timer(&sbi->s_err_report, >>+ jiffies + secs_to_jiffies(sbi->s_err_report_sec)); >> le32_add_cpu(&es->s_error_count, sbi->s_add_error_count); >> sbi->s_add_error_count = 0; >> } >>diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c >>index 987bd00f916a..ce9c18f6ba26 100644 >>--- a/fs/ext4/sysfs.c >>+++ b/fs/ext4/sysfs.c >>@@ -40,6 +40,7 @@ typedef enum { >> attr_pointer_string, >> attr_pointer_atomic, >> attr_journal_task, >>+ attr_err_report_sec, >> } attr_id_t; >> >> typedef enum { >>@@ -130,6 +131,36 @@ static ssize_t trigger_test_error(struct ext4_sb_info *sbi, >> return count; >> } >> >>+static ssize_t err_report_sec_store(struct ext4_sb_info *sbi, >>+ const char *buf, size_t count) >>+{ >>+ unsigned long t; >>+ int ret; >>+ >>+ ret = kstrtoul(skip_spaces(buf), 0, &t); >>+ if (ret) >>+ return ret; >>+ >>+ /*the maximum time interval must not exceed one year.*/ >>+ if (t > (365*24*60*60)) >>+ return -EINVAL; >>+ >>+ if (sbi->s_err_report_sec == t) /*nothing to do*/ >>+ goto out; >>+ else if (!sbi->s_err_report_sec && t) { >>+ timer_setup(&sbi->s_err_report, print_daily_error_info, 0); >>+ } else if (sbi->s_err_report_sec && !t) { >>+ timer_delete_sync(&sbi->s_err_report); >>+ goto out; >>+ } >>+ >>+ sbi->s_err_report_sec = t; >>+ mod_timer(&sbi->s_err_report, jiffies + secs_to_jiffies(sbi->s_err_report_sec)); >>+ >>+out: >>+ return count; >>+} >>+ >> static ssize_t journal_task_show(struct ext4_sb_info *sbi, char *buf) >> { >> if (!sbi->s_journal) >>@@ -217,6 +248,7 @@ EXT4_ATTR_OFFSET(mb_group_prealloc, 0644, clusters_in_group, >> ext4_sb_info, s_mb_group_prealloc); >> EXT4_ATTR_OFFSET(mb_best_avail_max_trim_order, 0644, mb_order, >> ext4_sb_info, s_mb_best_avail_max_trim_order); >>+EXT4_ATTR_OFFSET(err_report_sec, 0644, err_report_sec, ext4_sb_info, s_err_report_sec); >> EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal); >> EXT4_RW_ATTR_SBI_UI(mb_stats, s_mb_stats); >> EXT4_RW_ATTR_SBI_UI(mb_max_to_scan, s_mb_max_to_scan); >>@@ -309,6 +341,7 @@ static struct attribute *ext4_attrs[] = { >> ATTR_LIST(last_trim_minblks), >> ATTR_LIST(sb_update_sec), >> ATTR_LIST(sb_update_kb), >>+ ATTR_LIST(err_report_sec), >> NULL, >> }; >> ATTRIBUTE_GROUPS(ext4); >>@@ -396,6 +429,7 @@ static ssize_t ext4_generic_attr_show(struct ext4_attr *a, >> return sysfs_emit(buf, "%u\n", le32_to_cpup(ptr)); >> return sysfs_emit(buf, "%u\n", *((unsigned int *) ptr)); >> case attr_pointer_ul: >>+ case attr_err_report_sec: >> return sysfs_emit(buf, "%lu\n", *((unsigned long *) ptr)); >> case attr_pointer_u8: >> return sysfs_emit(buf, "%u\n", *((unsigned char *) ptr)); >>@@ -519,6 +553,8 @@ static ssize_t ext4_attr_store(struct kobject *kobj, >> return inode_readahead_blks_store(sbi, buf, len); >> case attr_trigger_test_error: >> return trigger_test_error(sbi, buf, len); >>+ case attr_err_report_sec: >>+ return err_report_sec_store(sbi, buf, len); >> default: >> return ext4_generic_attr_store(a, sbi, buf, len); >> } >>-- >>2.39.2 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v1] ext4: add sysfs attribute err_report_sec to control s_err_report timer 2025-12-09 10:13 ` liubaolin @ 2025-12-16 9:04 ` Zhang Yi 2025-12-17 2:33 ` liubaolin 0 siblings, 1 reply; 6+ messages in thread From: Zhang Yi @ 2025-12-16 9:04 UTC (permalink / raw) To: liubaolin; +Cc: tytso, adilger.kernel, linux-ext4, linux-kernel, Baolin Liu On 12/9/2025 6:13 PM, liubaolin wrote: >> Dear maintainers, >> Several customers have requested the ability to disable or adjust the frequency of the print_daily_error_info messages. The fields s_error_count, s_first_error_time, and s_last_error_time being non-zero only indicate that the filesystem has experienced errors in the past. >> They do not mean an error is currently happening or has just occurred. However, the presence of the word “error” in logs can confuse customers and trigger false alerts in their log monitoring systems. Hi baolin, Let me understand the background first. AFAIK, the log records the time of the first error and the last error occurrence. This allows customers to know when the errors happened. However, why might this cause confusion? In addition, FYI, if a file system error occurs, it is strongly recommended to use fsck to perform repairs, because such errors are usually caused by file system inconsistencies. Especially in errors=continue mode, these inconsistencies may potentially spread in some special cases, posing risks to user data. Regards, Yi. >> >> To address this, customers asked for a way to disable or tune the reporting interval. Based on this requirement, I implemented this patch and verified its behavior. Initially, the timer for s_err_report was set to five minutes during fill_super, and then adjusted to a default of one day. >> The new sysfs attribute err_report_sec allows users to disable the timer, enable it, or set a custom timeout value. > > > > 在 2025/12/9 18:09, Baolin Liu 写道: >> Add . >> >> >> >> >> >> >> At 2025-12-09 17:52:54, "Baolin Liu" <liubaolin12138@163.com> wrote: >>> From: Baolin Liu <liubaolin@kylinos.cn> >>> >>> Add a new sysfs attribute "err_report_sec" to control the s_err_report >>> timer in ext4_sb_info. Writing '0' disables the timer, while writing >>> a non-zero value enables the timer and sets the timeout in seconds. >>> >>> Signed-off-by: Baolin Liu <liubaolin@kylinos.cn> >>> --- >>> fs/ext4/ext4.h | 4 +++- >>> fs/ext4/super.c | 31 ++++++++++++++++++++----------- >>> fs/ext4/sysfs.c | 36 ++++++++++++++++++++++++++++++++++++ >>> 3 files changed, 59 insertions(+), 12 deletions(-) >>> >>> diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h >>> index 57087da6c7be..9eb5bf2a237a 100644 >>> --- a/fs/ext4/ext4.h >>> +++ b/fs/ext4/ext4.h >>> @@ -1673,6 +1673,8 @@ struct ext4_sb_info { >>> >>> /* timer for periodic error stats printing */ >>> struct timer_list s_err_report; >>> + /* timeout in seconds for s_err_report; 0 disables the timer. */ >>> + unsigned long s_err_report_sec; >>> >>> /* Lazy inode table initialization info */ >>> struct ext4_li_request *s_li_request; >>> @@ -2349,7 +2351,6 @@ static inline int ext4_emergency_state(struct super_block *sb) >>> #define EXT4_DEF_SB_UPDATE_INTERVAL_SEC (3600) /* seconds (1 hour) */ >>> #define EXT4_DEF_SB_UPDATE_INTERVAL_KB (16384) /* kilobytes (16MB) */ >>> >>> - >>> /* >>> * Minimum number of groups in a flexgroup before we separate out >>> * directories into the first block group of a flexgroup >>> @@ -3187,6 +3188,7 @@ extern void ext4_mark_group_bitmap_corrupted(struct super_block *sb, >>> unsigned int flags); >>> extern unsigned int ext4_num_base_meta_blocks(struct super_block *sb, >>> ext4_group_t block_group); >>> +extern void print_daily_error_info(struct timer_list *t); >>> >>> extern __printf(7, 8) >>> void __ext4_error(struct super_block *, const char *, unsigned int, bool, >>> diff --git a/fs/ext4/super.c b/fs/ext4/super.c >>> index 33e7c08c9529..a692fe2be1de 100644 >>> --- a/fs/ext4/super.c >>> +++ b/fs/ext4/super.c >>> @@ -3635,10 +3635,12 @@ int ext4_feature_set_ok(struct super_block *sb, int readonly) >>> } >>> >>> /* >>> - * This function is called once a day if we have errors logged >>> - * on the file system >>> + * This function is called once a day by default if we have errors logged >>> + * on the file system. >>> + * Use the err_report_sec sysfs attribute to disable or adjust its call >>> + * freequency. >>> */ >>> -static void print_daily_error_info(struct timer_list *t) >>> +void print_daily_error_info(struct timer_list *t) >>> { >>> struct ext4_sb_info *sbi = timer_container_of(sbi, t, s_err_report); >>> struct super_block *sb = sbi->s_sb; >>> @@ -3678,7 +3680,9 @@ static void print_daily_error_info(struct timer_list *t) >>> le64_to_cpu(es->s_last_error_block)); >>> printk(KERN_CONT "\n"); >>> } >>> - mod_timer(&sbi->s_err_report, jiffies + 24*60*60*HZ); /* Once a day */ >>> + >>> + if (sbi->s_err_report_sec) >>> + mod_timer(&sbi->s_err_report, jiffies + secs_to_jiffies(sbi->s_err_report_sec)); >>> } >>> >>> /* Find next suitable group and run ext4_init_inode_table */ >>> @@ -5350,7 +5354,6 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) >>> if (err) >>> goto failed_mount; >>> >>> - timer_setup(&sbi->s_err_report, print_daily_error_info, 0); >>> spin_lock_init(&sbi->s_error_lock); >>> INIT_WORK(&sbi->s_sb_upd_work, update_super_work); >>> >>> @@ -5637,8 +5640,13 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) >>> clear_opt(sb, DISCARD); >>> } >>> >>> - if (es->s_error_count) >>> - mod_timer(&sbi->s_err_report, jiffies + 300*HZ); /* 5 minutes */ >>> + timer_setup(&sbi->s_err_report, print_daily_error_info, 0); >>> + if (es->s_error_count) { >>> + sbi->s_err_report_sec = 5*60; /* first time 5 minutes */ >>> + mod_timer(&sbi->s_err_report, >>> + jiffies + secs_to_jiffies(sbi->s_err_report_sec)); >>> + } >>> + sbi->s_err_report_sec = 24*60*60; /* Once a day */ >>> >>> /* Enable message ratelimiting. Default is 10 messages per 5 secs. */ >>> ratelimit_state_init(&sbi->s_err_ratelimit_state, 5 * HZ, 10); >>> @@ -5656,6 +5664,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) >>> >>> failed_mount9: >>> ext4_quotas_off(sb, EXT4_MAXQUOTAS); >>> + timer_delete_sync(&sbi->s_err_report); >>> failed_mount8: __maybe_unused >>> ext4_release_orphan_info(sb); >>> failed_mount7: >>> @@ -5690,7 +5699,6 @@ failed_mount8: __maybe_unused >>> /* flush s_sb_upd_work before sbi destroy */ >>> flush_work(&sbi->s_sb_upd_work); >>> ext4_stop_mmpd(sbi); >>> - timer_delete_sync(&sbi->s_err_report); >>> ext4_group_desc_free(sbi); >>> failed_mount: >>> #if IS_ENABLED(CONFIG_UNICODE) >>> @@ -6184,10 +6192,11 @@ static void ext4_update_super(struct super_block *sb) >>> ext4_errno_to_code(sbi->s_last_error_code); >>> /* >>> * Start the daily error reporting function if it hasn't been >>> - * started already >>> + * started already and sbi->s_err_report_sec is not zero >>> */ >>> - if (!es->s_error_count) >>> - mod_timer(&sbi->s_err_report, jiffies + 24*60*60*HZ); >>> + if (!es->s_error_count && !sbi->s_err_report_sec) >>> + mod_timer(&sbi->s_err_report, >>> + jiffies + secs_to_jiffies(sbi->s_err_report_sec)); >>> le32_add_cpu(&es->s_error_count, sbi->s_add_error_count); >>> sbi->s_add_error_count = 0; >>> } >>> diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c >>> index 987bd00f916a..ce9c18f6ba26 100644 >>> --- a/fs/ext4/sysfs.c >>> +++ b/fs/ext4/sysfs.c >>> @@ -40,6 +40,7 @@ typedef enum { >>> attr_pointer_string, >>> attr_pointer_atomic, >>> attr_journal_task, >>> + attr_err_report_sec, >>> } attr_id_t; >>> >>> typedef enum { >>> @@ -130,6 +131,36 @@ static ssize_t trigger_test_error(struct ext4_sb_info *sbi, >>> return count; >>> } >>> >>> +static ssize_t err_report_sec_store(struct ext4_sb_info *sbi, >>> + const char *buf, size_t count) >>> +{ >>> + unsigned long t; >>> + int ret; >>> + >>> + ret = kstrtoul(skip_spaces(buf), 0, &t); >>> + if (ret) >>> + return ret; >>> + >>> + /*the maximum time interval must not exceed one year.*/ >>> + if (t > (365*24*60*60)) >>> + return -EINVAL; >>> + >>> + if (sbi->s_err_report_sec == t) /*nothing to do*/ >>> + goto out; >>> + else if (!sbi->s_err_report_sec && t) { >>> + timer_setup(&sbi->s_err_report, print_daily_error_info, 0); >>> + } else if (sbi->s_err_report_sec && !t) { >>> + timer_delete_sync(&sbi->s_err_report); >>> + goto out; >>> + } >>> + >>> + sbi->s_err_report_sec = t; >>> + mod_timer(&sbi->s_err_report, jiffies + secs_to_jiffies(sbi->s_err_report_sec)); >>> + >>> +out: >>> + return count; >>> +} >>> + >>> static ssize_t journal_task_show(struct ext4_sb_info *sbi, char *buf) >>> { >>> if (!sbi->s_journal) >>> @@ -217,6 +248,7 @@ EXT4_ATTR_OFFSET(mb_group_prealloc, 0644, clusters_in_group, >>> ext4_sb_info, s_mb_group_prealloc); >>> EXT4_ATTR_OFFSET(mb_best_avail_max_trim_order, 0644, mb_order, >>> ext4_sb_info, s_mb_best_avail_max_trim_order); >>> +EXT4_ATTR_OFFSET(err_report_sec, 0644, err_report_sec, ext4_sb_info, s_err_report_sec); >>> EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal); >>> EXT4_RW_ATTR_SBI_UI(mb_stats, s_mb_stats); >>> EXT4_RW_ATTR_SBI_UI(mb_max_to_scan, s_mb_max_to_scan); >>> @@ -309,6 +341,7 @@ static struct attribute *ext4_attrs[] = { >>> ATTR_LIST(last_trim_minblks), >>> ATTR_LIST(sb_update_sec), >>> ATTR_LIST(sb_update_kb), >>> + ATTR_LIST(err_report_sec), >>> NULL, >>> }; >>> ATTRIBUTE_GROUPS(ext4); >>> @@ -396,6 +429,7 @@ static ssize_t ext4_generic_attr_show(struct ext4_attr *a, >>> return sysfs_emit(buf, "%u\n", le32_to_cpup(ptr)); >>> return sysfs_emit(buf, "%u\n", *((unsigned int *) ptr)); >>> case attr_pointer_ul: >>> + case attr_err_report_sec: >>> return sysfs_emit(buf, "%lu\n", *((unsigned long *) ptr)); >>> case attr_pointer_u8: >>> return sysfs_emit(buf, "%u\n", *((unsigned char *) ptr)); >>> @@ -519,6 +553,8 @@ static ssize_t ext4_attr_store(struct kobject *kobj, >>> return inode_readahead_blks_store(sbi, buf, len); >>> case attr_trigger_test_error: >>> return trigger_test_error(sbi, buf, len); >>> + case attr_err_report_sec: >>> + return err_report_sec_store(sbi, buf, len); >>> default: >>> return ext4_generic_attr_store(a, sbi, buf, len); >>> } >>> -- >>> 2.39.2 > > ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v1] ext4: add sysfs attribute err_report_sec to control s_err_report timer 2025-12-16 9:04 ` Zhang Yi @ 2025-12-17 2:33 ` liubaolin 2025-12-18 1:21 ` Zhang Yi 0 siblings, 1 reply; 6+ messages in thread From: liubaolin @ 2025-12-17 2:33 UTC (permalink / raw) To: Zhang Yi; +Cc: tytso, adilger.kernel, linux-ext4, linux-kernel, Baolin Liu > Dear Yi, > Thank you for the review. I believe your comments are reasonable. > > The background is that customers monitor logs on a daily basis. > They believe that once the ext4 file system detects an error, it will immediately print error messages starting with “EXT4-fs error”. > From these logs, customers can already tell that the file system is in an abnormal state, > so they feel that the daily periodic printing of file system error timestamp information is of limited value. > They are more concerned about the immediate logs at the moment when the problem actually occurs. > > However, I think your point makes sense as well. > This daily periodic printing of error-related information is essentially harmless and may still be useful. > Therefore, this patch does not need further attention for now. > > I will shift my focus to other ext4-related tasks. Suggestions and discussions are always welcome. > > Best regards, > Baolin 在 2025/12/16 17:04, Zhang Yi 写道: > On 12/9/2025 6:13 PM, liubaolin wrote: >>> Dear maintainers, >>> Several customers have requested the ability to disable or adjust the frequency of the print_daily_error_info messages. The fields s_error_count, s_first_error_time, and s_last_error_time being non-zero only indicate that the filesystem has experienced errors in the past. >>> They do not mean an error is currently happening or has just occurred. However, the presence of the word “error” in logs can confuse customers and trigger false alerts in their log monitoring systems. > > Hi baolin, > > Let me understand the background first. AFAIK, the log records the time of > the first error and the last error occurrence. This allows customers to > know when the errors happened. However, why might this cause confusion? > > In addition, FYI, if a file system error occurs, it is strongly recommended > to use fsck to perform repairs, because such errors are usually caused by > file system inconsistencies. Especially in errors=continue mode, these > inconsistencies may potentially spread in some special cases, posing risks > to user data. > > Regards, > Yi. > >>> >>> To address this, customers asked for a way to disable or tune the reporting interval. Based on this requirement, I implemented this patch and verified its behavior. Initially, the timer for s_err_report was set to five minutes during fill_super, and then adjusted to a default of one day. >>> The new sysfs attribute err_report_sec allows users to disable the timer, enable it, or set a custom timeout value. >> >> >> >> 在 2025/12/9 18:09, Baolin Liu 写道: >>> Add . >>> >>> >>> >>> >>> >>> >>> At 2025-12-09 17:52:54, "Baolin Liu" <liubaolin12138@163.com> wrote: >>>> From: Baolin Liu <liubaolin@kylinos.cn> >>>> >>>> Add a new sysfs attribute "err_report_sec" to control the s_err_report >>>> timer in ext4_sb_info. Writing '0' disables the timer, while writing >>>> a non-zero value enables the timer and sets the timeout in seconds. >>>> >>>> Signed-off-by: Baolin Liu <liubaolin@kylinos.cn> >>>> --- >>>> fs/ext4/ext4.h | 4 +++- >>>> fs/ext4/super.c | 31 ++++++++++++++++++++----------- >>>> fs/ext4/sysfs.c | 36 ++++++++++++++++++++++++++++++++++++ >>>> 3 files changed, 59 insertions(+), 12 deletions(-) >>>> >>>> diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h >>>> index 57087da6c7be..9eb5bf2a237a 100644 >>>> --- a/fs/ext4/ext4.h >>>> +++ b/fs/ext4/ext4.h >>>> @@ -1673,6 +1673,8 @@ struct ext4_sb_info { >>>> >>>> /* timer for periodic error stats printing */ >>>> struct timer_list s_err_report; >>>> + /* timeout in seconds for s_err_report; 0 disables the timer. */ >>>> + unsigned long s_err_report_sec; >>>> >>>> /* Lazy inode table initialization info */ >>>> struct ext4_li_request *s_li_request; >>>> @@ -2349,7 +2351,6 @@ static inline int ext4_emergency_state(struct super_block *sb) >>>> #define EXT4_DEF_SB_UPDATE_INTERVAL_SEC (3600) /* seconds (1 hour) */ >>>> #define EXT4_DEF_SB_UPDATE_INTERVAL_KB (16384) /* kilobytes (16MB) */ >>>> >>>> - >>>> /* >>>> * Minimum number of groups in a flexgroup before we separate out >>>> * directories into the first block group of a flexgroup >>>> @@ -3187,6 +3188,7 @@ extern void ext4_mark_group_bitmap_corrupted(struct super_block *sb, >>>> unsigned int flags); >>>> extern unsigned int ext4_num_base_meta_blocks(struct super_block *sb, >>>> ext4_group_t block_group); >>>> +extern void print_daily_error_info(struct timer_list *t); >>>> >>>> extern __printf(7, 8) >>>> void __ext4_error(struct super_block *, const char *, unsigned int, bool, >>>> diff --git a/fs/ext4/super.c b/fs/ext4/super.c >>>> index 33e7c08c9529..a692fe2be1de 100644 >>>> --- a/fs/ext4/super.c >>>> +++ b/fs/ext4/super.c >>>> @@ -3635,10 +3635,12 @@ int ext4_feature_set_ok(struct super_block *sb, int readonly) >>>> } >>>> >>>> /* >>>> - * This function is called once a day if we have errors logged >>>> - * on the file system >>>> + * This function is called once a day by default if we have errors logged >>>> + * on the file system. >>>> + * Use the err_report_sec sysfs attribute to disable or adjust its call >>>> + * freequency. >>>> */ >>>> -static void print_daily_error_info(struct timer_list *t) >>>> +void print_daily_error_info(struct timer_list *t) >>>> { >>>> struct ext4_sb_info *sbi = timer_container_of(sbi, t, s_err_report); >>>> struct super_block *sb = sbi->s_sb; >>>> @@ -3678,7 +3680,9 @@ static void print_daily_error_info(struct timer_list *t) >>>> le64_to_cpu(es->s_last_error_block)); >>>> printk(KERN_CONT "\n"); >>>> } >>>> - mod_timer(&sbi->s_err_report, jiffies + 24*60*60*HZ); /* Once a day */ >>>> + >>>> + if (sbi->s_err_report_sec) >>>> + mod_timer(&sbi->s_err_report, jiffies + secs_to_jiffies(sbi->s_err_report_sec)); >>>> } >>>> >>>> /* Find next suitable group and run ext4_init_inode_table */ >>>> @@ -5350,7 +5354,6 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) >>>> if (err) >>>> goto failed_mount; >>>> >>>> - timer_setup(&sbi->s_err_report, print_daily_error_info, 0); >>>> spin_lock_init(&sbi->s_error_lock); >>>> INIT_WORK(&sbi->s_sb_upd_work, update_super_work); >>>> >>>> @@ -5637,8 +5640,13 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) >>>> clear_opt(sb, DISCARD); >>>> } >>>> >>>> - if (es->s_error_count) >>>> - mod_timer(&sbi->s_err_report, jiffies + 300*HZ); /* 5 minutes */ >>>> + timer_setup(&sbi->s_err_report, print_daily_error_info, 0); >>>> + if (es->s_error_count) { >>>> + sbi->s_err_report_sec = 5*60; /* first time 5 minutes */ >>>> + mod_timer(&sbi->s_err_report, >>>> + jiffies + secs_to_jiffies(sbi->s_err_report_sec)); >>>> + } >>>> + sbi->s_err_report_sec = 24*60*60; /* Once a day */ >>>> >>>> /* Enable message ratelimiting. Default is 10 messages per 5 secs. */ >>>> ratelimit_state_init(&sbi->s_err_ratelimit_state, 5 * HZ, 10); >>>> @@ -5656,6 +5664,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) >>>> >>>> failed_mount9: >>>> ext4_quotas_off(sb, EXT4_MAXQUOTAS); >>>> + timer_delete_sync(&sbi->s_err_report); >>>> failed_mount8: __maybe_unused >>>> ext4_release_orphan_info(sb); >>>> failed_mount7: >>>> @@ -5690,7 +5699,6 @@ failed_mount8: __maybe_unused >>>> /* flush s_sb_upd_work before sbi destroy */ >>>> flush_work(&sbi->s_sb_upd_work); >>>> ext4_stop_mmpd(sbi); >>>> - timer_delete_sync(&sbi->s_err_report); >>>> ext4_group_desc_free(sbi); >>>> failed_mount: >>>> #if IS_ENABLED(CONFIG_UNICODE) >>>> @@ -6184,10 +6192,11 @@ static void ext4_update_super(struct super_block *sb) >>>> ext4_errno_to_code(sbi->s_last_error_code); >>>> /* >>>> * Start the daily error reporting function if it hasn't been >>>> - * started already >>>> + * started already and sbi->s_err_report_sec is not zero >>>> */ >>>> - if (!es->s_error_count) >>>> - mod_timer(&sbi->s_err_report, jiffies + 24*60*60*HZ); >>>> + if (!es->s_error_count && !sbi->s_err_report_sec) >>>> + mod_timer(&sbi->s_err_report, >>>> + jiffies + secs_to_jiffies(sbi->s_err_report_sec)); >>>> le32_add_cpu(&es->s_error_count, sbi->s_add_error_count); >>>> sbi->s_add_error_count = 0; >>>> } >>>> diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c >>>> index 987bd00f916a..ce9c18f6ba26 100644 >>>> --- a/fs/ext4/sysfs.c >>>> +++ b/fs/ext4/sysfs.c >>>> @@ -40,6 +40,7 @@ typedef enum { >>>> attr_pointer_string, >>>> attr_pointer_atomic, >>>> attr_journal_task, >>>> + attr_err_report_sec, >>>> } attr_id_t; >>>> >>>> typedef enum { >>>> @@ -130,6 +131,36 @@ static ssize_t trigger_test_error(struct ext4_sb_info *sbi, >>>> return count; >>>> } >>>> >>>> +static ssize_t err_report_sec_store(struct ext4_sb_info *sbi, >>>> + const char *buf, size_t count) >>>> +{ >>>> + unsigned long t; >>>> + int ret; >>>> + >>>> + ret = kstrtoul(skip_spaces(buf), 0, &t); >>>> + if (ret) >>>> + return ret; >>>> + >>>> + /*the maximum time interval must not exceed one year.*/ >>>> + if (t > (365*24*60*60)) >>>> + return -EINVAL; >>>> + >>>> + if (sbi->s_err_report_sec == t) /*nothing to do*/ >>>> + goto out; >>>> + else if (!sbi->s_err_report_sec && t) { >>>> + timer_setup(&sbi->s_err_report, print_daily_error_info, 0); >>>> + } else if (sbi->s_err_report_sec && !t) { >>>> + timer_delete_sync(&sbi->s_err_report); >>>> + goto out; >>>> + } >>>> + >>>> + sbi->s_err_report_sec = t; >>>> + mod_timer(&sbi->s_err_report, jiffies + secs_to_jiffies(sbi->s_err_report_sec)); >>>> + >>>> +out: >>>> + return count; >>>> +} >>>> + >>>> static ssize_t journal_task_show(struct ext4_sb_info *sbi, char *buf) >>>> { >>>> if (!sbi->s_journal) >>>> @@ -217,6 +248,7 @@ EXT4_ATTR_OFFSET(mb_group_prealloc, 0644, clusters_in_group, >>>> ext4_sb_info, s_mb_group_prealloc); >>>> EXT4_ATTR_OFFSET(mb_best_avail_max_trim_order, 0644, mb_order, >>>> ext4_sb_info, s_mb_best_avail_max_trim_order); >>>> +EXT4_ATTR_OFFSET(err_report_sec, 0644, err_report_sec, ext4_sb_info, s_err_report_sec); >>>> EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal); >>>> EXT4_RW_ATTR_SBI_UI(mb_stats, s_mb_stats); >>>> EXT4_RW_ATTR_SBI_UI(mb_max_to_scan, s_mb_max_to_scan); >>>> @@ -309,6 +341,7 @@ static struct attribute *ext4_attrs[] = { >>>> ATTR_LIST(last_trim_minblks), >>>> ATTR_LIST(sb_update_sec), >>>> ATTR_LIST(sb_update_kb), >>>> + ATTR_LIST(err_report_sec), >>>> NULL, >>>> }; >>>> ATTRIBUTE_GROUPS(ext4); >>>> @@ -396,6 +429,7 @@ static ssize_t ext4_generic_attr_show(struct ext4_attr *a, >>>> return sysfs_emit(buf, "%u\n", le32_to_cpup(ptr)); >>>> return sysfs_emit(buf, "%u\n", *((unsigned int *) ptr)); >>>> case attr_pointer_ul: >>>> + case attr_err_report_sec: >>>> return sysfs_emit(buf, "%lu\n", *((unsigned long *) ptr)); >>>> case attr_pointer_u8: >>>> return sysfs_emit(buf, "%u\n", *((unsigned char *) ptr)); >>>> @@ -519,6 +553,8 @@ static ssize_t ext4_attr_store(struct kobject *kobj, >>>> return inode_readahead_blks_store(sbi, buf, len); >>>> case attr_trigger_test_error: >>>> return trigger_test_error(sbi, buf, len); >>>> + case attr_err_report_sec: >>>> + return err_report_sec_store(sbi, buf, len); >>>> default: >>>> return ext4_generic_attr_store(a, sbi, buf, len); >>>> } >>>> -- >>>> 2.39.2 >> >> ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v1] ext4: add sysfs attribute err_report_sec to control s_err_report timer 2025-12-17 2:33 ` liubaolin @ 2025-12-18 1:21 ` Zhang Yi 0 siblings, 0 replies; 6+ messages in thread From: Zhang Yi @ 2025-12-18 1:21 UTC (permalink / raw) To: liubaolin; +Cc: tytso, adilger.kernel, linux-ext4, linux-kernel, Baolin Liu On 12/17/2025 10:33 AM, liubaolin wrote: >> Dear Yi, Thank you for the review. I believe your comments are reasonable. >> >> The background is that customers monitor logs on a daily basis. They believe that once the ext4 file system detects an error, it will immediately print error messages starting with “EXT4-fs error”. From these logs, customers can already tell that the file system is in an abnormal state, so they feel that the daily periodic printing of file system error timestamp information is of limited value. They are more concerned about the immediate logs at the moment when the problem actually occurs. I see, thank you for the background detail. >> >> However, I think your point makes sense as well. This daily periodic printing of error-related information is essentially harmless and may still be useful. Therefore, this patch does not need further attention for now. >> Yeah, Because timely logs can sometimes be unreliable, they may be easily overlooked or even overwritten without the use of a notification mechanism or active polling for log checks. Best regards, Yi. >> I will shift my focus to other ext4-related tasks. Suggestions and discussions are always welcome. >> >> Best regards, >> Baolin > > > > > 在 2025/12/16 17:04, Zhang Yi 写道: >> On 12/9/2025 6:13 PM, liubaolin wrote: >>>> Dear maintainers, >>>> Several customers have requested the ability to disable or adjust the frequency of the print_daily_error_info messages. The fields s_error_count, s_first_error_time, and s_last_error_time being non-zero only indicate that the filesystem has experienced errors in the past. >>>> They do not mean an error is currently happening or has just occurred. However, the presence of the word “error” in logs can confuse customers and trigger false alerts in their log monitoring systems. >> >> Hi baolin, >> >> Let me understand the background first. AFAIK, the log records the time of >> the first error and the last error occurrence. This allows customers to >> know when the errors happened. However, why might this cause confusion? >> >> In addition, FYI, if a file system error occurs, it is strongly recommended >> to use fsck to perform repairs, because such errors are usually caused by >> file system inconsistencies. Especially in errors=continue mode, these >> inconsistencies may potentially spread in some special cases, posing risks >> to user data. >> >> Regards, >> Yi. >> >>>> >>>> To address this, customers asked for a way to disable or tune the reporting interval. Based on this requirement, I implemented this patch and verified its behavior. Initially, the timer for s_err_report was set to five minutes during fill_super, and then adjusted to a default of one day. >>>> The new sysfs attribute err_report_sec allows users to disable the timer, enable it, or set a custom timeout value. >>> >>> >>> >>> 在 2025/12/9 18:09, Baolin Liu 写道: >>>> Add . >>>> >>>> >>>> >>>> >>>> >>>> >>>> At 2025-12-09 17:52:54, "Baolin Liu" <liubaolin12138@163.com> wrote: >>>>> From: Baolin Liu <liubaolin@kylinos.cn> >>>>> >>>>> Add a new sysfs attribute "err_report_sec" to control the s_err_report >>>>> timer in ext4_sb_info. Writing '0' disables the timer, while writing >>>>> a non-zero value enables the timer and sets the timeout in seconds. >>>>> >>>>> Signed-off-by: Baolin Liu <liubaolin@kylinos.cn> >>>>> --- >>>>> fs/ext4/ext4.h | 4 +++- >>>>> fs/ext4/super.c | 31 ++++++++++++++++++++----------- >>>>> fs/ext4/sysfs.c | 36 ++++++++++++++++++++++++++++++++++++ >>>>> 3 files changed, 59 insertions(+), 12 deletions(-) >>>>> >>>>> diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h >>>>> index 57087da6c7be..9eb5bf2a237a 100644 >>>>> --- a/fs/ext4/ext4.h >>>>> +++ b/fs/ext4/ext4.h >>>>> @@ -1673,6 +1673,8 @@ struct ext4_sb_info { >>>>> >>>>> /* timer for periodic error stats printing */ >>>>> struct timer_list s_err_report; >>>>> + /* timeout in seconds for s_err_report; 0 disables the timer. */ >>>>> + unsigned long s_err_report_sec; >>>>> >>>>> /* Lazy inode table initialization info */ >>>>> struct ext4_li_request *s_li_request; >>>>> @@ -2349,7 +2351,6 @@ static inline int ext4_emergency_state(struct super_block *sb) >>>>> #define EXT4_DEF_SB_UPDATE_INTERVAL_SEC (3600) /* seconds (1 hour) */ >>>>> #define EXT4_DEF_SB_UPDATE_INTERVAL_KB (16384) /* kilobytes (16MB) */ >>>>> >>>>> - >>>>> /* >>>>> * Minimum number of groups in a flexgroup before we separate out >>>>> * directories into the first block group of a flexgroup >>>>> @@ -3187,6 +3188,7 @@ extern void ext4_mark_group_bitmap_corrupted(struct super_block *sb, >>>>> unsigned int flags); >>>>> extern unsigned int ext4_num_base_meta_blocks(struct super_block *sb, >>>>> ext4_group_t block_group); >>>>> +extern void print_daily_error_info(struct timer_list *t); >>>>> >>>>> extern __printf(7, 8) >>>>> void __ext4_error(struct super_block *, const char *, unsigned int, bool, >>>>> diff --git a/fs/ext4/super.c b/fs/ext4/super.c >>>>> index 33e7c08c9529..a692fe2be1de 100644 >>>>> --- a/fs/ext4/super.c >>>>> +++ b/fs/ext4/super.c >>>>> @@ -3635,10 +3635,12 @@ int ext4_feature_set_ok(struct super_block *sb, int readonly) >>>>> } >>>>> >>>>> /* >>>>> - * This function is called once a day if we have errors logged >>>>> - * on the file system >>>>> + * This function is called once a day by default if we have errors logged >>>>> + * on the file system. >>>>> + * Use the err_report_sec sysfs attribute to disable or adjust its call >>>>> + * freequency. >>>>> */ >>>>> -static void print_daily_error_info(struct timer_list *t) >>>>> +void print_daily_error_info(struct timer_list *t) >>>>> { >>>>> struct ext4_sb_info *sbi = timer_container_of(sbi, t, s_err_report); >>>>> struct super_block *sb = sbi->s_sb; >>>>> @@ -3678,7 +3680,9 @@ static void print_daily_error_info(struct timer_list *t) >>>>> le64_to_cpu(es->s_last_error_block)); >>>>> printk(KERN_CONT "\n"); >>>>> } >>>>> - mod_timer(&sbi->s_err_report, jiffies + 24*60*60*HZ); /* Once a day */ >>>>> + >>>>> + if (sbi->s_err_report_sec) >>>>> + mod_timer(&sbi->s_err_report, jiffies + secs_to_jiffies(sbi->s_err_report_sec)); >>>>> } >>>>> >>>>> /* Find next suitable group and run ext4_init_inode_table */ >>>>> @@ -5350,7 +5354,6 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) >>>>> if (err) >>>>> goto failed_mount; >>>>> >>>>> - timer_setup(&sbi->s_err_report, print_daily_error_info, 0); >>>>> spin_lock_init(&sbi->s_error_lock); >>>>> INIT_WORK(&sbi->s_sb_upd_work, update_super_work); >>>>> >>>>> @@ -5637,8 +5640,13 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) >>>>> clear_opt(sb, DISCARD); >>>>> } >>>>> >>>>> - if (es->s_error_count) >>>>> - mod_timer(&sbi->s_err_report, jiffies + 300*HZ); /* 5 minutes */ >>>>> + timer_setup(&sbi->s_err_report, print_daily_error_info, 0); >>>>> + if (es->s_error_count) { >>>>> + sbi->s_err_report_sec = 5*60; /* first time 5 minutes */ >>>>> + mod_timer(&sbi->s_err_report, >>>>> + jiffies + secs_to_jiffies(sbi->s_err_report_sec)); >>>>> + } >>>>> + sbi->s_err_report_sec = 24*60*60; /* Once a day */ >>>>> >>>>> /* Enable message ratelimiting. Default is 10 messages per 5 secs. */ >>>>> ratelimit_state_init(&sbi->s_err_ratelimit_state, 5 * HZ, 10); >>>>> @@ -5656,6 +5664,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) >>>>> >>>>> failed_mount9: >>>>> ext4_quotas_off(sb, EXT4_MAXQUOTAS); >>>>> + timer_delete_sync(&sbi->s_err_report); >>>>> failed_mount8: __maybe_unused >>>>> ext4_release_orphan_info(sb); >>>>> failed_mount7: >>>>> @@ -5690,7 +5699,6 @@ failed_mount8: __maybe_unused >>>>> /* flush s_sb_upd_work before sbi destroy */ >>>>> flush_work(&sbi->s_sb_upd_work); >>>>> ext4_stop_mmpd(sbi); >>>>> - timer_delete_sync(&sbi->s_err_report); >>>>> ext4_group_desc_free(sbi); >>>>> failed_mount: >>>>> #if IS_ENABLED(CONFIG_UNICODE) >>>>> @@ -6184,10 +6192,11 @@ static void ext4_update_super(struct super_block *sb) >>>>> ext4_errno_to_code(sbi->s_last_error_code); >>>>> /* >>>>> * Start the daily error reporting function if it hasn't been >>>>> - * started already >>>>> + * started already and sbi->s_err_report_sec is not zero >>>>> */ >>>>> - if (!es->s_error_count) >>>>> - mod_timer(&sbi->s_err_report, jiffies + 24*60*60*HZ); >>>>> + if (!es->s_error_count && !sbi->s_err_report_sec) >>>>> + mod_timer(&sbi->s_err_report, >>>>> + jiffies + secs_to_jiffies(sbi->s_err_report_sec)); >>>>> le32_add_cpu(&es->s_error_count, sbi->s_add_error_count); >>>>> sbi->s_add_error_count = 0; >>>>> } >>>>> diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c >>>>> index 987bd00f916a..ce9c18f6ba26 100644 >>>>> --- a/fs/ext4/sysfs.c >>>>> +++ b/fs/ext4/sysfs.c >>>>> @@ -40,6 +40,7 @@ typedef enum { >>>>> attr_pointer_string, >>>>> attr_pointer_atomic, >>>>> attr_journal_task, >>>>> + attr_err_report_sec, >>>>> } attr_id_t; >>>>> >>>>> typedef enum { >>>>> @@ -130,6 +131,36 @@ static ssize_t trigger_test_error(struct ext4_sb_info *sbi, >>>>> return count; >>>>> } >>>>> >>>>> +static ssize_t err_report_sec_store(struct ext4_sb_info *sbi, >>>>> + const char *buf, size_t count) >>>>> +{ >>>>> + unsigned long t; >>>>> + int ret; >>>>> + >>>>> + ret = kstrtoul(skip_spaces(buf), 0, &t); >>>>> + if (ret) >>>>> + return ret; >>>>> + >>>>> + /*the maximum time interval must not exceed one year.*/ >>>>> + if (t > (365*24*60*60)) >>>>> + return -EINVAL; >>>>> + >>>>> + if (sbi->s_err_report_sec == t) /*nothing to do*/ >>>>> + goto out; >>>>> + else if (!sbi->s_err_report_sec && t) { >>>>> + timer_setup(&sbi->s_err_report, print_daily_error_info, 0); >>>>> + } else if (sbi->s_err_report_sec && !t) { >>>>> + timer_delete_sync(&sbi->s_err_report); >>>>> + goto out; >>>>> + } >>>>> + >>>>> + sbi->s_err_report_sec = t; >>>>> + mod_timer(&sbi->s_err_report, jiffies + secs_to_jiffies(sbi->s_err_report_sec)); >>>>> + >>>>> +out: >>>>> + return count; >>>>> +} >>>>> + >>>>> static ssize_t journal_task_show(struct ext4_sb_info *sbi, char *buf) >>>>> { >>>>> if (!sbi->s_journal) >>>>> @@ -217,6 +248,7 @@ EXT4_ATTR_OFFSET(mb_group_prealloc, 0644, clusters_in_group, >>>>> ext4_sb_info, s_mb_group_prealloc); >>>>> EXT4_ATTR_OFFSET(mb_best_avail_max_trim_order, 0644, mb_order, >>>>> ext4_sb_info, s_mb_best_avail_max_trim_order); >>>>> +EXT4_ATTR_OFFSET(err_report_sec, 0644, err_report_sec, ext4_sb_info, s_err_report_sec); >>>>> EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal); >>>>> EXT4_RW_ATTR_SBI_UI(mb_stats, s_mb_stats); >>>>> EXT4_RW_ATTR_SBI_UI(mb_max_to_scan, s_mb_max_to_scan); >>>>> @@ -309,6 +341,7 @@ static struct attribute *ext4_attrs[] = { >>>>> ATTR_LIST(last_trim_minblks), >>>>> ATTR_LIST(sb_update_sec), >>>>> ATTR_LIST(sb_update_kb), >>>>> + ATTR_LIST(err_report_sec), >>>>> NULL, >>>>> }; >>>>> ATTRIBUTE_GROUPS(ext4); >>>>> @@ -396,6 +429,7 @@ static ssize_t ext4_generic_attr_show(struct ext4_attr *a, >>>>> return sysfs_emit(buf, "%u\n", le32_to_cpup(ptr)); >>>>> return sysfs_emit(buf, "%u\n", *((unsigned int *) ptr)); >>>>> case attr_pointer_ul: >>>>> + case attr_err_report_sec: >>>>> return sysfs_emit(buf, "%lu\n", *((unsigned long *) ptr)); >>>>> case attr_pointer_u8: >>>>> return sysfs_emit(buf, "%u\n", *((unsigned char *) ptr)); >>>>> @@ -519,6 +553,8 @@ static ssize_t ext4_attr_store(struct kobject *kobj, >>>>> return inode_readahead_blks_store(sbi, buf, len); >>>>> case attr_trigger_test_error: >>>>> return trigger_test_error(sbi, buf, len); >>>>> + case attr_err_report_sec: >>>>> + return err_report_sec_store(sbi, buf, len); >>>>> default: >>>>> return ext4_generic_attr_store(a, sbi, buf, len); >>>>> } >>>>> -- >>>>> 2.39.2 >>> >>> > > ^ permalink raw reply [flat|nested] 6+ messages in thread
* [syzbot ci] Re: ext4: add sysfs attribute err_report_sec to control s_err_report timer 2025-12-09 9:52 [PATCH v1] ext4: add sysfs attribute err_report_sec to control s_err_report timer Baolin Liu [not found] ` <21af8d64.9c77.19b0296bb66.Coremail.liubaolin12138@163.com> @ 2025-12-09 14:31 ` syzbot ci 1 sibling, 0 replies; 6+ messages in thread From: syzbot ci @ 2025-12-09 14:31 UTC (permalink / raw) To: adilger.kernel, linux-ext4, linux-kernel, liubaolin12138, liubaolin, tytso Cc: syzbot, syzkaller-bugs syzbot ci has tested the following series [v1] ext4: add sysfs attribute err_report_sec to control s_err_report timer https://lore.kernel.org/all/20251209095254.11569-1-liubaolin12138@163.com * [PATCH v1] ext4: add sysfs attribute err_report_sec to control s_err_report timer and found the following issue: WARNING: ODEBUG bug in ext4_update_super Full report is available here: https://ci.syzbot.org/series/0516238c-3b72-42ec-95e0-a3a1100dfe97 *** WARNING: ODEBUG bug in ext4_update_super tree: torvalds URL: https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux base: 67a454e6b1c604555c04501c77b7fedc5d98a779 arch: amd64 compiler: Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8 config: https://ci.syzbot.org/builds/d05c5a00-1dcc-4a73-9a08-de39905551e0/config C repro: https://ci.syzbot.org/findings/f5e1c416-0890-43de-a395-f7444bcf3202/c_repro syz repro: https://ci.syzbot.org/findings/f5e1c416-0890-43de-a395-f7444bcf3202/syz_repro EXT4-fs error (device loop0): ext4_orphan_get:1391: inode #15: comm syz.0.17: iget: bad i_size value: 360287970189639680 ------------[ cut here ]------------ ODEBUG: assert_init not available (active state 0) object: ffff88816a5866c8 object type: timer_list hint: 0x0 WARNING: lib/debugobjects.c:615 at 0x0, CPU#1: syz.0.17/5984 Modules linked in: CPU: 1 UID: 0 PID: 5984 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full) Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-debian-1.16.2-1 04/01/2014 RIP: 0010:debug_print_object+0x170/0x1e0 lib/debugobjects.c:612 Code: f8 48 c1 e8 03 80 3c 18 00 74 08 4c 89 ff e8 b7 e0 8f fd 4d 8b 0f 4c 89 ef 48 8b 74 24 08 48 89 ea 44 89 e1 4d 89 f0 ff 34 24 <67> 48 0f b9 3a 48 83 c4 08 ff 05 8d 86 e9 0a 48 83 c4 10 5b 41 5c RSP: 0018:ffffc90004927210 EFLAGS: 00010246 RAX: 1ffffffff16da490 RBX: dffffc0000000000 RCX: 0000000000000000 RDX: ffffffff8bc02f80 RSI: ffffffff8bc02a40 RDI: ffffffff8f8bd1a0 RBP: ffffffff8bc02f80 R08: ffff88816a5866c8 R09: ffffffff8b6d35e0 R10: dffffc0000000000 R11: ffffffff81aeb6f0 R12: 0000000000000000 R13: ffffffff8f8bd1a0 R14: ffff88816a5866c8 R15: ffffffff8b6d2480 FS: 0000555563b84500(0000) GS:ffff8882a9e44000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f3e58d73ea0 CR3: 0000000114724000 CR4: 00000000000006f0 Call Trace: <TASK> debug_object_assert_init+0x2db/0x380 lib/debugobjects.c:1020 debug_timer_assert_init kernel/time/timer.c:803 [inline] debug_assert_init kernel/time/timer.c:848 [inline] __mod_timer+0x4a/0xf30 kernel/time/timer.c:1025 ext4_update_super+0xc23/0x12f0 fs/ext4/super.c:6239 ext4_commit_super+0x67/0x430 fs/ext4/super.c:6257 ext4_handle_error+0x65e/0x950 fs/ext4/super.c:718 __ext4_error_inode+0x328/0x4f0 fs/ext4/super.c:861 __ext4_iget+0x187b/0x4280 fs/ext4/inode.c:-1 ext4_orphan_get+0x1e3/0x630 fs/ext4/ialloc.c:1391 ext4_orphan_cleanup+0xad2/0x1460 fs/ext4/orphan.c:465 __ext4_fill_super fs/ext4/super.c:5661 [inline] ext4_fill_super+0x58e5/0x6240 fs/ext4/super.c:5785 get_tree_bdev_flags+0x40e/0x4d0 fs/super.c:1691 vfs_get_tree+0x92/0x2a0 fs/super.c:1751 fc_mount fs/namespace.c:1199 [inline] do_new_mount_fc fs/namespace.c:3636 [inline] do_new_mount+0x302/0xa10 fs/namespace.c:3712 do_mount fs/namespace.c:4035 [inline] __do_sys_mount fs/namespace.c:4224 [inline] __se_sys_mount+0x313/0x410 fs/namespace.c:4201 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0xfa/0xf80 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7f3e58d90f6a Code: d8 64 89 02 48 c7 c0 ff ff ff ff eb a6 e8 de 1a 00 00 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 49 89 ca b8 a5 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007ffde744ab68 EFLAGS: 00000246 ORIG_RAX: 00000000000000a5 RAX: ffffffffffffffda RBX: 00007ffde744abf0 RCX: 00007f3e58d90f6a RDX: 0000200000000880 RSI: 0000200000000500 RDI: 00007ffde744abb0 RBP: 0000200000000880 R08: 00007ffde744abf0 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000200000000500 R13: 00007ffde744abb0 R14: 0000000000000524 R15: 00002000000003c0 </TASK> ---------------- Code disassembly (best guess): 0: f8 clc 1: 48 c1 e8 03 shr $0x3,%rax 5: 80 3c 18 00 cmpb $0x0,(%rax,%rbx,1) 9: 74 08 je 0x13 b: 4c 89 ff mov %r15,%rdi e: e8 b7 e0 8f fd call 0xfd8fe0ca 13: 4d 8b 0f mov (%r15),%r9 16: 4c 89 ef mov %r13,%rdi 19: 48 8b 74 24 08 mov 0x8(%rsp),%rsi 1e: 48 89 ea mov %rbp,%rdx 21: 44 89 e1 mov %r12d,%ecx 24: 4d 89 f0 mov %r14,%r8 27: ff 34 24 push (%rsp) * 2a: 67 48 0f b9 3a ud1 (%edx),%rdi <-- trapping instruction 2f: 48 83 c4 08 add $0x8,%rsp 33: ff 05 8d 86 e9 0a incl 0xae9868d(%rip) # 0xae986c6 39: 48 83 c4 10 add $0x10,%rsp 3d: 5b pop %rbx 3e: 41 5c pop %r12 *** If these findings have caused you to resend the series or submit a separate fix, please add the following tag to your commit message: Tested-by: syzbot@syzkaller.appspotmail.com --- This report is generated by a bot. It may contain errors. syzbot ci engineers can be reached at syzkaller@googlegroups.com. ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2025-12-18 1:21 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-09 9:52 [PATCH v1] ext4: add sysfs attribute err_report_sec to control s_err_report timer Baolin Liu
[not found] ` <21af8d64.9c77.19b0296bb66.Coremail.liubaolin12138@163.com>
2025-12-09 10:13 ` liubaolin
2025-12-16 9:04 ` Zhang Yi
2025-12-17 2:33 ` liubaolin
2025-12-18 1:21 ` Zhang Yi
2025-12-09 14:31 ` [syzbot ci] " syzbot ci
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox