Skip to content

Commit

Permalink
jbd: don't abort if flushing file data failed
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Hidehiro Kawai authored and Linus Torvalds committed Jul 25, 2008
1 parent 8ef2720 commit cbe5f46
Showing 1 changed file with 28 additions and 7 deletions.
35 changes: 28 additions & 7 deletions fs/jbd/commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,14 +185,15 @@ 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;
struct buffer_head *bh;
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
Expand Down Expand Up @@ -266,6 +267,8 @@ static void journal_submit_data_buffers(journal_t *journal,
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)
Expand All @@ -284,6 +287,8 @@ static void journal_submit_data_buffers(journal_t *journal,
}
spin_unlock(&journal->j_list_lock);
journal_do_submit_data(wbuf, bufs);

return err;
}

/*
Expand Down Expand Up @@ -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.
Expand All @@ -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);
Expand All @@ -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);

Expand Down

0 comments on commit cbe5f46

Please sign in to comment.