aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2013-10-17 21:11:01 -0400
committerTheodore Ts'o <tytso@mit.edu>2013-10-17 21:11:01 -0400
commitefbed4dc5857f845d787e406ce85097d1ccc5c4f (patch)
tree4cfd6a4c20e52b21c3f26632c849dd084df6f632 /fs
parentaeac589a74b91c4c07458272767e089810fbd23d (diff)
ext4: add ratelimiting to ext4 messages
In the case of a storage device that suddenly disappears, or in the case of significant file system corruption, this can result in a huge flood of messages being sent to the console. This can overflow the file system containing /var/log/messages, or if a serial console is configured, this can slow down the system so much that a hardware watchdog can end up triggering forcing a system reboot. Google-Bug-Id: 7258357 Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs')
-rw-r--r--fs/ext4/ext4.h6
-rw-r--r--fs/ext4/super.c152
2 files changed, 100 insertions, 58 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index af815ea9d7cc..65485ab7a889 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -29,6 +29,7 @@
29#include <linux/wait.h> 29#include <linux/wait.h>
30#include <linux/blockgroup_lock.h> 30#include <linux/blockgroup_lock.h>
31#include <linux/percpu_counter.h> 31#include <linux/percpu_counter.h>
32#include <linux/ratelimit.h>
32#include <crypto/hash.h> 33#include <crypto/hash.h>
33#ifdef __KERNEL__ 34#ifdef __KERNEL__
34#include <linux/compat.h> 35#include <linux/compat.h>
@@ -1314,6 +1315,11 @@ struct ext4_sb_info {
1314 unsigned long s_es_last_sorted; 1315 unsigned long s_es_last_sorted;
1315 struct percpu_counter s_extent_cache_cnt; 1316 struct percpu_counter s_extent_cache_cnt;
1316 spinlock_t s_es_lru_lock ____cacheline_aligned_in_smp; 1317 spinlock_t s_es_lru_lock ____cacheline_aligned_in_smp;
1318
1319 /* Ratelimit ext4 messages. */
1320 struct ratelimit_state s_err_ratelimit_state;
1321 struct ratelimit_state s_warning_ratelimit_state;
1322 struct ratelimit_state s_msg_ratelimit_state;
1317}; 1323};
1318 1324
1319static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb) 1325static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb)
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 2c2e6cbc6bed..d3a857bfae47 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -411,20 +411,26 @@ static void ext4_handle_error(struct super_block *sb)
411 sb->s_id); 411 sb->s_id);
412} 412}
413 413
414#define ext4_error_ratelimit(sb) \
415 ___ratelimit(&(EXT4_SB(sb)->s_err_ratelimit_state), \
416 "EXT4-fs error")
417
414void __ext4_error(struct super_block *sb, const char *function, 418void __ext4_error(struct super_block *sb, const char *function,
415 unsigned int line, const char *fmt, ...) 419 unsigned int line, const char *fmt, ...)
416{ 420{
417 struct va_format vaf; 421 struct va_format vaf;
418 va_list args; 422 va_list args;
419 423
420 va_start(args, fmt); 424 if (ext4_error_ratelimit(sb)) {
421 vaf.fmt = fmt; 425 va_start(args, fmt);
422 vaf.va = &args; 426 vaf.fmt = fmt;
423 printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: comm %s: %pV\n", 427 vaf.va = &args;
424 sb->s_id, function, line, current->comm, &vaf); 428 printk(KERN_CRIT
425 va_end(args); 429 "EXT4-fs error (device %s): %s:%d: comm %s: %pV\n",
430 sb->s_id, function, line, current->comm, &vaf);
431 va_end(args);
432 }
426 save_error_info(sb, function, line); 433 save_error_info(sb, function, line);
427
428 ext4_handle_error(sb); 434 ext4_handle_error(sb);
429} 435}
430 436
@@ -438,22 +444,23 @@ void __ext4_error_inode(struct inode *inode, const char *function,
438 444
439 es->s_last_error_ino = cpu_to_le32(inode->i_ino); 445 es->s_last_error_ino = cpu_to_le32(inode->i_ino);
440 es->s_last_error_block = cpu_to_le64(block); 446 es->s_last_error_block = cpu_to_le64(block);
447 if (ext4_error_ratelimit(inode->i_sb)) {
448 va_start(args, fmt);
449 vaf.fmt = fmt;
450 vaf.va = &args;
451 if (block)
452 printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: "
453 "inode #%lu: block %llu: comm %s: %pV\n",
454 inode->i_sb->s_id, function, line, inode->i_ino,
455 block, current->comm, &vaf);
456 else
457 printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: "
458 "inode #%lu: comm %s: %pV\n",
459 inode->i_sb->s_id, function, line, inode->i_ino,
460 current->comm, &vaf);
461 va_end(args);
462 }
441 save_error_info(inode->i_sb, function, line); 463 save_error_info(inode->i_sb, function, line);
442 va_start(args, fmt);
443 vaf.fmt = fmt;
444 vaf.va = &args;
445 if (block)
446 printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: "
447 "inode #%lu: block %llu: comm %s: %pV\n",
448 inode->i_sb->s_id, function, line, inode->i_ino,
449 block, current->comm, &vaf);
450 else
451 printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: "
452 "inode #%lu: comm %s: %pV\n",
453 inode->i_sb->s_id, function, line, inode->i_ino,
454 current->comm, &vaf);
455 va_end(args);
456
457 ext4_handle_error(inode->i_sb); 464 ext4_handle_error(inode->i_sb);
458} 465}
459 466
@@ -469,27 +476,28 @@ void __ext4_error_file(struct file *file, const char *function,
469 476
470 es = EXT4_SB(inode->i_sb)->s_es; 477 es = EXT4_SB(inode->i_sb)->s_es;
471 es->s_last_error_ino = cpu_to_le32(inode->i_ino); 478 es->s_last_error_ino = cpu_to_le32(inode->i_ino);
479 if (ext4_error_ratelimit(inode->i_sb)) {
480 path = d_path(&(file->f_path), pathname, sizeof(pathname));
481 if (IS_ERR(path))
482 path = "(unknown)";
483 va_start(args, fmt);
484 vaf.fmt = fmt;
485 vaf.va = &args;
486 if (block)
487 printk(KERN_CRIT
488 "EXT4-fs error (device %s): %s:%d: inode #%lu: "
489 "block %llu: comm %s: path %s: %pV\n",
490 inode->i_sb->s_id, function, line, inode->i_ino,
491 block, current->comm, path, &vaf);
492 else
493 printk(KERN_CRIT
494 "EXT4-fs error (device %s): %s:%d: inode #%lu: "
495 "comm %s: path %s: %pV\n",
496 inode->i_sb->s_id, function, line, inode->i_ino,
497 current->comm, path, &vaf);
498 va_end(args);
499 }
472 save_error_info(inode->i_sb, function, line); 500 save_error_info(inode->i_sb, function, line);
473 path = d_path(&(file->f_path), pathname, sizeof(pathname));
474 if (IS_ERR(path))
475 path = "(unknown)";
476 va_start(args, fmt);
477 vaf.fmt = fmt;
478 vaf.va = &args;
479 if (block)
480 printk(KERN_CRIT
481 "EXT4-fs error (device %s): %s:%d: inode #%lu: "
482 "block %llu: comm %s: path %s: %pV\n",
483 inode->i_sb->s_id, function, line, inode->i_ino,
484 block, current->comm, path, &vaf);
485 else
486 printk(KERN_CRIT
487 "EXT4-fs error (device %s): %s:%d: inode #%lu: "
488 "comm %s: path %s: %pV\n",
489 inode->i_sb->s_id, function, line, inode->i_ino,
490 current->comm, path, &vaf);
491 va_end(args);
492
493 ext4_handle_error(inode->i_sb); 501 ext4_handle_error(inode->i_sb);
494} 502}
495 503
@@ -543,11 +551,13 @@ void __ext4_std_error(struct super_block *sb, const char *function,
543 (sb->s_flags & MS_RDONLY)) 551 (sb->s_flags & MS_RDONLY))
544 return; 552 return;
545 553
546 errstr = ext4_decode_error(sb, errno, nbuf); 554 if (ext4_error_ratelimit(sb)) {
547 printk(KERN_CRIT "EXT4-fs error (device %s) in %s:%d: %s\n", 555 errstr = ext4_decode_error(sb, errno, nbuf);
548 sb->s_id, function, line, errstr); 556 printk(KERN_CRIT "EXT4-fs error (device %s) in %s:%d: %s\n",
549 save_error_info(sb, function, line); 557 sb->s_id, function, line, errstr);
558 }
550 559
560 save_error_info(sb, function, line);
551 ext4_handle_error(sb); 561 ext4_handle_error(sb);
552} 562}
553 563
@@ -597,6 +607,9 @@ void __ext4_msg(struct super_block *sb,
597 struct va_format vaf; 607 struct va_format vaf;
598 va_list args; 608 va_list args;
599 609
610 if (!___ratelimit(&(EXT4_SB(sb)->s_msg_ratelimit_state), "EXT4-fs"))
611 return;
612
600 va_start(args, fmt); 613 va_start(args, fmt);
601 vaf.fmt = fmt; 614 vaf.fmt = fmt;
602 vaf.va = &args; 615 vaf.va = &args;
@@ -610,6 +623,10 @@ void __ext4_warning(struct super_block *sb, const char *function,
610 struct va_format vaf; 623 struct va_format vaf;
611 va_list args; 624 va_list args;
612 625
626 if (!___ratelimit(&(EXT4_SB(sb)->s_warning_ratelimit_state),
627 "EXT4-fs warning"))
628 return;
629
613 va_start(args, fmt); 630 va_start(args, fmt);
614 vaf.fmt = fmt; 631 vaf.fmt = fmt;
615 vaf.va = &args; 632 vaf.va = &args;
@@ -633,18 +650,20 @@ __acquires(bitlock)
633 es->s_last_error_block = cpu_to_le64(block); 650 es->s_last_error_block = cpu_to_le64(block);
634 __save_error_info(sb, function, line); 651 __save_error_info(sb, function, line);
635 652
636 va_start(args, fmt); 653 if (ext4_error_ratelimit(sb)) {
637 654 va_start(args, fmt);
638 vaf.fmt = fmt; 655 vaf.fmt = fmt;
639 vaf.va = &args; 656 vaf.va = &args;
640 printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: group %u, ", 657 printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: group %u, ",
641 sb->s_id, function, line, grp); 658 sb->s_id, function, line, grp);
642 if (ino) 659 if (ino)
643 printk(KERN_CONT "inode %lu: ", ino); 660 printk(KERN_CONT "inode %lu: ", ino);
644 if (block) 661 if (block)
645 printk(KERN_CONT "block %llu:", (unsigned long long) block); 662 printk(KERN_CONT "block %llu:",
646 printk(KERN_CONT "%pV\n", &vaf); 663 (unsigned long long) block);
647 va_end(args); 664 printk(KERN_CONT "%pV\n", &vaf);
665 va_end(args);
666 }
648 667
649 if (test_opt(sb, ERRORS_CONT)) { 668 if (test_opt(sb, ERRORS_CONT)) {
650 ext4_commit_super(sb, 0); 669 ext4_commit_super(sb, 0);
@@ -2606,6 +2625,12 @@ EXT4_RW_ATTR_SBI_UI(mb_group_prealloc, s_mb_group_prealloc);
2606EXT4_DEPRECATED_ATTR(max_writeback_mb_bump, 128); 2625EXT4_DEPRECATED_ATTR(max_writeback_mb_bump, 128);
2607EXT4_RW_ATTR_SBI_UI(extent_max_zeroout_kb, s_extent_max_zeroout_kb); 2626EXT4_RW_ATTR_SBI_UI(extent_max_zeroout_kb, s_extent_max_zeroout_kb);
2608EXT4_ATTR(trigger_fs_error, 0200, NULL, trigger_test_error); 2627EXT4_ATTR(trigger_fs_error, 0200, NULL, trigger_test_error);
2628EXT4_RW_ATTR_SBI_UI(err_ratelimit_interval_ms, s_err_ratelimit_state.interval);
2629EXT4_RW_ATTR_SBI_UI(err_ratelimit_burst, s_err_ratelimit_state.burst);
2630EXT4_RW_ATTR_SBI_UI(warning_ratelimit_interval_ms, s_warning_ratelimit_state.interval);
2631EXT4_RW_ATTR_SBI_UI(warning_ratelimit_burst, s_warning_ratelimit_state.burst);
2632EXT4_RW_ATTR_SBI_UI(msg_ratelimit_interval_ms, s_msg_ratelimit_state.interval);
2633EXT4_RW_ATTR_SBI_UI(msg_ratelimit_burst, s_msg_ratelimit_state.burst);
2609 2634
2610static struct attribute *ext4_attrs[] = { 2635static struct attribute *ext4_attrs[] = {
2611 ATTR_LIST(delayed_allocation_blocks), 2636 ATTR_LIST(delayed_allocation_blocks),
@@ -2623,6 +2648,12 @@ static struct attribute *ext4_attrs[] = {
2623 ATTR_LIST(max_writeback_mb_bump), 2648 ATTR_LIST(max_writeback_mb_bump),
2624 ATTR_LIST(extent_max_zeroout_kb), 2649 ATTR_LIST(extent_max_zeroout_kb),
2625 ATTR_LIST(trigger_fs_error), 2650 ATTR_LIST(trigger_fs_error),
2651 ATTR_LIST(err_ratelimit_interval_ms),
2652 ATTR_LIST(err_ratelimit_burst),
2653 ATTR_LIST(warning_ratelimit_interval_ms),
2654 ATTR_LIST(warning_ratelimit_burst),
2655 ATTR_LIST(msg_ratelimit_interval_ms),
2656 ATTR_LIST(msg_ratelimit_burst),
2626 NULL, 2657 NULL,
2627}; 2658};
2628 2659
@@ -4118,6 +4149,11 @@ no_journal:
4118 if (es->s_error_count) 4149 if (es->s_error_count)
4119 mod_timer(&sbi->s_err_report, jiffies + 300*HZ); /* 5 minutes */ 4150 mod_timer(&sbi->s_err_report, jiffies + 300*HZ); /* 5 minutes */
4120 4151
4152 /* Enable message ratelimiting. Default is 10 messages per 5 secs. */
4153 ratelimit_state_init(&sbi->s_err_ratelimit_state, 5 * HZ, 10);
4154 ratelimit_state_init(&sbi->s_warning_ratelimit_state, 5 * HZ, 10);
4155 ratelimit_state_init(&sbi->s_msg_ratelimit_state, 5 * HZ, 10);
4156
4121 kfree(orig_data); 4157 kfree(orig_data);
4122 return 0; 4158 return 0;
4123 4159