gfs2: cancel timed-out glock requests
authorAndreas Gruenbacher <agruenba@redhat.com>
Mon, 24 Jan 2022 17:23:55 +0000 (12:23 -0500)
committerAndreas Gruenbacher <agruenba@redhat.com>
Tue, 15 Feb 2022 14:01:40 +0000 (15:01 +0100)
The gfs2 evict code tries to upgrade the iopen glock from SH to EX. If
the attempt to upgrade times out, gfs2 needs to tell dlm to cancel the
lock request or it can deadlock. We also need to wake up the process
waiting for the lock when dlm sends its AST back to gfs2.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
fs/gfs2/glock.c

index 6b23399eaee0cbcb6ea340a6741faf86957e4580..d368d9a2e8f00c277c16da9aac0f546469f74b1f 100644 (file)
@@ -669,6 +669,8 @@ static void finish_xmote(struct gfs2_glock *gl, unsigned int ret)
 
        /* Check for state != intended state */
        if (unlikely(state != gl->gl_target)) {
+               if (gh && (ret & LM_OUT_CANCELED))
+                       gfs2_holder_wake(gh);
                if (gh && !test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags)) {
                        /* move to back of queue and try next entry */
                        if (ret & LM_OUT_CANCELED) {
@@ -1691,6 +1693,14 @@ void gfs2_glock_dq(struct gfs2_holder *gh)
        struct gfs2_glock *gl = gh->gh_gl;
 
        spin_lock(&gl->gl_lockref.lock);
+       if (list_is_first(&gh->gh_list, &gl->gl_holders) &&
+           !test_bit(HIF_HOLDER, &gh->gh_iflags)) {
+               spin_unlock(&gl->gl_lockref.lock);
+               gl->gl_name.ln_sbd->sd_lockstruct.ls_ops->lm_cancel(gl);
+               wait_on_bit(&gh->gh_iflags, HIF_WAIT, TASK_UNINTERRUPTIBLE);
+               spin_lock(&gl->gl_lockref.lock);
+       }
+
        __gfs2_glock_dq(gh);
        spin_unlock(&gl->gl_lockref.lock);
 }