We don't wan't two ve namespaces linking to the same ve cgroup at the
same time, we wan't each container having its own ve cgroup and
namespace pair.

https://virtuozzo.atlassian.net/browse/VSTOR-119801
Signed-off-by: Pavel Tikhomirov <[email protected]>

Feature: ve: ve generic structures
---
v2: new patch
---
 include/linux/ve.h       |  2 ++
 kernel/ve/ve.c           |  1 +
 kernel/ve/ve_namespace.c | 44 +++++++++++++++++++++++++++++++++-------
 3 files changed, 40 insertions(+), 7 deletions(-)

diff --git a/include/linux/ve.h b/include/linux/ve.h
index 4a42f16c259a..224acf012821 100644
--- a/include/linux/ve.h
+++ b/include/linux/ve.h
@@ -25,6 +25,7 @@
 
 struct nsproxy;
 struct user_namespace;
+struct ve_namespace;
 struct cn_private;
 struct vfsmount;
 
@@ -52,6 +53,7 @@ struct ve_struct {
        /* per VE CPU stats*/
        u64                     start_jiffies;          /* Deprecated */
 
+       struct ve_namespace     *ve_ns;
        struct nsproxy __rcu    *ve_nsproxy;
        struct cred             *init_cred;
 
diff --git a/kernel/ve/ve.c b/kernel/ve/ve.c
index ef2d802a3949..897423a52c08 100644
--- a/kernel/ve/ve.c
+++ b/kernel/ve/ve.c
@@ -63,6 +63,7 @@ struct ve_struct ve0 = {
        .ve_name                = "0",
        .start_jiffies          = INITIAL_JIFFIES,
 
+       .ve_ns                  = &init_ve_ns,
        RCU_POINTER_INITIALIZER(ve_nsproxy, &init_nsproxy),
 
        .state                  = VE_STATE_RUNNING,
diff --git a/kernel/ve/ve_namespace.c b/kernel/ve/ve_namespace.c
index 44cb7f0c66b0..3dbe0dde2645 100644
--- a/kernel/ve/ve_namespace.c
+++ b/kernel/ve/ve_namespace.c
@@ -24,11 +24,41 @@ static void dec_ve_namespaces(struct ucounts *ucounts)
        dec_ucount(ucounts, UCOUNT_VE_NAMESPACES);
 }
 
+/*
+ * VE namespace links to current ve cgroup exclusively (1:1 link)
+ */
+static int ve_namespace_link_ve(struct ve_namespace *ns, struct ve_struct *ve)
+{
+       guard(rwsem_write)(&ve->op_sem);
+       if (ve->ve_ns)
+               return -EBUSY;
+
+       ns->ve = get_ve(ve);
+       ve->ve_ns = ns;
+
+       return 0;
+}
+
+static void ve_namespace_unlink_ve(struct ve_namespace *ns)
+{
+       struct ve_struct *ve = ns->ve;
+
+       /* Clean up the exclusive link from ve_struct */
+       if (ve) {
+               scoped_guard(rwsem_write, &ve->op_sem) {
+                       ns->ve = NULL;
+                       ve->ve_ns = NULL;
+               }
+               put_ve(ve);
+       }
+}
+
 static struct ve_namespace *clone_ve_ns(struct user_namespace *user_ns,
                                        struct ve_namespace *old_ns)
 {
        struct ve_namespace *ns;
        struct ucounts *ucounts;
+       struct ve_struct __free(put_ve) *ve = NULL;
        int err;
 
        ucounts = inc_ve_namespaces(user_ns);
@@ -50,17 +80,17 @@ static struct ve_namespace *clone_ve_ns(struct 
user_namespace *user_ns,
        ns->ns.ops = &ve_ns_operations;
        ns->user_ns = get_user_ns(user_ns);
 
-       /*
-        * VE namespace links to current ve cgroup
-        * FIXME it should be a 1:1 link
-        */
        scoped_guard(rcu)
-               ns->ve = get_ve(css_to_ve(task_css(current, ve_cgrp_id)));
-       if (!ns->ve) {
+               ve = get_ve(css_to_ve(task_css(current, ve_cgrp_id)));
+       if (!ve) {
                err = -EINVAL;
                goto err_free_inum;
        }
 
+       err = ve_namespace_link_ve(ns, ve);
+       if (err)
+               goto err_free_inum;
+
        return ns;
 err_free_inum:
        put_user_ns(ns->user_ns);
@@ -121,7 +151,7 @@ void free_ve_ns(struct ve_namespace *ns)
 {
        struct ucounts *ucounts = ns->ucounts;
 
-       put_ve(ns->ve);
+       ve_namespace_unlink_ve(ns);
        put_user_ns(ns->user_ns);
        ns_free_inum(&ns->ns);
        kfree(ns);
-- 
2.52.0

_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to