Commit | Line | Data |
---|---|---|
2bc64a20 AK |
1 | /* |
2 | * Copyright IBM Corporation, 2012 | |
3 | * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify it | |
6 | * under the terms of version 2.1 of the GNU Lesser General Public License | |
7 | * as published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it would be useful, but | |
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
12 | * | |
13 | */ | |
14 | ||
15 | #ifndef _LINUX_HUGETLB_CGROUP_H | |
16 | #define _LINUX_HUGETLB_CGROUP_H | |
17 | ||
309381fe | 18 | #include <linux/mmdebug.h> |
2bc64a20 AK |
19 | |
20 | struct hugetlb_cgroup; | |
e9fe92ae | 21 | struct resv_map; |
075a61d0 | 22 | struct file_region; |
e9fe92ae | 23 | |
cd39d4e9 | 24 | #ifdef CONFIG_CGROUP_HUGETLB |
9dd540e2 AK |
25 | /* |
26 | * Minimum page order trackable by hugetlb cgroup. | |
1adc4d41 | 27 | * At least 4 pages are necessary for all the tracking information. |
cd39d4e9 MS |
28 | * The second tail page (hpage[SUBPAGE_INDEX_CGROUP]) is the fault |
29 | * usage cgroup. The third tail page (hpage[SUBPAGE_INDEX_CGROUP_RSVD]) | |
30 | * is the reservation usage cgroup. | |
9dd540e2 | 31 | */ |
cd39d4e9 | 32 | #define HUGETLB_CGROUP_MIN_ORDER order_base_2(__MAX_CGROUP_SUBPAGE_INDEX + 1) |
2bc64a20 | 33 | |
e9fe92ae MA |
34 | enum hugetlb_memory_event { |
35 | HUGETLB_MAX, | |
36 | HUGETLB_NR_MEMORY_EVENTS, | |
37 | }; | |
38 | ||
39 | struct hugetlb_cgroup { | |
40 | struct cgroup_subsys_state css; | |
41 | ||
42 | /* | |
43 | * the counter to account for hugepages from hugetlb. | |
44 | */ | |
45 | struct page_counter hugepage[HUGE_MAX_HSTATE]; | |
46 | ||
47 | /* | |
48 | * the counter to account for hugepage reservations from hugetlb. | |
49 | */ | |
50 | struct page_counter rsvd_hugepage[HUGE_MAX_HSTATE]; | |
51 | ||
52 | atomic_long_t events[HUGE_MAX_HSTATE][HUGETLB_NR_MEMORY_EVENTS]; | |
53 | atomic_long_t events_local[HUGE_MAX_HSTATE][HUGETLB_NR_MEMORY_EVENTS]; | |
54 | ||
55 | /* Handle for "hugetlb.events" */ | |
56 | struct cgroup_file events_file[HUGE_MAX_HSTATE]; | |
57 | ||
58 | /* Handle for "hugetlb.events.local" */ | |
59 | struct cgroup_file events_local_file[HUGE_MAX_HSTATE]; | |
60 | }; | |
9dd540e2 | 61 | |
1adc4d41 MA |
62 | static inline struct hugetlb_cgroup * |
63 | __hugetlb_cgroup_from_page(struct page *page, bool rsvd) | |
9dd540e2 | 64 | { |
309381fe | 65 | VM_BUG_ON_PAGE(!PageHuge(page), page); |
9dd540e2 AK |
66 | |
67 | if (compound_order(page) < HUGETLB_CGROUP_MIN_ORDER) | |
68 | return NULL; | |
1adc4d41 | 69 | if (rsvd) |
cd39d4e9 | 70 | return (void *)page_private(page + SUBPAGE_INDEX_CGROUP_RSVD); |
1adc4d41 | 71 | else |
cd39d4e9 | 72 | return (void *)page_private(page + SUBPAGE_INDEX_CGROUP); |
1adc4d41 MA |
73 | } |
74 | ||
75 | static inline struct hugetlb_cgroup *hugetlb_cgroup_from_page(struct page *page) | |
76 | { | |
77 | return __hugetlb_cgroup_from_page(page, false); | |
9dd540e2 AK |
78 | } |
79 | ||
1adc4d41 MA |
80 | static inline struct hugetlb_cgroup * |
81 | hugetlb_cgroup_from_page_rsvd(struct page *page) | |
82 | { | |
83 | return __hugetlb_cgroup_from_page(page, true); | |
84 | } | |
85 | ||
86 | static inline int __set_hugetlb_cgroup(struct page *page, | |
87 | struct hugetlb_cgroup *h_cg, bool rsvd) | |
9dd540e2 | 88 | { |
309381fe | 89 | VM_BUG_ON_PAGE(!PageHuge(page), page); |
9dd540e2 AK |
90 | |
91 | if (compound_order(page) < HUGETLB_CGROUP_MIN_ORDER) | |
92 | return -1; | |
1adc4d41 | 93 | if (rsvd) |
cd39d4e9 MS |
94 | set_page_private(page + SUBPAGE_INDEX_CGROUP_RSVD, |
95 | (unsigned long)h_cg); | |
1adc4d41 | 96 | else |
cd39d4e9 MS |
97 | set_page_private(page + SUBPAGE_INDEX_CGROUP, |
98 | (unsigned long)h_cg); | |
9dd540e2 AK |
99 | return 0; |
100 | } | |
101 | ||
1adc4d41 MA |
102 | static inline int set_hugetlb_cgroup(struct page *page, |
103 | struct hugetlb_cgroup *h_cg) | |
104 | { | |
105 | return __set_hugetlb_cgroup(page, h_cg, false); | |
106 | } | |
107 | ||
108 | static inline int set_hugetlb_cgroup_rsvd(struct page *page, | |
109 | struct hugetlb_cgroup *h_cg) | |
110 | { | |
111 | return __set_hugetlb_cgroup(page, h_cg, true); | |
112 | } | |
113 | ||
2bc64a20 AK |
114 | static inline bool hugetlb_cgroup_disabled(void) |
115 | { | |
fc5ed1e9 | 116 | return !cgroup_subsys_enabled(hugetlb_cgrp_subsys); |
2bc64a20 AK |
117 | } |
118 | ||
d85aecf2 ML |
119 | static inline void hugetlb_cgroup_put_rsvd_cgroup(struct hugetlb_cgroup *h_cg) |
120 | { | |
121 | css_put(&h_cg->css); | |
122 | } | |
123 | ||
6d76dcf4 AK |
124 | extern int hugetlb_cgroup_charge_cgroup(int idx, unsigned long nr_pages, |
125 | struct hugetlb_cgroup **ptr); | |
1adc4d41 MA |
126 | extern int hugetlb_cgroup_charge_cgroup_rsvd(int idx, unsigned long nr_pages, |
127 | struct hugetlb_cgroup **ptr); | |
6d76dcf4 AK |
128 | extern void hugetlb_cgroup_commit_charge(int idx, unsigned long nr_pages, |
129 | struct hugetlb_cgroup *h_cg, | |
130 | struct page *page); | |
1adc4d41 MA |
131 | extern void hugetlb_cgroup_commit_charge_rsvd(int idx, unsigned long nr_pages, |
132 | struct hugetlb_cgroup *h_cg, | |
133 | struct page *page); | |
6d76dcf4 AK |
134 | extern void hugetlb_cgroup_uncharge_page(int idx, unsigned long nr_pages, |
135 | struct page *page); | |
1adc4d41 MA |
136 | extern void hugetlb_cgroup_uncharge_page_rsvd(int idx, unsigned long nr_pages, |
137 | struct page *page); | |
138 | ||
6d76dcf4 AK |
139 | extern void hugetlb_cgroup_uncharge_cgroup(int idx, unsigned long nr_pages, |
140 | struct hugetlb_cgroup *h_cg); | |
1adc4d41 MA |
141 | extern void hugetlb_cgroup_uncharge_cgroup_rsvd(int idx, unsigned long nr_pages, |
142 | struct hugetlb_cgroup *h_cg); | |
e9fe92ae MA |
143 | extern void hugetlb_cgroup_uncharge_counter(struct resv_map *resv, |
144 | unsigned long start, | |
145 | unsigned long end); | |
1adc4d41 | 146 | |
075a61d0 MA |
147 | extern void hugetlb_cgroup_uncharge_file_region(struct resv_map *resv, |
148 | struct file_region *rg, | |
d85aecf2 ML |
149 | unsigned long nr_pages, |
150 | bool region_del); | |
075a61d0 | 151 | |
7179e7bf | 152 | extern void hugetlb_cgroup_file_init(void) __init; |
8e6ac7fa AK |
153 | extern void hugetlb_cgroup_migrate(struct page *oldhpage, |
154 | struct page *newhpage); | |
6d76dcf4 | 155 | |
2bc64a20 | 156 | #else |
075a61d0 MA |
157 | static inline void hugetlb_cgroup_uncharge_file_region(struct resv_map *resv, |
158 | struct file_region *rg, | |
d85aecf2 ML |
159 | unsigned long nr_pages, |
160 | bool region_del) | |
075a61d0 MA |
161 | { |
162 | } | |
163 | ||
9dd540e2 AK |
164 | static inline struct hugetlb_cgroup *hugetlb_cgroup_from_page(struct page *page) |
165 | { | |
166 | return NULL; | |
167 | } | |
168 | ||
1adc4d41 MA |
169 | static inline struct hugetlb_cgroup * |
170 | hugetlb_cgroup_from_page_resv(struct page *page) | |
171 | { | |
172 | return NULL; | |
173 | } | |
174 | ||
175 | static inline struct hugetlb_cgroup * | |
176 | hugetlb_cgroup_from_page_rsvd(struct page *page) | |
177 | { | |
178 | return NULL; | |
179 | } | |
180 | ||
181 | static inline int set_hugetlb_cgroup(struct page *page, | |
182 | struct hugetlb_cgroup *h_cg) | |
183 | { | |
184 | return 0; | |
185 | } | |
186 | ||
187 | static inline int set_hugetlb_cgroup_rsvd(struct page *page, | |
188 | struct hugetlb_cgroup *h_cg) | |
9dd540e2 AK |
189 | { |
190 | return 0; | |
191 | } | |
192 | ||
2bc64a20 AK |
193 | static inline bool hugetlb_cgroup_disabled(void) |
194 | { | |
195 | return true; | |
196 | } | |
197 | ||
d85aecf2 ML |
198 | static inline void hugetlb_cgroup_put_rsvd_cgroup(struct hugetlb_cgroup *h_cg) |
199 | { | |
200 | } | |
201 | ||
1adc4d41 MA |
202 | static inline int hugetlb_cgroup_charge_cgroup(int idx, unsigned long nr_pages, |
203 | struct hugetlb_cgroup **ptr) | |
6d76dcf4 AK |
204 | { |
205 | return 0; | |
206 | } | |
207 | ||
1adc4d41 MA |
208 | static inline int hugetlb_cgroup_charge_cgroup_rsvd(int idx, |
209 | unsigned long nr_pages, | |
210 | struct hugetlb_cgroup **ptr) | |
211 | { | |
212 | return 0; | |
213 | } | |
214 | ||
215 | static inline void hugetlb_cgroup_commit_charge(int idx, unsigned long nr_pages, | |
216 | struct hugetlb_cgroup *h_cg, | |
217 | struct page *page) | |
6d76dcf4 | 218 | { |
6d76dcf4 AK |
219 | } |
220 | ||
221 | static inline void | |
1adc4d41 MA |
222 | hugetlb_cgroup_commit_charge_rsvd(int idx, unsigned long nr_pages, |
223 | struct hugetlb_cgroup *h_cg, | |
224 | struct page *page) | |
225 | { | |
226 | } | |
227 | ||
228 | static inline void hugetlb_cgroup_uncharge_page(int idx, unsigned long nr_pages, | |
229 | struct page *page) | |
230 | { | |
231 | } | |
232 | ||
233 | static inline void hugetlb_cgroup_uncharge_page_rsvd(int idx, | |
234 | unsigned long nr_pages, | |
235 | struct page *page) | |
236 | { | |
237 | } | |
238 | static inline void hugetlb_cgroup_uncharge_cgroup(int idx, | |
239 | unsigned long nr_pages, | |
240 | struct hugetlb_cgroup *h_cg) | |
6d76dcf4 | 241 | { |
6d76dcf4 AK |
242 | } |
243 | ||
244 | static inline void | |
1adc4d41 MA |
245 | hugetlb_cgroup_uncharge_cgroup_rsvd(int idx, unsigned long nr_pages, |
246 | struct hugetlb_cgroup *h_cg) | |
6d76dcf4 | 247 | { |
6d76dcf4 AK |
248 | } |
249 | ||
e9fe92ae MA |
250 | static inline void hugetlb_cgroup_uncharge_counter(struct resv_map *resv, |
251 | unsigned long start, | |
252 | unsigned long end) | |
253 | { | |
254 | } | |
255 | ||
7179e7bf | 256 | static inline void hugetlb_cgroup_file_init(void) |
abb8206c | 257 | { |
abb8206c AK |
258 | } |
259 | ||
8e6ac7fa AK |
260 | static inline void hugetlb_cgroup_migrate(struct page *oldhpage, |
261 | struct page *newhpage) | |
262 | { | |
8e6ac7fa AK |
263 | } |
264 | ||
2bc64a20 AK |
265 | #endif /* CONFIG_MEM_RES_CTLR_HUGETLB */ |
266 | #endif |