Re: [RFC][mm] [PATCH 3/4] Memory cgroup hierarchical reclaim (v3)

KAMEZAWA Hiroyuki
2008-11-13T04:18:59Z

On Wed, 12 Nov 2008 16:51:41 +0530
Balbir Singh <balbir@linux.vnet.ibm.com> wrote:

> Here is the iterative version of this patch. I tested it in my
> test environment. NOTE: The cgroup_locked check is still present, I'll
> remove that shortly after your patch is accepted.
>
> This patch introduces hierarchical reclaim. When an ancestor goes over its
> limit, the charging routine points to the parent that is above its limit.
> The reclaim process then starts from the last scanned child of the ancestor
> and reclaims until the ancestor goes below its limit.
>

complicated as you said but it seems it's from style.

I expected following kind of one.
==

struct mem_cgroup *memcg_select_next_token(struct mem_cgroup *itr,
struct mem_cgroup *cur,
struct mem_cgroup *root)
{
struct cgroup *pos, *tmp, *parent, *rootpos;

cgroup_lock();
if (!itr || itr->obsolete)
itr = cur;

rootpos = root->css.cgroup;
pos = itr->css.cgroup;
parent = pos->parent;
/* start from children */
if (!list_empty(&pos->children)) {
pos = list_entry(pos->children.next, struct cgroup, sibling);
mem_cgroup_put(itr);
itr = mem_cgroup_from_cont(pos);
mem_cgroup_get(itr);
goto unlock;
}
next_parent:
if (pos == rootpos) {
/* I'm root and no available children */
mem_cgroup_put(itr);
itr = mem_cgroup_from_cont(pos);
mem_cgroup_get(itr);
goto unlock;
}
/* Do I have next siblings ? */
if (pos->sibling.next != &parent->children) {
pos = list_entry(pos->sibling.next, struct cgroup, sibling);
mem_cgroup_put(itr);
itr = mem_cgroup_from_cont(pos);
mem_cgroup_get(itr);
goto unlock;
}
/* Ok, go back to parent */
pos = pos->parent;
goto next_parent;

unlock:
root->reclaim_token = token;
cgroup_unlock();
return itr;
}

struct mem_cgroup *memcg_select_start_token(struct mem_cgroup *cur,
struct mem_cgroup *root)
{
struct mem_cgroup *token;

if (cur == root)
return cur;

cgroup_lock();

token = root->reclaim_token;
if (token->obsolete) {
mem_cgroup_put(token); /* decrease refcnt */
root->reclaim_token = cur;
token = cur;
mem_cgroup_get(cur); /* increase refcnt */
cgroup_unlock();
return token;
}
cgroup_unlock();

return memcg_select_next_token(token, cur, root);
}

int mem_cgroup_do_reclaim(struct mem_cgroup *mem,
struct mem_cgroup *root_mem,
gfp_t mask)
{
struct cgroup *cgroup;
struct mem_cgroup *tmp, *token, *start;
/*
* We do memory reclaim under "root_mem".
* We have to be careful not to reclaim memory only from
* unlucky one. For avoiding that, we use "token".
*/

token = memcg_select_start_token(mem, root_mem);

start = NULL;

while (start != token) {
if (!token->obsolete) {
ret = try_to_free_mem_cgroup_pages(token,
GFP_HIGHUSER_MOVABLE);
if (!res_counter_check_under_limit(&root_mem->res))
return 0;
if (ret == 0)
retry--;
start = token;
token = memcg_select_next_token(token, mem, root_mem);
} else {
/* This mem_cgroup is destroyed. */
mem_cgroup_put(token);
token = memcg_select_next_token(NULL, mem, root_mem);
}
}

}