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

Reply via email to