From ef97e89438cbe0721819a1a73311a9e0857d0d2a Mon Sep 17 00:00:00 2001 From: Xunlei Pang Date: Wed, 3 Apr 2019 12:33:48 +0800 Subject: [PATCH] alinux: memcg: Point wb to root memcg/blkcg when offlining to avoid zombie After turning off the memcg kmem charging, we still suffer from various zombie memcg problems on production environment because of its non-zero reference count from both page caches and per-memcg writeback related structure(bdi_writeback takes a reference). After we reclaimed all the page caches of the zombie memcg, it still can't be dropped due to its bdi_writeback. bdi_writeback is further referenced by the inodes of files, so the memcg can't be truely released until the inodes are destroyed afterwards which is quite unlikely in short term. When memcg is offlining, change it's bdi_writeback to root, and call css_put to formally release it. We've tested on product environment, it yields pretty good effect. Ditto for wb_blkcg_offline(). Reviewed-by: Yang Shi Reviewed-by: Gavin Shan Signed-off-by: Xunlei Pang Signed-off-by: Joseph Qi Acked-by: Caspar Zhang --- mm/backing-dev.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 3a895c9ab69c..b4317e206c26 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -963,8 +963,16 @@ void wb_memcg_offline(struct mem_cgroup *memcg) struct bdi_writeback *wb, *next; spin_lock_irq(&cgwb_lock); - list_for_each_entry_safe(wb, next, memcg_cgwb_list, memcg_node) + list_for_each_entry_safe(wb, next, memcg_cgwb_list, memcg_node) { + percpu_ref_get(&wb->refcnt); cgwb_kill(wb); + if (wb->memcg_css) { + css_put(wb->memcg_css); + wb->memcg_css = &root_mem_cgroup->css; + css_get(wb->memcg_css); + } + percpu_ref_put(&wb->refcnt); + } memcg_cgwb_list->next = NULL; /* prevent new wb's */ spin_unlock_irq(&cgwb_lock); } @@ -980,8 +988,16 @@ void wb_blkcg_offline(struct blkcg *blkcg) struct bdi_writeback *wb, *next; spin_lock_irq(&cgwb_lock); - list_for_each_entry_safe(wb, next, &blkcg->cgwb_list, blkcg_node) + list_for_each_entry_safe(wb, next, &blkcg->cgwb_list, blkcg_node) { + percpu_ref_get(&wb->refcnt); cgwb_kill(wb); + if (wb->memcg_css) { + css_put(wb->memcg_css); + wb->memcg_css = &root_mem_cgroup->css; + css_get(wb->memcg_css); + } + percpu_ref_put(&wb->refcnt); + } blkcg->cgwb_list.next = NULL; /* prevent new wb's */ spin_unlock_irq(&cgwb_lock); } -- GitLab