[Devel] [PATCH v12 09/12] ve/cgroup: Implemented logic that uses 'cgroup->ve_owner' to run release_agent notifications.
Valeriy Vdovin
valeriy.vdovin at virtuozzo.com
Mon Apr 20 06:42:41 MSK 2020
release_agent_cgroup work will extract ve_owner information from each
cgroup in it's list and run user mode helper under it's namespaces.
Also some code was added to detect ve destruction and manage
release_agent executions in this case.
https://jira.sw.ru/browse/PSBM-83887
Signed-off-by: Valeriy Vdovin <valeriy.vdovin at virtuozzo.com>
---
kernel/cgroup.c | 29 +++++++++++++++++++++++++----
1 file changed, 25 insertions(+), 4 deletions(-)
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 80a4a01..7acdd01 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -5428,13 +5428,15 @@ static void check_for_release(struct cgroup *cgrp)
*/
void cgroup_release_agent(struct work_struct *work)
{
+ struct ve_struct *ve;
+ ve = container_of(work, struct ve_struct, release_agent_work);
mutex_lock(&cgroup_mutex);
raw_spin_lock(&ve->release_list_lock);
while (!list_empty(&ve->release_list)) {
char *argv[3], *envp[3];
int i, err;
char *pathbuf = NULL, *agentbuf = NULL;
- struct cgroup *cgrp;
+ struct cgroup *cgrp, *root_cgrp;
cgrp = list_entry(ve->release_list.next,
struct cgroup,
@@ -5445,8 +5447,24 @@ void cgroup_release_agent(struct work_struct *work)
pathbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!pathbuf)
goto continue_free;
- if (cgroup_path(cgrp, pathbuf, PAGE_SIZE) < 0)
+ if (__cgroup_path(cgrp, pathbuf, PAGE_SIZE, 1) < 0)
goto continue_free;
+ rcu_read_lock();
+ root_cgrp = cgroup_get_local_root(cgrp);
+ /*
+ * At VE destruction root cgroup looses VE_ROOT flag.
+ * Because of that 'cgroup_get_local_root' will not see
+ * VE root and return host's root cgroup instead.
+ * We can detect this because we have a pointer to
+ * original ve coming from work argument.
+ * We do not want to execute VE's notifications on host,
+ * so in this case we skip.
+ */
+ if (rcu_dereference(root_cgrp->ve_owner) != ve) {
+ rcu_read_unlock();
+ goto continue_free;
+ }
+ rcu_read_unlock();
agentbuf = kstrdup(cgrp->root->release_agent_path, GFP_KERNEL);
if (!agentbuf)
goto continue_free;
@@ -5466,8 +5484,11 @@ void cgroup_release_agent(struct work_struct *work)
* since the exec could involve hitting disk and hence
* be a slow process */
mutex_unlock(&cgroup_mutex);
- err = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
- if (err < 0)
+
+ err = call_usermodehelper_fns_ve(ve, argv[0], argv,
+ envp, UMH_WAIT_EXEC, NULL, NULL, NULL);
+ if (err < 0 && ve != &ve0 &&
+ !(ve->init_task->flags & PF_EXITING))
pr_warn_ratelimited("cgroup release_agent "
"%s %s failed: %d\n",
agentbuf, pathbuf, err);
--
1.8.3.1
More information about the Devel
mailing list