diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/memcontrol.c | 51 |
1 files changed, 26 insertions, 25 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index af920d0f9025..79f23a189941 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -1108,6 +1108,21 @@ void mem_cgroup_move_lists(struct page *page, | |||
1108 | mem_cgroup_add_lru_list(page, to); | 1108 | mem_cgroup_add_lru_list(page, to); |
1109 | } | 1109 | } |
1110 | 1110 | ||
1111 | /* | ||
1112 | * Checks whether given mem is same or in the root_mem's | ||
1113 | * hierarchy subtree | ||
1114 | */ | ||
1115 | static bool mem_cgroup_same_or_subtree(const struct mem_cgroup *root_mem, | ||
1116 | struct mem_cgroup *mem) | ||
1117 | { | ||
1118 | if (root_mem != mem) { | ||
1119 | return (root_mem->use_hierarchy && | ||
1120 | css_is_ancestor(&mem->css, &root_mem->css)); | ||
1121 | } | ||
1122 | |||
1123 | return true; | ||
1124 | } | ||
1125 | |||
1111 | int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem) | 1126 | int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem) |
1112 | { | 1127 | { |
1113 | int ret; | 1128 | int ret; |
@@ -1127,10 +1142,7 @@ int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem) | |||
1127 | * enabled in "curr" and "curr" is a child of "mem" in *cgroup* | 1142 | * enabled in "curr" and "curr" is a child of "mem" in *cgroup* |
1128 | * hierarchy(even if use_hierarchy is disabled in "mem"). | 1143 | * hierarchy(even if use_hierarchy is disabled in "mem"). |
1129 | */ | 1144 | */ |
1130 | if (mem->use_hierarchy) | 1145 | ret = mem_cgroup_same_or_subtree(mem, curr); |
1131 | ret = css_is_ancestor(&curr->css, &mem->css); | ||
1132 | else | ||
1133 | ret = (curr == mem); | ||
1134 | css_put(&curr->css); | 1146 | css_put(&curr->css); |
1135 | return ret; | 1147 | return ret; |
1136 | } | 1148 | } |
@@ -1369,10 +1381,9 @@ static bool mem_cgroup_under_move(struct mem_cgroup *mem) | |||
1369 | to = mc.to; | 1381 | to = mc.to; |
1370 | if (!from) | 1382 | if (!from) |
1371 | goto unlock; | 1383 | goto unlock; |
1372 | if (from == mem || to == mem | 1384 | |
1373 | || (mem->use_hierarchy && css_is_ancestor(&from->css, &mem->css)) | 1385 | ret = mem_cgroup_same_or_subtree(mem, from) |
1374 | || (mem->use_hierarchy && css_is_ancestor(&to->css, &mem->css))) | 1386 | || mem_cgroup_same_or_subtree(mem, to); |
1375 | ret = true; | ||
1376 | unlock: | 1387 | unlock: |
1377 | spin_unlock(&mc.lock); | 1388 | spin_unlock(&mc.lock); |
1378 | return ret; | 1389 | return ret; |
@@ -1915,25 +1926,20 @@ struct oom_wait_info { | |||
1915 | static int memcg_oom_wake_function(wait_queue_t *wait, | 1926 | static int memcg_oom_wake_function(wait_queue_t *wait, |
1916 | unsigned mode, int sync, void *arg) | 1927 | unsigned mode, int sync, void *arg) |
1917 | { | 1928 | { |
1918 | struct mem_cgroup *wake_mem = (struct mem_cgroup *)arg; | 1929 | struct mem_cgroup *wake_mem = (struct mem_cgroup *)arg, |
1930 | *oom_wait_mem; | ||
1919 | struct oom_wait_info *oom_wait_info; | 1931 | struct oom_wait_info *oom_wait_info; |
1920 | 1932 | ||
1921 | oom_wait_info = container_of(wait, struct oom_wait_info, wait); | 1933 | oom_wait_info = container_of(wait, struct oom_wait_info, wait); |
1934 | oom_wait_mem = oom_wait_info->mem; | ||
1922 | 1935 | ||
1923 | if (oom_wait_info->mem == wake_mem) | ||
1924 | goto wakeup; | ||
1925 | /* if no hierarchy, no match */ | ||
1926 | if (!oom_wait_info->mem->use_hierarchy || !wake_mem->use_hierarchy) | ||
1927 | return 0; | ||
1928 | /* | 1936 | /* |
1929 | * Both of oom_wait_info->mem and wake_mem are stable under us. | 1937 | * Both of oom_wait_info->mem and wake_mem are stable under us. |
1930 | * Then we can use css_is_ancestor without taking care of RCU. | 1938 | * Then we can use css_is_ancestor without taking care of RCU. |
1931 | */ | 1939 | */ |
1932 | if (!css_is_ancestor(&oom_wait_info->mem->css, &wake_mem->css) && | 1940 | if (!mem_cgroup_same_or_subtree(oom_wait_mem, wake_mem) |
1933 | !css_is_ancestor(&wake_mem->css, &oom_wait_info->mem->css)) | 1941 | && !mem_cgroup_same_or_subtree(wake_mem, oom_wait_mem)) |
1934 | return 0; | 1942 | return 0; |
1935 | |||
1936 | wakeup: | ||
1937 | return autoremove_wake_function(wait, mode, sync, arg); | 1943 | return autoremove_wake_function(wait, mode, sync, arg); |
1938 | } | 1944 | } |
1939 | 1945 | ||
@@ -2178,13 +2184,8 @@ static void drain_all_stock(struct mem_cgroup *root_mem, bool sync) | |||
2178 | mem = stock->cached; | 2184 | mem = stock->cached; |
2179 | if (!mem || !stock->nr_pages) | 2185 | if (!mem || !stock->nr_pages) |
2180 | continue; | 2186 | continue; |
2181 | if (mem != root_mem) { | 2187 | if (!mem_cgroup_same_or_subtree(root_mem, mem)) |
2182 | if (!root_mem->use_hierarchy) | 2188 | continue; |
2183 | continue; | ||
2184 | /* check whether "mem" is under tree of "root_mem" */ | ||
2185 | if (!css_is_ancestor(&mem->css, &root_mem->css)) | ||
2186 | continue; | ||
2187 | } | ||
2188 | if (!test_and_set_bit(FLUSHING_CACHED_CHARGE, &stock->flags)) { | 2189 | if (!test_and_set_bit(FLUSHING_CACHED_CHARGE, &stock->flags)) { |
2189 | if (cpu == curcpu) | 2190 | if (cpu == curcpu) |
2190 | drain_local_stock(&stock->work); | 2191 | drain_local_stock(&stock->work); |