| From 1a41e5bca22953cfed047234ba0958e51dce220f Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Sat, 20 Jun 2020 10:54:26 +0800 |
| Subject: jbd2: abort journal if free a async write error metadata buffer |
| |
| From: zhangyi (F) <yi.zhang@huawei.com> |
| |
| [ Upstream commit c044f3d8360d2ecf831ba2cc9f08cf9fb2c699fb ] |
| |
| If we free a metadata buffer which has been failed to async write out |
| in the background, the jbd2 checkpoint procedure will not detect this |
| failure in jbd2_log_do_checkpoint(), so it may lead to filesystem |
| inconsistency after cleanup journal tail. This patch abort the journal |
| if free a buffer has write_io_error flag to prevent potential further |
| inconsistency. |
| |
| Signed-off-by: zhangyi (F) <yi.zhang@huawei.com> |
| Link: https://lore.kernel.org/r/20200620025427.1756360-5-yi.zhang@huawei.com |
| Signed-off-by: Theodore Ts'o <tytso@mit.edu> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| fs/jbd2/transaction.c | 16 ++++++++++++++++ |
| 1 file changed, 16 insertions(+) |
| |
| diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c |
| index 1478512ecab3e..cfbf5474bccab 100644 |
| --- a/fs/jbd2/transaction.c |
| +++ b/fs/jbd2/transaction.c |
| @@ -1990,6 +1990,7 @@ int jbd2_journal_try_to_free_buffers(journal_t *journal, |
| { |
| struct buffer_head *head; |
| struct buffer_head *bh; |
| + bool has_write_io_error = false; |
| int ret = 0; |
| |
| J_ASSERT(PageLocked(page)); |
| @@ -2014,11 +2015,26 @@ int jbd2_journal_try_to_free_buffers(journal_t *journal, |
| jbd_unlock_bh_state(bh); |
| if (buffer_jbd(bh)) |
| goto busy; |
| + |
| + /* |
| + * If we free a metadata buffer which has been failed to |
| + * write out, the jbd2 checkpoint procedure will not detect |
| + * this failure and may lead to filesystem inconsistency |
| + * after cleanup journal tail. |
| + */ |
| + if (buffer_write_io_error(bh)) { |
| + pr_err("JBD2: Error while async write back metadata bh %llu.", |
| + (unsigned long long)bh->b_blocknr); |
| + has_write_io_error = true; |
| + } |
| } while ((bh = bh->b_this_page) != head); |
| |
| ret = try_to_free_buffers(page); |
| |
| busy: |
| + if (has_write_io_error) |
| + jbd2_journal_abort(journal, -EIO); |
| + |
| return ret; |
| } |
| |
| -- |
| 2.25.1 |
| |