diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index 115c4ac457e9..50c8519c7c8f 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c @@ -1000,10 +1000,11 @@ static void empty_ail1_list(struct gfs2_sbd *sdp) * but since we bypassed the after_commit functions, we need to remove the * items from the buf and databuf queue. */ -static void trans_drain(struct gfs2_trans *tr) +static void trans_drain(struct gfs2_sbd *sdp, struct gfs2_trans *tr) { struct gfs2_bufdata *bd; struct list_head *head; + struct buffer_head *bh; if (!tr) return; @@ -1011,17 +1012,23 @@ static void trans_drain(struct gfs2_trans *tr) head = &tr->tr_buf; while (!list_empty(head)) { bd = list_first_entry(head, struct gfs2_bufdata, bd_list); + bh = bd->bd_bh; + gfs2_assert_warn(sdp, bh->b_private == bd); list_del_init(&bd->bd_list); if (!list_empty(&bd->bd_ail_st_list)) gfs2_remove_from_ail(bd); + bh->b_private = NULL; kmem_cache_free(gfs2_bufdata_cachep, bd); } head = &tr->tr_databuf; while (!list_empty(head)) { bd = list_first_entry(head, struct gfs2_bufdata, bd_list); + bh = bd->bd_bh; + gfs2_assert_warn(sdp, bh->b_private == bd); list_del_init(&bd->bd_list); if (!list_empty(&bd->bd_ail_st_list)) gfs2_remove_from_ail(bd); + bh->b_private = NULL; kmem_cache_free(gfs2_bufdata_cachep, bd); } } @@ -1162,7 +1169,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags) return; out_withdraw: - trans_drain(tr); + trans_drain(sdp, tr); /** * If the tr_list is empty, we're withdrawing during a log * flush that targets a transaction, but the transaction was diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 9c8c305a75c4..1a5f03ccace8 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c @@ -888,13 +888,17 @@ void gfs2_drain_revokes(struct gfs2_sbd *sdp) { struct list_head *head = &sdp->sd_log_revokes; struct gfs2_bufdata *bd; + struct buffer_head *bh; struct gfs2_glock *gl; while (!list_empty(head)) { bd = list_first_entry(head, struct gfs2_bufdata, bd_list); + bh = bd->bd_bh; + gfs2_assert_warn(sdp, bh->b_private == bd); list_del_init(&bd->bd_list); gl = bd->bd_gl; gfs2_glock_remove_revoke(gl); + bh->b_private = NULL; kmem_cache_free(gfs2_bufdata_cachep, bd); } } diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c index 075f7e9abe47..de5d324ce0ce 100644 --- a/fs/gfs2/trans.c +++ b/fs/gfs2/trans.c @@ -325,16 +325,20 @@ void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) void gfs2_trans_remove_revoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len) { struct gfs2_bufdata *bd, *tmp; + struct buffer_head *bh; unsigned int n = len; gfs2_log_lock(sdp); list_for_each_entry_safe(bd, tmp, &sdp->sd_log_revokes, bd_list) { if ((bd->bd_blkno >= blkno) && (bd->bd_blkno < (blkno + len))) { + bh = bd->bd_bh; + gfs2_assert_warn(sdp, bh->b_private == bd); list_del_init(&bd->bd_list); gfs2_assert_withdraw(sdp, sdp->sd_log_num_revoke); sdp->sd_log_num_revoke--; if (bd->bd_gl) gfs2_glock_remove_revoke(bd->bd_gl); + bh->b_private = NULL; kmem_cache_free(gfs2_bufdata_cachep, bd); gfs2_log_release_revokes(sdp, 1); if (--n == 0)