Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932264AbbHWWry (ORCPT ); Sun, 23 Aug 2015 18:47:54 -0400 Received: from mga02.intel.com ([134.134.136.20]:16944 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753463AbbHWWq2 (ORCPT ); Sun, 23 Aug 2015 18:46:28 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.15,734,1432623600"; d="scan'208";a="789528135" From: Vikas Shivappa To: vikas.shivappa@intel.com Cc: vikas.shivappa@linux.intel.com, x86@kernel.org, linux-kernel@vger.kernel.org, hpa@zytor.com, tglx@linutronix.de, mingo@kernel.org, peterz@infradead.org, tj@kernel.org, matt.fleming@intel.com, will.auld@intel.com, kanaka.d.juvva@intel.com, glenn.p.williamson@intel.com, mtosatti@redhat.com Subject: [PATCH 1/6] cgroup: Adds cgroup_destroy_children Date: Sun, 23 Aug 2015 15:46:37 -0700 Message-Id: <1440370002-30618-2-git-send-email-vikas.shivappa@linux.intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1440370002-30618-1-git-send-email-vikas.shivappa@linux.intel.com> References: <1440370002-30618-1-git-send-email-vikas.shivappa@linux.intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4854 Lines: 159 cgroup currently does not support removing a cgroup directory if it has children. Adds a api cgroup_destroy_children which destroys all the children in the cgroup hierarchy starting from the bottom. After each cgroup node is destroyed we wait till the css is offlined and freed. Signed-off-by: Vikas Shivappa --- include/linux/cgroup.h | 4 +++ kernel/cgroup.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index b9cb94c..292ed97 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -609,6 +609,7 @@ char *task_cgroup_path(struct task_struct *task, char *buf, size_t buflen); int cgroup_add_dfl_cftypes(struct cgroup_subsys *ss, struct cftype *cfts); int cgroup_add_legacy_cftypes(struct cgroup_subsys *ss, struct cftype *cfts); int cgroup_rm_cftypes(struct cftype *cfts); +void cgroup_destroy_children(struct cgroup_subsys_state *css); bool cgroup_is_descendant(struct cgroup *cgrp, struct cgroup *ancestor); @@ -705,6 +706,9 @@ struct cgroup_subsys { * specifies the mask of subsystems that this one depends on. */ unsigned int depends_on; + + /* used to wait for freeing of csses */ + wait_queue_head_t pending_css_free_waitq; }; #define SUBSYS(_x) extern struct cgroup_subsys _x ## _cgrp_subsys; diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 469dd54..668f614 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -1733,6 +1733,33 @@ out: return ret; } +/* + * css_wait_free: Wait till css is freed. + * @css: The css that we need to wait for + * + * Wait for the release_css to call the ss->css_free and goto + * quiescent state for a while. + * This ensures that stage 4/last stage of css destruction is complete. + */ +static void css_wait_free(struct cgroup_subsys_state *css) +{ + struct cgroup_subsys *ss; + DEFINE_WAIT(wait); + + lockdep_assert_held(&cgroup_mutex); + + if (css && (css->flags & CSS_ONLINE)) { + ss = css->ss; + prepare_to_wait(&ss->pending_css_free_waitq, &wait, + TASK_UNINTERRUPTIBLE); + mutex_unlock(&cgroup_mutex); + schedule(); + finish_wait(&ss->pending_css_free_waitq, &wait); + msleep(10); + mutex_lock(&cgroup_mutex); + } +} + static struct dentry *cgroup_mount(struct file_system_type *fs_type, int flags, const char *unused_dev_name, void *data) @@ -4387,6 +4414,7 @@ static void css_free_work_fn(struct work_struct *work) ss->css_free(css); cgroup_idr_remove(&ss->css_idr, id); cgroup_put(cgrp); + wake_up_all(&ss->pending_css_free_waitq); } else { /* cgroup free path */ atomic_dec(&cgrp->root->nr_cgrps); @@ -4870,6 +4898,62 @@ static int cgroup_destroy_locked(struct cgroup *cgrp) return 0; }; +/* + * cgroup_destroy_recursive - Destroy the cgroup hierarchy + *@css: The css we need to wait for to be freed + * + * Destroy the cgroup hierarchy bottom-up. After destroying + * each directory, and wait for css to be freed before + * proceeding to destroy its parent. + */ +static void cgroup_destroy_recursive(struct cgroup_subsys_state *css) +{ + struct cgroup_subsys_state *prev,*par = css,*tmp; + + lockdep_assert_held(&cgroup_mutex); + + if (!css_has_online_children(css)) + cgroup_destroy_locked(css->cgroup); + else { + prev = css_next_child(NULL, par); + while(prev) { + tmp = css_next_child(prev, par); + cgroup_destroy_recursive(prev); + prev = tmp; + } + + cgroup_destroy_locked(css->cgroup); + } + css_wait_free(css); +} + +/* + * cgroup_destroy_children - Destroy all the children of the cgroup + * @css: the css which has the cgroup + */ +void cgroup_destroy_children(struct cgroup_subsys_state *css) +{ + struct cgroup_subsys_state *tmp,*prev, *par; + + lockdep_assert_held(&cgroup_mutex); + + par = css; + + /* + * Since we want to give a chance for the css_release + * to call the rcu callback, dont hold a rcu lock here. + * We destroy the prev and when destroying prev, + * make sure the next one is accessible. + */ + prev = css_next_child(NULL, par); + + while(prev) { + tmp = css_next_child(prev, par); + cgroup_destroy_recursive(prev); + prev = tmp; + } +} + static int cgroup_rmdir(struct kernfs_node *kn) { struct cgroup *cgrp; @@ -4910,6 +4994,7 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss, bool early) /* We don't handle early failures gracefully */ BUG_ON(IS_ERR(css)); init_and_link_css(css, ss, &cgrp_dfl_root.cgrp); + init_waitqueue_head(&ss->pending_css_free_waitq); /* * Root csses are never destroyed and we can't initialize -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/