Commit 87124e581bfeaa5864662a435b6ee2a19e91b905
1 parent
bbf25010f1
Exists in
master
and in
20 other branches
[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>
Showing 1 changed file with 18 additions and 6 deletions Side-by-side Diff
fs/gfs2/glock.c
... | ... | @@ -545,12 +545,14 @@ |
545 | 545 | return 0; |
546 | 546 | } |
547 | 547 | set_bit(GLF_LOCK, &gl->gl_flags); |
548 | - spin_unlock(&gl->gl_spin); | |
549 | 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 | 551 | gfs2_glock_drop_th(gl); |
552 | - else | |
552 | + } else { | |
553 | + spin_unlock(&gl->gl_spin); | |
553 | 554 | gfs2_glock_xmote_th(gl, NULL); |
555 | + } | |
554 | 556 | spin_lock(&gl->gl_spin); |
555 | 557 | |
556 | 558 | return 0; |
557 | 559 | |
558 | 560 | |
... | ... | @@ -760,10 +762,20 @@ |
760 | 762 | |
761 | 763 | if (!gh) { |
762 | 764 | gl->gl_stamp = jiffies; |
763 | - if (ret & LM_OUT_CANCELED) | |
765 | + if (ret & LM_OUT_CANCELED) { | |
764 | 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 | 776 | gfs2_demote_wake(gl); |
777 | + spin_unlock(&gl->gl_spin); | |
778 | + } | |
767 | 779 | } else { |
768 | 780 | spin_lock(&gl->gl_spin); |
769 | 781 | list_del_init(&gh->gh_list); |
... | ... | @@ -817,7 +829,7 @@ |
817 | 829 | * |
818 | 830 | */ |
819 | 831 | |
820 | -void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh) | |
832 | +static void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh) | |
821 | 833 | { |
822 | 834 | struct gfs2_sbd *sdp = gl->gl_sbd; |
823 | 835 | int flags = gh ? gh->gh_flags : 0; |