fs/ext4/ext4.h | 4 +++- fs/ext4/super.c | 31 ++++++++++++++++++++----------- fs/ext4/sysfs.c | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 12 deletions(-)
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
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.
© 2016 - 2026 Red Hat, Inc.