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