Received: by 2002:a05:6a10:9848:0:0:0:0 with SMTP id x8csp3407672pxf; Mon, 22 Mar 2021 05:53:59 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxv60535eDBq4oqpZPsvpc+j+FnpS3OfjSx5XbHo6sHAcxcKFb47VBZ4be28TLsTyJDtQea X-Received: by 2002:aa7:d448:: with SMTP id q8mr15996963edr.345.1616417639648; Mon, 22 Mar 2021 05:53:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1616417639; cv=none; d=google.com; s=arc-20160816; b=MFQsfLtpZnkbUIJsdwz87ctTT4k/ZOGB4yd+aK9lHL5W5EMkoUh6hZd8Xu2VUzqNAe k8gwAm4vSB5ufKLcn+2/HGNtcA9aJ75x5ZAEqJ1qz+OSrJSHgI3t4NR8yfbJguXGHx0u tyysFpqzJpyNFd66WjlqyMC7DRxnBbQMcYPOIht3K5DTdD3vofPpH2OXWPkAksjnG3Lh NHzGpyxxvfDA+lPuamtJRyIUS5koU4oVS7eREE9qpD4C92GWWxXn2osrCUem2Ko6+Lax Hl2vLDQu34DrMlgse1r+0ydsDKmlG0g/DYJn3iWCo6oIKUM/rF0vTg9cxjOM0UrbAhxD /wVw== 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:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=yuV8ZjtPv/yg78pYGbeMe1FCJvYDIUjWyw+GFItqLHo=; b=aOvkGOFyg4h7J5+1RUo4A2nP1ZerKMfImuBebW2jXmYluMxncpVB5yTBB4cOZh/P2L AUVeO2Wc5V/udjUEpyaopIpESNAouJEPiGmAg/C9h7am3J5Y8TDLq4wNgHs1tUi9H/tP ZOk3LPEDRmYhqw+4CDjWLFwdbRGgzTxa710OmnNpieralzX+dZYjWyy0aX8mu9zvwpYZ vf/no6s53uE6dQG3Vrf9mzmdBowy+6BLBZn3pHjdMmapeVL2KeK4RdUYcIdMViLx7HRw M/BSsgP2oiz5K8CmxpESXFmc6TtofHLBAdy5qB2wVcLx026s97AzF6Cfo1CyAvFTkpkM n73Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=Gg00+PEU; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id t12si11199310eds.41.2021.03.22.05.53.36; Mon, 22 Mar 2021 05:53:59 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=Gg00+PEU; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232954AbhCVMxF (ORCPT + 99 others); Mon, 22 Mar 2021 08:53:05 -0400 Received: from mail.kernel.org ([198.145.29.99]:35490 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232662AbhCVMnI (ORCPT ); Mon, 22 Mar 2021 08:43:08 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id C37B0619D1; Mon, 22 Mar 2021 12:40:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1616416855; bh=sDHk8xZSZeztgc/KGiaApaFqQzV99eogsvFOk1JoAEM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Gg00+PEUof8crB22nLRdIhlOAqeKF5naetNIDmO3aDGEvXLxXnxFURSTwl39rSQJk eqQjvlmq3rrakDo3TksaxUkeistIWgkGzJNmsyA3c54Lm3k06HZObRB1+XZoqoqFRI 8tFHs0F67VLKCUokMGGEv1ZyVhptZkIPNBnXQAC8= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Bob Peterson , Andreas Gruenbacher , Sasha Levin Subject: [PATCH 5.10 113/157] gfs2: move freeze glock outside the make_fs_rw and _ro functions Date: Mon, 22 Mar 2021 13:27:50 +0100 Message-Id: <20210322121937.359810721@linuxfoundation.org> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20210322121933.746237845@linuxfoundation.org> References: <20210322121933.746237845@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Bob Peterson [ Upstream commit 96b1454f2e8ede4c619fde405a1bb4e9ba8d218e ] Before this patch, sister functions gfs2_make_fs_rw and gfs2_make_fs_ro locked (held) the freeze glock by calling gfs2_freeze_lock and gfs2_freeze_unlock. The problem is, not all the callers of gfs2_make_fs_ro should be doing this. The three callers of gfs2_make_fs_ro are: remount (gfs2_reconfigure), signal_our_withdraw, and unmount (gfs2_put_super). But when unmounting the file system we can get into the following circular lock dependency: deactivate_super down_write(&s->s_umount); <-------------------------------------- s_umount deactivate_locked_super gfs2_kill_sb kill_block_super generic_shutdown_super gfs2_put_super gfs2_make_fs_ro gfs2_glock_nq_init sd_freeze_gl freeze_go_sync if (freeze glock in SH) freeze_super (vfs) down_write(&sb->s_umount); <------- s_umount This patch moves the hold of the freeze glock outside the two sister rw/ro functions to their callers, but it doesn't request the glock from gfs2_put_super, thus eliminating the circular dependency. Signed-off-by: Bob Peterson Signed-off-by: Andreas Gruenbacher Signed-off-by: Sasha Levin --- fs/gfs2/ops_fstype.c | 31 +++++++++++++++++-------------- fs/gfs2/super.c | 23 ----------------------- fs/gfs2/util.c | 18 ++++++++++++++++-- 3 files changed, 33 insertions(+), 39 deletions(-) diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 4ee56f5e93cb..f2c6bbe5cdb8 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -1084,6 +1084,7 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc) int silent = fc->sb_flags & SB_SILENT; struct gfs2_sbd *sdp; struct gfs2_holder mount_gh; + struct gfs2_holder freeze_gh; int error; sdp = init_sbd(sb); @@ -1195,23 +1196,18 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc) goto fail_per_node; } - if (sb_rdonly(sb)) { - struct gfs2_holder freeze_gh; + error = gfs2_freeze_lock(sdp, &freeze_gh, 0); + if (error) + goto fail_per_node; - error = gfs2_freeze_lock(sdp, &freeze_gh, 0); - if (error) { - fs_err(sdp, "can't make FS RO: %d\n", error); - goto fail_per_node; - } - gfs2_freeze_unlock(&freeze_gh); - } else { + if (!sb_rdonly(sb)) error = gfs2_make_fs_rw(sdp); - if (error) { - fs_err(sdp, "can't make FS RW: %d\n", error); - goto fail_per_node; - } - } + gfs2_freeze_unlock(&freeze_gh); + if (error) { + fs_err(sdp, "can't make FS RW: %d\n", error); + goto fail_per_node; + } gfs2_glock_dq_uninit(&mount_gh); gfs2_online_uevent(sdp); return 0; @@ -1512,6 +1508,12 @@ static int gfs2_reconfigure(struct fs_context *fc) fc->sb_flags |= SB_RDONLY; if ((sb->s_flags ^ fc->sb_flags) & SB_RDONLY) { + struct gfs2_holder freeze_gh; + + error = gfs2_freeze_lock(sdp, &freeze_gh, 0); + if (error) + return -EINVAL; + if (fc->sb_flags & SB_RDONLY) { error = gfs2_make_fs_ro(sdp); if (error) @@ -1521,6 +1523,7 @@ static int gfs2_reconfigure(struct fs_context *fc) if (error) errorfc(fc, "unable to remount read-write"); } + gfs2_freeze_unlock(&freeze_gh); } sdp->sd_args = *newargs; diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 6b0e8c0bb110..ddd40c96f7a2 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -165,7 +165,6 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp) { struct gfs2_inode *ip = GFS2_I(sdp->sd_jdesc->jd_inode); struct gfs2_glock *j_gl = ip->i_gl; - struct gfs2_holder freeze_gh; struct gfs2_log_header_host head; int error; @@ -173,10 +172,6 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp) if (error) return error; - error = gfs2_freeze_lock(sdp, &freeze_gh, 0); - if (error) - goto fail_threads; - j_gl->gl_ops->go_inval(j_gl, DIO_METADATA); if (gfs2_withdrawn(sdp)) { error = -EIO; @@ -203,13 +198,9 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp) set_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags); - gfs2_freeze_unlock(&freeze_gh); - return 0; fail: - gfs2_freeze_unlock(&freeze_gh); -fail_threads: if (sdp->sd_quotad_process) kthread_stop(sdp->sd_quotad_process); sdp->sd_quotad_process = NULL; @@ -609,21 +600,9 @@ static void gfs2_dirty_inode(struct inode *inode, int flags) int gfs2_make_fs_ro(struct gfs2_sbd *sdp) { - struct gfs2_holder freeze_gh; int error = 0; int log_write_allowed = test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags); - gfs2_holder_mark_uninitialized(&freeze_gh); - if (sdp->sd_freeze_gl && - !gfs2_glock_is_locked_by_me(sdp->sd_freeze_gl)) { - error = gfs2_freeze_lock(sdp, &freeze_gh, - log_write_allowed ? 0 : LM_FLAG_TRY); - if (error == GLR_TRYFAILED) - error = 0; - if (error && !gfs2_withdrawn(sdp)) - return error; - } - gfs2_flush_delete_work(sdp); if (!log_write_allowed && current == sdp->sd_quotad_process) fs_warn(sdp, "The quotad daemon is withdrawing.\n"); @@ -652,8 +631,6 @@ int gfs2_make_fs_ro(struct gfs2_sbd *sdp) atomic_read(&sdp->sd_reserving_log) == 0, HZ * 5); } - gfs2_freeze_unlock(&freeze_gh); - gfs2_quota_cleanup(sdp); if (!log_write_allowed) diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c index c8d55055e495..a1ecb2b48250 100644 --- a/fs/gfs2/util.c +++ b/fs/gfs2/util.c @@ -123,6 +123,7 @@ static void signal_our_withdraw(struct gfs2_sbd *sdp) struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_glock *i_gl = ip->i_gl; u64 no_formal_ino = ip->i_no_formal_ino; + int log_write_allowed = test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags); int ret = 0; int tries; @@ -143,8 +144,21 @@ static void signal_our_withdraw(struct gfs2_sbd *sdp) * therefore we need to clear SDF_JOURNAL_LIVE manually. */ clear_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags); - if (!sb_rdonly(sdp->sd_vfs)) - ret = gfs2_make_fs_ro(sdp); + if (!sb_rdonly(sdp->sd_vfs)) { + struct gfs2_holder freeze_gh; + + gfs2_holder_mark_uninitialized(&freeze_gh); + if (sdp->sd_freeze_gl && + !gfs2_glock_is_locked_by_me(sdp->sd_freeze_gl)) { + ret = gfs2_freeze_lock(sdp, &freeze_gh, + log_write_allowed ? 0 : LM_FLAG_TRY); + if (ret == GLR_TRYFAILED) + ret = 0; + } + if (!ret) + ret = gfs2_make_fs_ro(sdp); + gfs2_freeze_unlock(&freeze_gh); + } if (sdp->sd_lockstruct.ls_ops->lm_lock == NULL) { /* lock_nolock */ if (!ret) -- 2.30.1