]> err.no Git - linux-2.6/commitdiff
[GFS2] Fix delayed demote race
authorSteven Whitehouse <swhiteho@redhat.com>
Mon, 7 Jul 2008 09:02:36 +0000 (10:02 +0100)
committerSteven Whitehouse <swhiteho@redhat.com>
Mon, 7 Jul 2008 09:02:36 +0000 (10:02 +0100)
There is a race in the delayed demote code where it does the wrong thing
if a demotion to UN has occurred for other reasons before the delay has
expired. This patch adds an assert to catch that condition as well as
fixing the root cause by adding an additional check for the UN state.

Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Cc: Bob Peterson <rpeterso@redhat.com>
fs/gfs2/glock.c

index 8d5450f3c3ef562d87f9cd66cf2e3b7c530a64a0..cd0aa213fb2f56e29037f9f152637ddde1bcee2a 100644 (file)
@@ -587,6 +587,7 @@ static void run_queue(struct gfs2_glock *gl, const int nonblock)
                if (nonblock)
                        goto out_sched;
                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;
        } else {
                if (test_bit(GLF_DEMOTE, &gl->gl_flags))
@@ -617,7 +618,9 @@ static void glock_work_func(struct work_struct *work)
        if (test_and_clear_bit(GLF_REPLY_PENDING, &gl->gl_flags))
                finish_xmote(gl, gl->gl_reply);
        spin_lock(&gl->gl_spin);
-       if (test_and_clear_bit(GLF_PENDING_DEMOTE, &gl->gl_flags)) {
+       if (test_and_clear_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) &&
+           gl->gl_state != LM_ST_UNLOCKED &&
+           gl->gl_demote_state != LM_ST_EXCLUSIVE) {
                unsigned long holdtime, now = jiffies;
                holdtime = gl->gl_tchange + gl->gl_ops->go_min_hold_time;
                if (time_before(now, holdtime))