Commit 68835625 authored by Benjamin Marzinski's avatar Benjamin Marzinski Committed by Steven Whitehouse

[GFS2] Fix log entry list corruption

When glock_lo_add and rg_lo_add attempt to add an element to the log, they
check to see if has already been added before locking the log. If another
process adds that element to the log in this window between the check and
locking the log, the element will be added to the list twice. This causes
the log element list to become corrupted in such a way that the log element
can never be successfully removed from the list. This patch pulls the
list_empty() check inside the log lock, to remove this window.
Signed-off-by: default avatarBenjamin E. Marzinski <bmarzins@redhat.com>
Signed-off-by: default avatarSteven Whitehouse <swhiteho@redhat.com>
parent f35ac346
...@@ -33,16 +33,17 @@ static void glock_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) ...@@ -33,16 +33,17 @@ static void glock_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
tr->tr_touched = 1; tr->tr_touched = 1;
if (!list_empty(&le->le_list))
return;
gl = container_of(le, struct gfs2_glock, gl_le); gl = container_of(le, struct gfs2_glock, gl_le);
if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(gl))) if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(gl)))
return; return;
gfs2_glock_hold(gl);
set_bit(GLF_DIRTY, &gl->gl_flags);
gfs2_log_lock(sdp); gfs2_log_lock(sdp);
if (!list_empty(&le->le_list)){
gfs2_log_unlock(sdp);
return;
}
gfs2_glock_hold(gl);
set_bit(GLF_DIRTY, &gl->gl_flags);
sdp->sd_log_num_gl++; sdp->sd_log_num_gl++;
list_add(&le->le_list, &sdp->sd_log_le_gl); list_add(&le->le_list, &sdp->sd_log_le_gl);
gfs2_log_unlock(sdp); gfs2_log_unlock(sdp);
...@@ -415,13 +416,14 @@ static void rg_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) ...@@ -415,13 +416,14 @@ static void rg_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
tr->tr_touched = 1; tr->tr_touched = 1;
if (!list_empty(&le->le_list))
return;
rgd = container_of(le, struct gfs2_rgrpd, rd_le); rgd = container_of(le, struct gfs2_rgrpd, rd_le);
gfs2_rgrp_bh_hold(rgd);
gfs2_log_lock(sdp); gfs2_log_lock(sdp);
if (!list_empty(&le->le_list)){
gfs2_log_unlock(sdp);
return;
}
gfs2_rgrp_bh_hold(rgd);
sdp->sd_log_num_rg++; sdp->sd_log_num_rg++;
list_add(&le->le_list, &sdp->sd_log_le_rg); list_add(&le->le_list, &sdp->sd_log_le_rg);
gfs2_log_unlock(sdp); gfs2_log_unlock(sdp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment