From mboxrd@z Thu Jan 1 00:00:00 1970 From: Bob Peterson Date: Tue, 2 Aug 2022 12:58:10 -0500 Subject: [Cluster-devel] [PATCH 2/3] gfs2: Dequeue waiters when withdrawn In-Reply-To: <20220802175811.438067-1-rpeterso@redhat.com> References: <20220802175811.438067-1-rpeterso@redhat.com> Message-ID: <20220802175811.438067-3-rpeterso@redhat.com> List-Id: To: cluster-devel.redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit When a withdraw occurs, ordinary (not system) glocks may not be granted anymore. Later, when the file system is unmounted, gfs2_gl_hash_clear() tries to clear out all the glocks, but these un-grantable pending waiters prevent some glocks from being freed. So the unmount hangs, at least for its ten-minute timeout period. This patch takes measures to remove any pending waiters from the glocks that will never be granted. This allows the unmount to proceed in a reasonable period of time. Signed-off-by: Bob Peterson --- fs/gfs2/glock.c | 14 ++++++++++++++ fs/gfs2/glock.h | 1 + fs/gfs2/util.c | 5 +++++ 3 files changed, 20 insertions(+) diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index e540d1290099..0bfecffd71f1 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -2223,6 +2223,20 @@ static void dump_glock_func(struct gfs2_glock *gl) dump_glock(NULL, gl, true); } +static void withdraw_dq(struct gfs2_glock *gl) +{ + spin_lock(&gl->gl_lockref.lock); + if (!__lockref_is_dead(&gl->gl_lockref) && + glock_blocked_by_withdraw(gl)) + do_error(gl, LM_OUT_ERROR); /* remove pending waiters */ + spin_unlock(&gl->gl_lockref.lock); +} + +void gfs2_gl_dq_holders(struct gfs2_sbd *sdp) +{ + glock_hash_walk(withdraw_dq, sdp); +} + /** * gfs2_gl_hash_clear - Empty out the glock hash table * @sdp: the filesystem diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h index c0ae9100a0bc..d6fc449aa7ff 100644 --- a/fs/gfs2/glock.h +++ b/fs/gfs2/glock.h @@ -273,6 +273,7 @@ extern void gfs2_cancel_delete_work(struct gfs2_glock *gl); extern bool gfs2_delete_work_queued(const struct gfs2_glock *gl); extern void gfs2_flush_delete_work(struct gfs2_sbd *sdp); extern void gfs2_gl_hash_clear(struct gfs2_sbd *sdp); +extern void gfs2_gl_dq_holders(struct gfs2_sbd *sdp); extern void gfs2_glock_finish_truncate(struct gfs2_inode *ip); extern void gfs2_glock_thaw(struct gfs2_sbd *sdp); extern void gfs2_glock_add_to_lru(struct gfs2_glock *gl); diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c index 95c79a3ec161..88185a341504 100644 --- a/fs/gfs2/util.c +++ b/fs/gfs2/util.c @@ -164,6 +164,11 @@ static void signal_our_withdraw(struct gfs2_sbd *sdp) } if (!ret) gfs2_make_fs_ro(sdp); + /* + * Dequeue any pending non-system glock holders that can no + * longer be granted because the file system is withdrawn. + */ + gfs2_gl_dq_holders(sdp); gfs2_freeze_unlock(&freeze_gh); } -- 2.36.1