[RHEL7,COMMIT] ve/cgroup: Implemented logic that uses 'cgroup->ve_owner' to run release_agent notifications.

Submitted by Vasily Averin on Aug. 6, 2020, 5:31 a.m.

Details

Message ID 202008060531.0765Vn2v003916@vz7build.vvs.sw.ru
State New
Series "Make release_agent per-cgroup property. Run release_agent in proper ve."
Headers show

Commit Message

Vasily Averin Aug. 6, 2020, 5:31 a.m.
The commit is pushed to "branch-rh7-3.10.0-1127.18.2.vz7.163.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-1127.18.2.el7
------>
commit 160af2ad63fb9c98db998b37b016efcb9fec8d64
Author: Valeriy Vdovin <valeriy.vdovin@virtuozzo.com>
Date:   Thu Aug 6 08:31:49 2020 +0300

    ve/cgroup: Implemented logic that uses 'cgroup->ve_owner' to run release_agent notifications.
    
    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@virtuozzo.com>
    
    Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 kernel/cgroup.c | 29 +++++++++++++++++++++++++----
 1 file changed, 25 insertions(+), 4 deletions(-)

Patch hide | download patch | download mbox

diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index d0cd1b4..23bca35 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -5705,7 +5705,8 @@  void cgroup_release_agent(struct work_struct *work)
 		char *argv[3], *envp[3];
 		int i, err;
 		char *pathbuf = NULL, *agentbuf = NULL;
-		struct cgroup *cgrp;
+		struct cgroup *cgrp, *root_cgrp;
+		struct task_struct *ve_task;
 
 		cgrp = list_entry(ve->release_list.next,
 				  struct cgroup,
@@ -5716,8 +5717,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, true) < 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_access_pointer(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;
@@ -5737,8 +5754,12 @@  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);
+
+		ve_task = ve->init_task;
+		if (err < 0 && (!(ve_task->flags & PF_EXITING)))
 			pr_warn_ratelimited("cgroup release_agent "
 					    "%s %s failed: %d\n",
 					    agentbuf, pathbuf, err);