Before this patch, the state machine could call do_xmote which, in turn, could call back into the state machine. This patch unravels the logic so instead it sends back an -EAGAIN return code, which signals the state machine to loop under the new state.
Signed-off-by: Bob Peterson <rpete...@redhat.com> --- fs/gfs2/glock.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index b541c4053dd7..8dc98d069afa 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -527,9 +527,11 @@ static int finish_xmote(struct gfs2_glock *gl) * @gl: The lock state * @target: The target lock state * + * Returns: 0 if the lock is pending, or + * -EAGAIN if we need to run the state machine again to finish_xmote */ -static void do_xmote(struct gfs2_glock *gl, unsigned int target) +static int do_xmote(struct gfs2_glock *gl, unsigned int target) __releases(&gl->gl_lockref.lock) __acquires(&gl->gl_lockref.lock) { @@ -537,11 +539,11 @@ __acquires(&gl->gl_lockref.lock) struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; struct gfs2_holder *gh = find_first_waiter(gl); unsigned int lck_flags = (unsigned int)(gh ? gh->gh_flags : 0); - int ret; + int ret = 0; if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) && target != LM_ST_UNLOCKED) - return; + return 0; lck_flags &= (LM_FLAG_TRY | LM_FLAG_TRY_1CB | LM_FLAG_NOEXP | LM_FLAG_PRIORITY); GLOCK_BUG_ON(gl, gl->gl_state == target); @@ -572,21 +574,23 @@ __acquires(&gl->gl_lockref.lock) target == LM_ST_UNLOCKED && test_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags)) { gl->gl_reply = target; - state_machine(gl, GL_ST_FINISH_XMOTE); + ret = -EAGAIN; gfs2_glock_queue_work(gl, 0); } else if (ret) { fs_err(sdp, "lm_lock ret %d\n", ret); GLOCK_BUG_ON(gl, !test_bit(SDF_SHUTDOWN, &sdp->sd_flags)); + ret = 0; } } else { /* lock_nolock */ gl->gl_reply = target; - state_machine(gl, GL_ST_FINISH_XMOTE); + ret = -EAGAIN; gfs2_glock_queue_work(gl, 0); } spin_lock(&gl->gl_lockref.lock); + return ret; } /** @@ -698,13 +702,16 @@ static void __state_machine(struct gfs2_glock *gl, int new_state) case GL_ST_DO_XMOTE: gl->gl_mch = GL_ST_IDLE; - do_xmote(gl, gl->gl_target); + ret = do_xmote(gl, gl->gl_target); + if (ret == -EAGAIN) + gl->gl_mch = GL_ST_FINISH_XMOTE; break; case GL_ST_DO_XMOTE_UNLOCK: gl->gl_mch = GL_ST_IDLE; - do_xmote(gl, LM_ST_UNLOCKED); - finish_xmote(gl); + ret = do_xmote(gl, LM_ST_UNLOCKED); + if (ret == -EAGAIN) + gl->gl_mch = GL_ST_FINISH_XMOTE; break; } } while (gl->gl_mch != GL_ST_IDLE); -- 2.19.1