gfs2: Dequeue waiters when withdrawn
authorBob Peterson <rpeterso@redhat.com>
Thu, 18 Aug 2022 18:32:37 +0000 (13:32 -0500)
committerAndreas Gruenbacher <agruenba@redhat.com>
Thu, 25 Aug 2022 15:11:14 +0000 (17:11 +0200)
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 <rpeterso@redhat.com>
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
fs/gfs2/glock.c
fs/gfs2/glock.h
fs/gfs2/util.c

index 57dcfd0..858616a 100644 (file)
@@ -2196,6 +2196,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
index 5aed8b5..0199a3d 100644 (file)
@@ -274,6 +274,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_thaw(struct gfs2_sbd *sdp);
 extern void gfs2_glock_add_to_lru(struct gfs2_glock *gl);
 extern void gfs2_glock_free(struct gfs2_glock *gl);
index 95c79a3..88185a3 100644 (file)
@@ -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);
        }