In case of memcg_online_kmem() failure, memcg_cgroup::id remains hashed in mem_cgroup_idr even after memcg memory is freed. This leads to leak of ID in mem_cgroup_idr. This patch adds removal into mem_cgroup_css_alloc(), which fixes the problem. For better readability, it adds a generic helper which is used in mem_cgroup_alloc() and mem_cgroup_id_put_many() as well.
Unified · Split
| @@ -4037,6 +4037,14 @@ static struct cftype mem_cgroup_legacy_files[] = { · 4036 unmodified lines | ||
| 4037 | 4037 | |
| 4038 | 4038 | static DEFINE_IDR(mem_cgroup_idr); |
| 4039 | 4039 | |
| 4040 | +static void mem_cgroup_id_remove(struct mem_cgroup *memcg) | |
| 4041 | +{ | |
| 4042 | + if (memcg->id.id > 0) { | |
| 4043 | + idr_remove(&mem_cgroup_idr, memcg->id.id); | |
| 4044 | + memcg->id.id = 0; | |
| 4045 | + } | |
| 4046 | +} | |
| 4047 | + | |
| 4040 | 4048 | static void mem_cgroup_id_get_many(struct mem_cgroup *memcg, unsigned int n) |
| 4041 | 4049 | { |
| 4042 | 4050 | VM_BUG_ON(atomic_read(&memcg->id.ref) <= 0); |
| @@ -4047,8 +4055,7 @@ static void mem_cgroup_id_put_many(struct mem_cgroup *memcg, unsigned int n) · 4 unmodified lines | ||
| 4047 | 4055 | { |
| 4048 | 4056 | VM_BUG_ON(atomic_read(&memcg->id.ref) < n); |
| 4049 | 4057 | if (atomic_sub_and_test(n, &memcg->id.ref)) { |
| 4050 | − idr_remove(&mem_cgroup_idr, memcg->id.id); | |
| 4051 | − memcg->id.id = 0; | |
| 4058 | + mem_cgroup_id_remove(memcg); | |
| 4052 | 4059 | |
| 4053 | 4060 | /* Memcg ID pins CSS */ |
| 4054 | 4061 | css_put(&memcg->css); |
| @@ -4185,8 +4192,7 @@ static struct mem_cgroup *mem_cgroup_alloc(void) · 130 unmodified lines | ||
| 4185 | 4192 | idr_replace(&mem_cgroup_idr, memcg, memcg->id.id); |
| 4186 | 4193 | return memcg; |
| 4187 | 4194 | fail: |
| 4188 | − if (memcg->id.id > 0) | |
| 4189 | − idr_remove(&mem_cgroup_idr, memcg->id.id); | |
| 4195 | + mem_cgroup_id_remove(memcg); | |
| 4190 | 4196 | __mem_cgroup_free(memcg); |
| 4191 | 4197 | return NULL; |
| 4192 | 4198 | } |
| @@ -4245,6 +4251,7 @@ mem_cgroup_css_alloc(struct cgroup_subsys_state *parent_css) · 52 unmodified lines | ||
| 4245 | 4251 | |
| 4246 | 4252 | return &memcg->css; |
| 4247 | 4253 | fail: |
| 4254 | + mem_cgroup_id_remove(memcg); | |
| 4248 | 4255 | mem_cgroup_free(memcg); |
| 4249 | 4256 | return ERR_PTR(-ENOMEM); |
| 4250 | 4257 | } |