Received: by 2002:a05:6a10:17d3:0:0:0:0 with SMTP id hz19csp3109346pxb; Tue, 20 Apr 2021 00:18:48 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwiMJGNxU58TBuCdhygLoupr21cItUO7P2vfRlODxvqhRZ4seq3UZhedFXmfg3u93rbL7Fz X-Received: by 2002:a17:907:2ccf:: with SMTP id hg15mr25982000ejc.219.1618903127920; Tue, 20 Apr 2021 00:18:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1618903127; cv=none; d=google.com; s=arc-20160816; b=WSpDcidhXX4oanRkTZAI1ZFEbnJTzrJSIDhC937Grk58rFutZu2OmAoq3x9Ci6K/TA 1oDsh1ZvWi/jFYfgsKLr4l9GBaCFhLZKmBwcyUSXCTIf7Ta6HPbK/XIDJYsEWQU1N3v2 6pkIHGDJZksU0sggs2dBm/MK0BtdrbepRO/u9SeeYmd+GPOhBCivVkKfmQ8fMz8VTZ0M hOYgS7uUuWHipn5Q+iJrUKinhHog9xLA9MdDv1VKUJtH1/eA9Ut5830xd8Ce6jyU4G2L 5+UN1vGemAi4rAptxqIrB77jI2nSqDOaPzlZw5sES0XCj5Hl2BRIs10xkgKiSK9DNMEh t56w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:date:message-id:cc:to:subject:from; bh=OkrZAk4fA50fuKtxBMcyfYeqmaQZwPi/oLrzad4AcRk=; b=WVzYX20AYtCxIEMxDpPwdh6WocAjZJ/3/MyNu3th6BgkYRe/pevAPFJclmwtBtBYc5 NIW0GtwQk6zMj0nrvsX6ivgyEKqEwebp1oAkLu/p534nXyZcsA/J6cbUBzndMKcGvlFV Q5splnIEoh5iX8RWlwQvEhebtIezXlRF4ijcXR0vP2v2QDsMu1oXoUPT4N+JuVOBVVGz fdUXxNsPACZYW7s+ockRfvTiNgcCjWH6FVjmlulPn4UE8WlzF8eIzjrNYT3JbOfRQKbM n1bIvryz3ivz2yijrwszLBE9rab99Uyi7RLB32jDKFCX272gPLgWKbP4e/dIBVroFnuY Emow== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-ext4-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-ext4-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=huawei.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id c13si14261775eje.45.2021.04.20.00.18.20; Tue, 20 Apr 2021 00:18:47 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-ext4-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-ext4-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-ext4-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=huawei.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229793AbhDTHSr (ORCPT + 99 others); Tue, 20 Apr 2021 03:18:47 -0400 Received: from szxga07-in.huawei.com ([45.249.212.35]:17798 "EHLO szxga07-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229731AbhDTHSq (ORCPT ); Tue, 20 Apr 2021 03:18:46 -0400 Received: from DGGEMS411-HUB.china.huawei.com (unknown [172.30.72.58]) by szxga07-in.huawei.com (SkyGuard) with ESMTP id 4FPZj418c4zBrYk; Tue, 20 Apr 2021 15:15:52 +0800 (CST) Received: from [10.174.177.192] (10.174.177.192) by DGGEMS411-HUB.china.huawei.com (10.3.19.211) with Microsoft SMTP Server id 14.3.498.0; Tue, 20 Apr 2021 15:18:05 +0800 From: Haotian Li Subject: [PATCH] e2fsprogs: Try again to solve unreliable io case To: Ext4 Developers List CC: "Theodore Y. Ts'o" , "harshad shirwadkar," , "liuzhiqiang (I)" , linfeilong Message-ID: Date: Tue, 20 Apr 2021 15:18:05 +0800 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Thunderbird/78.1.0 MIME-Version: 1.0 Content-Type: text/plain; charset="gbk" Content-Transfer-Encoding: 7bit X-Originating-IP: [10.174.177.192] X-CFilter-Loop: Reflected Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org If some I/O error occured during e2fsck, for example the fibre channel connections are flasky, the e2fsck may exit. Try again in these I/O error cases may help e2fsck successfully execute and fix the disk correctly. We may try five times when io_channel_write/read failed. Enable this option by setting true on unreliable_io in configure file "e2fsck.conf". Signed-off-by: Haotian Li Signed-off-by: Zhiqiang Liu --- e2fsck/unix.c | 7 +++ lib/ext2fs/ext2_io.h | 3 ++ lib/ext2fs/ext2fs.h | 2 +- lib/ext2fs/io_manager.c | 102 ++++++++++++++++++++++++++++++---------- lib/ext2fs/openfs.c | 2 + lib/ext2fs/unix_io.c | 4 ++ 6 files changed, 93 insertions(+), 27 deletions(-) diff --git a/e2fsck/unix.c b/e2fsck/unix.c index c5f9e441..faa2f77d 100644 --- a/e2fsck/unix.c +++ b/e2fsck/unix.c @@ -1398,6 +1398,7 @@ int main (int argc, char *argv[]) int journal_size; int sysval, sys_page_size = 4096; int old_bitmaps; + int unreliable_io; __u32 features[3]; char *cp; enum quota_type qtype; @@ -1496,6 +1497,12 @@ restart: &old_bitmaps); if (!old_bitmaps) flags |= EXT2_FLAG_64BITS; + + profile_get_boolean(ctx->profile, "options", "unreliable_io", 0, 0, + &unreliable_io); + if (unreliable_io) + flags |= EXT2_FLAG_UNRELIABLE_IO; + if ((ctx->options & E2F_OPT_READONLY) == 0) { flags |= EXT2_FLAG_RW; if (!(ctx->mount_flags & EXT2_MF_ISROOT && diff --git a/lib/ext2fs/ext2_io.h b/lib/ext2fs/ext2_io.h index 8fe5b323..38d23a1b 100644 --- a/lib/ext2fs/ext2_io.h +++ b/lib/ext2fs/ext2_io.h @@ -34,8 +34,10 @@ typedef struct struct_io_stats *io_stats; #define CHANNEL_FLAGS_DISCARD_ZEROES 0x02 #define CHANNEL_FLAGS_BLOCK_DEVICE 0x04 #define CHANNEL_FLAGS_THREADS 0x08 +#define CHANNEL_FLAGS_UNRELIABLE_IO 0x10 #define io_channel_discard_zeroes_data(i) (i->flags & CHANNEL_FLAGS_DISCARD_ZEROES) +#define UNRELIABLE_IO_RETRY_TIMES 5 struct struct_io_channel { errcode_t magic; @@ -107,6 +109,7 @@ struct struct_io_manager { #define IO_FLAG_FORCE_BOUNCE 0x0008 #define IO_FLAG_THREADS 0x0010 #define IO_FLAG_NOCACHE 0x0020 +#define IO_FLAG_UNRELIABLE_IO 0x0040 /* * Convenience functions.... diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index df150f00..4ce5e311 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -207,7 +207,7 @@ typedef struct ext2_file *ext2_file_t; #define EXT2_FLAG_BBITMAP_TAIL_PROBLEM 0x1000000 #define EXT2_FLAG_IBITMAP_TAIL_PROBLEM 0x2000000 #define EXT2_FLAG_THREADS 0x4000000 - +#define EXT2_FLAG_UNRELIABLE_IO 0x8000000 /* * Special flag in the ext2 inode i_flag field that means that this is * a new inode. (So that ext2_write_inode() can clear extra fields.) diff --git a/lib/ext2fs/io_manager.c b/lib/ext2fs/io_manager.c index 996c31a1..f062ef0a 100644 --- a/lib/ext2fs/io_manager.c +++ b/lib/ext2fs/io_manager.c @@ -61,66 +61,116 @@ errcode_t io_channel_write_byte(io_channel channel, unsigned long offset, int count, const void *data) { EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - - if (channel->manager->write_byte) - return channel->manager->write_byte(channel, offset, + errcode_t ret = EXT2_ET_UNIMPLEMENTED; + int retry_times = (channel->flags & CHANNEL_FLAGS_UNRELIABLE_IO) ? + UNRELIABLE_IO_RETRY_TIMES : 0; +retry: + if (channel->manager->write_byte) { + ret = channel->manager->write_byte(channel, offset, count, data); - - return EXT2_ET_UNIMPLEMENTED; + if (ret && retry_times) { + retry_times--; + goto retry; + } + } + return ret; } errcode_t io_channel_read_blk64(io_channel channel, unsigned long long block, int count, void *data) { - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - - if (channel->manager->read_blk64) - return (channel->manager->read_blk64)(channel, block, + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + errcode_t ret = 0; + int retry_times = (channel->flags & CHANNEL_FLAGS_UNRELIABLE_IO) ? + UNRELIABLE_IO_RETRY_TIMES : 0; +retry_read_blk64: + if (channel->manager->read_blk64) { + ret = (channel->manager->read_blk64)(channel, block, count, data); + if (ret && retry_times) { + retry_times--; + goto retry_read_blk64; + } + return ret; + } if ((block >> 32) != 0) return EXT2_ET_IO_CHANNEL_NO_SUPPORT_64; - - return (channel->manager->read_blk)(channel, (unsigned long) block, +retry_read_blk: + ret = (channel->manager->read_blk)(channel, (unsigned long) block, count, data); + if (ret && retry_times) { + retry_times--; + goto retry_read_blk; + } + return ret; } + errcode_t io_channel_write_blk64(io_channel channel, unsigned long long block, int count, const void *data) { EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - - if (channel->manager->write_blk64) - return (channel->manager->write_blk64)(channel, block, + errcode_t ret = 0; + int retry_times = (channel->flags & CHANNEL_FLAGS_UNRELIABLE_IO) ? + UNRELIABLE_IO_RETRY_TIMES : 0; +retry_write_blk64: + if (channel->manager->write_blk64) { + ret = (channel->manager->write_blk64)(channel, block, count, data); + if (ret && retry_times) { + retry_times--; + goto retry_write_blk64; + } + return ret; + } if ((block >> 32) != 0) return EXT2_ET_IO_CHANNEL_NO_SUPPORT_64; - - return (channel->manager->write_blk)(channel, (unsigned long) block, +retry_write_blk: + ret = (channel->manager->write_blk)(channel, (unsigned long) block, count, data); + if (ret && retry_times) { + retry_times--; + goto retry_write_blk; + } + return ret; } errcode_t io_channel_discard(io_channel channel, unsigned long long block, unsigned long long count) { EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - - if (channel->manager->discard) - return (channel->manager->discard)(channel, block, count); - - return EXT2_ET_UNIMPLEMENTED; + errcode_t ret = EXT2_ET_UNIMPLEMENTED; + int retry_times = (channel->flags & CHANNEL_FLAGS_UNRELIABLE_IO) ? + UNRELIABLE_IO_RETRY_TIMES : 0; +retry: + if (channel->manager->discard) { + ret = (channel->manager->discard)(channel, block, count); + if (ret && retry_times) { + retry_times--; + goto retry; + } + } + return ret; } errcode_t io_channel_zeroout(io_channel channel, unsigned long long block, unsigned long long count) { EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - - if (channel->manager->zeroout) - return (channel->manager->zeroout)(channel, block, count); - - return EXT2_ET_UNIMPLEMENTED; + errcode_t ret = EXT2_ET_UNIMPLEMENTED; + int retry_times = (channel->flags & CHANNEL_FLAGS_UNRELIABLE_IO) ? + UNRELIABLE_IO_RETRY_TIMES : 0; +retry: + if (channel->manager->zeroout) { + ret = (channel->manager->zeroout)(channel, block, count); + if (ret && retry_times) { + retry_times--; + goto retry; + } + } + return ret; } errcode_t io_channel_alloc_buf(io_channel io, int count, void *ptr) diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c index 5ec8ed5c..a98a5815 100644 --- a/lib/ext2fs/openfs.c +++ b/lib/ext2fs/openfs.c @@ -172,6 +172,8 @@ errcode_t ext2fs_open2(const char *name, const char *io_options, io_flags |= IO_FLAG_DIRECT_IO; if (flags & EXT2_FLAG_THREADS) io_flags |= IO_FLAG_THREADS; + if (flags & EXT2_FLAG_UNRELIABLE_IO) + io_flags |= IO_FLAG_UNRELIABLE_IO; retval = manager->open(fs->device_name, io_flags, &fs->io); if (retval) goto cleanup; diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c index 64eee342..845a1e16 100644 --- a/lib/ext2fs/unix_io.c +++ b/lib/ext2fs/unix_io.c @@ -837,6 +837,10 @@ static errcode_t unix_open_channel(const char *name, int fd, } } #endif + if (flags & IO_FLAG_UNRELIABLE_IO) { + io->flags |= CHANNEL_FLAGS_UNRELIABLE_IO; + } + *channel = io; return 0; -- 2.23.0