diff options
author | Theodore Ts'o <tytso@mit.edu> | 2010-07-27 11:56:04 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2010-07-27 11:56:04 -0400 |
commit | 66e61a9e9504f61b9a928c9055368c81da613a50 (patch) | |
tree | afcd8147b4e4771103f75f5a03b836950882dece /fs | |
parent | 1c13d5c0872870cca3e612aa045d492ead9ab004 (diff) |
ext4: Once a day, printk file system error information to dmesg
This allows us to grab any file system error messages by scraping
/var/log/messages. This will make it easy for us to do error analysis
across the very large number of machines as we deploy ext4 across the
fleet.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ext4/ext4.h | 3 | ||||
-rw-r--r-- | fs/ext4/super.c | 59 |
2 files changed, 62 insertions, 0 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 6b96125e7255..5d3d768d9503 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -1166,6 +1166,9 @@ struct ext4_sb_info { | |||
1166 | 1166 | ||
1167 | /* workqueue for dio unwritten */ | 1167 | /* workqueue for dio unwritten */ |
1168 | struct workqueue_struct *dio_unwritten_wq; | 1168 | struct workqueue_struct *dio_unwritten_wq; |
1169 | |||
1170 | /* timer for periodic error stats printing */ | ||
1171 | struct timer_list s_err_report; | ||
1169 | }; | 1172 | }; |
1170 | 1173 | ||
1171 | static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb) | 1174 | static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb) |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index a94d3f56898f..ed00c14d7081 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -325,6 +325,12 @@ static void __save_error_info(struct super_block *sb, const char *func, | |||
325 | es->s_first_error_ino = es->s_last_error_ino; | 325 | es->s_first_error_ino = es->s_last_error_ino; |
326 | es->s_first_error_block = es->s_last_error_block; | 326 | es->s_first_error_block = es->s_last_error_block; |
327 | } | 327 | } |
328 | /* | ||
329 | * Start the daily error reporting function if it hasn't been | ||
330 | * started already | ||
331 | */ | ||
332 | if (!es->s_error_count) | ||
333 | mod_timer(&EXT4_SB(sb)->s_err_report, jiffies + 24*60*60*HZ); | ||
328 | es->s_error_count = cpu_to_le32(le32_to_cpu(es->s_error_count) + 1); | 334 | es->s_error_count = cpu_to_le32(le32_to_cpu(es->s_error_count) + 1); |
329 | } | 335 | } |
330 | 336 | ||
@@ -2480,6 +2486,53 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly) | |||
2480 | return 1; | 2486 | return 1; |
2481 | } | 2487 | } |
2482 | 2488 | ||
2489 | /* | ||
2490 | * This function is called once a day if we have errors logged | ||
2491 | * on the file system | ||
2492 | */ | ||
2493 | static void print_daily_error_info(unsigned long arg) | ||
2494 | { | ||
2495 | struct super_block *sb = (struct super_block *) arg; | ||
2496 | struct ext4_sb_info *sbi; | ||
2497 | struct ext4_super_block *es; | ||
2498 | |||
2499 | sbi = EXT4_SB(sb); | ||
2500 | es = sbi->s_es; | ||
2501 | |||
2502 | if (es->s_error_count) | ||
2503 | ext4_msg(sb, KERN_NOTICE, "error count: %u", | ||
2504 | le32_to_cpu(es->s_error_count)); | ||
2505 | if (es->s_first_error_time) { | ||
2506 | printk(KERN_NOTICE "EXT4-fs (%s): initial error at %u: %.*s:%d", | ||
2507 | sb->s_id, le32_to_cpu(es->s_first_error_time), | ||
2508 | (int) sizeof(es->s_first_error_func), | ||
2509 | es->s_first_error_func, | ||
2510 | le32_to_cpu(es->s_first_error_line)); | ||
2511 | if (es->s_first_error_ino) | ||
2512 | printk(": inode %u", | ||
2513 | le32_to_cpu(es->s_first_error_ino)); | ||
2514 | if (es->s_first_error_block) | ||
2515 | printk(": block %llu", (unsigned long long) | ||
2516 | le64_to_cpu(es->s_first_error_block)); | ||
2517 | printk("\n"); | ||
2518 | } | ||
2519 | if (es->s_last_error_time) { | ||
2520 | printk(KERN_NOTICE "EXT4-fs (%s): last error at %u: %.*s:%d", | ||
2521 | sb->s_id, le32_to_cpu(es->s_last_error_time), | ||
2522 | (int) sizeof(es->s_last_error_func), | ||
2523 | es->s_last_error_func, | ||
2524 | le32_to_cpu(es->s_last_error_line)); | ||
2525 | if (es->s_last_error_ino) | ||
2526 | printk(": inode %u", | ||
2527 | le32_to_cpu(es->s_last_error_ino)); | ||
2528 | if (es->s_last_error_block) | ||
2529 | printk(": block %llu", (unsigned long long) | ||
2530 | le64_to_cpu(es->s_last_error_block)); | ||
2531 | printk("\n"); | ||
2532 | } | ||
2533 | mod_timer(&sbi->s_err_report, jiffies + 24*60*60*HZ); /* Once a day */ | ||
2534 | } | ||
2535 | |||
2483 | static int ext4_fill_super(struct super_block *sb, void *data, int silent) | 2536 | static int ext4_fill_super(struct super_block *sb, void *data, int silent) |
2484 | __releases(kernel_lock) | 2537 | __releases(kernel_lock) |
2485 | __acquires(kernel_lock) | 2538 | __acquires(kernel_lock) |
@@ -3083,6 +3136,12 @@ no_journal: | |||
3083 | ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. " | 3136 | ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. " |
3084 | "Opts: %s", descr, orig_data); | 3137 | "Opts: %s", descr, orig_data); |
3085 | 3138 | ||
3139 | init_timer(&sbi->s_err_report); | ||
3140 | sbi->s_err_report.function = print_daily_error_info; | ||
3141 | sbi->s_err_report.data = (unsigned long) sb; | ||
3142 | if (es->s_error_count) | ||
3143 | mod_timer(&sbi->s_err_report, jiffies + 300*HZ); /* 5 minutes */ | ||
3144 | |||
3086 | lock_kernel(); | 3145 | lock_kernel(); |
3087 | kfree(orig_data); | 3146 | kfree(orig_data); |
3088 | return 0; | 3147 | return 0; |