diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2009-09-22 05:56:16 -0400 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2009-12-03 06:42:25 -0500 |
commit | 7e71c55ee73988d0cb61045660b899eaac23bf8f (patch) | |
tree | ef96dc44cd067cc758a8df0408ba36818c9ebc35 /fs/gfs2/glock.c | |
parent | 22763c5cf3690a681551162c15d34d935308c8d7 (diff) |
GFS2: Fix potential race in glock code
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>
Diffstat (limited to 'fs/gfs2/glock.c')
-rw-r--r-- | fs/gfs2/glock.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 8b674b1f3a55..a3f90ad2af80 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
@@ -672,12 +672,17 @@ out: | |||
672 | return; | 672 | return; |
673 | 673 | ||
674 | out_sched: | 674 | out_sched: |
675 | clear_bit(GLF_LOCK, &gl->gl_flags); | ||
676 | smp_mb__after_clear_bit(); | ||
675 | gfs2_glock_hold(gl); | 677 | gfs2_glock_hold(gl); |
676 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) | 678 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) |
677 | gfs2_glock_put_nolock(gl); | 679 | gfs2_glock_put_nolock(gl); |
680 | return; | ||
681 | |||
678 | out_unlock: | 682 | out_unlock: |
679 | clear_bit(GLF_LOCK, &gl->gl_flags); | 683 | clear_bit(GLF_LOCK, &gl->gl_flags); |
680 | goto out; | 684 | smp_mb__after_clear_bit(); |
685 | return; | ||
681 | } | 686 | } |
682 | 687 | ||
683 | static void delete_work_func(struct work_struct *work) | 688 | 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) | |||
1375 | handle_callback(gl, LM_ST_UNLOCKED, 0); | 1380 | handle_callback(gl, LM_ST_UNLOCKED, 0); |
1376 | nr--; | 1381 | nr--; |
1377 | } | 1382 | } |
1383 | clear_bit(GLF_LOCK, &gl->gl_flags); | ||
1384 | smp_mb__after_clear_bit(); | ||
1378 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) | 1385 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) |
1379 | gfs2_glock_put_nolock(gl); | 1386 | gfs2_glock_put_nolock(gl); |
1380 | spin_unlock(&gl->gl_spin); | 1387 | spin_unlock(&gl->gl_spin); |
1381 | clear_bit(GLF_LOCK, &gl->gl_flags); | ||
1382 | spin_lock(&lru_lock); | 1388 | spin_lock(&lru_lock); |
1383 | continue; | 1389 | continue; |
1384 | } | 1390 | } |