linux-ext4.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "zhangyi (F)" <yi.zhang@huawei.com>
To: <linux-ext4@vger.kernel.org>
Cc: <tytso@mit.edu>, <jack@suse.cz>, <adilger.kernel@dilger.ca>,
	<yi.zhang@huawei.com>, <zhangxiaoxu5@huawei.com>
Subject: [PATCH 09/10] ext4: abort the filesystem while freeing the write error io buffer
Date: Tue, 26 May 2020 15:17:53 +0800	[thread overview]
Message-ID: <20200526071754.33819-10-yi.zhang@huawei.com> (raw)
In-Reply-To: <20200526071754.33819-1-yi.zhang@huawei.com>

Now we can prevent reading old metadata buffer from the disk which has
been failed to write out through checking write io error when getting
the buffer. One more thing need to do is to prevent freeing the write
io error buffer. If the buffer was freed, we lose the latest data and
buffer stats, finally it will also lead to inconsistency.

So, this patch abort the journal in journal mode and invoke
ext4_error_err() in nojournal mode to prevent further inconsistency.

Signed-off-by: zhangyi (F) <yi.zhang@huawei.com>
---
 fs/ext4/super.c       | 32 +++++++++++++++++++++++++++++++-
 fs/jbd2/transaction.c | 13 +++++++++++++
 2 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index d25a0fe44bec..1e15179aa1c4 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1349,6 +1349,36 @@ static int ext4_nfs_commit_metadata(struct inode *inode)
 	return ext4_write_inode(inode, &wbc);
 }
 
+static int bdev_try_to_free_buffer(struct super_block *sb, struct page *page)
+{
+	struct buffer_head *head, *bh;
+	bool has_write_io_error = false;
+
+	head = page_buffers(page);
+	bh = head;
+	do {
+		/*
+		 * If the buffer has been failed to write out, the metadata
+		 * in this buffer is uptodate but which on disk is old, may
+		 * lead to inconsistency while reading the old data
+		 * successfully.
+		 */
+		if (buffer_write_io_error(bh) && !buffer_uptodate(bh)) {
+			has_write_io_error = true;
+			break;
+		}
+	} while ((bh = bh->b_this_page) != head);
+
+	if (has_write_io_error)
+		ext4_error_err(sb, EIO, "Free metadata buffer (%llu) that has "
+			       "been failed to write out. There is a risk of "
+			       "filesystem inconsistency in case of reading "
+			       "metadata from this block subsequently.",
+			       (unsigned long long) bh->b_blocknr);
+
+	return try_to_free_buffers(page);
+}
+
 /*
  * Try to release metadata pages (indirect blocks, directories) which are
  * mapped via the block device.  Since these pages could have journal heads
@@ -1366,7 +1396,7 @@ static int bdev_try_to_free_page(struct super_block *sb, struct page *page,
 	if (journal)
 		return jbd2_journal_try_to_free_buffers(journal, page,
 						wait & ~__GFP_DIRECT_RECLAIM);
-	return try_to_free_buffers(page);
+	return bdev_try_to_free_buffer(sb, page);
 }
 
 #ifdef CONFIG_FS_ENCRYPTION
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index 3dccc23cf010..ac6a077afec3 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -2109,6 +2109,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));
@@ -2133,11 +2134,23 @@ int jbd2_journal_try_to_free_buffers(journal_t *journal,
 		jbd2_journal_put_journal_head(jh);
 		if (buffer_jbd(bh))
 			goto busy;
+
+		/*
+		 * If the buffer has been failed to write out, the metadata
+		 * in this buffer is uptodate but which on disk is old,
+		 * abort journal to prevent subsequent inconsistency while
+		 * reading the old data successfully.
+		 */
+		if (buffer_write_io_error(bh) && !buffer_uptodate(bh))
+			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.21.3


  parent reply	other threads:[~2020-05-26  7:19 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-26  7:17 [PATCH 00/10] ext4: fix inconsistency since reading old metadata from disk zhangyi (F)
2020-05-26  7:17 ` [PATCH 01/10] ext4: move inode eio simulation behind io completeion zhangyi (F)
2020-05-26  7:17 ` [PATCH 02/10] fs: pick out ll_rw_one_block() helper function zhangyi (F)
2020-05-28  5:07   ` Christoph Hellwig
2020-05-28 13:23     ` zhangyi (F)
2020-05-26  7:17 ` [PATCH 03/10] ext4: add ext4_sb_getblk*() wrapper functions zhangyi (F)
2020-05-26  7:17 ` [PATCH 04/10] ext4: replace sb_getblk() with ext4_sb_getblk_locked() zhangyi (F)
2020-05-26  7:17 ` [PATCH 05/10] ext4: replace sb_bread*() with ext4_sb_bread*() zhangyi (F)
2020-05-26  7:17 ` [PATCH 06/10] ext4: replace sb_getblk() with ext4_sb_getblk() zhangyi (F)
2020-05-26  7:17 ` [PATCH 07/10] ext4: switch to use ext4_sb_getblk_locked() in ext4_getblk() zhangyi (F)
2020-05-26  7:17 ` [PATCH 08/10] ext4: replace sb_breadahead() with ext4_sb_breadahead() zhangyi (F)
2020-05-26  7:17 ` zhangyi (F) [this message]
2020-05-26  7:17 ` [PATCH 10/10] ext4: remove unused parameter in jbd2_journal_try_to_free_buffers() zhangyi (F)
2020-06-08  3:32 ` [PATCH 00/10] ext4: fix inconsistency since reading old metadata from disk zhangyi (F)
2020-06-08  8:20 ` Jan Kara
2020-06-08 14:39   ` zhangyi (F)
2020-06-09 12:19     ` Jan Kara
2020-06-10  8:55       ` zhangyi (F)
2020-06-10  9:57         ` Jan Kara
2020-06-10 15:45           ` Theodore Y. Ts'o
2020-06-10 16:27             ` Jan Kara
2020-06-11  2:12               ` zhangyi (F)
2020-06-11  8:21                 ` Jan Kara
2020-06-11 16:55                   ` Theodore Y. Ts'o
2020-06-12 11:13                     ` zhangyi (F)

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200526071754.33819-10-yi.zhang@huawei.com \
    --to=yi.zhang@huawei.com \
    --cc=adilger.kernel@dilger.ca \
    --cc=jack@suse.cz \
    --cc=linux-ext4@vger.kernel.org \
    --cc=tytso@mit.edu \
    --cc=zhangxiaoxu5@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).