[Devel] [PATCH VZ10 v2 10/12] ve_namespace: Make link between ve namespace and cgroup exclusive

Pavel Tikhomirov ptikhomirov at virtuozzo.com
Wed Dec 10 13:34:31 MSK 2025


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 <ptikhomirov at virtuozzo.com>

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



More information about the Devel mailing list