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