From patchwork Tue Jan 31 06:15:40 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Theodore Ts'o X-Patchwork-Id: 1734558 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=ozlabs.org (client-ip=2404:9400:2221:ea00::3; helo=gandalf.ozlabs.org; envelope-from=srs0=qszb=54=vger.kernel.org=linux-ext4-owner@ozlabs.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=mit.edu header.i=@mit.edu header.a=rsa-sha256 header.s=outgoing header.b=fhbcU8fP; dkim-atps=neutral Received: from gandalf.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4P5ZYp41Nfz23hg for ; Tue, 31 Jan 2023 17:16:14 +1100 (AEDT) Received: from gandalf.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3]) by gandalf.ozlabs.org (Postfix) with ESMTP id 4P5ZYn6M0nz4xwq for ; Tue, 31 Jan 2023 17:16:13 +1100 (AEDT) Received: by gandalf.ozlabs.org (Postfix) id 4P5ZYn6Flvz4xwy; Tue, 31 Jan 2023 17:16:13 +1100 (AEDT) Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: gandalf.ozlabs.org; dmarc=fail (p=none dis=none) header.from=mit.edu Authentication-Results: gandalf.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=2620:137:e000::1:20; helo=out1.vger.email; envelope-from=linux-ext4-owner@vger.kernel.org; receiver=) Authentication-Results: gandalf.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=mit.edu header.i=@mit.edu header.a=rsa-sha256 header.s=outgoing header.b=fhbcU8fP; dkim-atps=neutral Received: from out1.vger.email (out1.vger.email [IPv6:2620:137:e000::1:20]) by gandalf.ozlabs.org (Postfix) with ESMTP id 4P5ZYn0qDDz4xwq for ; Tue, 31 Jan 2023 17:16:13 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229588AbjAaGQL (ORCPT ); Tue, 31 Jan 2023 01:16:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55810 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230137AbjAaGQJ (ORCPT ); Tue, 31 Jan 2023 01:16:09 -0500 Received: from outgoing.mit.edu (outgoing-auth-1.mit.edu [18.9.28.11]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B6FD53BDBA for ; Mon, 30 Jan 2023 22:16:01 -0800 (PST) Received: from cwcc.thunk.org (pool-173-48-120-46.bstnma.fios.verizon.net [173.48.120.46]) (authenticated bits=0) (User authenticated as tytso@ATHENA.MIT.EDU) by outgoing.mit.edu (8.14.7/8.12.4) with ESMTP id 30V6FlAu024382 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 31 Jan 2023 01:15:49 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mit.edu; s=outgoing; t=1675145749; bh=kZvJHUTIUyHJrXL19dTYGYTlG0sjPmkge1I/9CEBrug=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=fhbcU8fPtHhDUgc7mfzxt/GIA+RZvMWdNV34Fq+JsYiVla3MithM5t4nRL9Hqy/Uw pABy/rLbVmPgywAR5ICHP4zMBnvXY7xvcbttTEt7UNmexAvOwB0xQoJfqhlq9uK0to nYY5aGf8SE6TbzidF0tL5KcPtZvn69YTXA3IrnuB8yDGwV7PhB3c68JHaqlNGbFOqj VvgrcebTzLaSboMLf64AUY1d46+6lQMAAqyEUSJf2dJg9KWJXmb+GiS0/Y8hv8X2QL X5+fT3H4RQBO1P4aKaBjCmu76Ndkbfpba8hfaVxyaOTg2YDi9NcFdfwrnkKiaoIFId +Z+kjHx7zCf9w== Received: by cwcc.thunk.org (Postfix, from userid 15806) id BE11815C359E; Tue, 31 Jan 2023 01:15:47 -0500 (EST) From: "Theodore Ts'o" To: Ext4 Developers List Cc: zhanchengbin1@huawei.com, linfeilong@huawei.com, "Theodore Ts'o" Subject: [PATCH 1/3] libext2fs: unix_io: add flag which suppresses calling the write error handler Date: Tue, 31 Jan 2023 01:15:40 -0500 Message-Id: <20230131061542.324172-2-tytso@mit.edu> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20230131061542.324172-1-tytso@mit.edu> References: <20230131061542.324172-1-tytso@mit.edu> MIME-Version: 1.0 X-Spam-Status: No, score=-4.0 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,RCVD_IN_DNSWL_MED,SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org Signed-off-by: Theodore Ts'o --- lib/ext2fs/unix_io.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c index e53db333..02d7fe1a 100644 --- a/lib/ext2fs/unix_io.c +++ b/lib/ext2fs/unix_io.c @@ -337,10 +337,13 @@ error_unlock: return retval; } +#define RAW_WRITE_NO_HANDLER 1 + static errcode_t raw_write_blk(io_channel channel, struct unix_private_data *data, unsigned long long block, - int count, const void *bufv) + int count, const void *bufv, + int flags) { ssize_t size; ext2_loff_t location; @@ -482,7 +485,7 @@ bounce_write: error_unlock: mutex_unlock(data, BOUNCE_MTX); error_out: - if (channel->write_error) + if (((flags & RAW_WRITE_NO_HANDLER) == 0) && channel->write_error) retval = (channel->write_error)(channel, block, count, buf, size, actual, retval); return retval; @@ -580,7 +583,7 @@ static void reuse_cache(io_channel channel, struct unix_private_data *data, struct unix_cache *cache, unsigned long long block) { if (cache->dirty && cache->in_use) - raw_write_blk(channel, data, cache->block, 1, cache->buf); + raw_write_blk(channel, data, cache->block, 1, cache->buf, 0); cache->in_use = 1; cache->dirty = 0; @@ -616,7 +619,7 @@ static errcode_t flush_cached_blocks(io_channel channel, continue; retval = raw_write_blk(channel, data, - cache->block, 1, cache->buf); + cache->block, 1, cache->buf, 0); if (retval) retval2 = retval; else @@ -1067,10 +1070,10 @@ static errcode_t unix_write_blk64(io_channel channel, unsigned long long block, EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); #ifdef NO_IO_CACHE - return raw_write_blk(channel, data, block, count, buf); + return raw_write_blk(channel, data, block, count, buf, 0); #else if (data->flags & IO_FLAG_NOCACHE) - return raw_write_blk(channel, data, block, count, buf); + return raw_write_blk(channel, data, block, count, buf, 0); /* * If we're doing an odd-sized write or a very large write, * flush out the cache completely and then do a direct write. @@ -1079,7 +1082,7 @@ static errcode_t unix_write_blk64(io_channel channel, unsigned long long block, if ((retval = flush_cached_blocks(channel, data, FLUSH_INVALIDATE))) return retval; - return raw_write_blk(channel, data, block, count, buf); + return raw_write_blk(channel, data, block, count, buf, 0); } /* @@ -1089,7 +1092,7 @@ static errcode_t unix_write_blk64(io_channel channel, unsigned long long block, */ writethrough = channel->flags & CHANNEL_FLAGS_WRITETHROUGH; if (writethrough) - retval = raw_write_blk(channel, data, block, count, buf); + retval = raw_write_blk(channel, data, block, count, buf, 0); cp = buf; mutex_lock(data, CACHE_MTX); From patchwork Tue Jan 31 06:15:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Theodore Ts'o X-Patchwork-Id: 1734561 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=ozlabs.org (client-ip=2404:9400:2221:ea00::3; helo=gandalf.ozlabs.org; envelope-from=srs0=qszb=54=vger.kernel.org=linux-ext4-owner@ozlabs.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=mit.edu header.i=@mit.edu header.a=rsa-sha256 header.s=outgoing header.b=fRZJt8WU; dkim-atps=neutral Received: from gandalf.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4P5ZYs5Wkhz23hg for ; Tue, 31 Jan 2023 17:16:17 +1100 (AEDT) Received: from gandalf.ozlabs.org (gandalf.ozlabs.org [150.107.74.76]) by gandalf.ozlabs.org (Postfix) with ESMTP id 4P5ZYs52bfz4wgv for ; Tue, 31 Jan 2023 17:16:17 +1100 (AEDT) Received: by gandalf.ozlabs.org (Postfix) id 4P5ZYs4tPGz4xwq; Tue, 31 Jan 2023 17:16:17 +1100 (AEDT) Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: gandalf.ozlabs.org; dmarc=fail (p=none dis=none) header.from=mit.edu Authentication-Results: gandalf.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=2620:137:e000::1:20; helo=out1.vger.email; envelope-from=linux-ext4-owner@vger.kernel.org; receiver=) Authentication-Results: gandalf.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=mit.edu header.i=@mit.edu header.a=rsa-sha256 header.s=outgoing header.b=fRZJt8WU; dkim-atps=neutral Received: from out1.vger.email (out1.vger.email [IPv6:2620:137:e000::1:20]) by gandalf.ozlabs.org (Postfix) with ESMTP id 4P5ZYs4LXhz4wgv for ; Tue, 31 Jan 2023 17:16:17 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230202AbjAaGQQ (ORCPT ); Tue, 31 Jan 2023 01:16:16 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55832 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229919AbjAaGQK (ORCPT ); Tue, 31 Jan 2023 01:16:10 -0500 Received: from outgoing.mit.edu (outgoing-auth-1.mit.edu [18.9.28.11]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D5AE73C290 for ; Mon, 30 Jan 2023 22:16:04 -0800 (PST) Received: from cwcc.thunk.org (pool-173-48-120-46.bstnma.fios.verizon.net [173.48.120.46]) (authenticated bits=0) (User authenticated as tytso@ATHENA.MIT.EDU) by outgoing.mit.edu (8.14.7/8.12.4) with ESMTP id 30V6FlR3024373 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 31 Jan 2023 01:15:49 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mit.edu; s=outgoing; t=1675145749; bh=bB3ol3QwJHPaCYD51i1b5VRfIPM/3/RD8IZoaQQRJng=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=fRZJt8WUpVA7l3xb5BsvS1lUmoNvEJWfugXGdvw3kTu+4q8PG/GjoQs+EBWcWX/7D QeIAaT9705uG9TdmCUoyV0yzVaH8E0+JD7ssQAoJLnVkOKi6+xsXjhjp3ewIMQSGZr +re9QP0+lHQyoowDExEBQXP3S+px2M9UIwIAdDULkxW/E+Rp8CG4sB9Wt2NTUlKd03 /EJ1qyS+qd2xIVWsLOWQPhNaRCEIh0xKyGP5mKOH6yBXzaOi1dTcVK3++7oTWvyvGx 2CAm9VN2s8nk77kpozP2+Kxgh1A7IDvFTr4cKRiS6A2XnCBSLgKjlvDBaEzMe1NKI7 pbCASFbHBj27w== Received: by cwcc.thunk.org (Postfix, from userid 15806) id C030315C359F; Tue, 31 Jan 2023 01:15:47 -0500 (EST) From: "Theodore Ts'o" To: Ext4 Developers List Cc: zhanchengbin1@huawei.com, linfeilong@huawei.com, "Theodore Ts'o" Subject: [PATCH 2/3] libext2fs: unix_io: fix potential error path deadlock in reuse_cache() Date: Tue, 31 Jan 2023 01:15:41 -0500 Message-Id: <20230131061542.324172-3-tytso@mit.edu> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20230131061542.324172-1-tytso@mit.edu> References: <20230131061542.324172-1-tytso@mit.edu> MIME-Version: 1.0 X-Spam-Status: No, score=-4.0 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,RCVD_IN_DNSWL_MED,SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org This was reported by [1] but the fix was incorrect. The issue is that when unix_io was made thread-safe, it was necessary that to add a CACHE_MUTEX to protect multiple threads from potentially colliding with the very simple writeback cache used by the unix_io I/O manager. The original I/O manager was purposefully kept simple, used a fixed-size cache; accordingly, the locking used also kept simple, and used a single global mutex. [1] https://lore.kernel.org/r/310fb77f-dfed-1196-c4ee-30d5138ee5a2@huawei.com The problem was that if an application (such as e2fsck) registers a write error handler, that handler would be called with the CACHE_MUTEX still held, and if that application tried to do any I/O --- for example, closing the file system using ext2fs_close() and then exiting --- the application would deadlock. We should perhaps fix this either by deciding that the simple Unix I/O cache doesn't actually buy much beyond some system call overhead, or by putting in a full-fledged buffer I/O cache system which uses a much larger cache with allocated memory, fine-grained locking and Direct I/O to prevent double cache at the kernel and userspace level. However, for now, fix the problem by waiting until after we have released the CACHE_MUTEX before calling the write handler. This is good enough given how e2fsck's ehandler.c use case, and in practice no one else really uses the error handler in any case. Signed-off-by: Theodore Ts'o --- lib/ext2fs/unix_io.c | 75 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 69 insertions(+), 6 deletions(-) diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c index 02d7fe1a..2e108a2f 100644 --- a/lib/ext2fs/unix_io.c +++ b/lib/ext2fs/unix_io.c @@ -94,6 +94,7 @@ struct unix_cache { int access_time; unsigned dirty:1; unsigned in_use:1; + unsigned write_err:1; }; #define CACHE_SIZE 8 @@ -579,16 +580,27 @@ static struct unix_cache *find_cached_block(struct unix_private_data *data, /* * Reuse a particular cache entry for another block. */ -static void reuse_cache(io_channel channel, struct unix_private_data *data, - struct unix_cache *cache, unsigned long long block) +static errcode_t reuse_cache(io_channel channel, + struct unix_private_data *data, struct unix_cache *cache, + unsigned long long block) { - if (cache->dirty && cache->in_use) - raw_write_blk(channel, data, cache->block, 1, cache->buf, 0); + if (cache->dirty && cache->in_use) { + errcode_t retval; + + retval = raw_write_blk(channel, data, cache->block, 1, + cache->buf, RAW_WRITE_NO_HANDLER); + if (retval) { + cache->write_err = 1; + return retval; + } + } cache->in_use = 1; cache->dirty = 0; + cache->write_err = 0; cache->block = block; cache->access_time = ++data->access_time; + return 0; } #define FLUSH_INVALIDATE 0x01 @@ -1037,7 +1049,10 @@ static errcode_t unix_read_blk64(io_channel channel, unsigned long long block, /* Save the results in the cache */ for (j=0; j < i; j++) { if (!find_cached_block(data, block, &cache)) { - reuse_cache(channel, data, cache, block); + retval = reuse_cache(channel, data, + cache, block); + if (retval) + goto call_write_handler; memcpy(cache->buf, cp, channel->block_size); } count--; @@ -1047,6 +1062,28 @@ static errcode_t unix_read_blk64(io_channel channel, unsigned long long block, } mutex_unlock(data, CACHE_MTX); return 0; + +call_write_handler: + if (cache->write_err && channel->write_error) { + char *err_buf = NULL; + unsigned long long err_block = cache->block; + + cache->dirty = 0; + cache->in_use = 0; + cache->write_err = 0; + if (io_channel_alloc_buf(channel, 0, &err_buf)) + err_buf = NULL; + else + memcpy(err_buf, cache->buf, channel->block_size); + mutex_unlock(data, CACHE_MTX); + (channel->write_error)(channel, err_block, 1, err_buf, + channel->block_size, -1, + retval); + if (err_buf) + ext2fs_free_mem(&err_buf); + } else + mutex_unlock(data, CACHE_MTX); + return retval; #endif /* NO_IO_CACHE */ } @@ -1099,8 +1136,12 @@ static errcode_t unix_write_blk64(io_channel channel, unsigned long long block, while (count > 0) { cache = find_cached_block(data, block, &reuse); if (!cache) { + errcode_t err; + cache = reuse; - reuse_cache(channel, data, cache, block); + err = reuse_cache(channel, data, cache, block); + if (err) + goto call_write_handler; } if (cache->buf != cp) memcpy(cache->buf, cp, channel->block_size); @@ -1111,6 +1152,28 @@ static errcode_t unix_write_blk64(io_channel channel, unsigned long long block, } mutex_unlock(data, CACHE_MTX); return retval; + +call_write_handler: + if (cache->write_err && channel->write_error) { + char *err_buf = NULL; + unsigned long long err_block = cache->block; + + cache->dirty = 0; + cache->in_use = 0; + cache->write_err = 0; + if (io_channel_alloc_buf(channel, 0, &err_buf)) + err_buf = NULL; + else + memcpy(err_buf, cache->buf, channel->block_size); + mutex_unlock(data, CACHE_MTX); + (channel->write_error)(channel, err_block, 1, err_buf, + channel->block_size, -1, + retval); + if (err_buf) + ext2fs_free_mem(&err_buf); + } else + mutex_unlock(data, CACHE_MTX); + return retval; #endif /* NO_IO_CACHE */ } From patchwork Tue Jan 31 06:15:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Theodore Ts'o X-Patchwork-Id: 1734560 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=ozlabs.org (client-ip=150.107.74.76; helo=gandalf.ozlabs.org; envelope-from=srs0=qszb=54=vger.kernel.org=linux-ext4-owner@ozlabs.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=mit.edu header.i=@mit.edu header.a=rsa-sha256 header.s=outgoing header.b=mruIK0rp; dkim-atps=neutral Received: from gandalf.ozlabs.org (gandalf.ozlabs.org [150.107.74.76]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4P5ZYr52xdz23hg for ; Tue, 31 Jan 2023 17:16:16 +1100 (AEDT) Received: from gandalf.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3]) by gandalf.ozlabs.org (Postfix) with ESMTP id 4P5ZYr4b2Dz4wgv for ; Tue, 31 Jan 2023 17:16:16 +1100 (AEDT) Received: by gandalf.ozlabs.org (Postfix) id 4P5ZYr4XLvz4xwq; Tue, 31 Jan 2023 17:16:16 +1100 (AEDT) Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: gandalf.ozlabs.org; dmarc=fail (p=none dis=none) header.from=mit.edu Authentication-Results: gandalf.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=2620:137:e000::1:20; helo=out1.vger.email; envelope-from=linux-ext4-owner@vger.kernel.org; receiver=) Authentication-Results: gandalf.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=mit.edu header.i=@mit.edu header.a=rsa-sha256 header.s=outgoing header.b=mruIK0rp; dkim-atps=neutral Received: from out1.vger.email (out1.vger.email [IPv6:2620:137:e000::1:20]) by gandalf.ozlabs.org (Postfix) with ESMTP id 4P5ZYr4QK5z4wgv for ; Tue, 31 Jan 2023 17:16:16 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230229AbjAaGQO (ORCPT ); Tue, 31 Jan 2023 01:16:14 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55812 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230202AbjAaGQJ (ORCPT ); Tue, 31 Jan 2023 01:16:09 -0500 Received: from outgoing.mit.edu (outgoing-auth-1.mit.edu [18.9.28.11]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3F9D53B668 for ; Mon, 30 Jan 2023 22:16:02 -0800 (PST) Received: from cwcc.thunk.org (pool-173-48-120-46.bstnma.fios.verizon.net [173.48.120.46]) (authenticated bits=0) (User authenticated as tytso@ATHENA.MIT.EDU) by outgoing.mit.edu (8.14.7/8.12.4) with ESMTP id 30V6Flm9024387 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 31 Jan 2023 01:15:49 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mit.edu; s=outgoing; t=1675145749; bh=UBnODzrvHrhWlE18sysyOhRWhOHYCrKAw7AocrTCRRY=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=mruIK0rpMEQm/7r6n1zD7+ojlH/xyW6BHsQ2RU9NlD+QQApxhF/Yh5E7aYraD4Mu5 0SpywscVgdwcGEPTKxEfGr4tXUITsmOOtlQON2hGwRTvlyTGKM9FN8EUSK5gCcAKf7 vRa03z3KV2V9Dwz6OhvAch5WsKdgo/ziBEg+X8diNBUiMQi3gBgQ4+LD5vHfruQCzl 3KhKjXcnsHyfOMvFnWM+Jkw5dnlz/dYGUeTcEDiAVQBLtpAr1JouGL2omsp+Dbp4OA H6k2VtSaonmsrajGh4wIV0RJa0AVeT5KQaHkgJ6AzwxVT/8hd9wz1qvokH0YdnHIvX FrLPSugfP+T/g== Received: by cwcc.thunk.org (Postfix, from userid 15806) id C191815C35A0; Tue, 31 Jan 2023 01:15:47 -0500 (EST) From: "Theodore Ts'o" To: Ext4 Developers List Cc: zhanchengbin1@huawei.com, linfeilong@huawei.com, "Theodore Ts'o" Subject: [PATCH 3/3] libext2fs: unix_io: fix_potential error path deadlock in flush_cached_blocks() Date: Tue, 31 Jan 2023 01:15:42 -0500 Message-Id: <20230131061542.324172-4-tytso@mit.edu> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20230131061542.324172-1-tytso@mit.edu> References: <20230131061542.324172-1-tytso@mit.edu> MIME-Version: 1.0 X-Spam-Status: No, score=-4.0 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,RCVD_IN_DNSWL_MED,SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org We can't call the error handler while holding the CACHE_MUTEX (see previous commit, "libext2fs: unix_io: fix_potential error path deadlock in reuse_cache()" for details), so first try to write out all of the dirty blocks in the cache, and then for those where we had errors, then call the error handler. Signed-off-by: Theodore Ts'o --- lib/ext2fs/unix_io.c | 61 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 13 deletions(-) diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c index 2e108a2f..353d85af 100644 --- a/lib/ext2fs/unix_io.c +++ b/lib/ext2fs/unix_io.c @@ -614,31 +614,66 @@ static errcode_t flush_cached_blocks(io_channel channel, int flags) { struct unix_cache *cache; - errcode_t retval, retval2; + errcode_t retval, retval2 = 0; int i; + int errors_found = 0; - retval2 = 0; if ((flags & FLUSH_NOLOCK) == 0) mutex_lock(data, CACHE_MTX); for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) { - if (!cache->in_use) + if (!cache->in_use || !cache->dirty) continue; - - if (flags & FLUSH_INVALIDATE) - cache->in_use = 0; - - if (!cache->dirty) - continue; - retval = raw_write_blk(channel, data, - cache->block, 1, cache->buf, 0); - if (retval) + cache->block, 1, cache->buf, + RAW_WRITE_NO_HANDLER); + if (retval) { + cache->write_err = 1; + errors_found = 1; retval2 = retval; - else + } else { cache->dirty = 0; + cache->write_err = 0; + if (flags & FLUSH_INVALIDATE) + cache->in_use = 0; + } } if ((flags & FLUSH_NOLOCK) == 0) mutex_unlock(data, CACHE_MTX); +retry: + while (errors_found) { + if ((flags & FLUSH_NOLOCK) == 0) + mutex_lock(data, CACHE_MTX); + errors_found = 0; + for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) { + if (!cache->in_use || !cache->write_err) + continue; + errors_found = 1; + if (cache->write_err && channel->write_error) { + char *err_buf = NULL; + unsigned long long err_block = cache->block; + + cache->dirty = 0; + cache->in_use = 0; + cache->write_err = 0; + if (io_channel_alloc_buf(channel, 0, + &err_buf)) + err_buf = NULL; + else + memcpy(err_buf, cache->buf, + channel->block_size); + mutex_unlock(data, CACHE_MTX); + (channel->write_error)(channel, err_block, + 1, err_buf, channel->block_size, -1, + retval2); + if (err_buf) + ext2fs_free_mem(&err_buf); + goto retry; + } else + cache->write_err = 0; + } + if ((flags & FLUSH_NOLOCK) == 0) + mutex_unlock(data, CACHE_MTX); + } return retval2; } #endif /* NO_IO_CACHE */