Commit 87124e581bfeaa5864662a435b6ee2a19e91b905

Authored by Steven Whitehouse
1 parent bbf25010f1

[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

... ... @@ -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;