Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ceph: fix ci->i_head_snapc leak

We missed two places that i_wrbuffer_ref_head, i_wr_ref, i_dirty_caps
and i_flushing_caps may change. When they are all zeros, we should free
i_head_snapc.

Cc: stable@vger.kernel.org
Link: https://tracker.ceph.com/issues/38224
Reported-and-tested-by: Luis Henriques <lhenriques@suse.com>
Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>

authored by

Yan, Zheng and committed by
Ilya Dryomov
37659182 4b822287

+15 -1
+9
fs/ceph/mds_client.c
··· 1414 1414 list_add(&ci->i_prealloc_cap_flush->i_list, &to_remove); 1415 1415 ci->i_prealloc_cap_flush = NULL; 1416 1416 } 1417 + 1418 + if (drop && 1419 + ci->i_wrbuffer_ref_head == 0 && 1420 + ci->i_wr_ref == 0 && 1421 + ci->i_dirty_caps == 0 && 1422 + ci->i_flushing_caps == 0) { 1423 + ceph_put_snap_context(ci->i_head_snapc); 1424 + ci->i_head_snapc = NULL; 1425 + } 1417 1426 } 1418 1427 spin_unlock(&ci->i_ceph_lock); 1419 1428 while (!list_empty(&to_remove)) {
+6 -1
fs/ceph/snap.c
··· 572 572 old_snapc = NULL; 573 573 574 574 update_snapc: 575 - if (ci->i_head_snapc) { 575 + if (ci->i_wrbuffer_ref_head == 0 && 576 + ci->i_wr_ref == 0 && 577 + ci->i_dirty_caps == 0 && 578 + ci->i_flushing_caps == 0) { 579 + ci->i_head_snapc = NULL; 580 + } else { 576 581 ci->i_head_snapc = ceph_get_snap_context(new_snapc); 577 582 dout(" new snapc is %p\n", new_snapc); 578 583 }