diff options
Diffstat (limited to 'fs/gfs2/lops.c')
-rw-r--r-- | fs/gfs2/lops.c | 33 |
1 files changed, 9 insertions, 24 deletions
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 33ab662c9aac..bb0e5b8e445e 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c @@ -860,34 +860,19 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) static void revoke_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) { struct list_head *head = &sdp->sd_log_revokes; - struct gfs2_bufdata *bd, *tmp; - - /* - * Glocks can be referenced repeatedly on the revoke list, but the list - * only holds one reference. All glocks on the list will have the - * GLF_REVOKES flag set initially. - */ - - list_for_each_entry_safe(bd, tmp, head, bd_list) { - struct gfs2_glock *gl = bd->bd_gl; + struct gfs2_bufdata *bd; + struct gfs2_glock *gl; - if (test_bit(GLF_REVOKES, &gl->gl_flags)) { - /* Keep each glock on the list exactly once. */ - clear_bit(GLF_REVOKES, &gl->gl_flags); - continue; + while (!list_empty(head)) { + bd = list_entry(head->next, struct gfs2_bufdata, bd_list); + list_del_init(&bd->bd_list); + gl = bd->bd_gl; + if (atomic_dec_return(&gl->gl_revokes) == 0) { + clear_bit(GLF_LFLUSH, &gl->gl_flags); + gfs2_glock_queue_put(gl); } - list_del(&bd->bd_list); - kmem_cache_free(gfs2_bufdata_cachep, bd); - } - list_for_each_entry_safe(bd, tmp, head, bd_list) { - struct gfs2_glock *gl = bd->bd_gl; - - list_del(&bd->bd_list); kmem_cache_free(gfs2_bufdata_cachep, bd); - clear_bit(GLF_LFLUSH, &gl->gl_flags); - gfs2_glock_queue_put(gl); } - /* the list is empty now */ } static void revoke_lo_before_scan(struct gfs2_jdesc *jd, |