[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>
This commit is contained in:
parent
bbf25010f1
commit
87124e581b
1 changed files with 18 additions and 6 deletions
|
@ -545,12 +545,14 @@ static int rq_demote(struct gfs2_glock *gl)
|
|||
return 0;
|
||||
}
|
||||
set_bit(GLF_LOCK, &gl->gl_flags);
|
||||
spin_unlock(&gl->gl_spin);
|
||||
if (gl->gl_demote_state == LM_ST_UNLOCKED ||
|
||||
gl->gl_state != LM_ST_EXCLUSIVE)
|
||||
gl->gl_state != LM_ST_EXCLUSIVE) {
|
||||
spin_unlock(&gl->gl_spin);
|
||||
gfs2_glock_drop_th(gl);
|
||||
else
|
||||
} else {
|
||||
spin_unlock(&gl->gl_spin);
|
||||
gfs2_glock_xmote_th(gl, NULL);
|
||||
}
|
||||
spin_lock(&gl->gl_spin);
|
||||
|
||||
return 0;
|
||||
|
@ -760,10 +762,20 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
|
|||
|
||||
if (!gh) {
|
||||
gl->gl_stamp = jiffies;
|
||||
if (ret & LM_OUT_CANCELED)
|
||||
if (ret & LM_OUT_CANCELED) {
|
||||
op_done = 0;
|
||||
else
|
||||
} else {
|
||||
spin_lock(&gl->gl_spin);
|
||||
if (gl->gl_state != gl->gl_demote_state) {
|
||||
gl->gl_req_bh = NULL;
|
||||
spin_unlock(&gl->gl_spin);
|
||||
gfs2_glock_drop_th(gl);
|
||||
gfs2_glock_put(gl);
|
||||
return;
|
||||
}
|
||||
gfs2_demote_wake(gl);
|
||||
spin_unlock(&gl->gl_spin);
|
||||
}
|
||||
} else {
|
||||
spin_lock(&gl->gl_spin);
|
||||
list_del_init(&gh->gh_list);
|
||||
|
@ -817,7 +829,7 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
|
|||
*
|
||||
*/
|
||||
|
||||
void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh)
|
||||
static void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh)
|
||||
{
|
||||
struct gfs2_sbd *sdp = gl->gl_sbd;
|
||||
int flags = gh ? gh->gh_flags : 0;
|
||||
|
|
Loading…
Reference in a new issue