From: Bob Peterson <rpete...@redhat.com>

In do_promote(), when the glock had no strong holders, we were
accidentally calling demote_incompat_holders() with new_gh == NULL, so
no weak holders were considered incompatible.  Instead, the new holder
should have been passed in.

For doing that, the HIF_HOLDER flag needs to be set in new_gh to prevent
may_grant() from complaining.  This means that the new holder will now
be recognized as a current holder, so skip over it explicitly in
demote_incompat_holders() to prevent it from being dequeued.

To further clarify things, we can now rename new_gh to current_gh in
demote_incompat_holders(); after all, the HIF_HOLDER flag is already set,
which means the new holder is already a current holder.

Signed-off-by: Bob Peterson <rpete...@redhat.com>
Signed-off-by: Andreas Gruenbacher <agrue...@redhat.com>
---
 fs/gfs2/glock.c | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 27b519099579..2138460a7369 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -405,10 +405,13 @@ static void do_error(struct gfs2_glock *gl, const int ret)
 /**
  * demote_incompat_holders - demote incompatible demoteable holders
  * @gl: the glock we want to promote
- * @new_gh: the new holder to be promoted
+ * @current_gh: the newly promoted holder
+ *
+ * We're passing the newly promoted holder in @current_gh, but actually, any of
+ * the strong holders would do.
  */
 static void demote_incompat_holders(struct gfs2_glock *gl,
-                                   struct gfs2_holder *new_gh)
+                                   struct gfs2_holder *current_gh)
 {
        struct gfs2_holder *gh, *tmp;
 
@@ -424,8 +427,10 @@ static void demote_incompat_holders(struct gfs2_glock *gl,
                 */
                if (!test_bit(HIF_HOLDER, &gh->gh_iflags))
                        return;
+               if (gh == current_gh)
+                       continue;
                if (test_bit(HIF_MAY_DEMOTE, &gh->gh_iflags) &&
-                   !may_grant(gl, new_gh, gh)) {
+                   !may_grant(gl, current_gh, gh)) {
                        /*
                         * We should not recurse into do_promote because
                         * __gfs2_glock_dq only calls handle_callback,
@@ -547,14 +552,14 @@ static int do_promote(struct gfs2_glock *gl)
                        do_error(gl, 0);
                        break;
                }
+               set_bit(HIF_HOLDER, &gh->gh_iflags);
+               trace_gfs2_promote(gh);
+               gfs2_holder_wake(gh);
                if (!incompat_holders_demoted) {
+                       current_gh = gh;
                        demote_incompat_holders(gl, current_gh);
                        incompat_holders_demoted = true;
-                       current_gh = gh;
                }
-               set_bit(HIF_HOLDER, &gh->gh_iflags);
-               trace_gfs2_promote(gh);
-               gfs2_holder_wake(gh);
        }
        return 0;
 }
-- 
2.35.1

Reply via email to