]>
Commit | Line | Data |
---|---|---|
4fa5b95e GKH |
1 | From 37659182bff1eeaaeadcfc8f853c6d2b6dbc3f47 Mon Sep 17 00:00:00 2001 |
2 | From: "Yan, Zheng" <zyan@redhat.com> | |
3 | Date: Thu, 18 Apr 2019 11:24:57 +0800 | |
4 | Subject: ceph: fix ci->i_head_snapc leak | |
5 | ||
6 | From: Yan, Zheng <zyan@redhat.com> | |
7 | ||
8 | commit 37659182bff1eeaaeadcfc8f853c6d2b6dbc3f47 upstream. | |
9 | ||
10 | We missed two places that i_wrbuffer_ref_head, i_wr_ref, i_dirty_caps | |
11 | and i_flushing_caps may change. When they are all zeros, we should free | |
12 | i_head_snapc. | |
13 | ||
14 | Cc: stable@vger.kernel.org | |
15 | Link: https://tracker.ceph.com/issues/38224 | |
16 | Reported-and-tested-by: Luis Henriques <lhenriques@suse.com> | |
17 | Signed-off-by: "Yan, Zheng" <zyan@redhat.com> | |
18 | Signed-off-by: Ilya Dryomov <idryomov@gmail.com> | |
19 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
20 | ||
21 | --- | |
22 | fs/ceph/mds_client.c | 9 +++++++++ | |
23 | fs/ceph/snap.c | 7 ++++++- | |
24 | 2 files changed, 15 insertions(+), 1 deletion(-) | |
25 | ||
26 | --- a/fs/ceph/mds_client.c | |
27 | +++ b/fs/ceph/mds_client.c | |
28 | @@ -1198,6 +1198,15 @@ static int remove_session_caps_cb(struct | |
29 | list_add(&ci->i_prealloc_cap_flush->list, &to_remove); | |
30 | ci->i_prealloc_cap_flush = NULL; | |
31 | } | |
32 | + | |
33 | + if (drop && | |
34 | + ci->i_wrbuffer_ref_head == 0 && | |
35 | + ci->i_wr_ref == 0 && | |
36 | + ci->i_dirty_caps == 0 && | |
37 | + ci->i_flushing_caps == 0) { | |
38 | + ceph_put_snap_context(ci->i_head_snapc); | |
39 | + ci->i_head_snapc = NULL; | |
40 | + } | |
41 | } | |
42 | spin_unlock(&ci->i_ceph_lock); | |
43 | while (!list_empty(&to_remove)) { | |
44 | --- a/fs/ceph/snap.c | |
45 | +++ b/fs/ceph/snap.c | |
46 | @@ -567,7 +567,12 @@ void ceph_queue_cap_snap(struct ceph_ino | |
47 | capsnap = NULL; | |
48 | ||
49 | update_snapc: | |
50 | - if (ci->i_head_snapc) { | |
51 | + if (ci->i_wrbuffer_ref_head == 0 && | |
52 | + ci->i_wr_ref == 0 && | |
53 | + ci->i_dirty_caps == 0 && | |
54 | + ci->i_flushing_caps == 0) { | |
55 | + ci->i_head_snapc = NULL; | |
56 | + } else { | |
57 | ci->i_head_snapc = ceph_get_snap_context(new_snapc); | |
58 | dout(" new snapc is %p\n", new_snapc); | |
59 | } |