Skip to content

Commit

Permalink
hugetlb/cgroup: add support for cgroup removal
Browse files Browse the repository at this point in the history
Add support for cgroup removal.  If we don't have parent cgroup, the
charges are moved to root cgroup.

Signed-off-by: Aneesh Kumar K.V <[email protected]>
Cc: David Rientjes <[email protected]>
Acked-by: KAMEZAWA Hiroyuki <[email protected]>
Cc: Hillf Danton <[email protected]>
Reviewed-by: Michal Hocko <[email protected]>
Cc: KOSAKI Motohiro <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
kvaneesh authored and torvalds committed Aug 1, 2012
1 parent 6d76dcf commit da1def5
Showing 1 changed file with 68 additions and 2 deletions.
70 changes: 68 additions & 2 deletions mm/hugetlb_cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,76 @@ static void hugetlb_cgroup_destroy(struct cgroup *cgroup)
kfree(h_cgroup);
}


/*
* Should be called with hugetlb_lock held.
* Since we are holding hugetlb_lock, pages cannot get moved from
* active list or uncharged from the cgroup, So no need to get
* page reference and test for page active here. This function
* cannot fail.
*/
static void hugetlb_cgroup_move_parent(int idx, struct cgroup *cgroup,
struct page *page)
{
int csize;
struct res_counter *counter;
struct res_counter *fail_res;
struct hugetlb_cgroup *page_hcg;
struct hugetlb_cgroup *h_cg = hugetlb_cgroup_from_cgroup(cgroup);
struct hugetlb_cgroup *parent = parent_hugetlb_cgroup(cgroup);

page_hcg = hugetlb_cgroup_from_page(page);
/*
* We can have pages in active list without any cgroup
* ie, hugepage with less than 3 pages. We can safely
* ignore those pages.
*/
if (!page_hcg || page_hcg != h_cg)
goto out;

csize = PAGE_SIZE << compound_order(page);
if (!parent) {
parent = root_h_cgroup;
/* root has no limit */
res_counter_charge_nofail(&parent->hugepage[idx],
csize, &fail_res);
}
counter = &h_cg->hugepage[idx];
res_counter_uncharge_until(counter, counter->parent, csize);

set_hugetlb_cgroup(page, parent);
out:
return;
}

/*
* Force the hugetlb cgroup to empty the hugetlb resources by moving them to
* the parent cgroup.
*/
static int hugetlb_cgroup_pre_destroy(struct cgroup *cgroup)
{
/* We will add the cgroup removal support in later patches */
return -EBUSY;
struct hstate *h;
struct page *page;
int ret = 0, idx = 0;

do {
if (cgroup_task_count(cgroup) ||
!list_empty(&cgroup->children)) {
ret = -EBUSY;
goto out;
}
for_each_hstate(h) {
spin_lock(&hugetlb_lock);
list_for_each_entry(page, &h->hugepage_activelist, lru)
hugetlb_cgroup_move_parent(idx, cgroup, page);

spin_unlock(&hugetlb_lock);
idx++;
}
cond_resched();
} while (hugetlb_cgroup_have_usage(cgroup));
out:
return ret;
}

int hugetlb_cgroup_charge_cgroup(int idx, unsigned long nr_pages,
Expand Down

0 comments on commit da1def5

Please sign in to comment.