aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2007-07-23 04:54:36 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2007-10-10 03:54:39 -0400
commit87124e581bfeaa5864662a435b6ee2a19e91b905 (patch)
treef9bc5d965834f1c7435123f26b9ab8f961c8848f
parentbbf25010f1a6b761914430f5fca081ec8c7accd1 (diff)
[GFS2] Fix two races relating to glock callbacks
One of the races relates to referencing a variable while not holding its protecting spinlock. The patch simply moves the test inside the spin lock. The other races occurs when a demote to unlocked request occurs during the time a demote to shared request is already running. This of course only happens in the case that the lock was in the exclusive mode to start with. The patch adds a check to see if another demote request has occurred in the mean time and if it has, then it performs a second demote. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
-rw-r--r--fs/gfs2/glock.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 3f0974e1afef..6a3eeba102f9 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -545,12 +545,14 @@ static int rq_demote(struct gfs2_glock *gl)
545 return 0; 545 return 0;
546 } 546 }
547 set_bit(GLF_LOCK, &gl->gl_flags); 547 set_bit(GLF_LOCK, &gl->gl_flags);
548 spin_unlock(&gl->gl_spin);
549 if (gl->gl_demote_state == LM_ST_UNLOCKED || 548 if (gl->gl_demote_state == LM_ST_UNLOCKED ||
550 gl->gl_state != LM_ST_EXCLUSIVE) 549 gl->gl_state != LM_ST_EXCLUSIVE) {
550 spin_unlock(&gl->gl_spin);
551 gfs2_glock_drop_th(gl); 551 gfs2_glock_drop_th(gl);
552 else 552 } else {
553 spin_unlock(&gl->gl_spin);
553 gfs2_glock_xmote_th(gl, NULL); 554 gfs2_glock_xmote_th(gl, NULL);
555 }
554 spin_lock(&gl->gl_spin); 556 spin_lock(&gl->gl_spin);
555 557
556 return 0; 558 return 0;
@@ -760,10 +762,20 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
760 762
761 if (!gh) { 763 if (!gh) {
762 gl->gl_stamp = jiffies; 764 gl->gl_stamp = jiffies;
763 if (ret & LM_OUT_CANCELED) 765 if (ret & LM_OUT_CANCELED) {
764 op_done = 0; 766 op_done = 0;
765 else 767 } else {
768 spin_lock(&gl->gl_spin);
769 if (gl->gl_state != gl->gl_demote_state) {
770 gl->gl_req_bh = NULL;
771 spin_unlock(&gl->gl_spin);
772 gfs2_glock_drop_th(gl);
773 gfs2_glock_put(gl);
774 return;
775 }
766 gfs2_demote_wake(gl); 776 gfs2_demote_wake(gl);
777 spin_unlock(&gl->gl_spin);
778 }
767 } else { 779 } else {
768 spin_lock(&gl->gl_spin); 780 spin_lock(&gl->gl_spin);
769 list_del_init(&gh->gh_list); 781 list_del_init(&gh->gh_list);
@@ -817,7 +829,7 @@ out:
817 * 829 *
818 */ 830 */
819 831
820void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh) 832static void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh)
821{ 833{
822 struct gfs2_sbd *sdp = gl->gl_sbd; 834 struct gfs2_sbd *sdp = gl->gl_sbd;
823 int flags = gh ? gh->gh_flags : 0; 835 int flags = gh ? gh->gh_flags : 0;