diff --git a/0011-libext2fs-don-t-old-the-CACHE_MTX-while-doing-I-O.patch b/0011-libext2fs-don-t-old-the-CACHE_MTX-while-doing-I-O.patch new file mode 100644 index 0000000000000000000000000000000000000000..0c71d7ef29eccfd666fadc4e18b4202ee27809ef --- /dev/null +++ b/0011-libext2fs-don-t-old-the-CACHE_MTX-while-doing-I-O.patch @@ -0,0 +1,106 @@ +From 699d448eee4b991acafaae4e4f8222be332d6837 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Thu, 9 Dec 2021 10:55:54 -0500 +Subject: [PATCH] libext2fs: don't old the CACHE_MTX while doing I/O + +A report a deadlock problem caused by I/O errors (caused by e2fsck's +error handler trying to write to a bad block to perform a forced +rewrite) uncovered that we were holding the CACHE_MTX while doing read +operations. This serialized read operations which destroyed the +performance benefits from doing parallel bitmap loading (or the +parallel e2fsck processing under development). + +So restructure the code in unix_read_blk64() so that the read is +always done into the user-provided buffer, and then copied into the +cache afterwards. + +Signed-off-by: Theodore Ts'o +--- + lib/ext2fs/unix_io.c | 38 +++++++++++++------------------------- + 1 file changed, 13 insertions(+), 25 deletions(-) + +diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c +index 50ac737..e53db33 100644 +--- a/lib/ext2fs/unix_io.c ++++ b/lib/ext2fs/unix_io.c +@@ -977,8 +977,8 @@ static errcode_t unix_read_blk64(io_channel channel, unsigned long long block, + int count, void *buf) + { + struct unix_private_data *data; +- struct unix_cache *cache, *reuse[READ_DIRECT_SIZE]; +- errcode_t retval = 0; ++ struct unix_cache *cache; ++ errcode_t retval; + char *cp; + int i, j; + +@@ -1005,7 +1005,7 @@ static errcode_t unix_read_blk64(io_channel channel, unsigned long long block, + mutex_lock(data, CACHE_MTX); + while (count > 0) { + /* If it's in the cache, use it! */ +- if ((cache = find_cached_block(data, block, &reuse[0]))) { ++ if ((cache = find_cached_block(data, block, NULL))) { + #ifdef DEBUG + printf("Using cached block %lu\n", block); + #endif +@@ -1015,47 +1015,35 @@ static errcode_t unix_read_blk64(io_channel channel, unsigned long long block, + cp += channel->block_size; + continue; + } +- if (count == 1) { +- /* +- * Special case where we read directly into the +- * cache buffer; important in the O_DIRECT case +- */ +- cache = reuse[0]; +- reuse_cache(channel, data, cache, block); +- if ((retval = raw_read_blk(channel, data, block, 1, +- cache->buf))) { +- cache->in_use = 0; +- break; +- } +- memcpy(cp, cache->buf, channel->block_size); +- retval = 0; +- break; +- } + + /* + * Find the number of uncached blocks so we can do a + * single read request + */ + for (i=1; i < count; i++) +- if (find_cached_block(data, block+i, &reuse[i])) ++ if (find_cached_block(data, block+i, NULL)) + break; + #ifdef DEBUG + printf("Reading %d blocks starting at %lu\n", i, block); + #endif ++ mutex_unlock(data, CACHE_MTX); + if ((retval = raw_read_blk(channel, data, block, i, cp))) +- break; ++ return retval; ++ mutex_lock(data, CACHE_MTX); + + /* 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); ++ memcpy(cache->buf, cp, channel->block_size); ++ } + count--; +- cache = reuse[j]; +- reuse_cache(channel, data, cache, block++); +- memcpy(cache->buf, cp, channel->block_size); ++ block++; + cp += channel->block_size; + } + } + mutex_unlock(data, CACHE_MTX); +- return retval; ++ return 0; + #endif /* NO_IO_CACHE */ + } + +-- +1.8.3.1 + diff --git a/e2fsprogs.spec b/e2fsprogs.spec index 23fada6c1f14d9b2034496f53b5cc4598967c58f..6058a84bfb3035c2dbb344bbb1a7c1ae27e720bb 100644 --- a/e2fsprogs.spec +++ b/e2fsprogs.spec @@ -1,6 +1,6 @@ Name: e2fsprogs Version: 1.46.4 -Release: 5 +Release: 6 Summary: Second extended file system management tools License: GPLv2+ and LGPLv2 and MIT URL: http://e2fsprogs.sourceforge.net/ @@ -16,6 +16,7 @@ Patch7: 0007-e2fsck-exit-journal-recovery-when-jounral-superblock.patch Patch8: 0008-e2fsck-add-env-param-E2FS_UNRELIABLE_IO-to-fi.patch Patch9: 0009-e2mmpstatus.8.in-detele-filesystem-can-be-UUID-or-LA.patch Patch10: 0010-tests-update-expect-file-for-u_direct_io.patch +Patch11: 0011-libext2fs-don-t-old-the-CACHE_MTX-while-doing-I-O.patch BuildRequires: gcc pkgconfig texinfo @@ -138,6 +139,9 @@ exit 0 %{_mandir}/man8/* %changelog +* Wed Feb 9 2022 zhanchengbin - 1.46.4-6 +- libext2fs: don't old the CACHE_MTX while doing I/O + * Thu Feb 8 2022 zhanchengbin - 1.46.4-5 - tests: update expect file for u_direct_io