[Devel] [PATCH RH9 3/6] ve/cgroup: Add ve_owner field to cgroup

Pavel Tikhomirov ptikhomirov at virtuozzo.com
Tue Oct 12 19:22:06 MSK 2021


From: Valeriy Vdovin <valeriy.vdovin at virtuozzo.com>

Each cgroup representing a container root of cgroup subsystem hierarchy
will have this field set to a valid ve_struct, that owns this root.

This way each cgroup in a system will be able to know it's owning
VE. Non root cgroups will have this field set to NULL, this is an
optimization for cleanup code: at VE destruction we only need to iterate
over all root cgroups to clean reference to former owning VE, rather
than over all cgroup hierarchy. Still any cgroup that wants to know
about it's owning VE can find it's virtual root cgroup and read it's
ve_owner field.

The field cgroup->ve_owner is declared as RCU pointer, because it fits
RCU semantics - rare writes/often reads. It can be read from multiple
locations in code and is only rarely (un)set at cgroup_(un)mark_ve_root.
Function cgroup_ve_owner is a read wrapper which goes up in cgroup tree
to find the ve owning this cgroup.

vz9 changes:
- remove excess cgroup_get_local_root, use existing cgroup_get_ve_root1
- don't set ->ve_owner to ve0, only actual containers set ->ve_owner.
- drop implicit fallback to ve0, caller of cgroup_ve_owner should now
handle NULL return in case of host cgroup argument

We drop release agent virtualization but this way of knowing ve by
cgroup can be useful (used for writeback per-ve io cgroup lookup).

https://jira.sw.ru/browse/PSBM-134002
(cherry picked from vz8 commit 647b4abb109fa2b7707c977c3d67aaa5946597a0)
Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
---
 include/linux/cgroup-defs.h |  3 +++
 include/linux/cgroup.h      |  1 +
 kernel/cgroup/cgroup.c      | 19 +++++++++++++++++++
 3 files changed, 23 insertions(+)

diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h
index 2b99254cf459..315c399c5d3b 100644
--- a/include/linux/cgroup-defs.h
+++ b/include/linux/cgroup-defs.h
@@ -499,6 +499,9 @@ struct cgroup {
 
 	u64 subgroups_limit;
 
+	/* ve_owner, responsible for running release agent. */
+	struct ve_struct __rcu *ve_owner;
+
 	/* ids of the ancestors at each level including self */
 	u64 ancestor_ids[];
 };
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 4dc3f2f007f1..05b4688cf949 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -889,6 +889,7 @@ int cgroup_path_ns(struct cgroup *cgrp, char *buf, size_t buflen,
 #ifdef CONFIG_VE
 extern int cgroup_mark_ve_root(struct ve_struct *ve);
 void cgroup_unmark_ve_roots(struct ve_struct *ve);
+struct ve_struct *cgroup_ve_owner(struct cgroup *cgrp);
 #endif
 
 #else /* !CONFIG_CGROUPS */
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index fbe8483b7035..06f0906a5ea5 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -307,6 +307,20 @@ bool cgroup_on_dfl(const struct cgroup *cgrp)
 	return cgrp->root == &cgrp_dfl_root;
 }
 
+/*
+ * The ve returned should be used only while holding rcu_read_lock
+ */
+struct ve_struct *cgroup_ve_owner(struct cgroup *cgrp)
+{
+	struct ve_struct *ve = NULL;
+	struct cgroup *ve_root;
+
+	ve_root = cgroup_get_ve_root1(cgrp);
+	if (ve_root)
+		ve = rcu_dereference(ve_root->ve_owner);
+	return ve;
+}
+
 /* IDR wrappers which synchronize using cgroup_idr_lock */
 static int cgroup_idr_alloc(struct idr *idr, void *ptr, int start, int end,
 			    gfp_t gfp_mask)
@@ -2039,11 +2053,13 @@ int cgroup_mark_ve_root(struct ve_struct *ve)
 		if (!is_virtualized_cgroup(cgrp))
 			continue;
 
+		rcu_assign_pointer(cgrp->ve_owner, ve);
 		set_bit(CGRP_VE_ROOT, &cgrp->flags);
 	}
 
 	link_ve_root_cpu_cgroup(cset->subsys[cpu_cgrp_id]);
 	spin_unlock_irq(&css_set_lock);
+	synchronize_rcu();
 	return 0;
 }
 
@@ -2069,10 +2085,13 @@ void cgroup_unmark_ve_roots(struct ve_struct *ve)
 		if (!is_virtualized_cgroup(cgrp))
 			continue;
 
+		rcu_assign_pointer(cgrp->ve_owner, NULL);
 		clear_bit(CGRP_VE_ROOT, &cgrp->flags);
 	}
 
 	spin_unlock_irq(&css_set_lock);
+	/* ve_owner == NULL will be visible */
+	synchronize_rcu();
 }
 
 struct cgroup *cgroup_get_ve_root1(struct cgroup *cgrp)
-- 
2.31.1



More information about the Devel mailing list