summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2008-07-07 10:02:36 +0100
committerSteven Whitehouse <swhiteho@redhat.com>2008-07-07 10:02:36 +0100
commit265d529cef6fd57698d79b3c0edd3a8178059ea6 (patch)
treed92cc42c3f9db89bdce635a78f9d8d1904dde43a
parentf58ba889106af60f52af792efbe1973e458a2138 (diff)
downloadlinux-3.10-265d529cef6fd57698d79b3c0edd3a8178059ea6.tar.gz
linux-3.10-265d529cef6fd57698d79b3c0edd3a8178059ea6.tar.bz2
linux-3.10-265d529cef6fd57698d79b3c0edd3a8178059ea6.zip
[GFS2] Fix delayed demote race
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>
-rw-r--r--fs/gfs2/glock.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 8d5450f3c3e..cd0aa213fb2 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -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))