Before this patch, function run_queue would do special processing
before calling the state machine for the blocking and non-blocking
demote-in-progress cases. This function rolls those functions into
the state machine, which will allow us to eventually simplify with
later patches.

Signed-off-by: Bob Peterson <rpete...@redhat.com>
---
 fs/gfs2/glock.c | 44 +++++++++++++++++++++++++++++---------------
 fs/gfs2/glock.h |  2 ++
 2 files changed, 31 insertions(+), 15 deletions(-)

diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 8dc98d069afa..023e2186b374 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -631,21 +631,9 @@ __acquires(&gl->gl_lockref.lock)
 
        if (test_bit(GLF_DEMOTE, &gl->gl_flags) &&
            gl->gl_demote_state != gl->gl_state) {
-               if (find_first_holder(gl)) {
-                       clear_bit(GLF_LOCK, &gl->gl_flags);
-                       smp_mb__after_atomic();
-                       return;
-               }
-               if (nonblock) {
-                       clear_bit(GLF_LOCK, &gl->gl_flags);
-                       smp_mb__after_atomic();
-                       gl->gl_lockref.count++;
-                       __gfs2_glock_queue_work(gl, 0);
-                       return;
-               }
-               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;
+               __state_machine(gl, nonblock ? GL_ST_DEMOTE_NONBLOCK :
+                               GL_ST_BLOCKING_DEMOTE);
+               return;
        } else {
                if (test_bit(GLF_DEMOTE, &gl->gl_flags))
                        gfs2_demote_wake(gl);
@@ -713,6 +701,32 @@ static void __state_machine(struct gfs2_glock *gl, int 
new_state)
                        if (ret == -EAGAIN)
                                gl->gl_mch = GL_ST_FINISH_XMOTE;
                        break;
+
+               case GL_ST_BLOCKING_DEMOTE:
+                       gl->gl_mch = GL_ST_IDLE;
+                       if (find_first_holder(gl)) {
+                               clear_bit(GLF_LOCK, &gl->gl_flags);
+                               smp_mb__after_atomic();
+                               break;
+                       }
+                       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;
+                       gl->gl_mch = GL_ST_DO_XMOTE;
+                       break;
+
+               case GL_ST_DEMOTE_NONBLOCK:
+                       gl->gl_mch = GL_ST_IDLE;
+                       if (find_first_holder(gl)) {
+                               clear_bit(GLF_LOCK, &gl->gl_flags);
+                               smp_mb__after_atomic();
+                               break;
+                       }
+                       clear_bit(GLF_LOCK, &gl->gl_flags);
+                       smp_mb__after_atomic();
+                       gl->gl_lockref.count++;
+                       __gfs2_glock_queue_work(gl, 0);
+                       break;
                }
        } while (gl->gl_mch != GL_ST_IDLE);
 }
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h
index 8333bbc5a197..c8b704a73638 100644
--- a/fs/gfs2/glock.h
+++ b/fs/gfs2/glock.h
@@ -126,6 +126,8 @@ enum gl_machine_states {
        GL_ST_DO_XMOTE = 2,     /* Promote or demote a waiter */
        GL_ST_DO_XMOTE_UNLOCK = 3, /* Promote or demote a waiter after a failed
                                      state change attempt from dlm. */
+       GL_ST_DEMOTE_NONBLOCK = 4, /* Demote is in progress - non-blocking */
+       GL_ST_BLOCKING_DEMOTE = 5, /* Demote is in progress - blocking */
 };
 
 struct lm_lockops {
-- 
2.19.1

Reply via email to