aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHidehiro Kawai <hidehiro.kawai.ez@hitachi.com>2008-10-18 23:27:57 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-20 11:52:37 -0400
commit0e4fb5e283870757024294bc4567a7c59d936f0b (patch)
tree162263fe9e712124d3df886ca57d8db752a3237d
parent46d01a225e694f1a4343beea44f1e85105aedd7e (diff)
ext3: add an option to control error handling on file data
If the journal doesn't abort when it gets an IO error in file data blocks, the file data corruption will spread silently. Because most of applications and commands do buffered writes without fsync(), they don't notice the IO error. It's scary for mission critical systems. On the other hand, if the journal aborts whenever it gets an IO error in file data blocks, the system will easily become inoperable. So this patch introduces a filesystem option to determine whether it aborts the journal or just call printk() when it gets an IO error in file data. If you mount a ext3 fs with data_err=abort option, it aborts on file data write error. If you mount it with data_err=ignore, it doesn't abort, just call printk(). data_err=ignore is the default. Signed-off-by: Hidehiro Kawai <hidehiro.kawai.ez@hitachi.com> Cc: Jan Kara <jack@ucw.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--Documentation/filesystems/ext3.txt5
-rw-r--r--fs/ext3/super.c16
-rw-r--r--fs/jbd/commit.c2
-rw-r--r--include/linux/ext3_fs.h2
-rw-r--r--include/linux/jbd.h3
5 files changed, 28 insertions, 0 deletions
diff --git a/Documentation/filesystems/ext3.txt b/Documentation/filesystems/ext3.txt
index 295f26cd895a..9dd2a3bb2acc 100644
--- a/Documentation/filesystems/ext3.txt
+++ b/Documentation/filesystems/ext3.txt
@@ -96,6 +96,11 @@ errors=remount-ro(*) Remount the filesystem read-only on an error.
96errors=continue Keep going on a filesystem error. 96errors=continue Keep going on a filesystem error.
97errors=panic Panic and halt the machine if an error occurs. 97errors=panic Panic and halt the machine if an error occurs.
98 98
99data_err=ignore(*) Just print an error message if an error occurs
100 in a file data buffer in ordered mode.
101data_err=abort Abort the journal if an error occurs in a file
102 data buffer in ordered mode.
103
99grpid Give objects the same group ID as their creator. 104grpid Give objects the same group ID as their creator.
100bsdgroups 105bsdgroups
101 106
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 399a96a6c556..3a260af5544d 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -625,6 +625,9 @@ static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs)
625 else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA) 625 else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA)
626 seq_puts(seq, ",data=writeback"); 626 seq_puts(seq, ",data=writeback");
627 627
628 if (test_opt(sb, DATA_ERR_ABORT))
629 seq_puts(seq, ",data_err=abort");
630
628 ext3_show_quota_options(seq, sb); 631 ext3_show_quota_options(seq, sb);
629 632
630 return 0; 633 return 0;
@@ -754,6 +757,7 @@ enum {
754 Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_bh, 757 Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_bh,
755 Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev, 758 Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev,
756 Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, 759 Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
760 Opt_data_err_abort, Opt_data_err_ignore,
757 Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, 761 Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
758 Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota, 762 Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
759 Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota, 763 Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
@@ -796,6 +800,8 @@ static const match_table_t tokens = {
796 {Opt_data_journal, "data=journal"}, 800 {Opt_data_journal, "data=journal"},
797 {Opt_data_ordered, "data=ordered"}, 801 {Opt_data_ordered, "data=ordered"},
798 {Opt_data_writeback, "data=writeback"}, 802 {Opt_data_writeback, "data=writeback"},
803 {Opt_data_err_abort, "data_err=abort"},
804 {Opt_data_err_ignore, "data_err=ignore"},
799 {Opt_offusrjquota, "usrjquota="}, 805 {Opt_offusrjquota, "usrjquota="},
800 {Opt_usrjquota, "usrjquota=%s"}, 806 {Opt_usrjquota, "usrjquota=%s"},
801 {Opt_offgrpjquota, "grpjquota="}, 807 {Opt_offgrpjquota, "grpjquota="},
@@ -1011,6 +1017,12 @@ static int parse_options (char *options, struct super_block *sb,
1011 sbi->s_mount_opt |= data_opt; 1017 sbi->s_mount_opt |= data_opt;
1012 } 1018 }
1013 break; 1019 break;
1020 case Opt_data_err_abort:
1021 set_opt(sbi->s_mount_opt, DATA_ERR_ABORT);
1022 break;
1023 case Opt_data_err_ignore:
1024 clear_opt(sbi->s_mount_opt, DATA_ERR_ABORT);
1025 break;
1014#ifdef CONFIG_QUOTA 1026#ifdef CONFIG_QUOTA
1015 case Opt_usrjquota: 1027 case Opt_usrjquota:
1016 qtype = USRQUOTA; 1028 qtype = USRQUOTA;
@@ -1986,6 +1998,10 @@ static void ext3_init_journal_params(struct super_block *sb, journal_t *journal)
1986 journal->j_flags |= JFS_BARRIER; 1998 journal->j_flags |= JFS_BARRIER;
1987 else 1999 else
1988 journal->j_flags &= ~JFS_BARRIER; 2000 journal->j_flags &= ~JFS_BARRIER;
2001 if (test_opt(sb, DATA_ERR_ABORT))
2002 journal->j_flags |= JFS_ABORT_ON_SYNCDATA_ERR;
2003 else
2004 journal->j_flags &= ~JFS_ABORT_ON_SYNCDATA_ERR;
1989 spin_unlock(&journal->j_state_lock); 2005 spin_unlock(&journal->j_state_lock);
1990} 2006}
1991 2007
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index d6a6659f3e46..25719d902c51 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -482,6 +482,8 @@ void journal_commit_transaction(journal_t *journal)
482 printk(KERN_WARNING 482 printk(KERN_WARNING
483 "JBD: Detected IO errors while flushing file data " 483 "JBD: Detected IO errors while flushing file data "
484 "on %s\n", bdevname(journal->j_fs_dev, b)); 484 "on %s\n", bdevname(journal->j_fs_dev, b));
485 if (journal->j_flags & JFS_ABORT_ON_SYNCDATA_ERR)
486 journal_abort(journal, err);
485 err = 0; 487 err = 0;
486 } 488 }
487 489
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
index 159d9b476cd7..d14f02918483 100644
--- a/include/linux/ext3_fs.h
+++ b/include/linux/ext3_fs.h
@@ -380,6 +380,8 @@ struct ext3_inode {
380#define EXT3_MOUNT_QUOTA 0x80000 /* Some quota option set */ 380#define EXT3_MOUNT_QUOTA 0x80000 /* Some quota option set */
381#define EXT3_MOUNT_USRQUOTA 0x100000 /* "old" user quota */ 381#define EXT3_MOUNT_USRQUOTA 0x100000 /* "old" user quota */
382#define EXT3_MOUNT_GRPQUOTA 0x200000 /* "old" group quota */ 382#define EXT3_MOUNT_GRPQUOTA 0x200000 /* "old" group quota */
383#define EXT3_MOUNT_DATA_ERR_ABORT 0x400000 /* Abort on file data write
384 * error in ordered mode */
383 385
384/* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */ 386/* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
385#ifndef _LINUX_EXT2_FS_H 387#ifndef _LINUX_EXT2_FS_H
diff --git a/include/linux/jbd.h b/include/linux/jbd.h
index 7ebbcb1c9ba4..35d4f6342fac 100644
--- a/include/linux/jbd.h
+++ b/include/linux/jbd.h
@@ -816,6 +816,9 @@ struct journal_s
816#define JFS_FLUSHED 0x008 /* The journal superblock has been flushed */ 816#define JFS_FLUSHED 0x008 /* The journal superblock has been flushed */
817#define JFS_LOADED 0x010 /* The journal superblock has been loaded */ 817#define JFS_LOADED 0x010 /* The journal superblock has been loaded */
818#define JFS_BARRIER 0x020 /* Use IDE barriers */ 818#define JFS_BARRIER 0x020 /* Use IDE barriers */
819#define JFS_ABORT_ON_SYNCDATA_ERR 0x040 /* Abort the journal on file
820 * data write error in ordered
821 * mode */
819 822
820/* 823/*
821 * Function declarations for the journaling transaction and buffer 824 * Function declarations for the journaling transaction and buffer