gfs2: fix glock reference problem in gfs2_trans_remove_revoke
Commit9287c6452d
fixed a situation in which gfs2 could use a glock after it had been freed. To do that, it temporarily added a new glock reference by calling gfs2_glock_hold in function gfs2_add_revoke. However, if the bd element was removed by gfs2_trans_remove_revoke, it failed to drop the additional reference. This patch adds logic to gfs2_trans_remove_revoke to properly drop the additional glock reference. Fixes:9287c6452d
("gfs2: Fix occasional glock use-after-free") Cc: stable@vger.kernel.org # v5.2+ Signed-off-by: Bob Peterson <rpeterso@redhat.com> Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
This commit is contained in:
parent
feed98a8e5
commit
fe5e7ba11f
|
@ -611,6 +611,14 @@ void gfs2_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
|
|||
list_add(&bd->bd_list, &sdp->sd_log_revokes);
|
||||
}
|
||||
|
||||
void gfs2_glock_remove_revoke(struct gfs2_glock *gl)
|
||||
{
|
||||
if (atomic_dec_return(&gl->gl_revokes) == 0) {
|
||||
clear_bit(GLF_LFLUSH, &gl->gl_flags);
|
||||
gfs2_glock_queue_put(gl);
|
||||
}
|
||||
}
|
||||
|
||||
void gfs2_write_revokes(struct gfs2_sbd *sdp)
|
||||
{
|
||||
struct gfs2_trans *tr;
|
||||
|
|
|
@ -76,6 +76,7 @@ extern void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc)
|
|||
|
||||
extern int gfs2_logd(void *data);
|
||||
extern void gfs2_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd);
|
||||
extern void gfs2_glock_remove_revoke(struct gfs2_glock *gl);
|
||||
extern void gfs2_write_revokes(struct gfs2_sbd *sdp);
|
||||
|
||||
#endif /* __LOG_DOT_H__ */
|
||||
|
|
|
@ -883,10 +883,7 @@ static void revoke_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
|
|||
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);
|
||||
}
|
||||
gfs2_glock_remove_revoke(gl);
|
||||
kmem_cache_free(gfs2_bufdata_cachep, bd);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -262,6 +262,8 @@ void gfs2_trans_remove_revoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len)
|
|||
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);
|
||||
kmem_cache_free(gfs2_bufdata_cachep, bd);
|
||||
tr->tr_num_revoke--;
|
||||
if (--n == 0)
|
||||
|
|
Loading…
Reference in New Issue