<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div id="appendonsend"></div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0)">
<br>
</div>
<hr tabindex="-1" style="display:inline-block; width:98%">
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<span><span>&gt; From: Kirill Tkhai &lt;ktkhai@virtuozzo.com&gt;<br>
</span>
<div>&gt; Sent: Tuesday, July 21, 2020 4:52 PM<br>
</div>
<div>&gt; To: Valeriy Vdovin &lt;Valeriy.Vdovin@virtuozzo.com&gt;; devel@openvz.org &gt; &lt;devel@openvz.org&gt;<br>
</div>
<div>&gt; Cc: Valeriy Vdovin &lt;valeriy.vdovin@virtuozz.com&gt;<br>
</div>
<div>&gt; Subject: Re: [PATCH RHEL7 v20 06/14] ve/cgroup: unmark ve-root cgroups at container stop<br>
</div>
<div>&gt;<br>
</div>
<div>&gt; On 25.06.2020 17:29, Valeriy Vdovin wrote:<br>
</div>
<div>&gt; &gt; Signed-off-by: Valeriy Vdovin &lt;valeriy.vdovin@virtuozzo.com&gt;<br>
</div>
<div>&gt; &gt; Reviewed-by: Kirill Tkhai &lt;ktkhai@virtuozzo.com&gt;<br>
</div>
<div>&gt; &gt; ---<br>
</div>
<div>&gt; &gt; &nbsp;include/linux/cgroup.h | &nbsp;1 +<br>
</div>
<div>&gt; &gt; &nbsp;kernel/cgroup.c &nbsp; &nbsp; &nbsp; &nbsp;| 38 ++++++++++++++++++++++++++++++++++++++<br>
</div>
<div>&gt; &gt; &nbsp;kernel/ve/ve.c &nbsp; &nbsp; &nbsp; &nbsp; | &nbsp;2 ++<br>
</div>
<div>&gt; &gt; &nbsp;3 files changed, 41 insertions(+)<br>
</div>
<div>&gt; &gt;<br>
</div>
<div>&gt; &gt; diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h<br>
</div>
<div>&gt; &gt; index ac60aaed..6e2c206 100644<br>
</div>
<div>&gt; &gt; --- a/include/linux/cgroup.h<br>
</div>
<div>&gt; &gt; +++ b/include/linux/cgroup.h<br>
</div>
<div>&gt; &gt; @@ -671,6 +671,7 @@ int cgroup_task_count(const struct cgroup *cgrp);<br>
</div>
<div>&gt; &gt;<br>
</div>
<span>&gt; &gt; &nbsp;#ifdef CONFIG_VE</span><br>
</span></div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<span>&gt; &gt; &nbsp;void cgroup_mark_ve_roots(struct ve_struct *ve);<br>
</span>
<div>&gt; &gt; +void cgroup_unmark_ve_roots(struct ve_struct *ve);<br>
</div>
<div>&gt; &gt; &nbsp;#endif<br>
</div>
<div>&gt; &gt;<br>
</div>
<div>&gt; &gt; &nbsp;/*<br>
</div>
<div>&gt; &gt; diff --git a/kernel/cgroup.c b/kernel/cgroup.c<br>
</div>
<div>&gt; &gt; index ce576c5..6e3871a 100644<br>
</div>
<div>&gt; &gt; --- a/kernel/cgroup.c<br>
</div>
<div>&gt; &gt; +++ b/kernel/cgroup.c<br>
</div>
<div>&gt; &gt; @@ -637,6 +637,31 @@ static struct css_set *find_css_set(<br>
</div>
<div>&gt; &gt; &nbsp;}<br>
</div>
<div>&gt; &gt;<br>
</div>
<div>&gt; &gt; &nbsp;/*<br>
</div>
<div>&gt; &gt; + * Walk each cgroup link of a given css_set and find a cgroup that<br>
</div>
<div>&gt; &gt; + * is the child of cgroupfs_root in argument.<br>
</div>
<div>&gt; &gt; + */<br>
</div>
<div>&gt; &gt; +static struct cgroup *css_cgroup_from_root(struct css_set *css_set,<br>
</div>
<div>&gt; &gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; struct cgroupfs_root *root)<br>
</div>
<div>&gt; &gt; +{<br>
</div>
<div>&gt; &gt; + &nbsp; &nbsp; struct cgroup *res = NULL;<br>
</div>
<div>&gt; &gt; + &nbsp; &nbsp; struct cg_cgroup_link *link;<br>
</div>
<div>&gt; &gt; +<br>
</div>
<div>&gt; &gt; + &nbsp; &nbsp; BUG_ON(!mutex_is_locked(&amp;cgroup_mutex));<br>
</div>
<div>&gt; &gt; + &nbsp; &nbsp; read_lock(&amp;css_set_lock);<br>
</div>
<div>&gt; &gt; +<br>
</div>
<div>&gt; &gt; + &nbsp; &nbsp; list_for_each_entry(link, &amp;css_set-&gt;cg_links, cg_link_list) {<br>
</div>
<div>&gt; &gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; struct cgroup *c = link-&gt;cgrp;<br>
</div>
<div>&gt; &gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (c-&gt;root == root) {<br>
</div>
<div>&gt; &gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; res = c;<br>
</div>
<div>&gt; &gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>
</div>
<div>&gt; &gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>
</div>
<div>&gt; &gt; + &nbsp; &nbsp; }<br>
</div>
<div>&gt; &gt; + &nbsp; &nbsp; read_unlock(&amp;css_set_lock);<br>
</div>
<div>&gt; &gt; + &nbsp; &nbsp; BUG_ON(!res);<br>
</div>
<div>&gt; &gt; + &nbsp; &nbsp; return res;<br>
</div>
<div>&gt; &gt; +}<br>
</div>
<div>&gt; &gt; +<br>
</div>
<div>&gt; &gt; +/*<br>
</div>
<div>&gt; &gt; &nbsp; * Return the cgroup for &quot;task&quot; from the given hierarchy. Must be<br>
</div>
<div>&gt; &gt; &nbsp; * called with cgroup_mutex held.<br>
</div>
<div>&gt; &gt; &nbsp; */<br>
</div>
<div>&gt; &gt; @@ -4329,6 +4354,19 @@ void cgroup_mark_ve_roots(struct ve_struct *ve)<br>
</div>
<div>&gt; &gt; &nbsp; &nbsp; &nbsp; &nbsp;mutex_unlock(&amp;cgroup_mutex);<br>
</div>
<div>&gt; &gt; &nbsp;}<br>
</div>
<span>&gt; &gt;</span><br>
</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<span>&gt; &gt; +void cgroup_unmark_ve_roots(struct ve_struct *ve)<br>
</span>
<div>&gt; &gt; +{<br>
</div>
<div>&gt; &gt; + &nbsp; &nbsp; struct cgroup *cgrp;<br>
</div>
<div>&gt; &gt; + &nbsp; &nbsp; struct cgroupfs_root *root;<br>
</div>
<div>&gt; &gt; + <br>
</div>
<div>&gt; &gt; + &nbsp; &nbsp; mutex_lock(&amp;cgroup_mutex);<br>
</div>
<div>&gt; &gt; + &nbsp; &nbsp; for_each_active_root(root) {<br>
</div>
<div>&gt; &gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cgrp = css_cgroup_from_root(ve-&gt;root_css_set, root);<br>
</div>
<div>&gt; &gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; clear_bit(CGRP_VE_ROOT, &amp;cgrp-&gt;flags);<br>
</div>
<div>&gt; &gt; + &nbsp; &nbsp; } &nbsp; <br>
</div>
<div>&gt; &gt; + &nbsp; &nbsp; mutex_unlock(&amp;cgroup_mutex);<br>
</div>
<div>&gt; &gt; +}<br>
</div>
<div>&gt; &gt; + <br>
</div>
<div>&gt; &gt; &nbsp;struct cgroup *cgroup_get_ve_root(struct cgroup *cgrp)<br>
</div>
<div>&gt; &gt; &nbsp;{<br>
</div>
<div>&gt; &gt; &nbsp; &nbsp; &nbsp; &nbsp;struct cgroup *ve_root = NULL;<br>
</div>
<div>&gt; &gt; diff --git a/kernel/ve/ve.c b/kernel/ve/ve.c<br>
</div>
<div>&gt; &gt; index 73cfee6..711050c 100644<br>
</div>
<div>&gt; &gt; --- a/kernel/ve/ve.c<br>
</div>
<div>&gt; &gt; +++ b/kernel/ve/ve.c<br>
</div>
<div>&gt; &gt; @@ -623,6 +623,8 @@ void ve_exit_ns(struct pid_namespace *pid_ns)<br>
</div>
<div>&gt; &gt; &nbsp; &nbsp; &nbsp; &nbsp;if (!ve-&gt;ve_ns || ve-&gt;ve_ns-&gt;pid_ns != pid_ns)<br>
</div>
<div>&gt; &gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return;<br>
</div>
<div>&gt; &gt; &nbsp; <br>
</div>
<div>&gt; &gt; + &nbsp; &nbsp; cgroup_unmark_ve_roots(ve);<br>
</div>
<div>&gt; <br>
</div>
<div>&gt; Is there a problem that ve workqueue works will run after we unmark roots?<br>
</div>
<div>&gt; Maybe we should call this cgroup_unmark_ve_roots() after ve_workqueue_stop()?<br>
</div>
<div><br>
</div>
<div>When a cgroup gets empty it's decided to which workqueue it should be put to await for
<br>
</div>
<div>release. Thus when we unmark ve root, we prevent any new empty cgroups from entering this<br>
</div>
<div>workqueue. After that we are safe to stop the workqueue by waiting for all the current jobs to<br>
</div>
<div>complete.<br>
</div>
<div><br>
</div>
<div>&gt; &gt; + <br>
</div>
<div>&gt; &gt; &nbsp; &nbsp; &nbsp; &nbsp;ve_workqueue_stop(ve);<br>
</div>
<div>&gt; &gt; &nbsp; <br>
</div>
<div>&gt; &gt; &nbsp; &nbsp; &nbsp; &nbsp;/* &nbsp;<br>
</div>
<div>&gt; &gt;<br>
</div>
<span></span><br>
</div>
</body>
</html>