|
@@ -185,7 +185,7 @@ static void journal_do_submit_data(struct buffer_head **wbuf, int bufs)
|
|
|
/*
|
|
|
* Submit all the data buffers to disk
|
|
|
*/
|
|
|
-static void journal_submit_data_buffers(journal_t *journal,
|
|
|
+static int journal_submit_data_buffers(journal_t *journal,
|
|
|
transaction_t *commit_transaction)
|
|
|
{
|
|
|
struct journal_head *jh;
|
|
@@ -193,6 +193,7 @@ static void journal_submit_data_buffers(journal_t *journal,
|
|
|
int locked;
|
|
|
int bufs = 0;
|
|
|
struct buffer_head **wbuf = journal->j_wbuf;
|
|
|
+ int err = 0;
|
|
|
|
|
|
/*
|
|
|
* Whenever we unlock the journal and sleep, things can get added
|
|
@@ -266,6 +267,8 @@ write_out_data:
|
|
|
put_bh(bh);
|
|
|
} else {
|
|
|
BUFFER_TRACE(bh, "writeout complete: unfile");
|
|
|
+ if (unlikely(!buffer_uptodate(bh)))
|
|
|
+ err = -EIO;
|
|
|
__journal_unfile_buffer(jh);
|
|
|
jbd_unlock_bh_state(bh);
|
|
|
if (locked)
|
|
@@ -284,6 +287,8 @@ write_out_data:
|
|
|
}
|
|
|
spin_unlock(&journal->j_list_lock);
|
|
|
journal_do_submit_data(wbuf, bufs);
|
|
|
+
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -423,8 +428,7 @@ void journal_commit_transaction(journal_t *journal)
|
|
|
* Now start flushing things to disk, in the order they appear
|
|
|
* on the transaction lists. Data blocks go first.
|
|
|
*/
|
|
|
- err = 0;
|
|
|
- journal_submit_data_buffers(journal, commit_transaction);
|
|
|
+ err = journal_submit_data_buffers(journal, commit_transaction);
|
|
|
|
|
|
/*
|
|
|
* Wait for all previously submitted IO to complete.
|
|
@@ -439,10 +443,21 @@ void journal_commit_transaction(journal_t *journal)
|
|
|
if (buffer_locked(bh)) {
|
|
|
spin_unlock(&journal->j_list_lock);
|
|
|
wait_on_buffer(bh);
|
|
|
- if (unlikely(!buffer_uptodate(bh)))
|
|
|
- err = -EIO;
|
|
|
spin_lock(&journal->j_list_lock);
|
|
|
}
|
|
|
+ if (unlikely(!buffer_uptodate(bh))) {
|
|
|
+ if (TestSetPageLocked(bh->b_page)) {
|
|
|
+ spin_unlock(&journal->j_list_lock);
|
|
|
+ lock_page(bh->b_page);
|
|
|
+ spin_lock(&journal->j_list_lock);
|
|
|
+ }
|
|
|
+ if (bh->b_page->mapping)
|
|
|
+ set_bit(AS_EIO, &bh->b_page->mapping->flags);
|
|
|
+
|
|
|
+ unlock_page(bh->b_page);
|
|
|
+ SetPageError(bh->b_page);
|
|
|
+ err = -EIO;
|
|
|
+ }
|
|
|
if (!inverted_lock(journal, bh)) {
|
|
|
put_bh(bh);
|
|
|
spin_lock(&journal->j_list_lock);
|
|
@@ -461,8 +476,14 @@ void journal_commit_transaction(journal_t *journal)
|
|
|
}
|
|
|
spin_unlock(&journal->j_list_lock);
|
|
|
|
|
|
- if (err)
|
|
|
- journal_abort(journal, err);
|
|
|
+ if (err) {
|
|
|
+ char b[BDEVNAME_SIZE];
|
|
|
+
|
|
|
+ printk(KERN_WARNING
|
|
|
+ "JBD: Detected IO errors while flushing file data "
|
|
|
+ "on %s\n", bdevname(journal->j_fs_dev, b));
|
|
|
+ err = 0;
|
|
|
+ }
|
|
|
|
|
|
journal_write_revoke_records(journal, commit_transaction);
|
|
|
|