/* 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;
#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
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,
}
/*
- * 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;
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 */
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);
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;
}
attr_pointer_string,
attr_pointer_atomic,
attr_journal_task,
+ attr_err_report_sec,
} attr_id_t;
typedef enum {
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)
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);
ATTR_LIST(last_trim_minblks),
ATTR_LIST(sb_update_sec),
ATTR_LIST(sb_update_kb),
+ ATTR_LIST(err_report_sec),
NULL,
};
ATTRIBUTE_GROUPS(ext4);
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));
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);
}