gfs2: Avoid dequeuing GL_ASYNC glock holders twice
authorAndreas Gruenbacher <agruenba@redhat.com>
Sun, 4 Dec 2022 12:02:39 +0000 (13:02 +0100)
committerAndreas Gruenbacher <agruenba@redhat.com>
Tue, 6 Dec 2022 15:06:31 +0000 (16:06 +0100)
When a locking request fails, the associated glock holder is
automatically dequeued from the list of active and waiting holders.  For
GL_ASYNC locking requests, this will obviously happen asynchronously
and it can race with attempts to cancel that locking request via
gfs2_glock_dq().  Therefore, don't forget to check if a locking request
has already been dequeued in gfs2_glock_dq().

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

index 1a6c1eb..0f5c5c1 100644 (file)
@@ -1707,6 +1707,13 @@ void gfs2_glock_dq(struct gfs2_holder *gh)
        struct gfs2_glock *gl = gh->gh_gl;
 
        spin_lock(&gl->gl_lockref.lock);
+       if (!gfs2_holder_queued(gh)) {
+               /*
+                * May have already been dequeued because the locking request
+                * was GL_ASYNC and it has failed in the meantime.
+                */
+               goto out;
+       }
        if (list_is_first(&gh->gh_list, &gl->gl_holders) &&
            !test_bit(HIF_HOLDER, &gh->gh_iflags)) {
                spin_unlock(&gl->gl_lockref.lock);
@@ -1716,6 +1723,7 @@ void gfs2_glock_dq(struct gfs2_holder *gh)
        }
 
        __gfs2_glock_dq(gh);
+out:
        spin_unlock(&gl->gl_lockref.lock);
 }