From: Baokun Li <libaokun1@huawei.com>
To: <linux-ext4@vger.kernel.org>
Cc: <tytso@mit.edu>, <adilger.kernel@dilger.ca>, <jack@suse.cz>,
<ritesh.list@gmail.com>, <lczerner@redhat.com>,
<enwlinux@gmail.com>, <linux-kernel@vger.kernel.org>,
<yi.zhang@huawei.com>, <yebin10@huawei.com>, <yukuai3@huawei.com>,
<libaokun1@huawei.com>
Subject: [PATCH 2/2] ext4: add inode table check in __ext4_get_inode_loc to aovid possible infinite loop
Date: Wed, 17 Aug 2022 21:27:01 +0800 [thread overview]
Message-ID: <20220817132701.3015912-3-libaokun1@huawei.com> (raw)
In-Reply-To: <20220817132701.3015912-1-libaokun1@huawei.com>
In do_writepages, if the value returned by ext4_writepages is "-ENOMEM"
and "wbc->sync_mode == WB_SYNC_ALL", retry until the condition is not met.
In __ext4_get_inode_loc, if the bh returned by sb_getblk is NULL,
the function returns -ENOMEM.
In __getblk_slow, if the return value of grow_buffers is less than 0,
the function returns NULL.
When the three processes are connected in series like the following stack,
an infinite loop may occur:
do_writepages <--- keep retrying
ext4_writepages
mpage_map_and_submit_extent
mpage_map_one_extent
ext4_map_blocks
ext4_ext_map_blocks
ext4_ext_handle_unwritten_extents
ext4_ext_convert_to_initialized
ext4_split_extent
ext4_split_extent_at
__ext4_ext_dirty
__ext4_mark_inode_dirty
ext4_reserve_inode_write
ext4_get_inode_loc
__ext4_get_inode_loc <--- return -ENOMEM
sb_getblk
__getblk_gfp
__getblk_slow <--- return NULL
grow_buffers
grow_dev_page <--- return -ENXIO
ret = (block < end_block) ? 1 : -ENXIO;
In this issue, bg_inode_table_hi is overwritten as an incorrect value.
As a result, `block < end_block` cannot be met in grow_dev_page.
Therefore, __ext4_get_inode_loc always returns '-ENOMEM' and do_writepages
keeps retrying. As a result, the writeback process is in the D state due
to an infinite loop.
Add a check on inode table block in the __ext4_get_inode_loc function by
referring to ext4_read_inode_bitmap to avoid this infinite loop.
Signed-off-by: Baokun Li <libaokun1@huawei.com>
---
fs/ext4/inode.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 601214453c3a..5e171879fa23 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -4466,9 +4466,17 @@ static int __ext4_get_inode_loc(struct super_block *sb, unsigned long ino,
inodes_per_block = EXT4_SB(sb)->s_inodes_per_block;
inode_offset = ((ino - 1) %
EXT4_INODES_PER_GROUP(sb));
- block = ext4_inode_table(sb, gdp) + (inode_offset / inodes_per_block);
iloc->offset = (inode_offset % inodes_per_block) * EXT4_INODE_SIZE(sb);
+ block = ext4_inode_table(sb, gdp);
+ if ((block <= le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block)) ||
+ (block >= ext4_blocks_count(EXT4_SB(sb)->s_es))) {
+ ext4_error(sb, "Invalid inode table block %llu in "
+ "block_group %u", block, iloc->block_group);
+ return -EFSCORRUPTED;
+ }
+ block += (inode_offset / inodes_per_block);
+
bh = sb_getblk(sb, block);
if (unlikely(!bh))
return -ENOMEM;
--
2.31.1
next prev parent reply other threads:[~2022-08-17 13:16 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-08-17 13:26 [PATCH 0/2] ext4: fix a infinite loop in do_writepages after online resizing Baokun Li
2022-08-17 13:27 ` [PATCH 1/2] ext4: fix GDT corruption after online resizing with bigalloc enable and blocksize is 1024 Baokun Li
2022-08-17 13:27 ` Baokun Li [this message]
2022-08-17 14:31 ` [PATCH 2/2] ext4: add inode table check in __ext4_get_inode_loc to aovid possible infinite loop Jan Kara
2022-08-18 1:54 ` Baokun Li
2022-08-18 14:43 ` Ritesh Harjani (IBM)
2022-08-18 17:23 ` Jan Kara
2022-08-18 23:15 ` Ritesh Harjani (IBM)
2022-08-19 8:44 ` Jan Kara
2022-11-28 20:44 ` Theodore Ts'o
2022-11-29 8:54 ` Ritesh Harjani (IBM)
2022-11-29 21:12 ` [PATCH 0/2] ext4: fix a infinite loop in do_writepages after online resizing Theodore Ts'o
2022-11-30 2:08 ` Baokun Li
2022-12-01 3:42 ` Theodore Ts'o
2022-12-01 6:26 ` Baokun Li
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=20220817132701.3015912-3-libaokun1@huawei.com \
--to=libaokun1@huawei.com \
--cc=adilger.kernel@dilger.ca \
--cc=enwlinux@gmail.com \
--cc=jack@suse.cz \
--cc=lczerner@redhat.com \
--cc=linux-ext4@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=ritesh.list@gmail.com \
--cc=tytso@mit.edu \
--cc=yebin10@huawei.com \
--cc=yi.zhang@huawei.com \
--cc=yukuai3@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.