diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/memcontrol.c | 61 |
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 | ||
1550 | static u64 mem_cgroup_hierarchy_read(struct cgroup *cont, struct cftype *cft) | ||
1551 | { | ||
1552 | return mem_cgroup_from_cont(cont)->use_hierarchy; | ||
1553 | } | ||
1554 | |||
1555 | static 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 | |||
1546 | static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft) | 1588 | static 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 | ||