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 /* 22 * Minimum page order trackable by hugetlb cgroup. 23 * At least 4 pages are necessary for all the tracking information. 24 * The second tail page (hpage[2]) is the fault usage cgroup. 25 * The third tail page (hpage[3]) is the reservation usage cgroup. 26 */ 27 #define HUGETLB_CGROUP_MIN_ORDER 2 28 29 #ifdef CONFIG_CGROUP_HUGETLB 30 31 static inline struct hugetlb_cgroup * 32 __hugetlb_cgroup_from_page(struct page *page, bool rsvd) 33 { 34 VM_BUG_ON_PAGE(!PageHuge(page), page); 35 36 if (compound_order(page) < HUGETLB_CGROUP_MIN_ORDER) 37 return NULL; 38 if (rsvd) 39 return (struct hugetlb_cgroup *)page[3].private; 40 else 41 return (struct hugetlb_cgroup *)page[2].private; 42 } 43 44 static inline struct hugetlb_cgroup *hugetlb_cgroup_from_page(struct page *page) 45 { 46 return __hugetlb_cgroup_from_page(page, false); 47 } 48 49 static inline struct hugetlb_cgroup * 50 hugetlb_cgroup_from_page_rsvd(struct page *page) 51 { 52 return __hugetlb_cgroup_from_page(page, true); 53 } 54 55 static inline int __set_hugetlb_cgroup(struct page *page, 56 struct hugetlb_cgroup *h_cg, bool rsvd) 57 { 58 VM_BUG_ON_PAGE(!PageHuge(page), page); 59 60 if (compound_order(page) < HUGETLB_CGROUP_MIN_ORDER) 61 return -1; 62 if (rsvd) 63 page[3].private = (unsigned long)h_cg; 64 else 65 page[2].private = (unsigned long)h_cg; 66 return 0; 67 } 68 69 static inline int set_hugetlb_cgroup(struct page *page, 70 struct hugetlb_cgroup *h_cg) 71 { 72 return __set_hugetlb_cgroup(page, h_cg, false); 73 } 74 75 static inline int set_hugetlb_cgroup_rsvd(struct page *page, 76 struct hugetlb_cgroup *h_cg) 77 { 78 return __set_hugetlb_cgroup(page, h_cg, true); 79 } 80 81 static inline bool hugetlb_cgroup_disabled(void) 82 { 83 return !cgroup_subsys_enabled(hugetlb_cgrp_subsys); 84 } 85 86 extern int hugetlb_cgroup_charge_cgroup(int idx, unsigned long nr_pages, 87 struct hugetlb_cgroup **ptr); 88 extern int hugetlb_cgroup_charge_cgroup_rsvd(int idx, unsigned long nr_pages, 89 struct hugetlb_cgroup **ptr); 90 extern void hugetlb_cgroup_commit_charge(int idx, unsigned long nr_pages, 91 struct hugetlb_cgroup *h_cg, 92 struct page *page); 93 extern void hugetlb_cgroup_commit_charge_rsvd(int idx, unsigned long nr_pages, 94 struct hugetlb_cgroup *h_cg, 95 struct page *page); 96 extern void hugetlb_cgroup_uncharge_page(int idx, unsigned long nr_pages, 97 struct page *page); 98 extern void hugetlb_cgroup_uncharge_page_rsvd(int idx, unsigned long nr_pages, 99 struct page *page); 100 101 extern void hugetlb_cgroup_uncharge_cgroup(int idx, unsigned long nr_pages, 102 struct hugetlb_cgroup *h_cg); 103 extern void hugetlb_cgroup_uncharge_cgroup_rsvd(int idx, unsigned long nr_pages, 104 struct hugetlb_cgroup *h_cg); 105 extern void hugetlb_cgroup_uncharge_counter(struct page_counter *p, 106 unsigned long nr_pages, 107 struct cgroup_subsys_state *css); 108 109 extern void hugetlb_cgroup_file_init(void) __init; 110 extern void hugetlb_cgroup_migrate(struct page *oldhpage, 111 struct page *newhpage); 112 113 #else 114 static inline struct hugetlb_cgroup *hugetlb_cgroup_from_page(struct page *page) 115 { 116 return NULL; 117 } 118 119 static inline struct hugetlb_cgroup * 120 hugetlb_cgroup_from_page_resv(struct page *page) 121 { 122 return NULL; 123 } 124 125 static inline struct hugetlb_cgroup * 126 hugetlb_cgroup_from_page_rsvd(struct page *page) 127 { 128 return NULL; 129 } 130 131 static inline int set_hugetlb_cgroup(struct page *page, 132 struct hugetlb_cgroup *h_cg) 133 { 134 return 0; 135 } 136 137 static inline int set_hugetlb_cgroup_rsvd(struct page *page, 138 struct hugetlb_cgroup *h_cg) 139 { 140 return 0; 141 } 142 143 static inline bool hugetlb_cgroup_disabled(void) 144 { 145 return true; 146 } 147 148 static inline int hugetlb_cgroup_charge_cgroup(int idx, unsigned long nr_pages, 149 struct hugetlb_cgroup **ptr) 150 { 151 return 0; 152 } 153 154 static inline int hugetlb_cgroup_charge_cgroup_rsvd(int idx, 155 unsigned long nr_pages, 156 struct hugetlb_cgroup **ptr) 157 { 158 return 0; 159 } 160 161 static inline void hugetlb_cgroup_commit_charge(int idx, unsigned long nr_pages, 162 struct hugetlb_cgroup *h_cg, 163 struct page *page) 164 { 165 } 166 167 static inline void 168 hugetlb_cgroup_commit_charge_rsvd(int idx, unsigned long nr_pages, 169 struct hugetlb_cgroup *h_cg, 170 struct page *page) 171 { 172 } 173 174 static inline void hugetlb_cgroup_uncharge_page(int idx, unsigned long nr_pages, 175 struct page *page) 176 { 177 } 178 179 static inline void hugetlb_cgroup_uncharge_page_rsvd(int idx, 180 unsigned long nr_pages, 181 struct page *page) 182 { 183 } 184 static inline void hugetlb_cgroup_uncharge_cgroup(int idx, 185 unsigned long nr_pages, 186 struct hugetlb_cgroup *h_cg) 187 { 188 } 189 190 static inline void 191 hugetlb_cgroup_uncharge_cgroup_rsvd(int idx, unsigned long nr_pages, 192 struct hugetlb_cgroup *h_cg) 193 { 194 } 195 196 static inline void hugetlb_cgroup_file_init(void) 197 { 198 } 199 200 static inline void hugetlb_cgroup_migrate(struct page *oldhpage, 201 struct page *newhpage) 202 { 203 } 204 205 #endif /* CONFIG_MEM_RES_CTLR_HUGETLB */ 206 #endif 207