[Devel] [PATCH RHEL9 COMMIT] ve/cgroup: Add ve_owner field to cgroup

Konstantin Khorenko khorenko at virtuozzo.com
Wed Oct 13 14:13:30 MSK 2021


The commit is pushed to "branch-rh9-5.14.vz9.1.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh9-5.14.0-4.vz9.10.1
------>
commit 0aa8d5b66160fa389809e3561b4b05bf62364d4c
Author: Valeriy Vdovin <valeriy.vdovin at virtuozzo.com>
Date:   Wed Oct 13 14:13:30 2021 +0300

    ve/cgroup: Add ve_owner field to cgroup
    
    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)


More information about the Devel mailing list