summaryrefslogtreecommitdiff
path: root/fs/ext3
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@us.ibm.com>2010-10-04 12:35:05 -0700
committerJan Kara <jack@suse.cz>2010-10-28 01:30:02 +0200
commitdff6825e9fde93891e60751e01480337a991235e (patch)
tree3b243584ee48752096b110c04ecd803e285325ae /fs/ext3
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/ext3')
-rw-r--r--fs/ext3/super.c24
1 files changed, 23 insertions, 1 deletions
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 5dbf4dba03c4..3ef272488ac9 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -2361,6 +2361,21 @@ static int ext3_commit_super(struct super_block *sb,
if (!sbh)
return error;
+
+ if (buffer_write_io_error(sbh)) {
+ /*
+ * Oh, dear. A previous attempt to write the
+ * superblock failed. This could happen because the
+ * USB device was yanked out. Or it could happen to
+ * be a transient write error and maybe the block will
+ * be remapped. Nothing we can do but to retry the
+ * write and hope for the best.
+ */
+ ext3_msg(sb, KERN_ERR, "previous I/O error to "
+ "superblock detected");
+ clear_buffer_write_io_error(sbh);
+ set_buffer_uptodate(sbh);
+ }
/*
* If the file system is mounted read-only, don't update the
* superblock write time. This avoids updating the superblock
@@ -2377,8 +2392,15 @@ static int ext3_commit_super(struct super_block *sb,
es->s_free_inodes_count = cpu_to_le32(ext3_count_free_inodes(sb));
BUFFER_TRACE(sbh, "marking dirty");
mark_buffer_dirty(sbh);
- if (sync)
+ if (sync) {
error = sync_dirty_buffer(sbh);
+ if (buffer_write_io_error(sbh)) {
+ ext3_msg(sb, KERN_ERR, "I/O error while writing "
+ "superblock");
+ clear_buffer_write_io_error(sbh);
+ set_buffer_uptodate(sbh);
+ }
+ }
return error;
}