From: Yafang Shao laoar.shao@gmail.com
mainline inclusion from mainline-v5.7-rc5 commit 11d6761218d19ca06ae5387f4e3692c4fa9e7493 category: bugfix bugzilla: 91659 CVE: NA
------------------------------------------------------------------
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.... Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Conflict: mm/memcontrol.c Signed-off-by: Lu Jialin lujialin4@huawei.com Reviewed-by: Xiu Jianfeng xiujianfeng@huawei.com Reviewed-by: weiyang wang wangweiyang2@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- mm/memcontrol.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 0bccf2b8cc599..e4f90577571dc 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -4923,20 +4923,23 @@ static struct mem_cgroup *mem_cgroup_alloc(void) struct mem_cgroup_extension *memcg_ext; size_t size; int node; + long error = -ENOMEM;
size = sizeof(struct mem_cgroup_extension); size += nr_node_ids * sizeof(struct mem_cgroup_per_node *);
memcg_ext = kzalloc(size, GFP_KERNEL); if (!memcg_ext) - return NULL; + return ERR_PTR(error);
memcg = &memcg_ext->memcg; 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_ext->vmstats_local = alloc_percpu(struct mem_cgroup_stat_cpu); if (!memcg_ext->vmstats_local) @@ -4978,7 +4981,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 @@ -4989,8 +4992,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; @@ -5037,7 +5040,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)