aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHidehiro Kawai <hidehiro.kawai.ez@hitachi.com>2008-07-25 04:46:30 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-25 13:53:32 -0400
commitcbe5f466f6995e10a10c7ae66d6dc8608f08a6b8 (patch)
tree237bbbda6ddd6e38dc7004cd870cbce7af0684c4
parent8ef2720397bb813d4985405a5ae7b8ad6474188b (diff)
jbd: don't abort if flushing file data failed
In ordered mode, the current jbd aborts the journal if a file data buffer has an error. But this behavior is unintended, and we found that it has been adopted accidentally. This patch undoes it and just calls printk() instead of aborting the journal. Additionally, set AS_EIO into the address_space object of the failed buffer which is submitted by journal_do_submit_data() so that fsync() can get -EIO. Missing error checkings are also added to inform errors on file data buffers to the user. The following buffers are targeted. (a) the buffer which has already been written out by pdflush (b) the buffer which has been unlocked before scanned in the t_locked_list loop [akpm@linux-foundation.org: improve grammar in a printk] Signed-off-by: Hidehiro Kawai <hidehiro.kawai.ez@hitachi.com> Acked-by: Jan Kara <jack@suse.cz> Cc: <linux-ext4@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/jbd/commit.c35
1 files changed, 28 insertions, 7 deletions
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index f943b9b3f208..2eccbfaa1d48 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -185,7 +185,7 @@ static void journal_do_submit_data(struct buffer_head **wbuf, int bufs)
185/* 185/*
186 * Submit all the data buffers to disk 186 * Submit all the data buffers to disk
187 */ 187 */
188static void journal_submit_data_buffers(journal_t *journal, 188static int journal_submit_data_buffers(journal_t *journal,
189 transaction_t *commit_transaction) 189 transaction_t *commit_transaction)
190{ 190{
191 struct journal_head *jh; 191 struct journal_head *jh;
@@ -193,6 +193,7 @@ static void journal_submit_data_buffers(journal_t *journal,
193 int locked; 193 int locked;
194 int bufs = 0; 194 int bufs = 0;
195 struct buffer_head **wbuf = journal->j_wbuf; 195 struct buffer_head **wbuf = journal->j_wbuf;
196 int err = 0;
196 197
197 /* 198 /*
198 * Whenever we unlock the journal and sleep, things can get added 199 * Whenever we unlock the journal and sleep, things can get added
@@ -266,6 +267,8 @@ write_out_data:
266 put_bh(bh); 267 put_bh(bh);
267 } else { 268 } else {
268 BUFFER_TRACE(bh, "writeout complete: unfile"); 269 BUFFER_TRACE(bh, "writeout complete: unfile");
270 if (unlikely(!buffer_uptodate(bh)))
271 err = -EIO;
269 __journal_unfile_buffer(jh); 272 __journal_unfile_buffer(jh);
270 jbd_unlock_bh_state(bh); 273 jbd_unlock_bh_state(bh);
271 if (locked) 274 if (locked)
@@ -284,6 +287,8 @@ write_out_data:
284 } 287 }
285 spin_unlock(&journal->j_list_lock); 288 spin_unlock(&journal->j_list_lock);
286 journal_do_submit_data(wbuf, bufs); 289 journal_do_submit_data(wbuf, bufs);
290
291 return err;
287} 292}
288 293
289/* 294/*
@@ -423,8 +428,7 @@ void journal_commit_transaction(journal_t *journal)
423 * Now start flushing things to disk, in the order they appear 428 * Now start flushing things to disk, in the order they appear
424 * on the transaction lists. Data blocks go first. 429 * on the transaction lists. Data blocks go first.
425 */ 430 */
426 err = 0; 431 err = journal_submit_data_buffers(journal, commit_transaction);
427 journal_submit_data_buffers(journal, commit_transaction);
428 432
429 /* 433 /*
430 * Wait for all previously submitted IO to complete. 434 * Wait for all previously submitted IO to complete.
@@ -439,10 +443,21 @@ void journal_commit_transaction(journal_t *journal)
439 if (buffer_locked(bh)) { 443 if (buffer_locked(bh)) {
440 spin_unlock(&journal->j_list_lock); 444 spin_unlock(&journal->j_list_lock);
441 wait_on_buffer(bh); 445 wait_on_buffer(bh);
442 if (unlikely(!buffer_uptodate(bh)))
443 err = -EIO;
444 spin_lock(&journal->j_list_lock); 446 spin_lock(&journal->j_list_lock);
445 } 447 }
448 if (unlikely(!buffer_uptodate(bh))) {
449 if (TestSetPageLocked(bh->b_page)) {
450 spin_unlock(&journal->j_list_lock);
451 lock_page(bh->b_page);
452 spin_lock(&journal->j_list_lock);
453 }
454 if (bh->b_page->mapping)
455 set_bit(AS_EIO, &bh->b_page->mapping->flags);
456
457 unlock_page(bh->b_page);
458 SetPageError(bh->b_page);
459 err = -EIO;
460 }
446 if (!inverted_lock(journal, bh)) { 461 if (!inverted_lock(journal, bh)) {
447 put_bh(bh); 462 put_bh(bh);
448 spin_lock(&journal->j_list_lock); 463 spin_lock(&journal->j_list_lock);
@@ -461,8 +476,14 @@ void journal_commit_transaction(journal_t *journal)
461 } 476 }
462 spin_unlock(&journal->j_list_lock); 477 spin_unlock(&journal->j_list_lock);
463 478
464 if (err) 479 if (err) {
465 journal_abort(journal, err); 480 char b[BDEVNAME_SIZE];
481
482 printk(KERN_WARNING
483 "JBD: Detected IO errors while flushing file data "
484 "on %s\n", bdevname(journal->j_fs_dev, b));
485 err = 0;
486 }
466 487
467 journal_write_revoke_records(journal, commit_transaction); 488 journal_write_revoke_records(journal, commit_transaction);
468 489