mm/hugetlb: add new HugeTLB cgroup
[platform/adaptation/renesas_rcar/renesas_kernel.git] / mm / hugetlb_cgroup.c
1 /*
2  *
3  * Copyright IBM Corporation, 2012
4  * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of version 2.1 of the GNU Lesser General Public License
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it would be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  *
14  */
15
16 #include <linux/cgroup.h>
17 #include <linux/slab.h>
18 #include <linux/hugetlb.h>
19 #include <linux/hugetlb_cgroup.h>
20
21 struct hugetlb_cgroup {
22         struct cgroup_subsys_state css;
23         /*
24          * the counter to account for hugepages from hugetlb.
25          */
26         struct res_counter hugepage[HUGE_MAX_HSTATE];
27 };
28
29 struct cgroup_subsys hugetlb_subsys __read_mostly;
30 static struct hugetlb_cgroup *root_h_cgroup __read_mostly;
31
32 static inline
33 struct hugetlb_cgroup *hugetlb_cgroup_from_css(struct cgroup_subsys_state *s)
34 {
35         return container_of(s, struct hugetlb_cgroup, css);
36 }
37
38 static inline
39 struct hugetlb_cgroup *hugetlb_cgroup_from_cgroup(struct cgroup *cgroup)
40 {
41         return hugetlb_cgroup_from_css(cgroup_subsys_state(cgroup,
42                                                            hugetlb_subsys_id));
43 }
44
45 static inline
46 struct hugetlb_cgroup *hugetlb_cgroup_from_task(struct task_struct *task)
47 {
48         return hugetlb_cgroup_from_css(task_subsys_state(task,
49                                                          hugetlb_subsys_id));
50 }
51
52 static inline bool hugetlb_cgroup_is_root(struct hugetlb_cgroup *h_cg)
53 {
54         return (h_cg == root_h_cgroup);
55 }
56
57 static inline struct hugetlb_cgroup *parent_hugetlb_cgroup(struct cgroup *cg)
58 {
59         if (!cg->parent)
60                 return NULL;
61         return hugetlb_cgroup_from_cgroup(cg->parent);
62 }
63
64 static inline bool hugetlb_cgroup_have_usage(struct cgroup *cg)
65 {
66         int idx;
67         struct hugetlb_cgroup *h_cg = hugetlb_cgroup_from_cgroup(cg);
68
69         for (idx = 0; idx < hugetlb_max_hstate; idx++) {
70                 if ((res_counter_read_u64(&h_cg->hugepage[idx], RES_USAGE)) > 0)
71                         return true;
72         }
73         return false;
74 }
75
76 static struct cgroup_subsys_state *hugetlb_cgroup_create(struct cgroup *cgroup)
77 {
78         int idx;
79         struct cgroup *parent_cgroup;
80         struct hugetlb_cgroup *h_cgroup, *parent_h_cgroup;
81
82         h_cgroup = kzalloc(sizeof(*h_cgroup), GFP_KERNEL);
83         if (!h_cgroup)
84                 return ERR_PTR(-ENOMEM);
85
86         parent_cgroup = cgroup->parent;
87         if (parent_cgroup) {
88                 parent_h_cgroup = hugetlb_cgroup_from_cgroup(parent_cgroup);
89                 for (idx = 0; idx < HUGE_MAX_HSTATE; idx++)
90                         res_counter_init(&h_cgroup->hugepage[idx],
91                                          &parent_h_cgroup->hugepage[idx]);
92         } else {
93                 root_h_cgroup = h_cgroup;
94                 for (idx = 0; idx < HUGE_MAX_HSTATE; idx++)
95                         res_counter_init(&h_cgroup->hugepage[idx], NULL);
96         }
97         return &h_cgroup->css;
98 }
99
100 static void hugetlb_cgroup_destroy(struct cgroup *cgroup)
101 {
102         struct hugetlb_cgroup *h_cgroup;
103
104         h_cgroup = hugetlb_cgroup_from_cgroup(cgroup);
105         kfree(h_cgroup);
106 }
107
108 static int hugetlb_cgroup_pre_destroy(struct cgroup *cgroup)
109 {
110         /* We will add the cgroup removal support in later patches */
111            return -EBUSY;
112 }
113
114 struct cgroup_subsys hugetlb_subsys = {
115         .name = "hugetlb",
116         .create     = hugetlb_cgroup_create,
117         .pre_destroy = hugetlb_cgroup_pre_destroy,
118         .destroy    = hugetlb_cgroup_destroy,
119         .subsys_id  = hugetlb_subsys_id,
120 };