diff options
-rw-r--r-- | fs/ext3/super.c | 24 | ||||
-rw-r--r-- | fs/jbd/journal.c | 30 |
2 files changed, 51 insertions, 3 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, | |||
2361 | 2361 | ||
2362 | if (!sbh) | 2362 | if (!sbh) |
2363 | return error; | 2363 | return error; |
2364 | |||
2365 | if (buffer_write_io_error(sbh)) { | ||
2366 | /* | ||
2367 | * Oh, dear. A previous attempt to write the | ||
2368 | * superblock failed. This could happen because the | ||
2369 | * USB device was yanked out. Or it could happen to | ||
2370 | * be a transient write error and maybe the block will | ||
2371 | * be remapped. Nothing we can do but to retry the | ||
2372 | * write and hope for the best. | ||
2373 | */ | ||
2374 | ext3_msg(sb, KERN_ERR, "previous I/O error to " | ||
2375 | "superblock detected"); | ||
2376 | clear_buffer_write_io_error(sbh); | ||
2377 | set_buffer_uptodate(sbh); | ||
2378 | } | ||
2364 | /* | 2379 | /* |
2365 | * If the file system is mounted read-only, don't update the | 2380 | * If the file system is mounted read-only, don't update the |
2366 | * superblock write time. This avoids updating the superblock | 2381 | * superblock write time. This avoids updating the superblock |
@@ -2377,8 +2392,15 @@ static int ext3_commit_super(struct super_block *sb, | |||
2377 | es->s_free_inodes_count = cpu_to_le32(ext3_count_free_inodes(sb)); | 2392 | es->s_free_inodes_count = cpu_to_le32(ext3_count_free_inodes(sb)); |
2378 | BUFFER_TRACE(sbh, "marking dirty"); | 2393 | BUFFER_TRACE(sbh, "marking dirty"); |
2379 | mark_buffer_dirty(sbh); | 2394 | mark_buffer_dirty(sbh); |
2380 | if (sync) | 2395 | if (sync) { |
2381 | error = sync_dirty_buffer(sbh); | 2396 | error = sync_dirty_buffer(sbh); |
2397 | if (buffer_write_io_error(sbh)) { | ||
2398 | ext3_msg(sb, KERN_ERR, "I/O error while writing " | ||
2399 | "superblock"); | ||
2400 | clear_buffer_write_io_error(sbh); | ||
2401 | set_buffer_uptodate(sbh); | ||
2402 | } | ||
2403 | } | ||
2382 | return error; | 2404 | return error; |
2383 | } | 2405 | } |
2384 | 2406 | ||
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 | ||
86 | static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *); | 86 | static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *); |
87 | static void __journal_abort_soft (journal_t *journal, int errno); | 87 | static void __journal_abort_soft (journal_t *journal, int errno); |
88 | static 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 | ||
1030 | out: | 1056 | out: |