Received: by 2002:a05:6a10:1287:0:0:0:0 with SMTP id d7csp1595497pxv; Fri, 23 Jul 2021 12:12:06 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwz5VdbSA8Y0ezT5OT/2GvyvB89l1/G9EIw8jcWN6QCi8b5j+JSthdn3P2gDta/zE77sEEw X-Received: by 2002:a92:b748:: with SMTP id c8mr4468211ilm.302.1627067525870; Fri, 23 Jul 2021 12:12:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1627067525; cv=none; d=google.com; s=arc-20160816; b=WvlwxA/x4GfUgvqMPHWxxZfzolZjVgRCregpd3m8+5HwbB9AVlXt5OntdjkBcvWQFJ xqUVjFPMhbcpxL22p7QFb7gHi9J0HXIBAvi3sdIxBeU71PFZQlxroVCHif0iuaJszmV9 E4UIg4bHvvpBOpaIGFeGQeUBgmCQ5cL5tmiM/VrLNAik9RhdNuXImfi87Ju2R9UilzIE 0cdVskRiGVqZaW/iLmXI2eR0qX+8VopI5noFl6M3HOweBK+wwm5dffKAEBi6eTSnjh2e weT19LkfBK3pJkdxZMlRj1LSdaZaf9s6TCKHNgh6+srzokm8DOgYe69w5Es3q4mE3tc9 bE2A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:in-reply-to:content-disposition:mime-version :message-id:subject:cc:to:from:date; bh=fqbNn/S2tgB2GHstb+TGLmF3YjwIHuhxuQljs0p6kHo=; b=VC0+vQ1ExdT9sA4d0iP/EoY/tBLhcr+vmLLfqIzP083MK4dc666alVMkjzSkJrUSdi GnHZdW+Xbq7RnVGW6qB6EvqJ/r67tvrtsB5vRcV2Hleo0LinNeDKUnC2H8XqQbBBCc0/ nZV9qRi8pL8jr9M413KjLXTiorAsRytSj7uUyqHhRJhLs7/GQrB7OhMWLY05kg0KmEYy 83d+Ea2zc4KlbBO2Df680idydHlsSiAeh61NYKsnuvGxiR4TAzN2j6zQ/lyNl1hxEHy7 VUFmK8vyVxBj8bbCfhNOys9AHjJxNUYPyCW5h/1DUDIf7b/in+O32/AqNo3dMcqdWxKB xPWg== 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id m8si24920225jav.78.2021.07.23.12.11.48; Fri, 23 Jul 2021 12:12:05 -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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230037AbhGWSbK (ORCPT + 99 others); Fri, 23 Jul 2021 14:31:10 -0400 Received: from outgoing-auth-1.mit.edu ([18.9.28.11]:36705 "EHLO outgoing.mit.edu" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S229761AbhGWSbJ (ORCPT ); Fri, 23 Jul 2021 14:31:09 -0400 Received: from cwcc.thunk.org (pool-72-74-133-215.bstnma.fios.verizon.net [72.74.133.215]) (authenticated bits=0) (User authenticated as tytso@ATHENA.MIT.EDU) by outgoing.mit.edu (8.14.7/8.12.4) with ESMTP id 16NJBXlc008045 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 23 Jul 2021 15:11:34 -0400 Received: by cwcc.thunk.org (Postfix, from userid 15806) id 577A715C37C0; Fri, 23 Jul 2021 15:11:33 -0400 (EDT) Date: Fri, 23 Jul 2021 15:11:33 -0400 From: "Theodore Ts'o" To: yangerkun Cc: jack@suse.cz, linux-ext4@vger.kernel.org, yukuai3@huawei.com Subject: Re: [PATCH] ext4: flush s_error_work before journal destroy in ext4_fill_super Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org On Fri, Jul 23, 2021 at 09:11:08PM +0800, yangerkun wrote: > > For example, before wo goto failed_mount_wq, we may meet some error and will > goto ext4_handle_error which can call > schedule_work(&EXT4_SB(sb)->s_error_work). So the work may start concurrent > with ext4_fill_super goto failed_mount_wq. There does not have any lock to > protect the concurrent read and modifies for sbi->s_journal. Yes, and I'm asking *how* is this actually happening in practice? I've been going through the code paths and I don't see any place where ext4_error*() would be called. That's why I wanted to see your test case which was reproducing it. (Not just where you added the msleep, but how the error was getting triggered in the first place.) On Fri, Jul 23, 2021 at 09:25:12PM +0800, yangerkun wrote: > > > Can you share with me your test case? Your patch will result in the > > shrinker potentially not getting released in some error paths (which > > will cause other kernel panics), and in any case, once the journal is > > The only logic we have changed is that we move the flush_work before we call > jbd2_journal_destory. I have not seen the problem you describe... Can you > help to explain more... Sorry, I was mistaken. I thought you were moving the ext4_es_unregister_shrinker() and flush_work() before the label for failed_mount_wq; that was a misreading of your patch. The other way we could fix this might be something like this: diff --git a/fs/ext4/super.c b/fs/ext4/super.c index dfa09a277b56..d663d11fa0de 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -693,7 +693,7 @@ static void flush_stashed_error_work(struct work_struct *work) { struct ext4_sb_info *sbi = container_of(work, struct ext4_sb_info, s_error_work); - journal_t *journal = sbi->s_journal; + journal_t *journal = READ_ONCE(sbi->s_journal); handle_t *handle; /* @@ -1184,9 +1184,11 @@ static void ext4_put_super(struct super_block *sb) ext4_unregister_sysfs(sb); if (sbi->s_journal) { - aborted = is_journal_aborted(sbi->s_journal); - err = jbd2_journal_destroy(sbi->s_journal); - sbi->s_journal = NULL; + journal_t *journal = sbi->s_journal; + + WRITE_ONCE(sbi->s_journal, NULL); + aborted = is_journal_aborted(journal); + err = jbd2_journal_destroy(journal); if ((err < 0) && !aborted) { ext4_abort(sb, -err, "Couldn't clean up the journal"); } @@ -5175,8 +5177,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) sbi->s_ea_block_cache = NULL; if (sbi->s_journal) { - jbd2_journal_destroy(sbi->s_journal); - sbi->s_journal = NULL; + journal_t *journal = sbi->s_journal; + + WRITE_ONCE(sbi->s_journal, NULL); + jbd2_journal_destroy(journal); } failed_mount3a: ext4_es_unregister_shrinker(sbi); @@ -5487,7 +5491,7 @@ static int ext4_load_journal(struct super_block *sb, EXT4_SB(sb)->s_journal = journal; err = ext4_clear_journal_err(sb, es); if (err) { - EXT4_SB(sb)->s_journal = NULL; + WRITE_ONCE(EXT4_SB(sb)->s_journal, NULL); jbd2_journal_destroy(journal); return err; } ... and here's another possible fix: diff --git a/fs/ext4/super.c b/fs/ext4/super.c index dfa09a277b56..e9e122e52ce8 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -704,7 +704,8 @@ static void flush_stashed_error_work(struct work_struct *work) * We use directly jbd2 functions here to avoid recursing back into * ext4 error handling code during handling of previous errors. */ - if (!sb_rdonly(sbi->s_sb) && journal) { + if (!sb_rdonly(sbi->s_sb) && journal && + !(journal->j_flags & JBD2_UNMOUNT)) { struct buffer_head *sbh = sbi->s_sbh; handle = jbd2_journal_start(journal, 1); if (IS_ERR(handle)) But I would be interested in understanding how we could be triggering this problem in the first place before deciding what's the best fix. Cheers, - Ted