Skip to content

Commit 2e5e67d

Browse files
pixelclusterptr1337
authored andcommitted
cgroup,cgroup/dmem: Add (dmem_)cgroup_common_ancestor helper
This helps to find a common subtree of two resources, which is important when determining whether it's helpful to evict one resource in favor of another. To facilitate this, add a common helper to find the ancestor of two cgroups using each cgroup's ancestor array. Signed-off-by: Natalie Vock <natalie.vock@gmx.de>
1 parent 58fdb65 commit 2e5e67d

3 files changed

Lines changed: 59 additions & 0 deletions

File tree

include/linux/cgroup.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,27 @@ static inline struct cgroup *cgroup_ancestor(struct cgroup *cgrp,
561561
return cgrp->ancestors[ancestor_level];
562562
}
563563

564+
/**
565+
* cgroup_common_ancestor - find common ancestor of two cgroups
566+
* @a: first cgroup to find common ancestor of
567+
* @b: second cgroup to find common ancestor of
568+
*
569+
* Find the first cgroup that is an ancestor of both @a and @b, if it exists
570+
* and return a pointer to it. If such a cgroup doesn't exist, return NULL.
571+
*
572+
* This function is safe to call as long as both @a and @b are accessible.
573+
*/
574+
static inline struct cgroup *cgroup_common_ancestor(struct cgroup *a,
575+
struct cgroup *b)
576+
{
577+
int level;
578+
579+
for (level = min(a->level, b->level); level >= 0; level--)
580+
if (a->ancestors[level] == b->ancestors[level])
581+
return a->ancestors[level];
582+
return NULL;
583+
}
584+
564585
/**
565586
* task_under_cgroup_hierarchy - test task's membership of cgroup ancestry
566587
* @task: the task to be tested

include/linux/cgroup_dmem.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ bool dmem_cgroup_below_min(struct dmem_cgroup_pool_state *root,
2828
struct dmem_cgroup_pool_state *test);
2929
bool dmem_cgroup_below_low(struct dmem_cgroup_pool_state *root,
3030
struct dmem_cgroup_pool_state *test);
31+
struct dmem_cgroup_pool_state *dmem_cgroup_get_common_ancestor(struct dmem_cgroup_pool_state *a,
32+
struct dmem_cgroup_pool_state *b);
3133

3234
void dmem_cgroup_pool_state_put(struct dmem_cgroup_pool_state *pool);
3335
#else
@@ -75,6 +77,13 @@ static inline bool dmem_cgroup_below_low(struct dmem_cgroup_pool_state *root,
7577
return false;
7678
}
7779

80+
static inline
81+
struct dmem_cgroup_pool_state *dmem_cgroup_get_common_ancestor(struct dmem_cgroup_pool_state *a,
82+
struct dmem_cgroup_pool_state *b)
83+
{
84+
return NULL;
85+
}
86+
7887
static inline void dmem_cgroup_pool_state_put(struct dmem_cgroup_pool_state *pool)
7988
{ }
8089

kernel/cgroup/dmem.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,35 @@ bool dmem_cgroup_below_low(struct dmem_cgroup_pool_state *root,
756756
}
757757
EXPORT_SYMBOL_GPL(dmem_cgroup_below_low);
758758

759+
/**
760+
* dmem_cgroup_get_common_ancestor(): Find the first common ancestor of two pools.
761+
* @a: First pool to find the common ancestor of.
762+
* @b: First pool to find the common ancestor of.
763+
*
764+
* Return: The first pool that is a parent of both @a and @b, or NULL if either @a or @b are NULL,
765+
* or if such a pool does not exist. A reference to the returned pool is grabbed and must be
766+
* released by the caller when it is done using the pool.
767+
*/
768+
struct dmem_cgroup_pool_state *dmem_cgroup_get_common_ancestor(struct dmem_cgroup_pool_state *a,
769+
struct dmem_cgroup_pool_state *b)
770+
{
771+
struct cgroup *ancestor_cgroup;
772+
struct cgroup_subsys_state *ancestor_css;
773+
774+
if (!a || !b)
775+
return NULL;
776+
777+
ancestor_cgroup = cgroup_common_ancestor(a->cs->css.cgroup, b->cs->css.cgroup);
778+
if (!ancestor_cgroup)
779+
return NULL;
780+
781+
ancestor_css = cgroup_e_css(ancestor_cgroup, &dmem_cgrp_subsys);
782+
css_get(ancestor_css);
783+
784+
return get_cg_pool_unlocked(css_to_dmemcs(ancestor_css), a->region);
785+
}
786+
EXPORT_SYMBOL_GPL(dmem_cgroup_get_common_ancestor);
787+
759788
static int dmem_cgroup_region_capacity_show(struct seq_file *sf, void *v)
760789
{
761790
struct dmem_cgroup_region *region;

0 commit comments

Comments
 (0)