mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
8ef2720397
commit
cbe5f466f6
|
@ -185,7 +185,7 @@ static void journal_do_submit_data(struct buffer_head **wbuf, int bufs)
|
||||||
/*
|
/*
|
||||||
* Submit all the data buffers to disk
|
* 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)
|
transaction_t *commit_transaction)
|
||||||
{
|
{
|
||||||
struct journal_head *jh;
|
struct journal_head *jh;
|
||||||
|
@ -193,6 +193,7 @@ static void journal_submit_data_buffers(journal_t *journal,
|
||||||
int locked;
|
int locked;
|
||||||
int bufs = 0;
|
int bufs = 0;
|
||||||
struct buffer_head **wbuf = journal->j_wbuf;
|
struct buffer_head **wbuf = journal->j_wbuf;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Whenever we unlock the journal and sleep, things can get added
|
* Whenever we unlock the journal and sleep, things can get added
|
||||||
|
@ -266,6 +267,8 @@ static void journal_submit_data_buffers(journal_t *journal,
|
||||||
put_bh(bh);
|
put_bh(bh);
|
||||||
} else {
|
} else {
|
||||||
BUFFER_TRACE(bh, "writeout complete: unfile");
|
BUFFER_TRACE(bh, "writeout complete: unfile");
|
||||||
|
if (unlikely(!buffer_uptodate(bh)))
|
||||||
|
err = -EIO;
|
||||||
__journal_unfile_buffer(jh);
|
__journal_unfile_buffer(jh);
|
||||||
jbd_unlock_bh_state(bh);
|
jbd_unlock_bh_state(bh);
|
||||||
if (locked)
|
if (locked)
|
||||||
|
@ -284,6 +287,8 @@ static void journal_submit_data_buffers(journal_t *journal,
|
||||||
}
|
}
|
||||||
spin_unlock(&journal->j_list_lock);
|
spin_unlock(&journal->j_list_lock);
|
||||||
journal_do_submit_data(wbuf, bufs);
|
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
|
* Now start flushing things to disk, in the order they appear
|
||||||
* on the transaction lists. Data blocks go first.
|
* on the transaction lists. Data blocks go first.
|
||||||
*/
|
*/
|
||||||
err = 0;
|
err = journal_submit_data_buffers(journal, commit_transaction);
|
||||||
journal_submit_data_buffers(journal, commit_transaction);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wait for all previously submitted IO to complete.
|
* Wait for all previously submitted IO to complete.
|
||||||
|
@ -439,10 +443,21 @@ void journal_commit_transaction(journal_t *journal)
|
||||||
if (buffer_locked(bh)) {
|
if (buffer_locked(bh)) {
|
||||||
spin_unlock(&journal->j_list_lock);
|
spin_unlock(&journal->j_list_lock);
|
||||||
wait_on_buffer(bh);
|
wait_on_buffer(bh);
|
||||||
if (unlikely(!buffer_uptodate(bh)))
|
|
||||||
err = -EIO;
|
|
||||||
spin_lock(&journal->j_list_lock);
|
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)) {
|
if (!inverted_lock(journal, bh)) {
|
||||||
put_bh(bh);
|
put_bh(bh);
|
||||||
spin_lock(&journal->j_list_lock);
|
spin_lock(&journal->j_list_lock);
|
||||||
|
@ -461,8 +476,14 @@ void journal_commit_transaction(journal_t *journal)
|
||||||
}
|
}
|
||||||
spin_unlock(&journal->j_list_lock);
|
spin_unlock(&journal->j_list_lock);
|
||||||
|
|
||||||
if (err)
|
if (err) {
|
||||||
journal_abort(journal, 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);
|
journal_write_revoke_records(journal, commit_transaction);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue