Commit d518215c authored by Baolin Liu's avatar Baolin Liu Committed by Theodore Ts'o
Browse files

ext4: add sysfs attribute err_report_sec to control s_err_report timer



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: default avatarBaolin Liu <liubaolin@kylinos.cn>
Link: https://patch.msgid.link/20251211030256.28613-1-liubaolin12138@163.com


Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent 27056451
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -1692,6 +1692,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;
@@ -2373,7 +2375,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
@@ -3199,6 +3200,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,
+18 −9
Original line number Diff line number Diff line
@@ -3638,10 +3638,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;
@@ -3681,7 +3683,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 */
@@ -5678,8 +5682,12 @@ 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 */
	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);
@@ -6225,10 +6233,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;
	}
+36 −0
Original line number Diff line number Diff line
@@ -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);
@@ -402,6 +435,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));
@@ -525,6 +559,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);
	}