aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorBenjamin Marzinski <bmarzins@redhat.com>2007-03-23 05:05:12 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2007-05-01 04:10:50 -0400
commit6883562588bc6c70776ecc396ee7eda36c2c8da9 (patch)
treec683994d1f805914fc18f3247cc86cc011a9aa0b /fs
parentf35ac346bc48b2086aa94f031baf1f6237a89de6 (diff)
[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: Benjamin E. Marzinski <bmarzins@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/gfs2/lops.c20
1 files changed, 11 insertions, 9 deletions
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index 16bb4b4561ae..f82d84d05d23 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -33,16 +33,17 @@ static void glock_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
33 33
34 tr->tr_touched = 1; 34 tr->tr_touched = 1;
35 35
36 if (!list_empty(&le->le_list))
37 return;
38
39 gl = container_of(le, struct gfs2_glock, gl_le); 36 gl = container_of(le, struct gfs2_glock, gl_le);
40 if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(gl))) 37 if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(gl)))
41 return; 38 return;
42 gfs2_glock_hold(gl);
43 set_bit(GLF_DIRTY, &gl->gl_flags);
44 39
45 gfs2_log_lock(sdp); 40 gfs2_log_lock(sdp);
41 if (!list_empty(&le->le_list)){
42 gfs2_log_unlock(sdp);
43 return;
44 }
45 gfs2_glock_hold(gl);
46 set_bit(GLF_DIRTY, &gl->gl_flags);
46 sdp->sd_log_num_gl++; 47 sdp->sd_log_num_gl++;
47 list_add(&le->le_list, &sdp->sd_log_le_gl); 48 list_add(&le->le_list, &sdp->sd_log_le_gl);
48 gfs2_log_unlock(sdp); 49 gfs2_log_unlock(sdp);
@@ -415,13 +416,14 @@ static void rg_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
415 416
416 tr->tr_touched = 1; 417 tr->tr_touched = 1;
417 418
418 if (!list_empty(&le->le_list))
419 return;
420
421 rgd = container_of(le, struct gfs2_rgrpd, rd_le); 419 rgd = container_of(le, struct gfs2_rgrpd, rd_le);
422 gfs2_rgrp_bh_hold(rgd);
423 420
424 gfs2_log_lock(sdp); 421 gfs2_log_lock(sdp);
422 if (!list_empty(&le->le_list)){
423 gfs2_log_unlock(sdp);
424 return;
425 }
426 gfs2_rgrp_bh_hold(rgd);
425 sdp->sd_log_num_rg++; 427 sdp->sd_log_num_rg++;
426 list_add(&le->le_list, &sdp->sd_log_le_rg); 428 list_add(&le->le_list, &sdp->sd_log_le_rg);
427 gfs2_log_unlock(sdp); 429 gfs2_log_unlock(sdp);