From patchwork Tue Jul 6 13:36:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Colin Ian King X-Patchwork-Id: 1501251 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4GK3VK41bsz9s5R; Tue, 6 Jul 2021 23:36:09 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1m0lF7-0006ZQ-6S; Tue, 06 Jul 2021 13:36:05 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1m0lF5-0006YT-2F for kernel-team@lists.ubuntu.com; Tue, 06 Jul 2021 13:36:03 +0000 Received: from 1.general.cking.uk.vpn ([10.172.193.212] helo=localhost) by youngberry.canonical.com with esmtpsa (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.93) (envelope-from ) id 1m0lF4-0006c8-QR; Tue, 06 Jul 2021 13:36:02 +0000 From: Colin King To: kernel-team@lists.ubuntu.com Subject: [PATCH][UBUNTU][SAUCE][SRU][B/F/G/H/I] ext4: fix directory index node split corruption Date: Tue, 6 Jul 2021 14:36:02 +0100 Message-Id: <20210706133602.30706-2-colin.king@canonical.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210706133602.30706-1-colin.king@canonical.com> References: <20210706133602.30706-1-colin.king@canonical.com> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Colin Ian King BugLink: https://bugs.launchpad.net/bugs/1933074 [ Note: This was originally sent upstream to linux-ext4@vger.kernel.org and Ted Tso but didn't seem to make it to the list, presumably as it was marked as SPAM See: http://www.voxelsoft.com/2021/ext4_large_dir_corruption.html ] Following commit b5776e7, a trivial sequential write of empty files to an empty ext4 file system (with large_dir enabled) fails after just over 26 million files. Depending on luck, file creation will give error EEXIST or EUCLEAN. Commit b5776e7 fixed the no-restart condition so that ext4_handle_dirty_dx_node is always called, but it also broke the restart condition. This is because when restart=1, the original implementation correctly skipped do_split() but b5776e7 clobbered the "if(restart)goto journal_error;" logic. This complementary change protects do_split() from restart condition, making it safe from both current and future ordering of goto statements in earlier sections of the code. Tested on 5.11.20 with handy testing script: i = 0 while i <= 32000000: print (i) with open('tmpmnt/%d' % i, 'wb') as fout: i += 1 Google-Bug-Id: 176345532 Fixes: b5776e7 ("ext4: fix potential htree index checksum corruption") Fixes: e08ac99 ("ext4: add largedir feature") Signed-off-by: denis@voxelsoft.com Signed-off-by: Colin Ian King Acked-by: Dimitri John Ledkov Acked-by: Stefan Bader --- fs/ext4/namei.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 4c37abe..9ad5cc6 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -2432,13 +2432,15 @@ static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname, goto journal_error; } } - de = do_split(handle, dir, &bh, frame, &fname->hinfo); - if (IS_ERR(de)) { - err = PTR_ERR(de); + if (!restart) { + de = do_split(handle, dir, &bh, frame, &fname->hinfo); + if (IS_ERR(de)) { + err = PTR_ERR(de); + goto cleanup; + } + err = add_dirent_to_buf(handle, fname, dir, inode, de, bh); goto cleanup; } - err = add_dirent_to_buf(handle, fname, dir, inode, de, bh); - goto cleanup; journal_error: ext4_std_error(dir->i_sb, err); /* this is a no-op if err == 0 */