1dc728923Sopenharmony_ciFrom 8625b843ab9e1327dcb83b025951f97c971175e0 Mon Sep 17 00:00:00 2001 2dc728923Sopenharmony_ciFrom: Wenchao Hao <haowenchao@huawei.com> 3dc728923Sopenharmony_ciDate: Fri, 11 Nov 2022 12:22:08 +0800 4dc728923Sopenharmony_ciSubject: [PATCH] unix_io.c: fix deadlock problem in unix_write_blk64 5dc728923Sopenharmony_ci 6dc728923Sopenharmony_ciWe will release CACHE_MTX lock, when enter e2fsck_handle_write_error. 7dc728923Sopenharmony_ci 8dc728923Sopenharmony_cistack: 9dc728923Sopenharmony_ci(gdb) bt 10dc728923Sopenharmony_ci0 0x0000ffffa740bc34 in ?? () from /usr/lib64/libc.so.6 11dc728923Sopenharmony_ci1 0x0000ffffa7412024 in pthread_mutex_lock () from /usr/lib64/libc.so.6 12dc728923Sopenharmony_ci2 0x0000ffffa7654e54 in mutex_lock (kind=CACHE_MTX, data=0xaaaaf5c98f30) at unix_io.c:151 13dc728923Sopenharmony_ci3 unix_write_blk64 (channel=0xaaaaf5c98e60, block=2, count=4, buf=0xaaaaf5c9d170) at unix_io.c:1092 14dc728923Sopenharmony_ci4 0x0000ffffa762e610 in ext2fs_flush2 (flags=0, fs=0xaaaaf5c98cc0) at closefs.c:401 15dc728923Sopenharmony_ci5 ext2fs_flush2 (fs=0xaaaaf5c98cc0, flags=0) at closefs.c:279 16dc728923Sopenharmony_ci6 0x0000ffffa762eb14 in ext2fs_close2 (fs=fs@entry=0xaaaaf5c98cc0, flags=flags@entry=0) at closefs.c:510 17dc728923Sopenharmony_ci7 0x0000ffffa762eba4 in ext2fs_close_free (fs_ptr=fs_ptr@entry=0xffffc8cbab30) at closefs.c:472 18dc728923Sopenharmony_ci8 0x0000aaaadcc39bd8 in preenhalt (ctx=ctx@entry=0xaaaaf5c98460) at util.c:365 19dc728923Sopenharmony_ci9 0x0000aaaadcc3bc5c in e2fsck_handle_write_error (channel=<optimized out>, block=262152, count=<optimized out>, data=<optimized out>, size=<optimized out>, actual=<optimized out>, error=5) 20dc728923Sopenharmony_ci at ehandler.c:114 21dc728923Sopenharmony_ci10 0x0000ffffa7655044 in reuse_cache (block=262206, cache=0xaaaaf5c98f80, data=0xaaaaf5c98f30, channel=0xaaaaf5c98e60) at unix_io.c:583 22dc728923Sopenharmony_ci11 unix_write_blk64 (channel=0xaaaaf5c98e60, block=262206, count=<optimized out>, buf=<optimized out>) at unix_io.c:1097 23dc728923Sopenharmony_ci12 0x0000aaaadcc3702c in ll_rw_block (rw=rw@entry=1, op_flags=op_flags@entry=0, nr=<optimized out>, nr@entry=1, bhp=0xffffc8cbac60, bhp@entry=0xffffc8cbac58) at journal.c:184 24dc728923Sopenharmony_ci13 0x0000aaaadcc375e8 in brelse (bh=<optimized out>, bh@entry=0xaaaaf5cac4a0) at journal.c:217 25dc728923Sopenharmony_ci14 0x0000aaaadcc3ebe0 in do_one_pass (journal=journal@entry=0xaaaaf5c9f590, info=info@entry=0xffffc8cbad60, pass=pass@entry=PASS_REPLAY) at recovery.c:693 26dc728923Sopenharmony_ci15 0x0000aaaadcc3ee74 in jbd2_journal_recover (journal=0xaaaaf5c9f590) at recovery.c:310 27dc728923Sopenharmony_ci16 0x0000aaaadcc386a8 in recover_ext3_journal (ctx=0xaaaaf5c98460) at journal.c:1653 28dc728923Sopenharmony_ci17 e2fsck_run_ext3_journal (ctx=0xaaaaf5c98460) at journal.c:1706 29dc728923Sopenharmony_ci18 0x0000aaaadcc207e0 in main (argc=<optimized out>, argv=<optimized out>) at unix.c:1791 30dc728923Sopenharmony_ci 31dc728923Sopenharmony_ciSigned-off-by: zhanchengbin <zhanchengbin1@huawei.com> 32dc728923Sopenharmony_ciSigned-off-by: Zhiqiang Liu <liuzhiqiang26@huawei.com> 33dc728923Sopenharmony_ci--- 34dc728923Sopenharmony_ci lib/ext2fs/unix_io.c | 63 +++++++++++++++++++++++++++++++++++++--------------- 35dc728923Sopenharmony_ci 1 file changed, 45 insertions(+), 18 deletions(-) 36dc728923Sopenharmony_ci 37dc728923Sopenharmony_cidiff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c 38dc728923Sopenharmony_ciindex c326f57..a7ab772 100644 39dc728923Sopenharmony_ci--- a/lib/ext2fs/unix_io.c 40dc728923Sopenharmony_ci+++ b/lib/ext2fs/unix_io.c 41dc728923Sopenharmony_ci@@ -210,7 +210,8 @@ static char *safe_getenv(const char *arg) 42dc728923Sopenharmony_ci static errcode_t raw_read_blk(io_channel channel, 43dc728923Sopenharmony_ci struct unix_private_data *data, 44dc728923Sopenharmony_ci unsigned long long block, 45dc728923Sopenharmony_ci- int count, void *bufv) 46dc728923Sopenharmony_ci+ int count, void *bufv, 47dc728923Sopenharmony_ci+ int cache_lock) 48dc728923Sopenharmony_ci { 49dc728923Sopenharmony_ci errcode_t retval; 50dc728923Sopenharmony_ci ssize_t size; 51dc728923Sopenharmony_ci@@ -331,16 +332,22 @@ error_unlock: 52dc728923Sopenharmony_ci mutex_unlock(data, BOUNCE_MTX); 53dc728923Sopenharmony_ci if (actual >= 0 && actual < size) 54dc728923Sopenharmony_ci memset((char *) buf+actual, 0, size-actual); 55dc728923Sopenharmony_ci- if (channel->read_error) 56dc728923Sopenharmony_ci+ if (channel->read_error) { 57dc728923Sopenharmony_ci+ if (cache_lock) 58dc728923Sopenharmony_ci+ mutex_unlock(data, CACHE_MTX); 59dc728923Sopenharmony_ci retval = (channel->read_error)(channel, block, count, buf, 60dc728923Sopenharmony_ci size, actual, retval); 61dc728923Sopenharmony_ci+ if (cache_lock) 62dc728923Sopenharmony_ci+ mutex_lock(data, CACHE_MTX); 63dc728923Sopenharmony_ci+ } 64dc728923Sopenharmony_ci return retval; 65dc728923Sopenharmony_ci } 66dc728923Sopenharmony_ci 67dc728923Sopenharmony_ci static errcode_t raw_write_blk(io_channel channel, 68dc728923Sopenharmony_ci struct unix_private_data *data, 69dc728923Sopenharmony_ci unsigned long long block, 70dc728923Sopenharmony_ci- int count, const void *bufv) 71dc728923Sopenharmony_ci+ int count, const void *bufv, 72dc728923Sopenharmony_ci+ int cache_lock) 73dc728923Sopenharmony_ci { 74dc728923Sopenharmony_ci ssize_t size; 75dc728923Sopenharmony_ci ext2_loff_t location; 76dc728923Sopenharmony_ci@@ -482,9 +489,14 @@ bounce_write: 77dc728923Sopenharmony_ci error_unlock: 78dc728923Sopenharmony_ci mutex_unlock(data, BOUNCE_MTX); 79dc728923Sopenharmony_ci error_out: 80dc728923Sopenharmony_ci- if (channel->write_error) 81dc728923Sopenharmony_ci+ if (channel->write_error) { 82dc728923Sopenharmony_ci+ if (cache_lock) 83dc728923Sopenharmony_ci+ mutex_unlock(data, CACHE_MTX); 84dc728923Sopenharmony_ci retval = (channel->write_error)(channel, block, count, buf, 85dc728923Sopenharmony_ci size, actual, retval); 86dc728923Sopenharmony_ci+ if (cache_lock) 87dc728923Sopenharmony_ci+ mutex_lock(data, CACHE_MTX); 88dc728923Sopenharmony_ci+ } 89dc728923Sopenharmony_ci return retval; 90dc728923Sopenharmony_ci } 91dc728923Sopenharmony_ci 92dc728923Sopenharmony_ci@@ -576,16 +588,22 @@ static struct unix_cache *find_cached_block(struct unix_private_data *data, 93dc728923Sopenharmony_ci /* 94dc728923Sopenharmony_ci * Reuse a particular cache entry for another block. 95dc728923Sopenharmony_ci */ 96dc728923Sopenharmony_ci-static void reuse_cache(io_channel channel, struct unix_private_data *data, 97dc728923Sopenharmony_ci+static errcode_t reuse_cache(io_channel channel, struct unix_private_data *data, 98dc728923Sopenharmony_ci struct unix_cache *cache, unsigned long long block) 99dc728923Sopenharmony_ci { 100dc728923Sopenharmony_ci- if (cache->dirty && cache->in_use) 101dc728923Sopenharmony_ci- raw_write_blk(channel, data, cache->block, 1, cache->buf); 102dc728923Sopenharmony_ci+ errcode_t retval = 0; 103dc728923Sopenharmony_ci+ if (cache->dirty && cache->in_use) { 104dc728923Sopenharmony_ci+ retval = raw_write_blk(channel, data, cache->block, 1, cache->buf, 1); 105dc728923Sopenharmony_ci+ if (retval) 106dc728923Sopenharmony_ci+ return retval; 107dc728923Sopenharmony_ci+ } 108dc728923Sopenharmony_ci 109dc728923Sopenharmony_ci cache->in_use = 1; 110dc728923Sopenharmony_ci cache->dirty = 0; 111dc728923Sopenharmony_ci cache->block = block; 112dc728923Sopenharmony_ci cache->access_time = ++data->access_time; 113dc728923Sopenharmony_ci+ 114dc728923Sopenharmony_ci+ return retval; 115dc728923Sopenharmony_ci } 116dc728923Sopenharmony_ci 117dc728923Sopenharmony_ci #define FLUSH_INVALIDATE 0x01 118dc728923Sopenharmony_ci@@ -616,7 +634,8 @@ static errcode_t flush_cached_blocks(io_channel channel, 119dc728923Sopenharmony_ci continue; 120dc728923Sopenharmony_ci 121dc728923Sopenharmony_ci retval = raw_write_blk(channel, data, 122dc728923Sopenharmony_ci- cache->block, 1, cache->buf); 123dc728923Sopenharmony_ci+ cache->block, 1, cache->buf, 124dc728923Sopenharmony_ci+ !(flags & FLUSH_NOLOCK)); 125dc728923Sopenharmony_ci if (retval) 126dc728923Sopenharmony_ci retval2 = retval; 127dc728923Sopenharmony_ci else 128dc728923Sopenharmony_ci@@ -984,10 +1003,10 @@ static errcode_t unix_read_blk64(io_channel channel, unsigned long long block, 129dc728923Sopenharmony_ci EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 130dc728923Sopenharmony_ci 131dc728923Sopenharmony_ci #ifdef NO_IO_CACHE 132dc728923Sopenharmony_ci- return raw_read_blk(channel, data, block, count, buf); 133dc728923Sopenharmony_ci+ return raw_read_blk(channel, data, block, count, buf, 0); 134dc728923Sopenharmony_ci #else 135dc728923Sopenharmony_ci if (data->flags & IO_FLAG_NOCACHE) 136dc728923Sopenharmony_ci- return raw_read_blk(channel, data, block, count, buf); 137dc728923Sopenharmony_ci+ return raw_read_blk(channel, data, block, count, buf, 0); 138dc728923Sopenharmony_ci /* 139dc728923Sopenharmony_ci * If we're doing an odd-sized read or a very large read, 140dc728923Sopenharmony_ci * flush out the cache and then do a direct read. 141dc728923Sopenharmony_ci@@ -995,7 +1014,7 @@ static errcode_t unix_read_blk64(io_channel channel, unsigned long long block, 142dc728923Sopenharmony_ci if (count < 0 || count > WRITE_DIRECT_SIZE) { 143dc728923Sopenharmony_ci if ((retval = flush_cached_blocks(channel, data, 0))) 144dc728923Sopenharmony_ci return retval; 145dc728923Sopenharmony_ci- return raw_read_blk(channel, data, block, count, buf); 146dc728923Sopenharmony_ci+ return raw_read_blk(channel, data, block, count, buf, 0); 147dc728923Sopenharmony_ci } 148dc728923Sopenharmony_ci 149dc728923Sopenharmony_ci cp = buf; 150dc728923Sopenharmony_ci@@ -1024,14 +1043,18 @@ static errcode_t unix_read_blk64(io_channel channel, unsigned long long block, 151dc728923Sopenharmony_ci printf("Reading %d blocks starting at %lu\n", i, block); 152dc728923Sopenharmony_ci #endif 153dc728923Sopenharmony_ci mutex_unlock(data, CACHE_MTX); 154dc728923Sopenharmony_ci- if ((retval = raw_read_blk(channel, data, block, i, cp))) 155dc728923Sopenharmony_ci+ if ((retval = raw_read_blk(channel, data, block, i, cp, 0))) 156dc728923Sopenharmony_ci return retval; 157dc728923Sopenharmony_ci mutex_lock(data, CACHE_MTX); 158dc728923Sopenharmony_ci 159dc728923Sopenharmony_ci /* Save the results in the cache */ 160dc728923Sopenharmony_ci for (j=0; j < i; j++) { 161dc728923Sopenharmony_ci if (!find_cached_block(data, block, &cache)) { 162dc728923Sopenharmony_ci- reuse_cache(channel, data, cache, block); 163dc728923Sopenharmony_ci+ retval = reuse_cache(channel, data, cache, block); 164dc728923Sopenharmony_ci+ if (retval) { 165dc728923Sopenharmony_ci+ mutex_unlock(data, CACHE_MTX); 166dc728923Sopenharmony_ci+ return retval; 167dc728923Sopenharmony_ci+ } 168dc728923Sopenharmony_ci memcpy(cache->buf, cp, channel->block_size); 169dc728923Sopenharmony_ci } 170dc728923Sopenharmony_ci count--; 171dc728923Sopenharmony_ci@@ -1064,10 +1087,10 @@ static errcode_t unix_write_blk64(io_channel channel, unsigned long long block, 172dc728923Sopenharmony_ci EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 173dc728923Sopenharmony_ci 174dc728923Sopenharmony_ci #ifdef NO_IO_CACHE 175dc728923Sopenharmony_ci- return raw_write_blk(channel, data, block, count, buf); 176dc728923Sopenharmony_ci+ return raw_write_blk(channel, data, block, count, buf, 0); 177dc728923Sopenharmony_ci #else 178dc728923Sopenharmony_ci if (data->flags & IO_FLAG_NOCACHE) 179dc728923Sopenharmony_ci- return raw_write_blk(channel, data, block, count, buf); 180dc728923Sopenharmony_ci+ return raw_write_blk(channel, data, block, count, buf, 0); 181dc728923Sopenharmony_ci /* 182dc728923Sopenharmony_ci * If we're doing an odd-sized write or a very large write, 183dc728923Sopenharmony_ci * flush out the cache completely and then do a direct write. 184dc728923Sopenharmony_ci@@ -1076,7 +1099,7 @@ static errcode_t unix_write_blk64(io_channel channel, unsigned long long block, 185dc728923Sopenharmony_ci if ((retval = flush_cached_blocks(channel, data, 186dc728923Sopenharmony_ci FLUSH_INVALIDATE))) 187dc728923Sopenharmony_ci return retval; 188dc728923Sopenharmony_ci- return raw_write_blk(channel, data, block, count, buf); 189dc728923Sopenharmony_ci+ return raw_write_blk(channel, data, block, count, buf, 0); 190dc728923Sopenharmony_ci } 191dc728923Sopenharmony_ci 192dc728923Sopenharmony_ci /* 193dc728923Sopenharmony_ci@@ -1086,7 +1109,7 @@ static errcode_t unix_write_blk64(io_channel channel, unsigned long long block, 194dc728923Sopenharmony_ci */ 195dc728923Sopenharmony_ci writethrough = channel->flags & CHANNEL_FLAGS_WRITETHROUGH; 196dc728923Sopenharmony_ci if (writethrough) 197dc728923Sopenharmony_ci- retval = raw_write_blk(channel, data, block, count, buf); 198dc728923Sopenharmony_ci+ retval = raw_write_blk(channel, data, block, count, buf, 0); 199dc728923Sopenharmony_ci 200dc728923Sopenharmony_ci cp = buf; 201dc728923Sopenharmony_ci mutex_lock(data, CACHE_MTX); 202dc728923Sopenharmony_ci@@ -1094,7 +1117,11 @@ static errcode_t unix_write_blk64(io_channel channel, unsigned long long block, 203dc728923Sopenharmony_ci cache = find_cached_block(data, block, &reuse); 204dc728923Sopenharmony_ci if (!cache) { 205dc728923Sopenharmony_ci cache = reuse; 206dc728923Sopenharmony_ci- reuse_cache(channel, data, cache, block); 207dc728923Sopenharmony_ci+ retval = reuse_cache(channel, data, cache, block); 208dc728923Sopenharmony_ci+ if (retval) { 209dc728923Sopenharmony_ci+ mutex_unlock(data, CACHE_MTX); 210dc728923Sopenharmony_ci+ return retval; 211dc728923Sopenharmony_ci+ } 212dc728923Sopenharmony_ci } 213dc728923Sopenharmony_ci if (cache->buf != cp) 214dc728923Sopenharmony_ci memcpy(cache->buf, cp, channel->block_size); 215dc728923Sopenharmony_ci-- 216dc728923Sopenharmony_ci1.8.3.1 217dc728923Sopenharmony_ci 218