xref: /openbmc/linux/mm/hugetlb_cgroup.c (revision ff7d853b)
12bc64a20SAneesh Kumar K.V /*
22bc64a20SAneesh Kumar K.V  *
32bc64a20SAneesh Kumar K.V  * Copyright IBM Corporation, 2012
42bc64a20SAneesh Kumar K.V  * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
52bc64a20SAneesh Kumar K.V  *
6faced7e0SGiuseppe Scrivano  * Cgroup v2
7faced7e0SGiuseppe Scrivano  * Copyright (C) 2019 Red Hat, Inc.
8faced7e0SGiuseppe Scrivano  * Author: Giuseppe Scrivano <gscrivan@redhat.com>
9faced7e0SGiuseppe Scrivano  *
102bc64a20SAneesh Kumar K.V  * This program is free software; you can redistribute it and/or modify it
112bc64a20SAneesh Kumar K.V  * under the terms of version 2.1 of the GNU Lesser General Public License
122bc64a20SAneesh Kumar K.V  * as published by the Free Software Foundation.
132bc64a20SAneesh Kumar K.V  *
142bc64a20SAneesh Kumar K.V  * This program is distributed in the hope that it would be useful, but
152bc64a20SAneesh Kumar K.V  * WITHOUT ANY WARRANTY; without even the implied warranty of
162bc64a20SAneesh Kumar K.V  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
172bc64a20SAneesh Kumar K.V  *
182bc64a20SAneesh Kumar K.V  */
192bc64a20SAneesh Kumar K.V 
202bc64a20SAneesh Kumar K.V #include <linux/cgroup.h>
2171f87beeSJohannes Weiner #include <linux/page_counter.h>
222bc64a20SAneesh Kumar K.V #include <linux/slab.h>
232bc64a20SAneesh Kumar K.V #include <linux/hugetlb.h>
242bc64a20SAneesh Kumar K.V #include <linux/hugetlb_cgroup.h>
252bc64a20SAneesh Kumar K.V 
26abb8206cSAneesh Kumar K.V #define MEMFILE_PRIVATE(x, val)	(((x) << 16) | (val))
27abb8206cSAneesh Kumar K.V #define MEMFILE_IDX(val)	(((val) >> 16) & 0xffff)
28abb8206cSAneesh Kumar K.V #define MEMFILE_ATTR(val)	((val) & 0xffff)
29abb8206cSAneesh Kumar K.V 
302bc64a20SAneesh Kumar K.V static struct hugetlb_cgroup *root_h_cgroup __read_mostly;
312bc64a20SAneesh Kumar K.V 
32cdc2fcfeSMina Almasry static inline struct page_counter *
__hugetlb_cgroup_counter_from_cgroup(struct hugetlb_cgroup * h_cg,int idx,bool rsvd)331adc4d41SMina Almasry __hugetlb_cgroup_counter_from_cgroup(struct hugetlb_cgroup *h_cg, int idx,
34cdc2fcfeSMina Almasry 				     bool rsvd)
35cdc2fcfeSMina Almasry {
36cdc2fcfeSMina Almasry 	if (rsvd)
37cdc2fcfeSMina Almasry 		return &h_cg->rsvd_hugepage[idx];
38cdc2fcfeSMina Almasry 	return &h_cg->hugepage[idx];
39cdc2fcfeSMina Almasry }
40cdc2fcfeSMina Almasry 
411adc4d41SMina Almasry static inline struct page_counter *
hugetlb_cgroup_counter_from_cgroup(struct hugetlb_cgroup * h_cg,int idx)421adc4d41SMina Almasry hugetlb_cgroup_counter_from_cgroup(struct hugetlb_cgroup *h_cg, int idx)
431adc4d41SMina Almasry {
441adc4d41SMina Almasry 	return __hugetlb_cgroup_counter_from_cgroup(h_cg, idx, false);
451adc4d41SMina Almasry }
461adc4d41SMina Almasry 
471adc4d41SMina Almasry static inline struct page_counter *
hugetlb_cgroup_counter_from_cgroup_rsvd(struct hugetlb_cgroup * h_cg,int idx)481adc4d41SMina Almasry hugetlb_cgroup_counter_from_cgroup_rsvd(struct hugetlb_cgroup *h_cg, int idx)
491adc4d41SMina Almasry {
501adc4d41SMina Almasry 	return __hugetlb_cgroup_counter_from_cgroup(h_cg, idx, true);
511adc4d41SMina Almasry }
521adc4d41SMina Almasry 
532bc64a20SAneesh Kumar K.V static inline
hugetlb_cgroup_from_css(struct cgroup_subsys_state * s)542bc64a20SAneesh Kumar K.V struct hugetlb_cgroup *hugetlb_cgroup_from_css(struct cgroup_subsys_state *s)
552bc64a20SAneesh Kumar K.V {
56a7c6d554STejun Heo 	return s ? container_of(s, struct hugetlb_cgroup, css) : NULL;
572bc64a20SAneesh Kumar K.V }
582bc64a20SAneesh Kumar K.V 
592bc64a20SAneesh Kumar K.V static inline
hugetlb_cgroup_from_task(struct task_struct * task)602bc64a20SAneesh Kumar K.V struct hugetlb_cgroup *hugetlb_cgroup_from_task(struct task_struct *task)
612bc64a20SAneesh Kumar K.V {
62073219e9STejun Heo 	return hugetlb_cgroup_from_css(task_css(task, hugetlb_cgrp_id));
632bc64a20SAneesh Kumar K.V }
642bc64a20SAneesh Kumar K.V 
hugetlb_cgroup_is_root(struct hugetlb_cgroup * h_cg)652bc64a20SAneesh Kumar K.V static inline bool hugetlb_cgroup_is_root(struct hugetlb_cgroup *h_cg)
662bc64a20SAneesh Kumar K.V {
672bc64a20SAneesh Kumar K.V 	return (h_cg == root_h_cgroup);
682bc64a20SAneesh Kumar K.V }
692bc64a20SAneesh Kumar K.V 
703f798518STejun Heo static inline struct hugetlb_cgroup *
parent_hugetlb_cgroup(struct hugetlb_cgroup * h_cg)713f798518STejun Heo parent_hugetlb_cgroup(struct hugetlb_cgroup *h_cg)
722bc64a20SAneesh Kumar K.V {
735c9d535bSTejun Heo 	return hugetlb_cgroup_from_css(h_cg->css.parent);
742bc64a20SAneesh Kumar K.V }
752bc64a20SAneesh Kumar K.V 
hugetlb_cgroup_have_usage(struct hugetlb_cgroup * h_cg)763f798518STejun Heo static inline bool hugetlb_cgroup_have_usage(struct hugetlb_cgroup *h_cg)
772bc64a20SAneesh Kumar K.V {
78c37213c5SMiaohe Lin 	struct hstate *h;
792bc64a20SAneesh Kumar K.V 
80c37213c5SMiaohe Lin 	for_each_hstate(h) {
811adc4d41SMina Almasry 		if (page_counter_read(
82c37213c5SMiaohe Lin 		    hugetlb_cgroup_counter_from_cgroup(h_cg, hstate_index(h))))
832bc64a20SAneesh Kumar K.V 			return true;
842bc64a20SAneesh Kumar K.V 	}
852bc64a20SAneesh Kumar K.V 	return false;
862bc64a20SAneesh Kumar K.V }
872bc64a20SAneesh Kumar K.V 
hugetlb_cgroup_init(struct hugetlb_cgroup * h_cgroup,struct hugetlb_cgroup * parent_h_cgroup)88297880f4SDavid Rientjes static void hugetlb_cgroup_init(struct hugetlb_cgroup *h_cgroup,
89297880f4SDavid Rientjes 				struct hugetlb_cgroup *parent_h_cgroup)
90297880f4SDavid Rientjes {
91297880f4SDavid Rientjes 	int idx;
92297880f4SDavid Rientjes 
93297880f4SDavid Rientjes 	for (idx = 0; idx < HUGE_MAX_HSTATE; idx++) {
941adc4d41SMina Almasry 		struct page_counter *fault_parent = NULL;
951adc4d41SMina Almasry 		struct page_counter *rsvd_parent = NULL;
96297880f4SDavid Rientjes 		unsigned long limit;
97297880f4SDavid Rientjes 		int ret;
98297880f4SDavid Rientjes 
991adc4d41SMina Almasry 		if (parent_h_cgroup) {
1001adc4d41SMina Almasry 			fault_parent = hugetlb_cgroup_counter_from_cgroup(
1011adc4d41SMina Almasry 				parent_h_cgroup, idx);
1021adc4d41SMina Almasry 			rsvd_parent = hugetlb_cgroup_counter_from_cgroup_rsvd(
1031adc4d41SMina Almasry 				parent_h_cgroup, idx);
1041adc4d41SMina Almasry 		}
1051adc4d41SMina Almasry 		page_counter_init(hugetlb_cgroup_counter_from_cgroup(h_cgroup,
1061adc4d41SMina Almasry 								     idx),
1071adc4d41SMina Almasry 				  fault_parent);
1081adc4d41SMina Almasry 		page_counter_init(
1091adc4d41SMina Almasry 			hugetlb_cgroup_counter_from_cgroup_rsvd(h_cgroup, idx),
1101adc4d41SMina Almasry 			rsvd_parent);
111297880f4SDavid Rientjes 
112297880f4SDavid Rientjes 		limit = round_down(PAGE_COUNTER_MAX,
1138938494cSMiaohe Lin 				   pages_per_huge_page(&hstates[idx]));
1141adc4d41SMina Almasry 
1151adc4d41SMina Almasry 		ret = page_counter_set_max(
1161adc4d41SMina Almasry 			hugetlb_cgroup_counter_from_cgroup(h_cgroup, idx),
1171adc4d41SMina Almasry 			limit);
1181adc4d41SMina Almasry 		VM_BUG_ON(ret);
1191adc4d41SMina Almasry 		ret = page_counter_set_max(
1201adc4d41SMina Almasry 			hugetlb_cgroup_counter_from_cgroup_rsvd(h_cgroup, idx),
1211adc4d41SMina Almasry 			limit);
122297880f4SDavid Rientjes 		VM_BUG_ON(ret);
123297880f4SDavid Rientjes 	}
124297880f4SDavid Rientjes }
125297880f4SDavid Rientjes 
hugetlb_cgroup_free(struct hugetlb_cgroup * h_cgroup)126f4776199SMina Almasry static void hugetlb_cgroup_free(struct hugetlb_cgroup *h_cgroup)
127f4776199SMina Almasry {
128f4776199SMina Almasry 	int node;
129f4776199SMina Almasry 
130f4776199SMina Almasry 	for_each_node(node)
131f4776199SMina Almasry 		kfree(h_cgroup->nodeinfo[node]);
132f4776199SMina Almasry 	kfree(h_cgroup);
133f4776199SMina Almasry }
134f4776199SMina Almasry 
135eb95419bSTejun Heo static struct cgroup_subsys_state *
hugetlb_cgroup_css_alloc(struct cgroup_subsys_state * parent_css)136eb95419bSTejun Heo hugetlb_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)
1372bc64a20SAneesh Kumar K.V {
138eb95419bSTejun Heo 	struct hugetlb_cgroup *parent_h_cgroup = hugetlb_cgroup_from_css(parent_css);
139eb95419bSTejun Heo 	struct hugetlb_cgroup *h_cgroup;
140f4776199SMina Almasry 	int node;
1412bc64a20SAneesh Kumar K.V 
142f4776199SMina Almasry 	h_cgroup = kzalloc(struct_size(h_cgroup, nodeinfo, nr_node_ids),
143f4776199SMina Almasry 			   GFP_KERNEL);
144f4776199SMina Almasry 
1452bc64a20SAneesh Kumar K.V 	if (!h_cgroup)
1462bc64a20SAneesh Kumar K.V 		return ERR_PTR(-ENOMEM);
1472bc64a20SAneesh Kumar K.V 
148297880f4SDavid Rientjes 	if (!parent_h_cgroup)
1492bc64a20SAneesh Kumar K.V 		root_h_cgroup = h_cgroup;
150297880f4SDavid Rientjes 
151f4776199SMina Almasry 	/*
152f4776199SMina Almasry 	 * TODO: this routine can waste much memory for nodes which will
153f4776199SMina Almasry 	 * never be onlined. It's better to use memory hotplug callback
154f4776199SMina Almasry 	 * function.
155f4776199SMina Almasry 	 */
156f4776199SMina Almasry 	for_each_node(node) {
15799249387SMiaohe Lin 		/* Set node_to_alloc to NUMA_NO_NODE for offline nodes. */
158f4776199SMina Almasry 		int node_to_alloc =
15999249387SMiaohe Lin 			node_state(node, N_NORMAL_MEMORY) ? node : NUMA_NO_NODE;
160f4776199SMina Almasry 		h_cgroup->nodeinfo[node] =
161f4776199SMina Almasry 			kzalloc_node(sizeof(struct hugetlb_cgroup_per_node),
162f4776199SMina Almasry 				     GFP_KERNEL, node_to_alloc);
163f4776199SMina Almasry 		if (!h_cgroup->nodeinfo[node])
164f4776199SMina Almasry 			goto fail_alloc_nodeinfo;
165f4776199SMina Almasry 	}
166f4776199SMina Almasry 
167297880f4SDavid Rientjes 	hugetlb_cgroup_init(h_cgroup, parent_h_cgroup);
1682bc64a20SAneesh Kumar K.V 	return &h_cgroup->css;
169f4776199SMina Almasry 
170f4776199SMina Almasry fail_alloc_nodeinfo:
171f4776199SMina Almasry 	hugetlb_cgroup_free(h_cgroup);
172f4776199SMina Almasry 	return ERR_PTR(-ENOMEM);
1732bc64a20SAneesh Kumar K.V }
1742bc64a20SAneesh Kumar K.V 
hugetlb_cgroup_css_free(struct cgroup_subsys_state * css)175eb95419bSTejun Heo static void hugetlb_cgroup_css_free(struct cgroup_subsys_state *css)
1762bc64a20SAneesh Kumar K.V {
177f4776199SMina Almasry 	hugetlb_cgroup_free(hugetlb_cgroup_from_css(css));
1782bc64a20SAneesh Kumar K.V }
1792bc64a20SAneesh Kumar K.V 
180da1def55SAneesh Kumar K.V /*
181da1def55SAneesh Kumar K.V  * Should be called with hugetlb_lock held.
182da1def55SAneesh Kumar K.V  * Since we are holding hugetlb_lock, pages cannot get moved from
183da1def55SAneesh Kumar K.V  * active list or uncharged from the cgroup, So no need to get
184da1def55SAneesh Kumar K.V  * page reference and test for page active here. This function
185da1def55SAneesh Kumar K.V  * cannot fail.
186da1def55SAneesh Kumar K.V  */
hugetlb_cgroup_move_parent(int idx,struct hugetlb_cgroup * h_cg,struct page * page)1873f798518STejun Heo static void hugetlb_cgroup_move_parent(int idx, struct hugetlb_cgroup *h_cg,
188da1def55SAneesh Kumar K.V 				       struct page *page)
189da1def55SAneesh Kumar K.V {
19071f87beeSJohannes Weiner 	unsigned int nr_pages;
19171f87beeSJohannes Weiner 	struct page_counter *counter;
192da1def55SAneesh Kumar K.V 	struct hugetlb_cgroup *page_hcg;
1933f798518STejun Heo 	struct hugetlb_cgroup *parent = parent_hugetlb_cgroup(h_cg);
194f074732dSSidhartha Kumar 	struct folio *folio = page_folio(page);
195da1def55SAneesh Kumar K.V 
196f074732dSSidhartha Kumar 	page_hcg = hugetlb_cgroup_from_folio(folio);
197da1def55SAneesh Kumar K.V 	/*
198da1def55SAneesh Kumar K.V 	 * We can have pages in active list without any cgroup
199da1def55SAneesh Kumar K.V 	 * ie, hugepage with less than 3 pages. We can safely
200da1def55SAneesh Kumar K.V 	 * ignore those pages.
201da1def55SAneesh Kumar K.V 	 */
202da1def55SAneesh Kumar K.V 	if (!page_hcg || page_hcg != h_cg)
203da1def55SAneesh Kumar K.V 		goto out;
204da1def55SAneesh Kumar K.V 
205d8c6546bSMatthew Wilcox (Oracle) 	nr_pages = compound_nr(page);
206da1def55SAneesh Kumar K.V 	if (!parent) {
207da1def55SAneesh Kumar K.V 		parent = root_h_cgroup;
208da1def55SAneesh Kumar K.V 		/* root has no limit */
20971f87beeSJohannes Weiner 		page_counter_charge(&parent->hugepage[idx], nr_pages);
210da1def55SAneesh Kumar K.V 	}
211da1def55SAneesh Kumar K.V 	counter = &h_cg->hugepage[idx];
21271f87beeSJohannes Weiner 	/* Take the pages off the local counter */
21371f87beeSJohannes Weiner 	page_counter_cancel(counter, nr_pages);
214da1def55SAneesh Kumar K.V 
215de656ed3SSidhartha Kumar 	set_hugetlb_cgroup(folio, parent);
216da1def55SAneesh Kumar K.V out:
217da1def55SAneesh Kumar K.V 	return;
218da1def55SAneesh Kumar K.V }
219da1def55SAneesh Kumar K.V 
220da1def55SAneesh Kumar K.V /*
221da1def55SAneesh Kumar K.V  * Force the hugetlb cgroup to empty the hugetlb resources by moving them to
222da1def55SAneesh Kumar K.V  * the parent cgroup.
223da1def55SAneesh Kumar K.V  */
hugetlb_cgroup_css_offline(struct cgroup_subsys_state * css)224eb95419bSTejun Heo static void hugetlb_cgroup_css_offline(struct cgroup_subsys_state *css)
2252bc64a20SAneesh Kumar K.V {
226eb95419bSTejun Heo 	struct hugetlb_cgroup *h_cg = hugetlb_cgroup_from_css(css);
227da1def55SAneesh Kumar K.V 	struct hstate *h;
228da1def55SAneesh Kumar K.V 	struct page *page;
229da1def55SAneesh Kumar K.V 
230da1def55SAneesh Kumar K.V 	do {
231da1def55SAneesh Kumar K.V 		for_each_hstate(h) {
232db71ef79SMike Kravetz 			spin_lock_irq(&hugetlb_lock);
233da1def55SAneesh Kumar K.V 			list_for_each_entry(page, &h->hugepage_activelist, lru)
234c37213c5SMiaohe Lin 				hugetlb_cgroup_move_parent(hstate_index(h), h_cg, page);
235da1def55SAneesh Kumar K.V 
236db71ef79SMike Kravetz 			spin_unlock_irq(&hugetlb_lock);
237da1def55SAneesh Kumar K.V 		}
238da1def55SAneesh Kumar K.V 		cond_resched();
2393f798518STejun Heo 	} while (hugetlb_cgroup_have_usage(h_cg));
2402bc64a20SAneesh Kumar K.V }
2412bc64a20SAneesh Kumar K.V 
hugetlb_event(struct hugetlb_cgroup * hugetlb,int idx,enum hugetlb_memory_event event)242faced7e0SGiuseppe Scrivano static inline void hugetlb_event(struct hugetlb_cgroup *hugetlb, int idx,
243faced7e0SGiuseppe Scrivano 				 enum hugetlb_memory_event event)
244faced7e0SGiuseppe Scrivano {
245faced7e0SGiuseppe Scrivano 	atomic_long_inc(&hugetlb->events_local[idx][event]);
246faced7e0SGiuseppe Scrivano 	cgroup_file_notify(&hugetlb->events_local_file[idx]);
247faced7e0SGiuseppe Scrivano 
248faced7e0SGiuseppe Scrivano 	do {
249faced7e0SGiuseppe Scrivano 		atomic_long_inc(&hugetlb->events[idx][event]);
250faced7e0SGiuseppe Scrivano 		cgroup_file_notify(&hugetlb->events_file[idx]);
251faced7e0SGiuseppe Scrivano 	} while ((hugetlb = parent_hugetlb_cgroup(hugetlb)) &&
252faced7e0SGiuseppe Scrivano 		 !hugetlb_cgroup_is_root(hugetlb));
253faced7e0SGiuseppe Scrivano }
254faced7e0SGiuseppe Scrivano 
__hugetlb_cgroup_charge_cgroup(int idx,unsigned long nr_pages,struct hugetlb_cgroup ** ptr,bool rsvd)2551adc4d41SMina Almasry static int __hugetlb_cgroup_charge_cgroup(int idx, unsigned long nr_pages,
2561adc4d41SMina Almasry 					  struct hugetlb_cgroup **ptr,
2571adc4d41SMina Almasry 					  bool rsvd)
2586d76dcf4SAneesh Kumar K.V {
2596d76dcf4SAneesh Kumar K.V 	int ret = 0;
26071f87beeSJohannes Weiner 	struct page_counter *counter;
2616d76dcf4SAneesh Kumar K.V 	struct hugetlb_cgroup *h_cg = NULL;
2626d76dcf4SAneesh Kumar K.V 
2636d76dcf4SAneesh Kumar K.V 	if (hugetlb_cgroup_disabled())
2646d76dcf4SAneesh Kumar K.V 		goto done;
2656d76dcf4SAneesh Kumar K.V 	/*
2666d76dcf4SAneesh Kumar K.V 	 * We don't charge any cgroup if the compound page have less
2676d76dcf4SAneesh Kumar K.V 	 * than 3 pages.
2686d76dcf4SAneesh Kumar K.V 	 */
2696d76dcf4SAneesh Kumar K.V 	if (huge_page_order(&hstates[idx]) < HUGETLB_CGROUP_MIN_ORDER)
2706d76dcf4SAneesh Kumar K.V 		goto done;
2716d76dcf4SAneesh Kumar K.V again:
2726d76dcf4SAneesh Kumar K.V 	rcu_read_lock();
2736d76dcf4SAneesh Kumar K.V 	h_cg = hugetlb_cgroup_from_task(current);
2740362f326SRoman Gushchin 	if (!css_tryget(&h_cg->css)) {
2756d76dcf4SAneesh Kumar K.V 		rcu_read_unlock();
2766d76dcf4SAneesh Kumar K.V 		goto again;
2776d76dcf4SAneesh Kumar K.V 	}
2786d76dcf4SAneesh Kumar K.V 	rcu_read_unlock();
2796d76dcf4SAneesh Kumar K.V 
2801adc4d41SMina Almasry 	if (!page_counter_try_charge(
2811adc4d41SMina Almasry 		    __hugetlb_cgroup_counter_from_cgroup(h_cg, idx, rsvd),
2821adc4d41SMina Almasry 		    nr_pages, &counter)) {
2836071ca52SJohannes Weiner 		ret = -ENOMEM;
284726b7bbeSMina Almasry 		hugetlb_event(h_cg, idx, HUGETLB_MAX);
2851adc4d41SMina Almasry 		css_put(&h_cg->css);
2861adc4d41SMina Almasry 		goto done;
287faced7e0SGiuseppe Scrivano 	}
2881adc4d41SMina Almasry 	/* Reservations take a reference to the css because they do not get
2891adc4d41SMina Almasry 	 * reparented.
2901adc4d41SMina Almasry 	 */
2911adc4d41SMina Almasry 	if (!rsvd)
2926d76dcf4SAneesh Kumar K.V 		css_put(&h_cg->css);
2936d76dcf4SAneesh Kumar K.V done:
2946d76dcf4SAneesh Kumar K.V 	*ptr = h_cg;
2956d76dcf4SAneesh Kumar K.V 	return ret;
2966d76dcf4SAneesh Kumar K.V }
2976d76dcf4SAneesh Kumar K.V 
hugetlb_cgroup_charge_cgroup(int idx,unsigned long nr_pages,struct hugetlb_cgroup ** ptr)2981adc4d41SMina Almasry int hugetlb_cgroup_charge_cgroup(int idx, unsigned long nr_pages,
2991adc4d41SMina Almasry 				 struct hugetlb_cgroup **ptr)
3001adc4d41SMina Almasry {
3011adc4d41SMina Almasry 	return __hugetlb_cgroup_charge_cgroup(idx, nr_pages, ptr, false);
3021adc4d41SMina Almasry }
3031adc4d41SMina Almasry 
hugetlb_cgroup_charge_cgroup_rsvd(int idx,unsigned long nr_pages,struct hugetlb_cgroup ** ptr)3041adc4d41SMina Almasry int hugetlb_cgroup_charge_cgroup_rsvd(int idx, unsigned long nr_pages,
3051adc4d41SMina Almasry 				      struct hugetlb_cgroup **ptr)
3061adc4d41SMina Almasry {
3071adc4d41SMina Almasry 	return __hugetlb_cgroup_charge_cgroup(idx, nr_pages, ptr, true);
3081adc4d41SMina Almasry }
3091adc4d41SMina Almasry 
31094ae8ba7SAneesh Kumar K.V /* Should be called with hugetlb_lock held */
__hugetlb_cgroup_commit_charge(int idx,unsigned long nr_pages,struct hugetlb_cgroup * h_cg,struct folio * folio,bool rsvd)3111adc4d41SMina Almasry static void __hugetlb_cgroup_commit_charge(int idx, unsigned long nr_pages,
3126d76dcf4SAneesh Kumar K.V 					   struct hugetlb_cgroup *h_cg,
313541b7c7bSSidhartha Kumar 					   struct folio *folio, bool rsvd)
3146d76dcf4SAneesh Kumar K.V {
3156d76dcf4SAneesh Kumar K.V 	if (hugetlb_cgroup_disabled() || !h_cg)
3166d76dcf4SAneesh Kumar K.V 		return;
3176d76dcf4SAneesh Kumar K.V 
318541b7c7bSSidhartha Kumar 	__set_hugetlb_cgroup(folio, h_cg, rsvd);
319f4776199SMina Almasry 	if (!rsvd) {
320f4776199SMina Almasry 		unsigned long usage =
321541b7c7bSSidhartha Kumar 			h_cg->nodeinfo[folio_nid(folio)]->usage[idx];
322f4776199SMina Almasry 		/*
323f4776199SMina Almasry 		 * This write is not atomic due to fetching usage and writing
324f4776199SMina Almasry 		 * to it, but that's fine because we call this with
325f4776199SMina Almasry 		 * hugetlb_lock held anyway.
326f4776199SMina Almasry 		 */
327541b7c7bSSidhartha Kumar 		WRITE_ONCE(h_cg->nodeinfo[folio_nid(folio)]->usage[idx],
328f4776199SMina Almasry 			   usage + nr_pages);
329f4776199SMina Almasry 	}
3306d76dcf4SAneesh Kumar K.V }
3316d76dcf4SAneesh Kumar K.V 
hugetlb_cgroup_commit_charge(int idx,unsigned long nr_pages,struct hugetlb_cgroup * h_cg,struct folio * folio)3321adc4d41SMina Almasry void hugetlb_cgroup_commit_charge(int idx, unsigned long nr_pages,
3331adc4d41SMina Almasry 				  struct hugetlb_cgroup *h_cg,
334*ff7d853bSSidhartha Kumar 				  struct folio *folio)
3351adc4d41SMina Almasry {
336541b7c7bSSidhartha Kumar 	__hugetlb_cgroup_commit_charge(idx, nr_pages, h_cg, folio, false);
3371adc4d41SMina Almasry }
3381adc4d41SMina Almasry 
hugetlb_cgroup_commit_charge_rsvd(int idx,unsigned long nr_pages,struct hugetlb_cgroup * h_cg,struct folio * folio)3391adc4d41SMina Almasry void hugetlb_cgroup_commit_charge_rsvd(int idx, unsigned long nr_pages,
3401adc4d41SMina Almasry 				       struct hugetlb_cgroup *h_cg,
341*ff7d853bSSidhartha Kumar 				       struct folio *folio)
3421adc4d41SMina Almasry {
343541b7c7bSSidhartha Kumar 	__hugetlb_cgroup_commit_charge(idx, nr_pages, h_cg, folio, true);
3441adc4d41SMina Almasry }
3451adc4d41SMina Almasry 
3466d76dcf4SAneesh Kumar K.V /*
3476d76dcf4SAneesh Kumar K.V  * Should be called with hugetlb_lock held
3486d76dcf4SAneesh Kumar K.V  */
__hugetlb_cgroup_uncharge_folio(int idx,unsigned long nr_pages,struct folio * folio,bool rsvd)349d4ab0316SSidhartha Kumar static void __hugetlb_cgroup_uncharge_folio(int idx, unsigned long nr_pages,
350d4ab0316SSidhartha Kumar 					   struct folio *folio, bool rsvd)
3516d76dcf4SAneesh Kumar K.V {
3526d76dcf4SAneesh Kumar K.V 	struct hugetlb_cgroup *h_cg;
3536d76dcf4SAneesh Kumar K.V 
3546d76dcf4SAneesh Kumar K.V 	if (hugetlb_cgroup_disabled())
3556d76dcf4SAneesh Kumar K.V 		return;
3567ea8574eSMichal Hocko 	lockdep_assert_held(&hugetlb_lock);
357f074732dSSidhartha Kumar 	h_cg = __hugetlb_cgroup_from_folio(folio, rsvd);
3586d76dcf4SAneesh Kumar K.V 	if (unlikely(!h_cg))
3596d76dcf4SAneesh Kumar K.V 		return;
360f074732dSSidhartha Kumar 	__set_hugetlb_cgroup(folio, NULL, rsvd);
3611adc4d41SMina Almasry 
3621adc4d41SMina Almasry 	page_counter_uncharge(__hugetlb_cgroup_counter_from_cgroup(h_cg, idx,
3631adc4d41SMina Almasry 								   rsvd),
3641adc4d41SMina Almasry 			      nr_pages);
3651adc4d41SMina Almasry 
3661adc4d41SMina Almasry 	if (rsvd)
3671adc4d41SMina Almasry 		css_put(&h_cg->css);
368f4776199SMina Almasry 	else {
369f4776199SMina Almasry 		unsigned long usage =
370d4ab0316SSidhartha Kumar 			h_cg->nodeinfo[folio_nid(folio)]->usage[idx];
371f4776199SMina Almasry 		/*
372f4776199SMina Almasry 		 * This write is not atomic due to fetching usage and writing
373f4776199SMina Almasry 		 * to it, but that's fine because we call this with
374f4776199SMina Almasry 		 * hugetlb_lock held anyway.
375f4776199SMina Almasry 		 */
376d4ab0316SSidhartha Kumar 		WRITE_ONCE(h_cg->nodeinfo[folio_nid(folio)]->usage[idx],
377f4776199SMina Almasry 			   usage - nr_pages);
378f4776199SMina Almasry 	}
3796d76dcf4SAneesh Kumar K.V }
3806d76dcf4SAneesh Kumar K.V 
hugetlb_cgroup_uncharge_folio(int idx,unsigned long nr_pages,struct folio * folio)381d4ab0316SSidhartha Kumar void hugetlb_cgroup_uncharge_folio(int idx, unsigned long nr_pages,
382d4ab0316SSidhartha Kumar 				  struct folio *folio)
3831adc4d41SMina Almasry {
384d4ab0316SSidhartha Kumar 	__hugetlb_cgroup_uncharge_folio(idx, nr_pages, folio, false);
3851adc4d41SMina Almasry }
3861adc4d41SMina Almasry 
hugetlb_cgroup_uncharge_folio_rsvd(int idx,unsigned long nr_pages,struct folio * folio)387d4ab0316SSidhartha Kumar void hugetlb_cgroup_uncharge_folio_rsvd(int idx, unsigned long nr_pages,
388d4ab0316SSidhartha Kumar 				       struct folio *folio)
3891adc4d41SMina Almasry {
390d4ab0316SSidhartha Kumar 	__hugetlb_cgroup_uncharge_folio(idx, nr_pages, folio, true);
3911adc4d41SMina Almasry }
3921adc4d41SMina Almasry 
__hugetlb_cgroup_uncharge_cgroup(int idx,unsigned long nr_pages,struct hugetlb_cgroup * h_cg,bool rsvd)3931adc4d41SMina Almasry static void __hugetlb_cgroup_uncharge_cgroup(int idx, unsigned long nr_pages,
3941adc4d41SMina Almasry 					     struct hugetlb_cgroup *h_cg,
3951adc4d41SMina Almasry 					     bool rsvd)
3966d76dcf4SAneesh Kumar K.V {
3976d76dcf4SAneesh Kumar K.V 	if (hugetlb_cgroup_disabled() || !h_cg)
3986d76dcf4SAneesh Kumar K.V 		return;
3996d76dcf4SAneesh Kumar K.V 
4006d76dcf4SAneesh Kumar K.V 	if (huge_page_order(&hstates[idx]) < HUGETLB_CGROUP_MIN_ORDER)
4016d76dcf4SAneesh Kumar K.V 		return;
4026d76dcf4SAneesh Kumar K.V 
4031adc4d41SMina Almasry 	page_counter_uncharge(__hugetlb_cgroup_counter_from_cgroup(h_cg, idx,
4041adc4d41SMina Almasry 								   rsvd),
4051adc4d41SMina Almasry 			      nr_pages);
4061adc4d41SMina Almasry 
4071adc4d41SMina Almasry 	if (rsvd)
4081adc4d41SMina Almasry 		css_put(&h_cg->css);
4091adc4d41SMina Almasry }
4101adc4d41SMina Almasry 
hugetlb_cgroup_uncharge_cgroup(int idx,unsigned long nr_pages,struct hugetlb_cgroup * h_cg)4111adc4d41SMina Almasry void hugetlb_cgroup_uncharge_cgroup(int idx, unsigned long nr_pages,
4121adc4d41SMina Almasry 				    struct hugetlb_cgroup *h_cg)
4131adc4d41SMina Almasry {
4141adc4d41SMina Almasry 	__hugetlb_cgroup_uncharge_cgroup(idx, nr_pages, h_cg, false);
4151adc4d41SMina Almasry }
4161adc4d41SMina Almasry 
hugetlb_cgroup_uncharge_cgroup_rsvd(int idx,unsigned long nr_pages,struct hugetlb_cgroup * h_cg)4171adc4d41SMina Almasry void hugetlb_cgroup_uncharge_cgroup_rsvd(int idx, unsigned long nr_pages,
4181adc4d41SMina Almasry 					 struct hugetlb_cgroup *h_cg)
4191adc4d41SMina Almasry {
4201adc4d41SMina Almasry 	__hugetlb_cgroup_uncharge_cgroup(idx, nr_pages, h_cg, true);
4211adc4d41SMina Almasry }
4221adc4d41SMina Almasry 
hugetlb_cgroup_uncharge_counter(struct resv_map * resv,unsigned long start,unsigned long end)423e9fe92aeSMina Almasry void hugetlb_cgroup_uncharge_counter(struct resv_map *resv, unsigned long start,
424e9fe92aeSMina Almasry 				     unsigned long end)
4251adc4d41SMina Almasry {
426e9fe92aeSMina Almasry 	if (hugetlb_cgroup_disabled() || !resv || !resv->reservation_counter ||
427e9fe92aeSMina Almasry 	    !resv->css)
4286d76dcf4SAneesh Kumar K.V 		return;
4291adc4d41SMina Almasry 
430e9fe92aeSMina Almasry 	page_counter_uncharge(resv->reservation_counter,
431e9fe92aeSMina Almasry 			      (end - start) * resv->pages_per_hpage);
432e9fe92aeSMina Almasry 	css_put(resv->css);
4336d76dcf4SAneesh Kumar K.V }
4346d76dcf4SAneesh Kumar K.V 
hugetlb_cgroup_uncharge_file_region(struct resv_map * resv,struct file_region * rg,unsigned long nr_pages,bool region_del)435075a61d0SMina Almasry void hugetlb_cgroup_uncharge_file_region(struct resv_map *resv,
436075a61d0SMina Almasry 					 struct file_region *rg,
437d85aecf2SMiaohe Lin 					 unsigned long nr_pages,
438d85aecf2SMiaohe Lin 					 bool region_del)
439075a61d0SMina Almasry {
440075a61d0SMina Almasry 	if (hugetlb_cgroup_disabled() || !resv || !rg || !nr_pages)
441075a61d0SMina Almasry 		return;
442075a61d0SMina Almasry 
443862f7f65SMiaohe Lin 	if (rg->reservation_counter && resv->pages_per_hpage &&
444075a61d0SMina Almasry 	    !resv->reservation_counter) {
445075a61d0SMina Almasry 		page_counter_uncharge(rg->reservation_counter,
446075a61d0SMina Almasry 				      nr_pages * resv->pages_per_hpage);
447d85aecf2SMiaohe Lin 		/*
448d85aecf2SMiaohe Lin 		 * Only do css_put(rg->css) when we delete the entire region
449d85aecf2SMiaohe Lin 		 * because one file_region must hold exactly one css reference.
450d85aecf2SMiaohe Lin 		 */
451d85aecf2SMiaohe Lin 		if (region_del)
452075a61d0SMina Almasry 			css_put(rg->css);
453075a61d0SMina Almasry 	}
454075a61d0SMina Almasry }
455075a61d0SMina Almasry 
45671f87beeSJohannes Weiner enum {
45771f87beeSJohannes Weiner 	RES_USAGE,
458cdc2fcfeSMina Almasry 	RES_RSVD_USAGE,
45971f87beeSJohannes Weiner 	RES_LIMIT,
460cdc2fcfeSMina Almasry 	RES_RSVD_LIMIT,
46171f87beeSJohannes Weiner 	RES_MAX_USAGE,
462cdc2fcfeSMina Almasry 	RES_RSVD_MAX_USAGE,
46371f87beeSJohannes Weiner 	RES_FAILCNT,
464cdc2fcfeSMina Almasry 	RES_RSVD_FAILCNT,
46571f87beeSJohannes Weiner };
46671f87beeSJohannes Weiner 
hugetlb_cgroup_read_numa_stat(struct seq_file * seq,void * dummy)467f4776199SMina Almasry static int hugetlb_cgroup_read_numa_stat(struct seq_file *seq, void *dummy)
468f4776199SMina Almasry {
469f4776199SMina Almasry 	int nid;
470f4776199SMina Almasry 	struct cftype *cft = seq_cft(seq);
471f4776199SMina Almasry 	int idx = MEMFILE_IDX(cft->private);
472f4776199SMina Almasry 	bool legacy = MEMFILE_ATTR(cft->private);
473f4776199SMina Almasry 	struct hugetlb_cgroup *h_cg = hugetlb_cgroup_from_css(seq_css(seq));
474f4776199SMina Almasry 	struct cgroup_subsys_state *css;
475f4776199SMina Almasry 	unsigned long usage;
476f4776199SMina Almasry 
477f4776199SMina Almasry 	if (legacy) {
478f4776199SMina Almasry 		/* Add up usage across all nodes for the non-hierarchical total. */
479f4776199SMina Almasry 		usage = 0;
480f4776199SMina Almasry 		for_each_node_state(nid, N_MEMORY)
481f4776199SMina Almasry 			usage += READ_ONCE(h_cg->nodeinfo[nid]->usage[idx]);
482f4776199SMina Almasry 		seq_printf(seq, "total=%lu", usage * PAGE_SIZE);
483f4776199SMina Almasry 
484f4776199SMina Almasry 		/* Simply print the per-node usage for the non-hierarchical total. */
485f4776199SMina Almasry 		for_each_node_state(nid, N_MEMORY)
486f4776199SMina Almasry 			seq_printf(seq, " N%d=%lu", nid,
487f4776199SMina Almasry 				   READ_ONCE(h_cg->nodeinfo[nid]->usage[idx]) *
488f4776199SMina Almasry 					   PAGE_SIZE);
489f4776199SMina Almasry 		seq_putc(seq, '\n');
490f4776199SMina Almasry 	}
491f4776199SMina Almasry 
492f4776199SMina Almasry 	/*
493f4776199SMina Almasry 	 * The hierarchical total is pretty much the value recorded by the
494f4776199SMina Almasry 	 * counter, so use that.
495f4776199SMina Almasry 	 */
496f4776199SMina Almasry 	seq_printf(seq, "%stotal=%lu", legacy ? "hierarchical_" : "",
497f4776199SMina Almasry 		   page_counter_read(&h_cg->hugepage[idx]) * PAGE_SIZE);
498f4776199SMina Almasry 
499f4776199SMina Almasry 	/*
500f4776199SMina Almasry 	 * For each node, transverse the css tree to obtain the hierarchical
501f4776199SMina Almasry 	 * node usage.
502f4776199SMina Almasry 	 */
503f4776199SMina Almasry 	for_each_node_state(nid, N_MEMORY) {
504f4776199SMina Almasry 		usage = 0;
505f4776199SMina Almasry 		rcu_read_lock();
506f4776199SMina Almasry 		css_for_each_descendant_pre(css, &h_cg->css) {
507f4776199SMina Almasry 			usage += READ_ONCE(hugetlb_cgroup_from_css(css)
508f4776199SMina Almasry 						   ->nodeinfo[nid]
509f4776199SMina Almasry 						   ->usage[idx]);
510f4776199SMina Almasry 		}
511f4776199SMina Almasry 		rcu_read_unlock();
512f4776199SMina Almasry 		seq_printf(seq, " N%d=%lu", nid, usage * PAGE_SIZE);
513f4776199SMina Almasry 	}
514f4776199SMina Almasry 
515f4776199SMina Almasry 	seq_putc(seq, '\n');
516f4776199SMina Almasry 
517f4776199SMina Almasry 	return 0;
518f4776199SMina Almasry }
519f4776199SMina Almasry 
hugetlb_cgroup_read_u64(struct cgroup_subsys_state * css,struct cftype * cft)520716f479dSTejun Heo static u64 hugetlb_cgroup_read_u64(struct cgroup_subsys_state *css,
521716f479dSTejun Heo 				   struct cftype *cft)
522abb8206cSAneesh Kumar K.V {
52371f87beeSJohannes Weiner 	struct page_counter *counter;
524cdc2fcfeSMina Almasry 	struct page_counter *rsvd_counter;
525182446d0STejun Heo 	struct hugetlb_cgroup *h_cg = hugetlb_cgroup_from_css(css);
526abb8206cSAneesh Kumar K.V 
52771f87beeSJohannes Weiner 	counter = &h_cg->hugepage[MEMFILE_IDX(cft->private)];
528cdc2fcfeSMina Almasry 	rsvd_counter = &h_cg->rsvd_hugepage[MEMFILE_IDX(cft->private)];
529abb8206cSAneesh Kumar K.V 
53071f87beeSJohannes Weiner 	switch (MEMFILE_ATTR(cft->private)) {
53171f87beeSJohannes Weiner 	case RES_USAGE:
53271f87beeSJohannes Weiner 		return (u64)page_counter_read(counter) * PAGE_SIZE;
533cdc2fcfeSMina Almasry 	case RES_RSVD_USAGE:
534cdc2fcfeSMina Almasry 		return (u64)page_counter_read(rsvd_counter) * PAGE_SIZE;
53571f87beeSJohannes Weiner 	case RES_LIMIT:
536bbec2e15SRoman Gushchin 		return (u64)counter->max * PAGE_SIZE;
537cdc2fcfeSMina Almasry 	case RES_RSVD_LIMIT:
538cdc2fcfeSMina Almasry 		return (u64)rsvd_counter->max * PAGE_SIZE;
53971f87beeSJohannes Weiner 	case RES_MAX_USAGE:
54071f87beeSJohannes Weiner 		return (u64)counter->watermark * PAGE_SIZE;
541cdc2fcfeSMina Almasry 	case RES_RSVD_MAX_USAGE:
542cdc2fcfeSMina Almasry 		return (u64)rsvd_counter->watermark * PAGE_SIZE;
54371f87beeSJohannes Weiner 	case RES_FAILCNT:
54471f87beeSJohannes Weiner 		return counter->failcnt;
545cdc2fcfeSMina Almasry 	case RES_RSVD_FAILCNT:
546cdc2fcfeSMina Almasry 		return rsvd_counter->failcnt;
54771f87beeSJohannes Weiner 	default:
54871f87beeSJohannes Weiner 		BUG();
549abb8206cSAneesh Kumar K.V 	}
55071f87beeSJohannes Weiner }
55171f87beeSJohannes Weiner 
hugetlb_cgroup_read_u64_max(struct seq_file * seq,void * v)552faced7e0SGiuseppe Scrivano static int hugetlb_cgroup_read_u64_max(struct seq_file *seq, void *v)
553faced7e0SGiuseppe Scrivano {
554faced7e0SGiuseppe Scrivano 	int idx;
555faced7e0SGiuseppe Scrivano 	u64 val;
556faced7e0SGiuseppe Scrivano 	struct cftype *cft = seq_cft(seq);
557faced7e0SGiuseppe Scrivano 	unsigned long limit;
558faced7e0SGiuseppe Scrivano 	struct page_counter *counter;
559faced7e0SGiuseppe Scrivano 	struct hugetlb_cgroup *h_cg = hugetlb_cgroup_from_css(seq_css(seq));
560faced7e0SGiuseppe Scrivano 
561faced7e0SGiuseppe Scrivano 	idx = MEMFILE_IDX(cft->private);
562faced7e0SGiuseppe Scrivano 	counter = &h_cg->hugepage[idx];
563faced7e0SGiuseppe Scrivano 
564faced7e0SGiuseppe Scrivano 	limit = round_down(PAGE_COUNTER_MAX,
5658938494cSMiaohe Lin 			   pages_per_huge_page(&hstates[idx]));
566faced7e0SGiuseppe Scrivano 
567faced7e0SGiuseppe Scrivano 	switch (MEMFILE_ATTR(cft->private)) {
568cdc2fcfeSMina Almasry 	case RES_RSVD_USAGE:
569cdc2fcfeSMina Almasry 		counter = &h_cg->rsvd_hugepage[idx];
570e4a9bc58SJoe Perches 		fallthrough;
571faced7e0SGiuseppe Scrivano 	case RES_USAGE:
572faced7e0SGiuseppe Scrivano 		val = (u64)page_counter_read(counter);
573faced7e0SGiuseppe Scrivano 		seq_printf(seq, "%llu\n", val * PAGE_SIZE);
574faced7e0SGiuseppe Scrivano 		break;
575cdc2fcfeSMina Almasry 	case RES_RSVD_LIMIT:
576cdc2fcfeSMina Almasry 		counter = &h_cg->rsvd_hugepage[idx];
577e4a9bc58SJoe Perches 		fallthrough;
578faced7e0SGiuseppe Scrivano 	case RES_LIMIT:
579faced7e0SGiuseppe Scrivano 		val = (u64)counter->max;
580faced7e0SGiuseppe Scrivano 		if (val == limit)
581faced7e0SGiuseppe Scrivano 			seq_puts(seq, "max\n");
582faced7e0SGiuseppe Scrivano 		else
583faced7e0SGiuseppe Scrivano 			seq_printf(seq, "%llu\n", val * PAGE_SIZE);
584faced7e0SGiuseppe Scrivano 		break;
585faced7e0SGiuseppe Scrivano 	default:
586faced7e0SGiuseppe Scrivano 		BUG();
587faced7e0SGiuseppe Scrivano 	}
588faced7e0SGiuseppe Scrivano 
589faced7e0SGiuseppe Scrivano 	return 0;
590faced7e0SGiuseppe Scrivano }
591faced7e0SGiuseppe Scrivano 
59271f87beeSJohannes Weiner static DEFINE_MUTEX(hugetlb_limit_mutex);
593abb8206cSAneesh Kumar K.V 
hugetlb_cgroup_write(struct kernfs_open_file * of,char * buf,size_t nbytes,loff_t off,const char * max)594451af504STejun Heo static ssize_t hugetlb_cgroup_write(struct kernfs_open_file *of,
595faced7e0SGiuseppe Scrivano 				    char *buf, size_t nbytes, loff_t off,
596faced7e0SGiuseppe Scrivano 				    const char *max)
597abb8206cSAneesh Kumar K.V {
59871f87beeSJohannes Weiner 	int ret, idx;
59971f87beeSJohannes Weiner 	unsigned long nr_pages;
600451af504STejun Heo 	struct hugetlb_cgroup *h_cg = hugetlb_cgroup_from_css(of_css(of));
601cdc2fcfeSMina Almasry 	bool rsvd = false;
602abb8206cSAneesh Kumar K.V 
60371f87beeSJohannes Weiner 	if (hugetlb_cgroup_is_root(h_cg)) /* Can't set limit on root */
60471f87beeSJohannes Weiner 		return -EINVAL;
605abb8206cSAneesh Kumar K.V 
60671f87beeSJohannes Weiner 	buf = strstrip(buf);
607faced7e0SGiuseppe Scrivano 	ret = page_counter_memparse(buf, max, &nr_pages);
608abb8206cSAneesh Kumar K.V 	if (ret)
60971f87beeSJohannes Weiner 		return ret;
61071f87beeSJohannes Weiner 
61171f87beeSJohannes Weiner 	idx = MEMFILE_IDX(of_cft(of)->private);
6128938494cSMiaohe Lin 	nr_pages = round_down(nr_pages, pages_per_huge_page(&hstates[idx]));
61371f87beeSJohannes Weiner 
61471f87beeSJohannes Weiner 	switch (MEMFILE_ATTR(of_cft(of)->private)) {
615cdc2fcfeSMina Almasry 	case RES_RSVD_LIMIT:
616cdc2fcfeSMina Almasry 		rsvd = true;
617e4a9bc58SJoe Perches 		fallthrough;
61871f87beeSJohannes Weiner 	case RES_LIMIT:
61971f87beeSJohannes Weiner 		mutex_lock(&hugetlb_limit_mutex);
620cdc2fcfeSMina Almasry 		ret = page_counter_set_max(
6211adc4d41SMina Almasry 			__hugetlb_cgroup_counter_from_cgroup(h_cg, idx, rsvd),
622cdc2fcfeSMina Almasry 			nr_pages);
62371f87beeSJohannes Weiner 		mutex_unlock(&hugetlb_limit_mutex);
624abb8206cSAneesh Kumar K.V 		break;
625abb8206cSAneesh Kumar K.V 	default:
626abb8206cSAneesh Kumar K.V 		ret = -EINVAL;
627abb8206cSAneesh Kumar K.V 		break;
628abb8206cSAneesh Kumar K.V 	}
629451af504STejun Heo 	return ret ?: nbytes;
630abb8206cSAneesh Kumar K.V }
631abb8206cSAneesh Kumar K.V 
hugetlb_cgroup_write_legacy(struct kernfs_open_file * of,char * buf,size_t nbytes,loff_t off)632faced7e0SGiuseppe Scrivano static ssize_t hugetlb_cgroup_write_legacy(struct kernfs_open_file *of,
633faced7e0SGiuseppe Scrivano 					   char *buf, size_t nbytes, loff_t off)
634faced7e0SGiuseppe Scrivano {
635faced7e0SGiuseppe Scrivano 	return hugetlb_cgroup_write(of, buf, nbytes, off, "-1");
636faced7e0SGiuseppe Scrivano }
637faced7e0SGiuseppe Scrivano 
hugetlb_cgroup_write_dfl(struct kernfs_open_file * of,char * buf,size_t nbytes,loff_t off)638faced7e0SGiuseppe Scrivano static ssize_t hugetlb_cgroup_write_dfl(struct kernfs_open_file *of,
639faced7e0SGiuseppe Scrivano 					char *buf, size_t nbytes, loff_t off)
640faced7e0SGiuseppe Scrivano {
641faced7e0SGiuseppe Scrivano 	return hugetlb_cgroup_write(of, buf, nbytes, off, "max");
642faced7e0SGiuseppe Scrivano }
643faced7e0SGiuseppe Scrivano 
hugetlb_cgroup_reset(struct kernfs_open_file * of,char * buf,size_t nbytes,loff_t off)6446770c64eSTejun Heo static ssize_t hugetlb_cgroup_reset(struct kernfs_open_file *of,
6456770c64eSTejun Heo 				    char *buf, size_t nbytes, loff_t off)
646abb8206cSAneesh Kumar K.V {
64771f87beeSJohannes Weiner 	int ret = 0;
648cdc2fcfeSMina Almasry 	struct page_counter *counter, *rsvd_counter;
6496770c64eSTejun Heo 	struct hugetlb_cgroup *h_cg = hugetlb_cgroup_from_css(of_css(of));
650abb8206cSAneesh Kumar K.V 
65171f87beeSJohannes Weiner 	counter = &h_cg->hugepage[MEMFILE_IDX(of_cft(of)->private)];
652cdc2fcfeSMina Almasry 	rsvd_counter = &h_cg->rsvd_hugepage[MEMFILE_IDX(of_cft(of)->private)];
653abb8206cSAneesh Kumar K.V 
65471f87beeSJohannes Weiner 	switch (MEMFILE_ATTR(of_cft(of)->private)) {
655abb8206cSAneesh Kumar K.V 	case RES_MAX_USAGE:
65671f87beeSJohannes Weiner 		page_counter_reset_watermark(counter);
657abb8206cSAneesh Kumar K.V 		break;
658cdc2fcfeSMina Almasry 	case RES_RSVD_MAX_USAGE:
659cdc2fcfeSMina Almasry 		page_counter_reset_watermark(rsvd_counter);
660cdc2fcfeSMina Almasry 		break;
661abb8206cSAneesh Kumar K.V 	case RES_FAILCNT:
66271f87beeSJohannes Weiner 		counter->failcnt = 0;
663abb8206cSAneesh Kumar K.V 		break;
664cdc2fcfeSMina Almasry 	case RES_RSVD_FAILCNT:
665cdc2fcfeSMina Almasry 		rsvd_counter->failcnt = 0;
666cdc2fcfeSMina Almasry 		break;
667abb8206cSAneesh Kumar K.V 	default:
668abb8206cSAneesh Kumar K.V 		ret = -EINVAL;
669abb8206cSAneesh Kumar K.V 		break;
670abb8206cSAneesh Kumar K.V 	}
6716770c64eSTejun Heo 	return ret ?: nbytes;
672abb8206cSAneesh Kumar K.V }
673abb8206cSAneesh Kumar K.V 
mem_fmt(char * buf,int size,unsigned long hsize)674abb8206cSAneesh Kumar K.V static char *mem_fmt(char *buf, int size, unsigned long hsize)
675abb8206cSAneesh Kumar K.V {
676abfb09e2SMiaohe Lin 	if (hsize >= SZ_1G)
677abfb09e2SMiaohe Lin 		snprintf(buf, size, "%luGB", hsize / SZ_1G);
678abfb09e2SMiaohe Lin 	else if (hsize >= SZ_1M)
679abfb09e2SMiaohe Lin 		snprintf(buf, size, "%luMB", hsize / SZ_1M);
680abb8206cSAneesh Kumar K.V 	else
681abfb09e2SMiaohe Lin 		snprintf(buf, size, "%luKB", hsize / SZ_1K);
682abb8206cSAneesh Kumar K.V 	return buf;
683abb8206cSAneesh Kumar K.V }
684abb8206cSAneesh Kumar K.V 
__hugetlb_events_show(struct seq_file * seq,bool local)685faced7e0SGiuseppe Scrivano static int __hugetlb_events_show(struct seq_file *seq, bool local)
686faced7e0SGiuseppe Scrivano {
687faced7e0SGiuseppe Scrivano 	int idx;
688faced7e0SGiuseppe Scrivano 	long max;
689faced7e0SGiuseppe Scrivano 	struct cftype *cft = seq_cft(seq);
690faced7e0SGiuseppe Scrivano 	struct hugetlb_cgroup *h_cg = hugetlb_cgroup_from_css(seq_css(seq));
691faced7e0SGiuseppe Scrivano 
692faced7e0SGiuseppe Scrivano 	idx = MEMFILE_IDX(cft->private);
693faced7e0SGiuseppe Scrivano 
694faced7e0SGiuseppe Scrivano 	if (local)
695faced7e0SGiuseppe Scrivano 		max = atomic_long_read(&h_cg->events_local[idx][HUGETLB_MAX]);
696faced7e0SGiuseppe Scrivano 	else
697faced7e0SGiuseppe Scrivano 		max = atomic_long_read(&h_cg->events[idx][HUGETLB_MAX]);
698faced7e0SGiuseppe Scrivano 
699faced7e0SGiuseppe Scrivano 	seq_printf(seq, "max %lu\n", max);
700faced7e0SGiuseppe Scrivano 
701faced7e0SGiuseppe Scrivano 	return 0;
702faced7e0SGiuseppe Scrivano }
703faced7e0SGiuseppe Scrivano 
hugetlb_events_show(struct seq_file * seq,void * v)704faced7e0SGiuseppe Scrivano static int hugetlb_events_show(struct seq_file *seq, void *v)
705faced7e0SGiuseppe Scrivano {
706faced7e0SGiuseppe Scrivano 	return __hugetlb_events_show(seq, false);
707faced7e0SGiuseppe Scrivano }
708faced7e0SGiuseppe Scrivano 
hugetlb_events_local_show(struct seq_file * seq,void * v)709faced7e0SGiuseppe Scrivano static int hugetlb_events_local_show(struct seq_file *seq, void *v)
710faced7e0SGiuseppe Scrivano {
711faced7e0SGiuseppe Scrivano 	return __hugetlb_events_show(seq, true);
712faced7e0SGiuseppe Scrivano }
713faced7e0SGiuseppe Scrivano 
__hugetlb_cgroup_file_dfl_init(int idx)714faced7e0SGiuseppe Scrivano static void __init __hugetlb_cgroup_file_dfl_init(int idx)
715abb8206cSAneesh Kumar K.V {
716abb8206cSAneesh Kumar K.V 	char buf[32];
717abb8206cSAneesh Kumar K.V 	struct cftype *cft;
718abb8206cSAneesh Kumar K.V 	struct hstate *h = &hstates[idx];
719abb8206cSAneesh Kumar K.V 
720abb8206cSAneesh Kumar K.V 	/* format the size */
721cdc2fcfeSMina Almasry 	mem_fmt(buf, sizeof(buf), huge_page_size(h));
722abb8206cSAneesh Kumar K.V 
723abb8206cSAneesh Kumar K.V 	/* Add the limit file */
724faced7e0SGiuseppe Scrivano 	cft = &h->cgroup_files_dfl[0];
725faced7e0SGiuseppe Scrivano 	snprintf(cft->name, MAX_CFTYPE_NAME, "%s.max", buf);
726faced7e0SGiuseppe Scrivano 	cft->private = MEMFILE_PRIVATE(idx, RES_LIMIT);
727faced7e0SGiuseppe Scrivano 	cft->seq_show = hugetlb_cgroup_read_u64_max;
728faced7e0SGiuseppe Scrivano 	cft->write = hugetlb_cgroup_write_dfl;
729faced7e0SGiuseppe Scrivano 	cft->flags = CFTYPE_NOT_ON_ROOT;
730faced7e0SGiuseppe Scrivano 
731cdc2fcfeSMina Almasry 	/* Add the reservation limit file */
732faced7e0SGiuseppe Scrivano 	cft = &h->cgroup_files_dfl[1];
733cdc2fcfeSMina Almasry 	snprintf(cft->name, MAX_CFTYPE_NAME, "%s.rsvd.max", buf);
734cdc2fcfeSMina Almasry 	cft->private = MEMFILE_PRIVATE(idx, RES_RSVD_LIMIT);
735cdc2fcfeSMina Almasry 	cft->seq_show = hugetlb_cgroup_read_u64_max;
736cdc2fcfeSMina Almasry 	cft->write = hugetlb_cgroup_write_dfl;
737cdc2fcfeSMina Almasry 	cft->flags = CFTYPE_NOT_ON_ROOT;
738cdc2fcfeSMina Almasry 
739cdc2fcfeSMina Almasry 	/* Add the current usage file */
740cdc2fcfeSMina Almasry 	cft = &h->cgroup_files_dfl[2];
741faced7e0SGiuseppe Scrivano 	snprintf(cft->name, MAX_CFTYPE_NAME, "%s.current", buf);
742faced7e0SGiuseppe Scrivano 	cft->private = MEMFILE_PRIVATE(idx, RES_USAGE);
743faced7e0SGiuseppe Scrivano 	cft->seq_show = hugetlb_cgroup_read_u64_max;
744faced7e0SGiuseppe Scrivano 	cft->flags = CFTYPE_NOT_ON_ROOT;
745faced7e0SGiuseppe Scrivano 
746cdc2fcfeSMina Almasry 	/* Add the current reservation usage file */
747cdc2fcfeSMina Almasry 	cft = &h->cgroup_files_dfl[3];
748cdc2fcfeSMina Almasry 	snprintf(cft->name, MAX_CFTYPE_NAME, "%s.rsvd.current", buf);
749cdc2fcfeSMina Almasry 	cft->private = MEMFILE_PRIVATE(idx, RES_RSVD_USAGE);
750cdc2fcfeSMina Almasry 	cft->seq_show = hugetlb_cgroup_read_u64_max;
751cdc2fcfeSMina Almasry 	cft->flags = CFTYPE_NOT_ON_ROOT;
752cdc2fcfeSMina Almasry 
753faced7e0SGiuseppe Scrivano 	/* Add the events file */
754cdc2fcfeSMina Almasry 	cft = &h->cgroup_files_dfl[4];
755faced7e0SGiuseppe Scrivano 	snprintf(cft->name, MAX_CFTYPE_NAME, "%s.events", buf);
756faced7e0SGiuseppe Scrivano 	cft->private = MEMFILE_PRIVATE(idx, 0);
757faced7e0SGiuseppe Scrivano 	cft->seq_show = hugetlb_events_show;
758d5a16959SXu Wang 	cft->file_offset = offsetof(struct hugetlb_cgroup, events_file[idx]);
759faced7e0SGiuseppe Scrivano 	cft->flags = CFTYPE_NOT_ON_ROOT;
760faced7e0SGiuseppe Scrivano 
761faced7e0SGiuseppe Scrivano 	/* Add the events.local file */
762cdc2fcfeSMina Almasry 	cft = &h->cgroup_files_dfl[5];
763faced7e0SGiuseppe Scrivano 	snprintf(cft->name, MAX_CFTYPE_NAME, "%s.events.local", buf);
764faced7e0SGiuseppe Scrivano 	cft->private = MEMFILE_PRIVATE(idx, 0);
765faced7e0SGiuseppe Scrivano 	cft->seq_show = hugetlb_events_local_show;
766faced7e0SGiuseppe Scrivano 	cft->file_offset = offsetof(struct hugetlb_cgroup,
767d5a16959SXu Wang 				    events_local_file[idx]);
768faced7e0SGiuseppe Scrivano 	cft->flags = CFTYPE_NOT_ON_ROOT;
769faced7e0SGiuseppe Scrivano 
770f4776199SMina Almasry 	/* Add the numa stat file */
771cdc2fcfeSMina Almasry 	cft = &h->cgroup_files_dfl[6];
772f4776199SMina Almasry 	snprintf(cft->name, MAX_CFTYPE_NAME, "%s.numa_stat", buf);
7732727cfe4SMiaohe Lin 	cft->private = MEMFILE_PRIVATE(idx, 0);
774f4776199SMina Almasry 	cft->seq_show = hugetlb_cgroup_read_numa_stat;
775f4776199SMina Almasry 	cft->flags = CFTYPE_NOT_ON_ROOT;
776f4776199SMina Almasry 
777f4776199SMina Almasry 	/* NULL terminate the last cft */
778f4776199SMina Almasry 	cft = &h->cgroup_files_dfl[7];
779faced7e0SGiuseppe Scrivano 	memset(cft, 0, sizeof(*cft));
780faced7e0SGiuseppe Scrivano 
781faced7e0SGiuseppe Scrivano 	WARN_ON(cgroup_add_dfl_cftypes(&hugetlb_cgrp_subsys,
782faced7e0SGiuseppe Scrivano 				       h->cgroup_files_dfl));
783faced7e0SGiuseppe Scrivano }
784faced7e0SGiuseppe Scrivano 
__hugetlb_cgroup_file_legacy_init(int idx)785faced7e0SGiuseppe Scrivano static void __init __hugetlb_cgroup_file_legacy_init(int idx)
786faced7e0SGiuseppe Scrivano {
787faced7e0SGiuseppe Scrivano 	char buf[32];
788faced7e0SGiuseppe Scrivano 	struct cftype *cft;
789faced7e0SGiuseppe Scrivano 	struct hstate *h = &hstates[idx];
790faced7e0SGiuseppe Scrivano 
791faced7e0SGiuseppe Scrivano 	/* format the size */
792cdc2fcfeSMina Almasry 	mem_fmt(buf, sizeof(buf), huge_page_size(h));
793faced7e0SGiuseppe Scrivano 
794faced7e0SGiuseppe Scrivano 	/* Add the limit file */
795faced7e0SGiuseppe Scrivano 	cft = &h->cgroup_files_legacy[0];
796abb8206cSAneesh Kumar K.V 	snprintf(cft->name, MAX_CFTYPE_NAME, "%s.limit_in_bytes", buf);
797abb8206cSAneesh Kumar K.V 	cft->private = MEMFILE_PRIVATE(idx, RES_LIMIT);
798716f479dSTejun Heo 	cft->read_u64 = hugetlb_cgroup_read_u64;
799faced7e0SGiuseppe Scrivano 	cft->write = hugetlb_cgroup_write_legacy;
800abb8206cSAneesh Kumar K.V 
801cdc2fcfeSMina Almasry 	/* Add the reservation limit file */
802faced7e0SGiuseppe Scrivano 	cft = &h->cgroup_files_legacy[1];
803cdc2fcfeSMina Almasry 	snprintf(cft->name, MAX_CFTYPE_NAME, "%s.rsvd.limit_in_bytes", buf);
804cdc2fcfeSMina Almasry 	cft->private = MEMFILE_PRIVATE(idx, RES_RSVD_LIMIT);
805cdc2fcfeSMina Almasry 	cft->read_u64 = hugetlb_cgroup_read_u64;
806cdc2fcfeSMina Almasry 	cft->write = hugetlb_cgroup_write_legacy;
807cdc2fcfeSMina Almasry 
808cdc2fcfeSMina Almasry 	/* Add the usage file */
809cdc2fcfeSMina Almasry 	cft = &h->cgroup_files_legacy[2];
810abb8206cSAneesh Kumar K.V 	snprintf(cft->name, MAX_CFTYPE_NAME, "%s.usage_in_bytes", buf);
811abb8206cSAneesh Kumar K.V 	cft->private = MEMFILE_PRIVATE(idx, RES_USAGE);
812716f479dSTejun Heo 	cft->read_u64 = hugetlb_cgroup_read_u64;
813abb8206cSAneesh Kumar K.V 
814cdc2fcfeSMina Almasry 	/* Add the reservation usage file */
815cdc2fcfeSMina Almasry 	cft = &h->cgroup_files_legacy[3];
816cdc2fcfeSMina Almasry 	snprintf(cft->name, MAX_CFTYPE_NAME, "%s.rsvd.usage_in_bytes", buf);
817cdc2fcfeSMina Almasry 	cft->private = MEMFILE_PRIVATE(idx, RES_RSVD_USAGE);
818cdc2fcfeSMina Almasry 	cft->read_u64 = hugetlb_cgroup_read_u64;
819cdc2fcfeSMina Almasry 
820abb8206cSAneesh Kumar K.V 	/* Add the MAX usage file */
821cdc2fcfeSMina Almasry 	cft = &h->cgroup_files_legacy[4];
822abb8206cSAneesh Kumar K.V 	snprintf(cft->name, MAX_CFTYPE_NAME, "%s.max_usage_in_bytes", buf);
823abb8206cSAneesh Kumar K.V 	cft->private = MEMFILE_PRIVATE(idx, RES_MAX_USAGE);
8246770c64eSTejun Heo 	cft->write = hugetlb_cgroup_reset;
825716f479dSTejun Heo 	cft->read_u64 = hugetlb_cgroup_read_u64;
826abb8206cSAneesh Kumar K.V 
827cdc2fcfeSMina Almasry 	/* Add the MAX reservation usage file */
828cdc2fcfeSMina Almasry 	cft = &h->cgroup_files_legacy[5];
829cdc2fcfeSMina Almasry 	snprintf(cft->name, MAX_CFTYPE_NAME, "%s.rsvd.max_usage_in_bytes", buf);
830cdc2fcfeSMina Almasry 	cft->private = MEMFILE_PRIVATE(idx, RES_RSVD_MAX_USAGE);
831cdc2fcfeSMina Almasry 	cft->write = hugetlb_cgroup_reset;
832cdc2fcfeSMina Almasry 	cft->read_u64 = hugetlb_cgroup_read_u64;
833cdc2fcfeSMina Almasry 
834abb8206cSAneesh Kumar K.V 	/* Add the failcntfile */
835cdc2fcfeSMina Almasry 	cft = &h->cgroup_files_legacy[6];
836abb8206cSAneesh Kumar K.V 	snprintf(cft->name, MAX_CFTYPE_NAME, "%s.failcnt", buf);
837abb8206cSAneesh Kumar K.V 	cft->private = MEMFILE_PRIVATE(idx, RES_FAILCNT);
8386770c64eSTejun Heo 	cft->write = hugetlb_cgroup_reset;
839716f479dSTejun Heo 	cft->read_u64 = hugetlb_cgroup_read_u64;
840abb8206cSAneesh Kumar K.V 
841cdc2fcfeSMina Almasry 	/* Add the reservation failcntfile */
842cdc2fcfeSMina Almasry 	cft = &h->cgroup_files_legacy[7];
843cdc2fcfeSMina Almasry 	snprintf(cft->name, MAX_CFTYPE_NAME, "%s.rsvd.failcnt", buf);
844cdc2fcfeSMina Almasry 	cft->private = MEMFILE_PRIVATE(idx, RES_RSVD_FAILCNT);
845cdc2fcfeSMina Almasry 	cft->write = hugetlb_cgroup_reset;
846cdc2fcfeSMina Almasry 	cft->read_u64 = hugetlb_cgroup_read_u64;
847cdc2fcfeSMina Almasry 
848f4776199SMina Almasry 	/* Add the numa stat file */
849cdc2fcfeSMina Almasry 	cft = &h->cgroup_files_legacy[8];
850f4776199SMina Almasry 	snprintf(cft->name, MAX_CFTYPE_NAME, "%s.numa_stat", buf);
851f4776199SMina Almasry 	cft->private = MEMFILE_PRIVATE(idx, 1);
852f4776199SMina Almasry 	cft->seq_show = hugetlb_cgroup_read_numa_stat;
853f4776199SMina Almasry 
854f4776199SMina Almasry 	/* NULL terminate the last cft */
855f4776199SMina Almasry 	cft = &h->cgroup_files_legacy[9];
856abb8206cSAneesh Kumar K.V 	memset(cft, 0, sizeof(*cft));
857abb8206cSAneesh Kumar K.V 
8582cf669a5STejun Heo 	WARN_ON(cgroup_add_legacy_cftypes(&hugetlb_cgrp_subsys,
859faced7e0SGiuseppe Scrivano 					  h->cgroup_files_legacy));
860faced7e0SGiuseppe Scrivano }
861faced7e0SGiuseppe Scrivano 
__hugetlb_cgroup_file_init(int idx)862faced7e0SGiuseppe Scrivano static void __init __hugetlb_cgroup_file_init(int idx)
863faced7e0SGiuseppe Scrivano {
864faced7e0SGiuseppe Scrivano 	__hugetlb_cgroup_file_dfl_init(idx);
865faced7e0SGiuseppe Scrivano 	__hugetlb_cgroup_file_legacy_init(idx);
8667179e7bfSJianguo Wu }
8677179e7bfSJianguo Wu 
hugetlb_cgroup_file_init(void)8687179e7bfSJianguo Wu void __init hugetlb_cgroup_file_init(void)
8697179e7bfSJianguo Wu {
8707179e7bfSJianguo Wu 	struct hstate *h;
8717179e7bfSJianguo Wu 
8727179e7bfSJianguo Wu 	for_each_hstate(h) {
8737179e7bfSJianguo Wu 		/*
8747179e7bfSJianguo Wu 		 * Add cgroup control files only if the huge page consists
8757179e7bfSJianguo Wu 		 * of more than two normal pages. This is because we use
8761d798ca3SKirill A. Shutemov 		 * page[2].private for storing cgroup details.
8777179e7bfSJianguo Wu 		 */
8787179e7bfSJianguo Wu 		if (huge_page_order(h) >= HUGETLB_CGROUP_MIN_ORDER)
8797179e7bfSJianguo Wu 			__hugetlb_cgroup_file_init(hstate_index(h));
8807179e7bfSJianguo Wu 	}
881abb8206cSAneesh Kumar K.V }
882abb8206cSAneesh Kumar K.V 
88375754681SAneesh Kumar K.V /*
88475754681SAneesh Kumar K.V  * hugetlb_lock will make sure a parallel cgroup rmdir won't happen
88575754681SAneesh Kumar K.V  * when we migrate hugepages
88675754681SAneesh Kumar K.V  */
hugetlb_cgroup_migrate(struct folio * old_folio,struct folio * new_folio)88729f39430SSidhartha Kumar void hugetlb_cgroup_migrate(struct folio *old_folio, struct folio *new_folio)
8888e6ac7faSAneesh Kumar K.V {
8898e6ac7faSAneesh Kumar K.V 	struct hugetlb_cgroup *h_cg;
8901adc4d41SMina Almasry 	struct hugetlb_cgroup *h_cg_rsvd;
89129f39430SSidhartha Kumar 	struct hstate *h = folio_hstate(old_folio);
8928e6ac7faSAneesh Kumar K.V 
8938e6ac7faSAneesh Kumar K.V 	if (hugetlb_cgroup_disabled())
8948e6ac7faSAneesh Kumar K.V 		return;
8958e6ac7faSAneesh Kumar K.V 
896db71ef79SMike Kravetz 	spin_lock_irq(&hugetlb_lock);
897f074732dSSidhartha Kumar 	h_cg = hugetlb_cgroup_from_folio(old_folio);
898f074732dSSidhartha Kumar 	h_cg_rsvd = hugetlb_cgroup_from_folio_rsvd(old_folio);
899de656ed3SSidhartha Kumar 	set_hugetlb_cgroup(old_folio, NULL);
900de656ed3SSidhartha Kumar 	set_hugetlb_cgroup_rsvd(old_folio, NULL);
9018e6ac7faSAneesh Kumar K.V 
9028e6ac7faSAneesh Kumar K.V 	/* move the h_cg details to new cgroup */
903de656ed3SSidhartha Kumar 	set_hugetlb_cgroup(new_folio, h_cg);
904de656ed3SSidhartha Kumar 	set_hugetlb_cgroup_rsvd(new_folio, h_cg_rsvd);
90529f39430SSidhartha Kumar 	list_move(&new_folio->lru, &h->hugepage_activelist);
906db71ef79SMike Kravetz 	spin_unlock_irq(&hugetlb_lock);
9078e6ac7faSAneesh Kumar K.V 	return;
9088e6ac7faSAneesh Kumar K.V }
9098e6ac7faSAneesh Kumar K.V 
910faced7e0SGiuseppe Scrivano static struct cftype hugetlb_files[] = {
911faced7e0SGiuseppe Scrivano 	{} /* terminate */
912faced7e0SGiuseppe Scrivano };
913faced7e0SGiuseppe Scrivano 
914073219e9STejun Heo struct cgroup_subsys hugetlb_cgrp_subsys = {
91592fb9748STejun Heo 	.css_alloc	= hugetlb_cgroup_css_alloc,
91692fb9748STejun Heo 	.css_offline	= hugetlb_cgroup_css_offline,
91792fb9748STejun Heo 	.css_free	= hugetlb_cgroup_css_free,
918faced7e0SGiuseppe Scrivano 	.dfl_cftypes	= hugetlb_files,
919faced7e0SGiuseppe Scrivano 	.legacy_cftypes	= hugetlb_files,
9202bc64a20SAneesh Kumar K.V };
921