| From c9a1e6c1e727ecfa9bb858db1a6071e4c348a513 Mon Sep 17 00:00:00 2001 |
| From: Yafang Shao <laoar.shao@gmail.com> |
| Date: Thu, 7 May 2020 18:35:43 -0700 |
| Subject: [PATCH] mm, memcg: fix error return value of mem_cgroup_css_alloc() |
| |
| commit 11d6761218d19ca06ae5387f4e3692c4fa9e7493 upstream. |
| |
| When I run my memcg testcase which creates lots of memcgs, I found |
| there're unexpected out of memory logs while there're still enough |
| available free memory. The error log is |
| |
| mkdir: cannot create directory 'foo.65533': Cannot allocate memory |
| |
| The reason is when we try to create more than MEM_CGROUP_ID_MAX memcgs, |
| an -ENOMEM errno will be set by mem_cgroup_css_alloc(), but the right |
| errno should be -ENOSPC "No space left on device", which is an |
| appropriate errno for userspace's failed mkdir. |
| |
| As the errno really misled me, we should make it right. After this |
| patch, the error log will be |
| |
| mkdir: cannot create directory 'foo.65533': No space left on device |
| |
| [akpm@linux-foundation.org: s/EBUSY/ENOSPC/, per Michal] |
| [akpm@linux-foundation.org: s/EBUSY/ENOSPC/, per Michal] |
| Fixes: 73f576c04b94 ("mm: memcontrol: fix cgroup creation failure after many small jobs") |
| Suggested-by: Matthew Wilcox <willy@infradead.org> |
| Signed-off-by: Yafang Shao <laoar.shao@gmail.com> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Acked-by: Michal Hocko <mhocko@kernel.org> |
| Acked-by: Johannes Weiner <hannes@cmpxchg.org> |
| Cc: Vladimir Davydov <vdavydov.dev@gmail.com> |
| Link: http://lkml.kernel.org/r/20200407063621.GA18914@dhcp22.suse.cz |
| Link: http://lkml.kernel.org/r/1586192163-20099-1-git-send-email-laoar.shao@gmail.com |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/mm/memcontrol.c b/mm/memcontrol.c |
| index 6e5d87714853..e05bb6ea5771 100644 |
| --- a/mm/memcontrol.c |
| +++ b/mm/memcontrol.c |
| @@ -4654,19 +4654,22 @@ static struct mem_cgroup *mem_cgroup_alloc(void) |
| struct mem_cgroup *memcg; |
| unsigned int size; |
| int node; |
| + long error = -ENOMEM; |
| |
| size = sizeof(struct mem_cgroup); |
| size += nr_node_ids * sizeof(struct mem_cgroup_per_node *); |
| |
| memcg = kzalloc(size, GFP_KERNEL); |
| if (!memcg) |
| - return NULL; |
| + return ERR_PTR(error); |
| |
| memcg->id.id = idr_alloc(&mem_cgroup_idr, NULL, |
| 1, MEM_CGROUP_ID_MAX, |
| GFP_KERNEL); |
| - if (memcg->id.id < 0) |
| + if (memcg->id.id < 0) { |
| + error = memcg->id.id; |
| goto fail; |
| + } |
| |
| memcg->vmstats_local = alloc_percpu(struct memcg_vmstats_percpu); |
| if (!memcg->vmstats_local) |
| @@ -4703,7 +4706,7 @@ static struct mem_cgroup *mem_cgroup_alloc(void) |
| fail: |
| mem_cgroup_id_remove(memcg); |
| __mem_cgroup_free(memcg); |
| - return NULL; |
| + return ERR_PTR(error); |
| } |
| |
| static struct cgroup_subsys_state * __ref |
| @@ -4714,8 +4717,8 @@ mem_cgroup_css_alloc(struct cgroup_subsys_state *parent_css) |
| long error = -ENOMEM; |
| |
| memcg = mem_cgroup_alloc(); |
| - if (!memcg) |
| - return ERR_PTR(error); |
| + if (IS_ERR(memcg)) |
| + return ERR_CAST(memcg); |
| |
| memcg->high = PAGE_COUNTER_MAX; |
| memcg->soft_limit = PAGE_COUNTER_MAX; |
| @@ -4762,7 +4765,7 @@ mem_cgroup_css_alloc(struct cgroup_subsys_state *parent_css) |
| fail: |
| mem_cgroup_id_remove(memcg); |
| mem_cgroup_free(memcg); |
| - return ERR_PTR(-ENOMEM); |
| + return ERR_PTR(error); |
| } |
| |
| static int mem_cgroup_css_online(struct cgroup_subsys_state *css) |
| -- |
| 2.7.4 |
| |