hugetlb_cgroup.c 10.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 *
 * Copyright IBM Corporation, 2012
 * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2.1 of the GNU Lesser General Public License
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it would be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 */

#include <linux/cgroup.h>
17
#include <linux/page_counter.h>
18 19 20 21 22 23 24 25 26
#include <linux/slab.h>
#include <linux/hugetlb.h>
#include <linux/hugetlb_cgroup.h>

struct hugetlb_cgroup {
	struct cgroup_subsys_state css;
	/*
	 * the counter to account for hugepages from hugetlb.
	 */
27
	struct page_counter hugepage[HUGE_MAX_HSTATE];
28 29
};

30 31 32 33
#define MEMFILE_PRIVATE(x, val)	(((x) << 16) | (val))
#define MEMFILE_IDX(val)	(((val) >> 16) & 0xffff)
#define MEMFILE_ATTR(val)	((val) & 0xffff)

34 35 36 37 38
static struct hugetlb_cgroup *root_h_cgroup __read_mostly;

static inline
struct hugetlb_cgroup *hugetlb_cgroup_from_css(struct cgroup_subsys_state *s)
{
39
	return s ? container_of(s, struct hugetlb_cgroup, css) : NULL;
40 41 42 43 44
}

static inline
struct hugetlb_cgroup *hugetlb_cgroup_from_task(struct task_struct *task)
{
45
	return hugetlb_cgroup_from_css(task_css(task, hugetlb_cgrp_id));
46 47 48 49 50 51 52
}

static inline bool hugetlb_cgroup_is_root(struct hugetlb_cgroup *h_cg)
{
	return (h_cg == root_h_cgroup);
}

53 54
static inline struct hugetlb_cgroup *
parent_hugetlb_cgroup(struct hugetlb_cgroup *h_cg)
55
{
Tejun Heo's avatar
Tejun Heo committed
56
	return hugetlb_cgroup_from_css(h_cg->css.parent);
57 58
}

59
static inline bool hugetlb_cgroup_have_usage(struct hugetlb_cgroup *h_cg)
60 61 62 63
{
	int idx;

	for (idx = 0; idx < hugetlb_max_hstate; idx++) {
64
		if (page_counter_read(&h_cg->hugepage[idx]))
65 66 67 68 69
			return true;
	}
	return false;
}

70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
static void hugetlb_cgroup_init(struct hugetlb_cgroup *h_cgroup,
				struct hugetlb_cgroup *parent_h_cgroup)
{
	int idx;

	for (idx = 0; idx < HUGE_MAX_HSTATE; idx++) {
		struct page_counter *counter = &h_cgroup->hugepage[idx];
		struct page_counter *parent = NULL;
		unsigned long limit;
		int ret;

		if (parent_h_cgroup)
			parent = &parent_h_cgroup->hugepage[idx];
		page_counter_init(counter, parent);

		limit = round_down(PAGE_COUNTER_MAX,
				   1 << huge_page_order(&hstates[idx]));
87
		ret = page_counter_set_max(counter, limit);
88 89 90 91
		VM_BUG_ON(ret);
	}
}

92 93
static struct cgroup_subsys_state *
hugetlb_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)
94
{
95 96
	struct hugetlb_cgroup *parent_h_cgroup = hugetlb_cgroup_from_css(parent_css);
	struct hugetlb_cgroup *h_cgroup;
97 98 99 100 101

	h_cgroup = kzalloc(sizeof(*h_cgroup), GFP_KERNEL);
	if (!h_cgroup)
		return ERR_PTR(-ENOMEM);

102
	if (!parent_h_cgroup)
103
		root_h_cgroup = h_cgroup;
104 105

	hugetlb_cgroup_init(h_cgroup, parent_h_cgroup);
106 107 108
	return &h_cgroup->css;
}

109
static void hugetlb_cgroup_css_free(struct cgroup_subsys_state *css)
110 111 112
{
	struct hugetlb_cgroup *h_cgroup;

113
	h_cgroup = hugetlb_cgroup_from_css(css);
114 115 116
	kfree(h_cgroup);
}

117 118 119 120 121 122 123 124

/*
 * Should be called with hugetlb_lock held.
 * Since we are holding hugetlb_lock, pages cannot get moved from
 * active list or uncharged from the cgroup, So no need to get
 * page reference and test for page active here. This function
 * cannot fail.
 */
125
static void hugetlb_cgroup_move_parent(int idx, struct hugetlb_cgroup *h_cg,
126 127
				       struct page *page)
{
128 129
	unsigned int nr_pages;
	struct page_counter *counter;
130
	struct hugetlb_cgroup *page_hcg;
131
	struct hugetlb_cgroup *parent = parent_hugetlb_cgroup(h_cg);
132 133 134 135 136 137 138 139 140 141

	page_hcg = hugetlb_cgroup_from_page(page);
	/*
	 * We can have pages in active list without any cgroup
	 * ie, hugepage with less than 3 pages. We can safely
	 * ignore those pages.
	 */
	if (!page_hcg || page_hcg != h_cg)
		goto out;

142
	nr_pages = 1 << compound_order(page);
143 144 145
	if (!parent) {
		parent = root_h_cgroup;
		/* root has no limit */
146
		page_counter_charge(&parent->hugepage[idx], nr_pages);
147 148
	}
	counter = &h_cg->hugepage[idx];
149 150
	/* Take the pages off the local counter */
	page_counter_cancel(counter, nr_pages);
151 152 153 154 155 156 157 158 159 160

	set_hugetlb_cgroup(page, parent);
out:
	return;
}

/*
 * Force the hugetlb cgroup to empty the hugetlb resources by moving them to
 * the parent cgroup.
 */
161
static void hugetlb_cgroup_css_offline(struct cgroup_subsys_state *css)
162
{
163
	struct hugetlb_cgroup *h_cg = hugetlb_cgroup_from_css(css);
164 165
	struct hstate *h;
	struct page *page;
166
	int idx = 0;
167 168 169 170 171

	do {
		for_each_hstate(h) {
			spin_lock(&hugetlb_lock);
			list_for_each_entry(page, &h->hugepage_activelist, lru)
172
				hugetlb_cgroup_move_parent(idx, h_cg, page);
173 174 175 176 177

			spin_unlock(&hugetlb_lock);
			idx++;
		}
		cond_resched();
178
	} while (hugetlb_cgroup_have_usage(h_cg));
179 180
}

181 182 183 184
int hugetlb_cgroup_charge_cgroup(int idx, unsigned long nr_pages,
				 struct hugetlb_cgroup **ptr)
{
	int ret = 0;
185
	struct page_counter *counter;
186 187 188 189 190 191 192 193 194 195 196 197 198
	struct hugetlb_cgroup *h_cg = NULL;

	if (hugetlb_cgroup_disabled())
		goto done;
	/*
	 * We don't charge any cgroup if the compound page have less
	 * than 3 pages.
	 */
	if (huge_page_order(&hstates[idx]) < HUGETLB_CGROUP_MIN_ORDER)
		goto done;
again:
	rcu_read_lock();
	h_cg = hugetlb_cgroup_from_task(current);
199
	if (!css_tryget_online(&h_cg->css)) {
200 201 202 203 204
		rcu_read_unlock();
		goto again;
	}
	rcu_read_unlock();

205 206
	if (!page_counter_try_charge(&h_cg->hugepage[idx], nr_pages, &counter))
		ret = -ENOMEM;
207 208 209 210 211 212
	css_put(&h_cg->css);
done:
	*ptr = h_cg;
	return ret;
}

213
/* Should be called with hugetlb_lock held */
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
void hugetlb_cgroup_commit_charge(int idx, unsigned long nr_pages,
				  struct hugetlb_cgroup *h_cg,
				  struct page *page)
{
	if (hugetlb_cgroup_disabled() || !h_cg)
		return;

	set_hugetlb_cgroup(page, h_cg);
	return;
}

/*
 * Should be called with hugetlb_lock held
 */
void hugetlb_cgroup_uncharge_page(int idx, unsigned long nr_pages,
				  struct page *page)
{
	struct hugetlb_cgroup *h_cg;

	if (hugetlb_cgroup_disabled())
		return;
235
	lockdep_assert_held(&hugetlb_lock);
236 237 238 239
	h_cg = hugetlb_cgroup_from_page(page);
	if (unlikely(!h_cg))
		return;
	set_hugetlb_cgroup(page, NULL);
240
	page_counter_uncharge(&h_cg->hugepage[idx], nr_pages);
241 242 243 244 245 246 247 248 249 250 251 252
	return;
}

void hugetlb_cgroup_uncharge_cgroup(int idx, unsigned long nr_pages,
				    struct hugetlb_cgroup *h_cg)
{
	if (hugetlb_cgroup_disabled() || !h_cg)
		return;

	if (huge_page_order(&hstates[idx]) < HUGETLB_CGROUP_MIN_ORDER)
		return;

253
	page_counter_uncharge(&h_cg->hugepage[idx], nr_pages);
254 255 256
	return;
}

257 258 259 260 261 262 263
enum {
	RES_USAGE,
	RES_LIMIT,
	RES_MAX_USAGE,
	RES_FAILCNT,
};

264 265
static u64 hugetlb_cgroup_read_u64(struct cgroup_subsys_state *css,
				   struct cftype *cft)
266
{
267
	struct page_counter *counter;
268
	struct hugetlb_cgroup *h_cg = hugetlb_cgroup_from_css(css);
269

270
	counter = &h_cg->hugepage[MEMFILE_IDX(cft->private)];
271

272 273 274 275
	switch (MEMFILE_ATTR(cft->private)) {
	case RES_USAGE:
		return (u64)page_counter_read(counter) * PAGE_SIZE;
	case RES_LIMIT:
276
		return (u64)counter->max * PAGE_SIZE;
277 278 279 280 281 282 283
	case RES_MAX_USAGE:
		return (u64)counter->watermark * PAGE_SIZE;
	case RES_FAILCNT:
		return counter->failcnt;
	default:
		BUG();
	}
284 285
}

286 287
static DEFINE_MUTEX(hugetlb_limit_mutex);

288 289
static ssize_t hugetlb_cgroup_write(struct kernfs_open_file *of,
				    char *buf, size_t nbytes, loff_t off)
290
{
291 292
	int ret, idx;
	unsigned long nr_pages;
293
	struct hugetlb_cgroup *h_cg = hugetlb_cgroup_from_css(of_css(of));
294

295 296 297
	if (hugetlb_cgroup_is_root(h_cg)) /* Can't set limit on root */
		return -EINVAL;

298
	buf = strstrip(buf);
299
	ret = page_counter_memparse(buf, "-1", &nr_pages);
300 301 302
	if (ret)
		return ret;

303
	idx = MEMFILE_IDX(of_cft(of)->private);
304
	nr_pages = round_down(nr_pages, 1 << huge_page_order(&hstates[idx]));
305

306
	switch (MEMFILE_ATTR(of_cft(of)->private)) {
307
	case RES_LIMIT:
308
		mutex_lock(&hugetlb_limit_mutex);
309
		ret = page_counter_set_max(&h_cg->hugepage[idx], nr_pages);
310
		mutex_unlock(&hugetlb_limit_mutex);
311 312 313 314 315
		break;
	default:
		ret = -EINVAL;
		break;
	}
316
	return ret ?: nbytes;
317 318
}

319 320
static ssize_t hugetlb_cgroup_reset(struct kernfs_open_file *of,
				    char *buf, size_t nbytes, loff_t off)
321
{
322 323
	int ret = 0;
	struct page_counter *counter;
324
	struct hugetlb_cgroup *h_cg = hugetlb_cgroup_from_css(of_css(of));
325

326
	counter = &h_cg->hugepage[MEMFILE_IDX(of_cft(of)->private)];
327

328
	switch (MEMFILE_ATTR(of_cft(of)->private)) {
329
	case RES_MAX_USAGE:
330
		page_counter_reset_watermark(counter);
331 332
		break;
	case RES_FAILCNT:
333
		counter->failcnt = 0;
334 335 336 337 338
		break;
	default:
		ret = -EINVAL;
		break;
	}
339
	return ret ?: nbytes;
340 341 342 343 344 345 346 347 348 349 350 351 352
}

static char *mem_fmt(char *buf, int size, unsigned long hsize)
{
	if (hsize >= (1UL << 30))
		snprintf(buf, size, "%luGB", hsize >> 30);
	else if (hsize >= (1UL << 20))
		snprintf(buf, size, "%luMB", hsize >> 20);
	else
		snprintf(buf, size, "%luKB", hsize >> 10);
	return buf;
}

353
static void __init __hugetlb_cgroup_file_init(int idx)
354 355 356 357 358 359 360 361 362 363 364 365
{
	char buf[32];
	struct cftype *cft;
	struct hstate *h = &hstates[idx];

	/* format the size */
	mem_fmt(buf, 32, huge_page_size(h));

	/* Add the limit file */
	cft = &h->cgroup_files[0];
	snprintf(cft->name, MAX_CFTYPE_NAME, "%s.limit_in_bytes", buf);
	cft->private = MEMFILE_PRIVATE(idx, RES_LIMIT);
366
	cft->read_u64 = hugetlb_cgroup_read_u64;
367
	cft->write = hugetlb_cgroup_write;
368 369 370 371 372

	/* Add the usage file */
	cft = &h->cgroup_files[1];
	snprintf(cft->name, MAX_CFTYPE_NAME, "%s.usage_in_bytes", buf);
	cft->private = MEMFILE_PRIVATE(idx, RES_USAGE);
373
	cft->read_u64 = hugetlb_cgroup_read_u64;
374 375 376 377 378

	/* Add the MAX usage file */
	cft = &h->cgroup_files[2];
	snprintf(cft->name, MAX_CFTYPE_NAME, "%s.max_usage_in_bytes", buf);
	cft->private = MEMFILE_PRIVATE(idx, RES_MAX_USAGE);
379
	cft->write = hugetlb_cgroup_reset;
380
	cft->read_u64 = hugetlb_cgroup_read_u64;
381 382 383 384 385

	/* Add the failcntfile */
	cft = &h->cgroup_files[3];
	snprintf(cft->name, MAX_CFTYPE_NAME, "%s.failcnt", buf);
	cft->private  = MEMFILE_PRIVATE(idx, RES_FAILCNT);
386
	cft->write = hugetlb_cgroup_reset;
387
	cft->read_u64 = hugetlb_cgroup_read_u64;
388 389 390 391 392

	/* NULL terminate the last cft */
	cft = &h->cgroup_files[4];
	memset(cft, 0, sizeof(*cft));

393 394
	WARN_ON(cgroup_add_legacy_cftypes(&hugetlb_cgrp_subsys,
					  h->cgroup_files));
395 396 397 398 399 400 401 402 403 404
}

void __init hugetlb_cgroup_file_init(void)
{
	struct hstate *h;

	for_each_hstate(h) {
		/*
		 * Add cgroup control files only if the huge page consists
		 * of more than two normal pages. This is because we use
405
		 * page[2].private for storing cgroup details.
406 407 408 409
		 */
		if (huge_page_order(h) >= HUGETLB_CGROUP_MIN_ORDER)
			__hugetlb_cgroup_file_init(hstate_index(h));
	}
410 411
}

412 413 414 415
/*
 * hugetlb_lock will make sure a parallel cgroup rmdir won't happen
 * when we migrate hugepages
 */
416 417 418
void hugetlb_cgroup_migrate(struct page *oldhpage, struct page *newhpage)
{
	struct hugetlb_cgroup *h_cg;
419
	struct hstate *h = page_hstate(oldhpage);
420 421 422 423

	if (hugetlb_cgroup_disabled())
		return;

424
	VM_BUG_ON_PAGE(!PageHuge(oldhpage), oldhpage);
425 426 427 428 429 430
	spin_lock(&hugetlb_lock);
	h_cg = hugetlb_cgroup_from_page(oldhpage);
	set_hugetlb_cgroup(oldhpage, NULL);

	/* move the h_cg details to new cgroup */
	set_hugetlb_cgroup(newhpage, h_cg);
431
	list_move(&newhpage->lru, &h->hugepage_activelist);
432 433 434 435
	spin_unlock(&hugetlb_lock);
	return;
}

436
struct cgroup_subsys hugetlb_cgrp_subsys = {
437 438 439
	.css_alloc	= hugetlb_cgroup_css_alloc,
	.css_offline	= hugetlb_cgroup_css_offline,
	.css_free	= hugetlb_cgroup_css_free,
440
};