aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jbd
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@us.ibm.com>2010-10-04 15:35:05 -0400
committerJan Kara <jack@suse.cz>2010-10-27 19:30:02 -0400
commitdff6825e9fde93891e60751e01480337a991235e (patch)
tree3b243584ee48752096b110c04ecd803e285325ae /fs/jbd
parent8117f98c058dbe463eaba2b51b84d19bd5d78804 (diff)
ext3/jbd: Avoid WARN() messages when failing to write the superblock
This fixes a WARN backtrace in mark_buffer_dirty() that occurs during unmount when the underlying block device is removed. This bug has been seen on System Z when removing all paths from a multipath-backed ext3 mount; on System P when injecting enough PCI EEH errors to make the SCSI controller go offline; and similar warnings have been seen (and patched) with ext2/ext4. The super block update from a previous operation has marked the buffer as in error, and the flag has to be cleared before doing the update. Similar changes have been made to ext4 by commit 914258bf2cb22bf4336a1b1d90c551b4b11ca5aa. Signed-off-by: Darrick J. Wong <djwong@us.ibm.com> Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/jbd')
-rw-r--r--fs/jbd/journal.c30
1 files changed, 28 insertions, 2 deletions
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index d7a86935553a..e56117651826 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -85,6 +85,7 @@ EXPORT_SYMBOL(journal_force_commit);
85 85
86static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *); 86static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *);
87static void __journal_abort_soft (journal_t *journal, int errno); 87static void __journal_abort_soft (journal_t *journal, int errno);
88static const char *journal_dev_name(journal_t *journal, char *buffer);
88 89
89/* 90/*
90 * Helper function used to manage commit timeouts 91 * Helper function used to manage commit timeouts
@@ -1011,6 +1012,23 @@ void journal_update_superblock(journal_t *journal, int wait)
1011 goto out; 1012 goto out;
1012 } 1013 }
1013 1014
1015 if (buffer_write_io_error(bh)) {
1016 char b[BDEVNAME_SIZE];
1017 /*
1018 * Oh, dear. A previous attempt to write the journal
1019 * superblock failed. This could happen because the
1020 * USB device was yanked out. Or it could happen to
1021 * be a transient write error and maybe the block will
1022 * be remapped. Nothing we can do but to retry the
1023 * write and hope for the best.
1024 */
1025 printk(KERN_ERR "JBD: previous I/O error detected "
1026 "for journal superblock update for %s.\n",
1027 journal_dev_name(journal, b));
1028 clear_buffer_write_io_error(bh);
1029 set_buffer_uptodate(bh);
1030 }
1031
1014 spin_lock(&journal->j_state_lock); 1032 spin_lock(&journal->j_state_lock);
1015 jbd_debug(1,"JBD: updating superblock (start %u, seq %d, errno %d)\n", 1033 jbd_debug(1,"JBD: updating superblock (start %u, seq %d, errno %d)\n",
1016 journal->j_tail, journal->j_tail_sequence, journal->j_errno); 1034 journal->j_tail, journal->j_tail_sequence, journal->j_errno);
@@ -1022,9 +1040,17 @@ void journal_update_superblock(journal_t *journal, int wait)
1022 1040
1023 BUFFER_TRACE(bh, "marking dirty"); 1041 BUFFER_TRACE(bh, "marking dirty");
1024 mark_buffer_dirty(bh); 1042 mark_buffer_dirty(bh);
1025 if (wait) 1043 if (wait) {
1026 sync_dirty_buffer(bh); 1044 sync_dirty_buffer(bh);
1027 else 1045 if (buffer_write_io_error(bh)) {
1046 char b[BDEVNAME_SIZE];
1047 printk(KERN_ERR "JBD: I/O error detected "
1048 "when updating journal superblock for %s.\n",
1049 journal_dev_name(journal, b));
1050 clear_buffer_write_io_error(bh);
1051 set_buffer_uptodate(bh);
1052 }
1053 } else
1028 write_dirty_buffer(bh, WRITE); 1054 write_dirty_buffer(bh, WRITE);
1029 1055
1030out: 1056out: