[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