[Devel] [PATCH v12 07/12] ve/cgroup: Added ve_owner field to cgroup
Kirill Tkhai
ktkhai at virtuozzo.com
Mon Apr 20 12:27:34 MSK 2020
On 20.04.2020 06:42, 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.
>
> Signed-off-by: Valeriy Vdovin <valeriy.vdovin at virtuozzo.com>
Reviewed-by: Kirill Tkhai <ktkhai at virtuozzo.com>
> ---
> include/linux/cgroup.h | 4 ++++
> kernel/cgroup.c | 43 +++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 47 insertions(+)
>
> diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
> index 1bd0fe7..7ed718d 100644
> --- a/include/linux/cgroup.h
> +++ b/include/linux/cgroup.h
> @@ -292,6 +292,9 @@ struct cgroup {
> /* directory xattrs */
> struct simple_xattrs xattrs;
> u64 subgroups_limit;
> +
> + /* ve_owner, responsible for running release agent. */
> + struct ve_struct *ve_owner;
> };
>
> #define MAX_CGROUP_ROOT_NAMELEN 64
> @@ -637,6 +640,7 @@ int cgroup_task_count(const struct cgroup *cgrp);
> #ifdef CONFIG_VE
> void cgroup_mark_ve_roots(struct ve_struct *ve);
> void cgroup_unmark_ve_roots(struct ve_struct *ve);
> +struct ve_struct *cgroup_get_ve_owner(struct cgroup *cgrp);
> #endif
>
> /*
> diff --git a/kernel/cgroup.c b/kernel/cgroup.c
> index 010a23e..b19d749 100644
> --- a/kernel/cgroup.c
> +++ b/kernel/cgroup.c
> @@ -805,6 +805,42 @@ static struct cgroup_name *cgroup_alloc_name(struct dentry *dentry)
> return name;
> }
>
> +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->parent && !test_bit(CGRP_VE_ROOT, &cgrp->flags))
> + cgrp = cgrp->parent;
> +
> + 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;
> +}
> +
> static void cgroup_free_fn(struct work_struct *work)
> {
> struct cgroup *cgrp = container_of(work, struct cgroup, destroy_work);
> @@ -1647,6 +1683,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
> const struct cred *cred;
> int i;
> struct css_set *cg;
> + root_cgrp->ve_owner = &ve0;
>
> BUG_ON(sb->s_root != NULL);
>
> @@ -4254,6 +4291,7 @@ void cgroup_mark_ve_roots(struct ve_struct *ve)
> mutex_lock(&cgroup_mutex);
> for_each_active_root(root) {
> cgrp = task_cgroup_from_root(ve->init_task, root);
> + cgrp->ve_owner = ve;
> set_bit(CGRP_VE_ROOT, &cgrp->flags);
>
> if (test_bit(cpu_cgroup_subsys_id, &root->subsys_mask))
> @@ -4270,9 +4308,14 @@ void cgroup_unmark_ve_roots(struct ve_struct *ve)
> mutex_lock(&cgroup_mutex);
> for_each_active_root(root) {
> cgrp = css_cgroup_from_root(ve->root_css_set, root);
> + BUG_ON(!rcu_dereference_protected(cgrp->ve_owner,
> + lockdep_is_held(&cgroup_mutex)));
> + rcu_assign_pointer(cgrp->ve_owner, NULL);
> clear_bit(CGRP_VE_ROOT, &cgrp->flags);
> }
> mutex_unlock(&cgroup_mutex);
> + /* ve_owner == NULL will be visible */
> + synchronize_rcu();
> }
>
> struct cgroup *cgroup_get_ve_root(struct cgroup *cgrp)
>
More information about the Devel
mailing list