From nobody Fri Dec 19 09:51:30 2025 Received: from szxga04-in.huawei.com (szxga04-in.huawei.com [45.249.212.190]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 846213A1A0; Mon, 18 Dec 2023 14:14:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.162.112]) by szxga04-in.huawei.com (SkyGuard) with ESMTP id 4Sv1yW1C8Zz29g8n; Mon, 18 Dec 2023 22:13:39 +0800 (CST) Received: from dggpeml500021.china.huawei.com (unknown [7.185.36.21]) by mail.maildlp.com (Postfix) with ESMTPS id 29BC91402D0; Mon, 18 Dec 2023 22:14:51 +0800 (CST) Received: from huawei.com (10.175.127.227) by dggpeml500021.china.huawei.com (7.185.36.21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35; Mon, 18 Dec 2023 22:14:50 +0800 From: Baokun Li To: CC: , , , , , , , , , Wei Chen , xingwei lee , Subject: [PATCH 1/4] ext4: fix double-free of blocks due to wrong extents moved_len Date: Mon, 18 Dec 2023 22:18:11 +0800 Message-ID: <20231218141814.1477338-2-libaokun1@huawei.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20231218141814.1477338-1-libaokun1@huawei.com> References: <20231218141814.1477338-1-libaokun1@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: dggems706-chm.china.huawei.com (10.3.19.183) To dggpeml500021.china.huawei.com (7.185.36.21) Content-Type: text/plain; charset="utf-8" In ext4_move_extents(), moved_len is only updated when all moves are successfully executed, and only discards orig_inode and donor_inode preallocations when moved_len is not zero. When the loop fails to exit after successfully moving some extents, moved_len is not updated and remains at 0, so it does not discard the preallocations. If the moved extents overlap with the preallocated extents, the overlapped extents are freed twice in ext4_mb_release_inode_pa() and ext4_process_freed_data() (as described in commit 94d7c16cbbbd), and bb_free is incremented twice. Hence when trim is executed, a zero-division bug is triggered in mb_update_avg_fragment_size() because bb_free is not zero and bb_fragments is zero. Therefore, update move_len after each extent move to avoid the issue. Reported-by: Wei Chen Reported-by: xingwei lee Closes: https://lore.kernel.org/r/CAO4mrferzqBUnCag8R3m2zf897ts9UEuhjFQGPtO= DT92rYyR2Q@mail.gmail.com Fixes: fcf6b1b729bc ("ext4: refactor ext4_move_extents code base") CC: stable@vger.kernel.org # 3.18 Signed-off-by: Baokun Li --- fs/ext4/move_extent.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index 3aa57376d9c2..4b9b503c6346 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c @@ -672,7 +672,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_f= ilp, __u64 orig_blk, */ ext4_double_up_write_data_sem(orig_inode, donor_inode); /* Swap original branches with new branches */ - move_extent_per_page(o_filp, donor_inode, + *moved_len +=3D move_extent_per_page(o_filp, donor_inode, orig_page_index, donor_page_index, offset_in_page, cur_len, unwritten, &ret); @@ -682,7 +682,6 @@ ext4_move_extents(struct file *o_filp, struct file *d_f= ilp, __u64 orig_blk, o_start +=3D cur_len; d_start +=3D cur_len; } - *moved_len =3D o_start - orig_blk; if (*moved_len > len) *moved_len =3D len; =20 --=20 2.31.1 From nobody Fri Dec 19 09:51:30 2025 Received: from szxga06-in.huawei.com (szxga06-in.huawei.com [45.249.212.32]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E84583A1A0; Mon, 18 Dec 2023 14:14:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.162.112]) by szxga06-in.huawei.com (SkyGuard) with ESMTP id 4Sv1zn3y22z2mGxV; Mon, 18 Dec 2023 22:14:45 +0800 (CST) Received: from dggpeml500021.china.huawei.com (unknown [7.185.36.21]) by mail.maildlp.com (Postfix) with ESMTPS id B7C141402D0; Mon, 18 Dec 2023 22:14:51 +0800 (CST) Received: from huawei.com (10.175.127.227) by dggpeml500021.china.huawei.com (7.185.36.21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35; Mon, 18 Dec 2023 22:14:51 +0800 From: Baokun Li To: CC: , , , , , , , , Subject: [PATCH 2/4] ext4: do not trim the group with corrupted block bitmap Date: Mon, 18 Dec 2023 22:18:12 +0800 Message-ID: <20231218141814.1477338-3-libaokun1@huawei.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20231218141814.1477338-1-libaokun1@huawei.com> References: <20231218141814.1477338-1-libaokun1@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: dggems706-chm.china.huawei.com (10.3.19.183) To dggpeml500021.china.huawei.com (7.185.36.21) Content-Type: text/plain; charset="utf-8" Otherwise operating on an incorrupted block bitmap can lead to all sorts of unknown problems. Signed-off-by: Baokun Li Reviewed-by: Jan Kara --- fs/ext4/mballoc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index d72b5e3c92ec..a95fa6e2b0f9 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -6757,6 +6757,9 @@ __releases(ext4_group_lock_ptr(sb, e4b->bd_group)) bool set_trimmed =3D false; void *bitmap; =20 + if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(e4b->bd_info))) + return 0; + bitmap =3D e4b->bd_bitmap; if (start =3D=3D 0 && max >=3D ext4_last_grp_cluster(sb, e4b->bd_group)) set_trimmed =3D true; --=20 2.31.1 From nobody Fri Dec 19 09:51:30 2025 Received: from szxga03-in.huawei.com (szxga03-in.huawei.com [45.249.212.189]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AAB4E3A1A9; Mon, 18 Dec 2023 14:14:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.88.194]) by szxga03-in.huawei.com (SkyGuard) with ESMTP id 4Sv1zg1CjNzMnxK; Mon, 18 Dec 2023 22:14:39 +0800 (CST) Received: from dggpeml500021.china.huawei.com (unknown [7.185.36.21]) by mail.maildlp.com (Postfix) with ESMTPS id 3F89014040D; Mon, 18 Dec 2023 22:14:52 +0800 (CST) Received: from huawei.com (10.175.127.227) by dggpeml500021.china.huawei.com (7.185.36.21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35; Mon, 18 Dec 2023 22:14:51 +0800 From: Baokun Li To: CC: , , , , , , , , , Subject: [PATCH 3/4] ext4: avoid bb_free and bb_fragments inconsistency in mb_free_blocks() Date: Mon, 18 Dec 2023 22:18:13 +0800 Message-ID: <20231218141814.1477338-4-libaokun1@huawei.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20231218141814.1477338-1-libaokun1@huawei.com> References: <20231218141814.1477338-1-libaokun1@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: dggems706-chm.china.huawei.com (10.3.19.183) To dggpeml500021.china.huawei.com (7.185.36.21) Content-Type: text/plain; charset="utf-8" After updating bb_free in mb_free_blocks, it is possible to return without updating bb_fragments because the block being freed is found to have already been freed, which leads to inconsistency between bb_free and bb_fragments. Since the group may be unlocked in ext4_grp_locked_error(), this can lead to problems such as dividing by zero when calculating the average fragment length. Therefore, to ensure consistency, move the update of bb_free to after the block double-free check. Fixes: eabe0444df90 ("ext4: speed-up releasing blocks on commit") CC: stable@vger.kernel.org # 3.10 Signed-off-by: Baokun Li --- fs/ext4/mballoc.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index a95fa6e2b0f9..2fbee0f0f5c3 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -1892,11 +1892,6 @@ static void mb_free_blocks(struct inode *inode, stru= ct ext4_buddy *e4b, mb_check_buddy(e4b); mb_free_blocks_double(inode, e4b, first, count); =20 - this_cpu_inc(discard_pa_seq); - e4b->bd_info->bb_free +=3D count; - if (first < e4b->bd_info->bb_first_free) - e4b->bd_info->bb_first_free =3D first; - /* access memory sequentially: check left neighbour, * clear range and then check right neighbour */ @@ -1922,9 +1917,14 @@ static void mb_free_blocks(struct inode *inode, stru= ct ext4_buddy *e4b, sb, e4b->bd_group, EXT4_GROUP_INFO_BBITMAP_CORRUPT); } - goto done; + return; } =20 + this_cpu_inc(discard_pa_seq); + e4b->bd_info->bb_free +=3D count; + if (first < e4b->bd_info->bb_first_free) + e4b->bd_info->bb_first_free =3D first; + /* let's maintain fragments counter */ if (left_is_free && right_is_free) e4b->bd_info->bb_fragments--; @@ -1949,7 +1949,6 @@ static void mb_free_blocks(struct inode *inode, struc= t ext4_buddy *e4b, if (first <=3D last) mb_buddy_mark_free(e4b, first >> 1, last >> 1); =20 -done: mb_set_largest_free_order(sb, e4b->bd_info); mb_update_avg_fragment_size(sb, e4b->bd_info); mb_check_buddy(e4b); --=20 2.31.1 From nobody Fri Dec 19 09:51:30 2025 Received: from szxga01-in.huawei.com (szxga01-in.huawei.com [45.249.212.187]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EBB1A37885; Mon, 18 Dec 2023 14:14:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.163.252]) by szxga01-in.huawei.com (SkyGuard) with ESMTP id 4Sv1yw2hqrzYsp5; Mon, 18 Dec 2023 22:14:00 +0800 (CST) Received: from dggpeml500021.china.huawei.com (unknown [7.185.36.21]) by mail.maildlp.com (Postfix) with ESMTPS id CA832180087; Mon, 18 Dec 2023 22:14:52 +0800 (CST) Received: from huawei.com (10.175.127.227) by dggpeml500021.china.huawei.com (7.185.36.21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35; Mon, 18 Dec 2023 22:14:52 +0800 From: Baokun Li To: CC: , , , , , , , , , Subject: [PATCH 4/4] ext4: avoid dividing by 0 in mb_update_avg_fragment_size() when block bitmap corrupt Date: Mon, 18 Dec 2023 22:18:14 +0800 Message-ID: <20231218141814.1477338-5-libaokun1@huawei.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20231218141814.1477338-1-libaokun1@huawei.com> References: <20231218141814.1477338-1-libaokun1@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: dggems706-chm.china.huawei.com (10.3.19.183) To dggpeml500021.china.huawei.com (7.185.36.21) Content-Type: text/plain; charset="utf-8" When bb_free is not 0 but bb_fragments is 0, return directly to avoid system crash due to division by zero. Fixes: 83e80a6e3543 ("ext4: use buckets for cr 1 block scan instead of rbtr= ee") CC: stable@vger.kernel.org Signed-off-by: Baokun Li --- fs/ext4/mballoc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 2fbee0f0f5c3..e2a167240335 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -845,6 +845,9 @@ mb_update_avg_fragment_size(struct super_block *sb, str= uct ext4_group_info *grp) if (!test_opt2(sb, MB_OPTIMIZE_SCAN) || grp->bb_free =3D=3D 0) return; =20 + if (unlikely(grp->bb_fragments =3D=3D 0)) + return; + new_order =3D mb_avg_fragment_size_order(sb, grp->bb_free / grp->bb_fragments); if (new_order =3D=3D grp->bb_avg_fragment_size_order) --=20 2.31.1