aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r--fs/ext4/super.c80
1 files changed, 61 insertions, 19 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index bcf74b31d014..a94d3f56898f 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -307,6 +307,35 @@ void ext4_journal_abort_handle(const char *caller, unsigned int line,
307 jbd2_journal_abort_handle(handle); 307 jbd2_journal_abort_handle(handle);
308} 308}
309 309
310static void __save_error_info(struct super_block *sb, const char *func,
311 unsigned int line)
312{
313 struct ext4_super_block *es = EXT4_SB(sb)->s_es;
314
315 EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
316 es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
317 es->s_last_error_time = cpu_to_le32(get_seconds());
318 strncpy(es->s_last_error_func, func, sizeof(es->s_last_error_func));
319 es->s_last_error_line = cpu_to_le32(line);
320 if (!es->s_first_error_time) {
321 es->s_first_error_time = es->s_last_error_time;
322 strncpy(es->s_first_error_func, func,
323 sizeof(es->s_first_error_func));
324 es->s_first_error_line = cpu_to_le32(line);
325 es->s_first_error_ino = es->s_last_error_ino;
326 es->s_first_error_block = es->s_last_error_block;
327 }
328 es->s_error_count = cpu_to_le32(le32_to_cpu(es->s_error_count) + 1);
329}
330
331static void save_error_info(struct super_block *sb, const char *func,
332 unsigned int line)
333{
334 __save_error_info(sb, func, line);
335 ext4_commit_super(sb, 1);
336}
337
338
310/* Deal with the reporting of failure conditions on a filesystem such as 339/* Deal with the reporting of failure conditions on a filesystem such as
311 * inconsistencies detected or read IO failures. 340 * inconsistencies detected or read IO failures.
312 * 341 *
@@ -324,11 +353,6 @@ void ext4_journal_abort_handle(const char *caller, unsigned int line,
324 353
325static void ext4_handle_error(struct super_block *sb) 354static void ext4_handle_error(struct super_block *sb)
326{ 355{
327 struct ext4_super_block *es = EXT4_SB(sb)->s_es;
328
329 EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
330 es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
331
332 if (sb->s_flags & MS_RDONLY) 356 if (sb->s_flags & MS_RDONLY)
333 return; 357 return;
334 358
@@ -343,7 +367,6 @@ static void ext4_handle_error(struct super_block *sb)
343 ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only"); 367 ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
344 sb->s_flags |= MS_RDONLY; 368 sb->s_flags |= MS_RDONLY;
345 } 369 }
346 ext4_commit_super(sb, 1);
347 if (test_opt(sb, ERRORS_PANIC)) 370 if (test_opt(sb, ERRORS_PANIC))
348 panic("EXT4-fs (device %s): panic forced after error\n", 371 panic("EXT4-fs (device %s): panic forced after error\n",
349 sb->s_id); 372 sb->s_id);
@@ -369,7 +392,11 @@ void ext4_error_inode(struct inode *inode, const char *function,
369 const char *fmt, ...) 392 const char *fmt, ...)
370{ 393{
371 va_list args; 394 va_list args;
395 struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
372 396
397 es->s_last_error_ino = cpu_to_le32(inode->i_ino);
398 es->s_last_error_block = cpu_to_le64(block);
399 save_error_info(inode->i_sb, function, line);
373 va_start(args, fmt); 400 va_start(args, fmt);
374 printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: inode #%lu: ", 401 printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: inode #%lu: ",
375 inode->i_sb->s_id, function, line, inode->i_ino); 402 inode->i_sb->s_id, function, line, inode->i_ino);
@@ -387,9 +414,13 @@ void ext4_error_file(struct file *file, const char *function,
387 unsigned int line, const char *fmt, ...) 414 unsigned int line, const char *fmt, ...)
388{ 415{
389 va_list args; 416 va_list args;
417 struct ext4_super_block *es;
390 struct inode *inode = file->f_dentry->d_inode; 418 struct inode *inode = file->f_dentry->d_inode;
391 char pathname[80], *path; 419 char pathname[80], *path;
392 420
421 es = EXT4_SB(inode->i_sb)->s_es;
422 es->s_last_error_ino = cpu_to_le32(inode->i_ino);
423 save_error_info(inode->i_sb, function, line);
393 va_start(args, fmt); 424 va_start(args, fmt);
394 path = d_path(&(file->f_path), pathname, sizeof(pathname)); 425 path = d_path(&(file->f_path), pathname, sizeof(pathname));
395 if (!path) 426 if (!path)
@@ -459,6 +490,7 @@ void __ext4_std_error(struct super_block *sb, const char *function,
459 errstr = ext4_decode_error(sb, errno, nbuf); 490 errstr = ext4_decode_error(sb, errno, nbuf);
460 printk(KERN_CRIT "EXT4-fs error (device %s) in %s:%d: %s\n", 491 printk(KERN_CRIT "EXT4-fs error (device %s) in %s:%d: %s\n",
461 sb->s_id, function, line, errstr); 492 sb->s_id, function, line, errstr);
493 save_error_info(sb, function, line);
462 494
463 ext4_handle_error(sb); 495 ext4_handle_error(sb);
464} 496}
@@ -478,6 +510,7 @@ void __ext4_abort(struct super_block *sb, const char *function,
478{ 510{
479 va_list args; 511 va_list args;
480 512
513 save_error_info(sb, function, line);
481 va_start(args, fmt); 514 va_start(args, fmt);
482 printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: ", sb->s_id, 515 printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: ", sb->s_id,
483 function, line); 516 function, line);
@@ -485,18 +518,16 @@ void __ext4_abort(struct super_block *sb, const char *function,
485 printk("\n"); 518 printk("\n");
486 va_end(args); 519 va_end(args);
487 520
521 if ((sb->s_flags & MS_RDONLY) == 0) {
522 ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
523 sb->s_flags |= MS_RDONLY;
524 EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED;
525 if (EXT4_SB(sb)->s_journal)
526 jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO);
527 save_error_info(sb, function, line);
528 }
488 if (test_opt(sb, ERRORS_PANIC)) 529 if (test_opt(sb, ERRORS_PANIC))
489 panic("EXT4-fs panic from previous error\n"); 530 panic("EXT4-fs panic from previous error\n");
490
491 if (sb->s_flags & MS_RDONLY)
492 return;
493
494 ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
495 EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
496 sb->s_flags |= MS_RDONLY;
497 EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED;
498 if (EXT4_SB(sb)->s_journal)
499 jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO);
500} 531}
501 532
502void ext4_msg (struct super_block * sb, const char *prefix, 533void ext4_msg (struct super_block * sb, const char *prefix,
@@ -534,6 +565,9 @@ __acquires(bitlock)
534 va_list args; 565 va_list args;
535 struct ext4_super_block *es = EXT4_SB(sb)->s_es; 566 struct ext4_super_block *es = EXT4_SB(sb)->s_es;
536 567
568 es->s_last_error_ino = cpu_to_le32(ino);
569 es->s_last_error_block = cpu_to_le64(block);
570 __save_error_info(sb, function, line);
537 va_start(args, fmt); 571 va_start(args, fmt);
538 printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: group %u", 572 printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: group %u",
539 sb->s_id, function, line, grp); 573 sb->s_id, function, line, grp);
@@ -546,11 +580,10 @@ __acquires(bitlock)
546 va_end(args); 580 va_end(args);
547 581
548 if (test_opt(sb, ERRORS_CONT)) { 582 if (test_opt(sb, ERRORS_CONT)) {
549 EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
550 es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
551 ext4_commit_super(sb, 0); 583 ext4_commit_super(sb, 0);
552 return; 584 return;
553 } 585 }
586
554 ext4_unlock_group(sb, grp); 587 ext4_unlock_group(sb, grp);
555 ext4_handle_error(sb); 588 ext4_handle_error(sb);
556 /* 589 /*
@@ -3332,8 +3365,17 @@ static int ext4_load_journal(struct super_block *sb,
3332 3365
3333 if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER)) 3366 if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER))
3334 err = jbd2_journal_wipe(journal, !really_read_only); 3367 err = jbd2_journal_wipe(journal, !really_read_only);
3335 if (!err) 3368 if (!err) {
3369 char *save = kmalloc(EXT4_S_ERR_LEN, GFP_KERNEL);
3370 if (save)
3371 memcpy(save, ((char *) es) +
3372 EXT4_S_ERR_START, EXT4_S_ERR_LEN);
3336 err = jbd2_journal_load(journal); 3373 err = jbd2_journal_load(journal);
3374 if (save)
3375 memcpy(((char *) es) + EXT4_S_ERR_START,
3376 save, EXT4_S_ERR_LEN);
3377 kfree(save);
3378 }
3337 3379
3338 if (err) { 3380 if (err) {
3339 ext4_msg(sb, KERN_ERR, "error loading journal"); 3381 ext4_msg(sb, KERN_ERR, "error loading journal");