aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
Diffstat (limited to 'mm')
-rw-r--r--mm/memcontrol.c61
1 files changed, 57 insertions, 4 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 20e1d90b3363..886e2224c5fd 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -149,6 +149,10 @@ struct mem_cgroup {
149 * reclaimed from. Protected by cgroup_lock() 149 * reclaimed from. Protected by cgroup_lock()
150 */ 150 */
151 struct mem_cgroup *last_scanned_child; 151 struct mem_cgroup *last_scanned_child;
152 /*
153 * Should the accounting and control be hierarchical, per subtree?
154 */
155 bool use_hierarchy;
152 156
153 int obsolete; 157 int obsolete;
154 atomic_t refcnt; 158 atomic_t refcnt;
@@ -1543,6 +1547,44 @@ int mem_cgroup_force_empty_write(struct cgroup *cont, unsigned int event)
1543} 1547}
1544 1548
1545 1549
1550static u64 mem_cgroup_hierarchy_read(struct cgroup *cont, struct cftype *cft)
1551{
1552 return mem_cgroup_from_cont(cont)->use_hierarchy;
1553}
1554
1555static int mem_cgroup_hierarchy_write(struct cgroup *cont, struct cftype *cft,
1556 u64 val)
1557{
1558 int retval = 0;
1559 struct mem_cgroup *mem = mem_cgroup_from_cont(cont);
1560 struct cgroup *parent = cont->parent;
1561 struct mem_cgroup *parent_mem = NULL;
1562
1563 if (parent)
1564 parent_mem = mem_cgroup_from_cont(parent);
1565
1566 cgroup_lock();
1567 /*
1568 * If parent's use_hiearchy is set, we can't make any modifications
1569 * in the child subtrees. If it is unset, then the change can
1570 * occur, provided the current cgroup has no children.
1571 *
1572 * For the root cgroup, parent_mem is NULL, we allow value to be
1573 * set if there are no children.
1574 */
1575 if ((!parent_mem || !parent_mem->use_hierarchy) &&
1576 (val == 1 || val == 0)) {
1577 if (list_empty(&cont->children))
1578 mem->use_hierarchy = val;
1579 else
1580 retval = -EBUSY;
1581 } else
1582 retval = -EINVAL;
1583 cgroup_unlock();
1584
1585 return retval;
1586}
1587
1546static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft) 1588static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft)
1547{ 1589{
1548 struct mem_cgroup *mem = mem_cgroup_from_cont(cont); 1590 struct mem_cgroup *mem = mem_cgroup_from_cont(cont);
@@ -1706,6 +1748,11 @@ static struct cftype mem_cgroup_files[] = {
1706 .name = "force_empty", 1748 .name = "force_empty",
1707 .trigger = mem_cgroup_force_empty_write, 1749 .trigger = mem_cgroup_force_empty_write,
1708 }, 1750 },
1751 {
1752 .name = "use_hierarchy",
1753 .write_u64 = mem_cgroup_hierarchy_write,
1754 .read_u64 = mem_cgroup_hierarchy_read,
1755 },
1709}; 1756};
1710 1757
1711#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP 1758#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP
@@ -1881,12 +1928,18 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont)
1881 if (cont->parent == NULL) { 1928 if (cont->parent == NULL) {
1882 enable_swap_cgroup(); 1929 enable_swap_cgroup();
1883 parent = NULL; 1930 parent = NULL;
1884 } else 1931 } else {
1885 parent = mem_cgroup_from_cont(cont->parent); 1932 parent = mem_cgroup_from_cont(cont->parent);
1933 mem->use_hierarchy = parent->use_hierarchy;
1934 }
1886 1935
1887 res_counter_init(&mem->res, parent ? &parent->res : NULL); 1936 if (parent && parent->use_hierarchy) {
1888 res_counter_init(&mem->memsw, parent ? &parent->memsw : NULL); 1937 res_counter_init(&mem->res, &parent->res);
1889 1938 res_counter_init(&mem->memsw, &parent->memsw);
1939 } else {
1940 res_counter_init(&mem->res, NULL);
1941 res_counter_init(&mem->memsw, NULL);
1942 }
1890 1943
1891 mem->last_scanned_child = NULL; 1944 mem->last_scanned_child = NULL;
1892 1945