[Devel] [PATCH VZ8 v1 07/14] ve/cgroup: Added ve_owner field to cgroup
Kirill Tkhai
ktkhai at virtuozzo.com
Mon Jan 25 13:11:34 MSK 2021
On 20.01.2021 12:56, Valeriy Vdovin wrote:
> Each cgroup representing a host or a container root of
> cgroup subsystem hierarhy 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.
>
> cgroup->ve_owner is declared as RCU pointer, because it fits
> RCU semantics - rare writes/often reads. ve_owner will be
> read from multiple locations in code in further patches and
> is only rarely set at cgroup_mark_ve_root/cgroup_mount.
> cgroup_get_ve_owner is a read wrapper for this purpose.
>
> (Cherry-picked from eb9c0bfae39fe336173a0dec11bc24f7275de3f8)
> Signed-off-by: Valeriy Vdovin <valeriy.vdovin at virtuozzo.com>
Reviewed-by: Kirill Tkhai <ktkhai at virtuozzo.com>
> ---
> include/linux/cgroup-defs.h | 3 +++
> include/linux/cgroup.h | 1 +
> kernel/cgroup/cgroup.c | 44 +++++++++++++++++++++++++++++++++++++
> 3 files changed, 48 insertions(+)
>
> diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h
> index 4fd566414274..e497387872f4 100644
> --- a/include/linux/cgroup-defs.h
> +++ b/include/linux/cgroup-defs.h
> @@ -528,6 +528,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 */
> int ancestor_ids[];
> };
> diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
> index a1e6822bca8f..df9a9a09ce2a 100644
> --- a/include/linux/cgroup.h
> +++ b/include/linux/cgroup.h
> @@ -900,6 +900,7 @@ int cgroup_path_ns(struct cgroup *cgrp, char *buf, size_t buflen,
> #ifdef CONFIG_VE
> extern void cgroup_mark_ve_root(struct ve_struct *ve);
> void cgroup_unmark_ve_roots(struct ve_struct *ve);
> +struct ve_struct *cgroup_get_ve_owner(struct cgroup *cgrp);
> #endif
>
> #else /* !CONFIG_CGROUPS */
> diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
> index 53a349539256..ff0a803c3aad 100644
> --- a/kernel/cgroup/cgroup.c
> +++ b/kernel/cgroup/cgroup.c
> @@ -303,6 +303,43 @@ bool cgroup_on_dfl(const struct cgroup *cgrp)
> return cgrp->root == &cgrp_dfl_root;
> }
>
> +struct cgroup *cgroup_get_local_root(struct cgroup *cgrp)
> +{
> + /*
> + * Find nearest root cgroup, which might be host cgroup root
> + * or ve cgroup root.
> + *
> + * <host_root_cgroup> -> local_root
> + * \ ^
> + * <cgroup> |
> + * \ |
> + * <cgroup> ---> from here
> + * \
> + * <ve_root_cgroup> -> local_root
> + * \ ^
> + * <cgroup> |
> + * \ |
> + * <cgroup> ---> from here
> + */
> +
> + while (cgrp->kn->parent && !test_bit(CGRP_VE_ROOT, &cgrp->flags))
> + cgrp = cgrp->kn->parent->priv;
> +
> + return cgrp;
> +}
> +
> +struct ve_struct *cgroup_get_ve_owner(struct cgroup *cgrp)
> +{
> + struct ve_struct *ve;
> + /* Caller should hold RCU */
> +
> + cgrp = cgroup_get_local_root(cgrp);
> + ve = rcu_dereference(cgrp->ve_owner);
> + if (!ve)
> + ve = get_ve0();
> + 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)
> @@ -1900,6 +1937,7 @@ void cgroup_mark_ve_root(struct ve_struct *ve)
>
> list_for_each_entry(link, &cset->cgrp_links, cgrp_link) {
> cgrp = link->cgrp;
> + rcu_assign_pointer(cgrp->ve_owner, ve);
> set_bit(CGRP_VE_ROOT, &cgrp->flags);
> }
> link_ve_root_cpu_cgroup(cset->subsys[cpu_cgrp_id]);
> @@ -1907,6 +1945,7 @@ void cgroup_mark_ve_root(struct ve_struct *ve)
> rcu_read_unlock();
>
> spin_unlock_irq(&css_set_lock);
> + synchronize_rcu();
> }
>
> void cgroup_unmark_ve_roots(struct ve_struct *ve)
> @@ -1924,6 +1963,7 @@ void cgroup_unmark_ve_roots(struct ve_struct *ve)
>
> list_for_each_entry(link, &cset->cgrp_links, cgrp_link) {
> cgrp = link->cgrp;
> + rcu_assign_pointer(cgrp->ve_owner, NULL);
> clear_bit(CGRP_VE_ROOT, &cgrp->flags);
> }
> link_ve_root_cpu_cgroup(cset->subsys[cpu_cgrp_id]);
> @@ -1931,6 +1971,8 @@ void cgroup_unmark_ve_roots(struct ve_struct *ve)
> rcu_read_unlock();
>
> spin_unlock_irq(&css_set_lock);
> + /* ve_owner == NULL will be visible */
> + synchronize_rcu();
> }
>
> struct cgroup *cgroup_get_ve_root1(struct cgroup *cgrp)
> @@ -2115,6 +2157,8 @@ struct dentry *cgroup_do_mount(struct file_system_type *fs_type, int flags,
> struct dentry *dentry;
> bool new_sb = false;
>
> + RCU_INIT_POINTER(root->cgrp.ve_owner, &ve0);
> +
> dentry = kernfs_mount(fs_type, flags, root->kf_root, magic, &new_sb);
>
> /*
>
More information about the Devel
mailing list