]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
gfs2: Check for empty queue in run_queue
authorAndreas Gruenbacher <agruenba@redhat.com>
Thu, 6 Feb 2025 13:58:39 +0000 (14:58 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 29 May 2025 09:12:49 +0000 (11:12 +0200)
[ Upstream commit d838605fea6eabae3746a276fd448f6719eb3926 ]

In run_queue(), check if the queue of pending requests is empty instead
of blindly assuming that it won't be.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/gfs2/glock.c

index 65c07aa95718419cc3d2daecac841763d0d32b92..7f9cc7872214e2e5c24b0d5ef83058b9f2ae094a 100644 (file)
@@ -843,12 +843,13 @@ static void run_queue(struct gfs2_glock *gl, const int nonblock)
 __releases(&gl->gl_lockref.lock)
 __acquires(&gl->gl_lockref.lock)
 {
-       struct gfs2_holder *gh = NULL;
+       struct gfs2_holder *gh;
 
        if (test_bit(GLF_LOCK, &gl->gl_flags))
                return;
        set_bit(GLF_LOCK, &gl->gl_flags);
 
+       /* While a demote is in progress, the GLF_LOCK flag must be set. */
        GLOCK_BUG_ON(gl, test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags));
 
        if (test_bit(GLF_DEMOTE, &gl->gl_flags) &&
@@ -860,18 +861,22 @@ __acquires(&gl->gl_lockref.lock)
                set_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags);
                GLOCK_BUG_ON(gl, gl->gl_demote_state == LM_ST_EXCLUSIVE);
                gl->gl_target = gl->gl_demote_state;
+               do_xmote(gl, NULL, gl->gl_target);
+               return;
        } else {
                if (test_bit(GLF_DEMOTE, &gl->gl_flags))
                        gfs2_demote_wake(gl);
                if (do_promote(gl))
                        goto out_unlock;
                gh = find_first_waiter(gl);
+               if (!gh)
+                       goto out_unlock;
                gl->gl_target = gh->gh_state;
                if (!(gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)))
                        do_error(gl, 0); /* Fail queued try locks */
+               do_xmote(gl, gh, gl->gl_target);
+               return;
        }
-       do_xmote(gl, gh, gl->gl_target);
-       return;
 
 out_sched:
        clear_bit(GLF_LOCK, &gl->gl_flags);