GFS2: Fix potential race in glock code
authorSteven Whitehouse <swhiteho@redhat.com>
Tue, 22 Sep 2009 09:56:16 +0000 (10:56 +0100)
committerSteven Whitehouse <swhiteho@redhat.com>
Thu, 3 Dec 2009 11:42:25 +0000 (11:42 +0000)
We need to be careful of the ordering between clearing the
GLF_LOCK bit and scheduling the workqueue.

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

index 8b674b1f3a554d4300e7965328f750c13b34bbe1..a3f90ad2af806cd5ddf0d61e6dd88768c669b670 100644 (file)
@@ -672,12 +672,17 @@ out:
        return;
 
 out_sched:
+       clear_bit(GLF_LOCK, &gl->gl_flags);
+       smp_mb__after_clear_bit();
        gfs2_glock_hold(gl);
        if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
                gfs2_glock_put_nolock(gl);
+       return;
+
 out_unlock:
        clear_bit(GLF_LOCK, &gl->gl_flags);
-       goto out;
+       smp_mb__after_clear_bit();
+       return;
 }
 
 static void delete_work_func(struct work_struct *work)
@@ -1375,10 +1380,11 @@ static int gfs2_shrink_glock_memory(int nr, gfp_t gfp_mask)
                                handle_callback(gl, LM_ST_UNLOCKED, 0);
                                nr--;
                        }
+                       clear_bit(GLF_LOCK, &gl->gl_flags);
+                       smp_mb__after_clear_bit();
                        if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
                                gfs2_glock_put_nolock(gl);
                        spin_unlock(&gl->gl_spin);
-                       clear_bit(GLF_LOCK, &gl->gl_flags);
                        spin_lock(&lru_lock);
                        continue;
                }