diff options
-rw-r--r-- | include/linux/cgroup_subsys.h | 6 | ||||
-rw-r--r-- | include/linux/hugetlb_cgroup.h | 37 | ||||
-rw-r--r-- | init/Kconfig | 15 | ||||
-rw-r--r-- | mm/Makefile | 1 | ||||
-rw-r--r-- | mm/hugetlb_cgroup.c | 120 |
5 files changed, 179 insertions, 0 deletions
diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h index 0bd390ce98b2..5b41ce079024 100644 --- a/include/linux/cgroup_subsys.h +++ b/include/linux/cgroup_subsys.h | |||
@@ -72,3 +72,9 @@ SUBSYS(net_prio) | |||
72 | #endif | 72 | #endif |
73 | 73 | ||
74 | /* */ | 74 | /* */ |
75 | |||
76 | #ifdef CONFIG_CGROUP_HUGETLB | ||
77 | SUBSYS(hugetlb) | ||
78 | #endif | ||
79 | |||
80 | /* */ | ||
diff --git a/include/linux/hugetlb_cgroup.h b/include/linux/hugetlb_cgroup.h new file mode 100644 index 000000000000..f19889e56b47 --- /dev/null +++ b/include/linux/hugetlb_cgroup.h | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | * Copyright IBM Corporation, 2012 | ||
3 | * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | ||
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/res_counter.h> | ||
19 | |||
20 | struct hugetlb_cgroup; | ||
21 | |||
22 | #ifdef CONFIG_CGROUP_HUGETLB | ||
23 | static inline bool hugetlb_cgroup_disabled(void) | ||
24 | { | ||
25 | if (hugetlb_subsys.disabled) | ||
26 | return true; | ||
27 | return false; | ||
28 | } | ||
29 | |||
30 | #else | ||
31 | static inline bool hugetlb_cgroup_disabled(void) | ||
32 | { | ||
33 | return true; | ||
34 | } | ||
35 | |||
36 | #endif /* CONFIG_MEM_RES_CTLR_HUGETLB */ | ||
37 | #endif | ||
diff --git a/init/Kconfig b/init/Kconfig index b3f55f15e107..72437760e90e 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
@@ -751,6 +751,21 @@ config CGROUP_MEM_RES_CTLR_KMEM | |||
751 | the kmem extension can use it to guarantee that no group of processes | 751 | the kmem extension can use it to guarantee that no group of processes |
752 | will ever exhaust kernel resources alone. | 752 | will ever exhaust kernel resources alone. |
753 | 753 | ||
754 | config CGROUP_HUGETLB | ||
755 | bool "HugeTLB Resource Controller for Control Groups" | ||
756 | depends on RESOURCE_COUNTERS && HUGETLB_PAGE && EXPERIMENTAL | ||
757 | default n | ||
758 | help | ||
759 | Provides a cgroup Resource Controller for HugeTLB pages. | ||
760 | When you enable this, you can put a per cgroup limit on HugeTLB usage. | ||
761 | The limit is enforced during page fault. Since HugeTLB doesn't | ||
762 | support page reclaim, enforcing the limit at page fault time implies | ||
763 | that, the application will get SIGBUS signal if it tries to access | ||
764 | HugeTLB pages beyond its limit. This requires the application to know | ||
765 | beforehand how much HugeTLB pages it would require for its use. The | ||
766 | control group is tracked in the third page lru pointer. This means | ||
767 | that we cannot use the controller with huge page less than 3 pages. | ||
768 | |||
754 | config CGROUP_PERF | 769 | config CGROUP_PERF |
755 | bool "Enable perf_event per-cpu per-container group (cgroup) monitoring" | 770 | bool "Enable perf_event per-cpu per-container group (cgroup) monitoring" |
756 | depends on PERF_EVENTS && CGROUPS | 771 | depends on PERF_EVENTS && CGROUPS |
diff --git a/mm/Makefile b/mm/Makefile index 8e81fe263c94..fd6fc1c1966c 100644 --- a/mm/Makefile +++ b/mm/Makefile | |||
@@ -50,6 +50,7 @@ obj-$(CONFIG_MIGRATION) += migrate.o | |||
50 | obj-$(CONFIG_QUICKLIST) += quicklist.o | 50 | obj-$(CONFIG_QUICKLIST) += quicklist.o |
51 | obj-$(CONFIG_TRANSPARENT_HUGEPAGE) += huge_memory.o | 51 | obj-$(CONFIG_TRANSPARENT_HUGEPAGE) += huge_memory.o |
52 | obj-$(CONFIG_CGROUP_MEM_RES_CTLR) += memcontrol.o page_cgroup.o | 52 | obj-$(CONFIG_CGROUP_MEM_RES_CTLR) += memcontrol.o page_cgroup.o |
53 | obj-$(CONFIG_CGROUP_HUGETLB) += hugetlb_cgroup.o | ||
53 | obj-$(CONFIG_MEMORY_FAILURE) += memory-failure.o | 54 | obj-$(CONFIG_MEMORY_FAILURE) += memory-failure.o |
54 | obj-$(CONFIG_HWPOISON_INJECT) += hwpoison-inject.o | 55 | obj-$(CONFIG_HWPOISON_INJECT) += hwpoison-inject.o |
55 | obj-$(CONFIG_DEBUG_KMEMLEAK) += kmemleak.o | 56 | obj-$(CONFIG_DEBUG_KMEMLEAK) += kmemleak.o |
diff --git a/mm/hugetlb_cgroup.c b/mm/hugetlb_cgroup.c new file mode 100644 index 000000000000..0d1a66e9039b --- /dev/null +++ b/mm/hugetlb_cgroup.c | |||
@@ -0,0 +1,120 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Copyright IBM Corporation, 2012 | ||
4 | * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of version 2.1 of the GNU Lesser General Public License | ||
8 | * as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it would be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/cgroup.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/hugetlb.h> | ||
19 | #include <linux/hugetlb_cgroup.h> | ||
20 | |||
21 | struct hugetlb_cgroup { | ||
22 | struct cgroup_subsys_state css; | ||
23 | /* | ||
24 | * the counter to account for hugepages from hugetlb. | ||
25 | */ | ||
26 | struct res_counter hugepage[HUGE_MAX_HSTATE]; | ||
27 | }; | ||
28 | |||
29 | struct cgroup_subsys hugetlb_subsys __read_mostly; | ||
30 | static struct hugetlb_cgroup *root_h_cgroup __read_mostly; | ||
31 | |||
32 | static inline | ||
33 | struct hugetlb_cgroup *hugetlb_cgroup_from_css(struct cgroup_subsys_state *s) | ||
34 | { | ||
35 | return container_of(s, struct hugetlb_cgroup, css); | ||
36 | } | ||
37 | |||
38 | static inline | ||
39 | struct hugetlb_cgroup *hugetlb_cgroup_from_cgroup(struct cgroup *cgroup) | ||
40 | { | ||
41 | return hugetlb_cgroup_from_css(cgroup_subsys_state(cgroup, | ||
42 | hugetlb_subsys_id)); | ||
43 | } | ||
44 | |||
45 | static inline | ||
46 | struct hugetlb_cgroup *hugetlb_cgroup_from_task(struct task_struct *task) | ||
47 | { | ||
48 | return hugetlb_cgroup_from_css(task_subsys_state(task, | ||
49 | hugetlb_subsys_id)); | ||
50 | } | ||
51 | |||
52 | static inline bool hugetlb_cgroup_is_root(struct hugetlb_cgroup *h_cg) | ||
53 | { | ||
54 | return (h_cg == root_h_cgroup); | ||
55 | } | ||
56 | |||
57 | static inline struct hugetlb_cgroup *parent_hugetlb_cgroup(struct cgroup *cg) | ||
58 | { | ||
59 | if (!cg->parent) | ||
60 | return NULL; | ||
61 | return hugetlb_cgroup_from_cgroup(cg->parent); | ||
62 | } | ||
63 | |||
64 | static inline bool hugetlb_cgroup_have_usage(struct cgroup *cg) | ||
65 | { | ||
66 | int idx; | ||
67 | struct hugetlb_cgroup *h_cg = hugetlb_cgroup_from_cgroup(cg); | ||
68 | |||
69 | for (idx = 0; idx < hugetlb_max_hstate; idx++) { | ||
70 | if ((res_counter_read_u64(&h_cg->hugepage[idx], RES_USAGE)) > 0) | ||
71 | return true; | ||
72 | } | ||
73 | return false; | ||
74 | } | ||
75 | |||
76 | static struct cgroup_subsys_state *hugetlb_cgroup_create(struct cgroup *cgroup) | ||
77 | { | ||
78 | int idx; | ||
79 | struct cgroup *parent_cgroup; | ||
80 | struct hugetlb_cgroup *h_cgroup, *parent_h_cgroup; | ||
81 | |||
82 | h_cgroup = kzalloc(sizeof(*h_cgroup), GFP_KERNEL); | ||
83 | if (!h_cgroup) | ||
84 | return ERR_PTR(-ENOMEM); | ||
85 | |||
86 | parent_cgroup = cgroup->parent; | ||
87 | if (parent_cgroup) { | ||
88 | parent_h_cgroup = hugetlb_cgroup_from_cgroup(parent_cgroup); | ||
89 | for (idx = 0; idx < HUGE_MAX_HSTATE; idx++) | ||
90 | res_counter_init(&h_cgroup->hugepage[idx], | ||
91 | &parent_h_cgroup->hugepage[idx]); | ||
92 | } else { | ||
93 | root_h_cgroup = h_cgroup; | ||
94 | for (idx = 0; idx < HUGE_MAX_HSTATE; idx++) | ||
95 | res_counter_init(&h_cgroup->hugepage[idx], NULL); | ||
96 | } | ||
97 | return &h_cgroup->css; | ||
98 | } | ||
99 | |||
100 | static void hugetlb_cgroup_destroy(struct cgroup *cgroup) | ||
101 | { | ||
102 | struct hugetlb_cgroup *h_cgroup; | ||
103 | |||
104 | h_cgroup = hugetlb_cgroup_from_cgroup(cgroup); | ||
105 | kfree(h_cgroup); | ||
106 | } | ||
107 | |||
108 | static int hugetlb_cgroup_pre_destroy(struct cgroup *cgroup) | ||
109 | { | ||
110 | /* We will add the cgroup removal support in later patches */ | ||
111 | return -EBUSY; | ||
112 | } | ||
113 | |||
114 | struct cgroup_subsys hugetlb_subsys = { | ||
115 | .name = "hugetlb", | ||
116 | .create = hugetlb_cgroup_create, | ||
117 | .pre_destroy = hugetlb_cgroup_pre_destroy, | ||
118 | .destroy = hugetlb_cgroup_destroy, | ||
119 | .subsys_id = hugetlb_subsys_id, | ||
120 | }; | ||