xref: /linux-6.15/include/linux/hugetlb_cgroup.h (revision e9fe92ae)
1 /*
2  * Copyright IBM Corporation, 2012
3  * Author Aneesh Kumar K.V <[email protected]>
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 
18 #include <linux/mmdebug.h>
19 
20 struct hugetlb_cgroup;
21 struct resv_map;
22 
23 /*
24  * Minimum page order trackable by hugetlb cgroup.
25  * At least 4 pages are necessary for all the tracking information.
26  * The second tail page (hpage[2]) is the fault usage cgroup.
27  * The third tail page (hpage[3]) is the reservation usage cgroup.
28  */
29 #define HUGETLB_CGROUP_MIN_ORDER	2
30 
31 #ifdef CONFIG_CGROUP_HUGETLB
32 enum hugetlb_memory_event {
33 	HUGETLB_MAX,
34 	HUGETLB_NR_MEMORY_EVENTS,
35 };
36 
37 struct hugetlb_cgroup {
38 	struct cgroup_subsys_state css;
39 
40 	/*
41 	 * the counter to account for hugepages from hugetlb.
42 	 */
43 	struct page_counter hugepage[HUGE_MAX_HSTATE];
44 
45 	/*
46 	 * the counter to account for hugepage reservations from hugetlb.
47 	 */
48 	struct page_counter rsvd_hugepage[HUGE_MAX_HSTATE];
49 
50 	atomic_long_t events[HUGE_MAX_HSTATE][HUGETLB_NR_MEMORY_EVENTS];
51 	atomic_long_t events_local[HUGE_MAX_HSTATE][HUGETLB_NR_MEMORY_EVENTS];
52 
53 	/* Handle for "hugetlb.events" */
54 	struct cgroup_file events_file[HUGE_MAX_HSTATE];
55 
56 	/* Handle for "hugetlb.events.local" */
57 	struct cgroup_file events_local_file[HUGE_MAX_HSTATE];
58 };
59 
60 static inline struct hugetlb_cgroup *
61 __hugetlb_cgroup_from_page(struct page *page, bool rsvd)
62 {
63 	VM_BUG_ON_PAGE(!PageHuge(page), page);
64 
65 	if (compound_order(page) < HUGETLB_CGROUP_MIN_ORDER)
66 		return NULL;
67 	if (rsvd)
68 		return (struct hugetlb_cgroup *)page[3].private;
69 	else
70 		return (struct hugetlb_cgroup *)page[2].private;
71 }
72 
73 static inline struct hugetlb_cgroup *hugetlb_cgroup_from_page(struct page *page)
74 {
75 	return __hugetlb_cgroup_from_page(page, false);
76 }
77 
78 static inline struct hugetlb_cgroup *
79 hugetlb_cgroup_from_page_rsvd(struct page *page)
80 {
81 	return __hugetlb_cgroup_from_page(page, true);
82 }
83 
84 static inline int __set_hugetlb_cgroup(struct page *page,
85 				       struct hugetlb_cgroup *h_cg, bool rsvd)
86 {
87 	VM_BUG_ON_PAGE(!PageHuge(page), page);
88 
89 	if (compound_order(page) < HUGETLB_CGROUP_MIN_ORDER)
90 		return -1;
91 	if (rsvd)
92 		page[3].private = (unsigned long)h_cg;
93 	else
94 		page[2].private = (unsigned long)h_cg;
95 	return 0;
96 }
97 
98 static inline int set_hugetlb_cgroup(struct page *page,
99 				     struct hugetlb_cgroup *h_cg)
100 {
101 	return __set_hugetlb_cgroup(page, h_cg, false);
102 }
103 
104 static inline int set_hugetlb_cgroup_rsvd(struct page *page,
105 					  struct hugetlb_cgroup *h_cg)
106 {
107 	return __set_hugetlb_cgroup(page, h_cg, true);
108 }
109 
110 static inline bool hugetlb_cgroup_disabled(void)
111 {
112 	return !cgroup_subsys_enabled(hugetlb_cgrp_subsys);
113 }
114 
115 extern int hugetlb_cgroup_charge_cgroup(int idx, unsigned long nr_pages,
116 					struct hugetlb_cgroup **ptr);
117 extern int hugetlb_cgroup_charge_cgroup_rsvd(int idx, unsigned long nr_pages,
118 					     struct hugetlb_cgroup **ptr);
119 extern void hugetlb_cgroup_commit_charge(int idx, unsigned long nr_pages,
120 					 struct hugetlb_cgroup *h_cg,
121 					 struct page *page);
122 extern void hugetlb_cgroup_commit_charge_rsvd(int idx, unsigned long nr_pages,
123 					      struct hugetlb_cgroup *h_cg,
124 					      struct page *page);
125 extern void hugetlb_cgroup_uncharge_page(int idx, unsigned long nr_pages,
126 					 struct page *page);
127 extern void hugetlb_cgroup_uncharge_page_rsvd(int idx, unsigned long nr_pages,
128 					      struct page *page);
129 
130 extern void hugetlb_cgroup_uncharge_cgroup(int idx, unsigned long nr_pages,
131 					   struct hugetlb_cgroup *h_cg);
132 extern void hugetlb_cgroup_uncharge_cgroup_rsvd(int idx, unsigned long nr_pages,
133 						struct hugetlb_cgroup *h_cg);
134 extern void hugetlb_cgroup_uncharge_counter(struct resv_map *resv,
135 					    unsigned long start,
136 					    unsigned long end);
137 
138 extern void hugetlb_cgroup_file_init(void) __init;
139 extern void hugetlb_cgroup_migrate(struct page *oldhpage,
140 				   struct page *newhpage);
141 
142 #else
143 static inline struct hugetlb_cgroup *hugetlb_cgroup_from_page(struct page *page)
144 {
145 	return NULL;
146 }
147 
148 static inline struct hugetlb_cgroup *
149 hugetlb_cgroup_from_page_resv(struct page *page)
150 {
151 	return NULL;
152 }
153 
154 static inline struct hugetlb_cgroup *
155 hugetlb_cgroup_from_page_rsvd(struct page *page)
156 {
157 	return NULL;
158 }
159 
160 static inline int set_hugetlb_cgroup(struct page *page,
161 				     struct hugetlb_cgroup *h_cg)
162 {
163 	return 0;
164 }
165 
166 static inline int set_hugetlb_cgroup_rsvd(struct page *page,
167 					  struct hugetlb_cgroup *h_cg)
168 {
169 	return 0;
170 }
171 
172 static inline bool hugetlb_cgroup_disabled(void)
173 {
174 	return true;
175 }
176 
177 static inline int hugetlb_cgroup_charge_cgroup(int idx, unsigned long nr_pages,
178 					       struct hugetlb_cgroup **ptr)
179 {
180 	return 0;
181 }
182 
183 static inline int hugetlb_cgroup_charge_cgroup_rsvd(int idx,
184 						    unsigned long nr_pages,
185 						    struct hugetlb_cgroup **ptr)
186 {
187 	return 0;
188 }
189 
190 static inline void hugetlb_cgroup_commit_charge(int idx, unsigned long nr_pages,
191 						struct hugetlb_cgroup *h_cg,
192 						struct page *page)
193 {
194 }
195 
196 static inline void
197 hugetlb_cgroup_commit_charge_rsvd(int idx, unsigned long nr_pages,
198 				  struct hugetlb_cgroup *h_cg,
199 				  struct page *page)
200 {
201 }
202 
203 static inline void hugetlb_cgroup_uncharge_page(int idx, unsigned long nr_pages,
204 						struct page *page)
205 {
206 }
207 
208 static inline void hugetlb_cgroup_uncharge_page_rsvd(int idx,
209 						     unsigned long nr_pages,
210 						     struct page *page)
211 {
212 }
213 static inline void hugetlb_cgroup_uncharge_cgroup(int idx,
214 						  unsigned long nr_pages,
215 						  struct hugetlb_cgroup *h_cg)
216 {
217 }
218 
219 static inline void
220 hugetlb_cgroup_uncharge_cgroup_rsvd(int idx, unsigned long nr_pages,
221 				    struct hugetlb_cgroup *h_cg)
222 {
223 }
224 
225 static inline void hugetlb_cgroup_uncharge_counter(struct resv_map *resv,
226 						   unsigned long start,
227 						   unsigned long end)
228 {
229 }
230 
231 static inline void hugetlb_cgroup_file_init(void)
232 {
233 }
234 
235 static inline void hugetlb_cgroup_migrate(struct page *oldhpage,
236 					  struct page *newhpage)
237 {
238 }
239 
240 #endif  /* CONFIG_MEM_RES_CTLR_HUGETLB */
241 #endif
242