diff options
author | Andrew Morton <akpm@linux-foundation.org> | 2013-09-24 18:27:37 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-24 20:00:26 -0400 |
commit | 694fbc0fe78518d06efa63910bf4ecee660e7852 (patch) | |
tree | 895244c4cc010759ce5c29333bee3cddc8c852d2 /mm | |
parent | 30361e51cae7a4df3fec89f935a450a6fe6f16fa (diff) |
revert "memcg: enhance memcg iterator to support predicates"
Revert commit de57780dc659 ("memcg: enhance memcg iterator to support
predicates")
I merged this prematurely - Michal and Johannes still disagree about the
overall design direction and the future remains unclear.
Cc: Michal Hocko <mhocko@suse.cz>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/memcontrol.c | 70 | ||||
-rw-r--r-- | mm/vmscan.c | 16 |
2 files changed, 26 insertions, 60 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 916892c2b8e0..65e7bec4b0f0 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -862,15 +862,6 @@ struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm) | |||
862 | return memcg; | 862 | return memcg; |
863 | } | 863 | } |
864 | 864 | ||
865 | static enum mem_cgroup_filter_t | ||
866 | mem_cgroup_filter(struct mem_cgroup *memcg, struct mem_cgroup *root, | ||
867 | mem_cgroup_iter_filter cond) | ||
868 | { | ||
869 | if (!cond) | ||
870 | return VISIT; | ||
871 | return cond(memcg, root); | ||
872 | } | ||
873 | |||
874 | /* | 865 | /* |
875 | * Returns a next (in a pre-order walk) alive memcg (with elevated css | 866 | * Returns a next (in a pre-order walk) alive memcg (with elevated css |
876 | * ref. count) or NULL if the whole root's subtree has been visited. | 867 | * ref. count) or NULL if the whole root's subtree has been visited. |
@@ -878,7 +869,7 @@ mem_cgroup_filter(struct mem_cgroup *memcg, struct mem_cgroup *root, | |||
878 | * helper function to be used by mem_cgroup_iter | 869 | * helper function to be used by mem_cgroup_iter |
879 | */ | 870 | */ |
880 | static struct mem_cgroup *__mem_cgroup_iter_next(struct mem_cgroup *root, | 871 | static struct mem_cgroup *__mem_cgroup_iter_next(struct mem_cgroup *root, |
881 | struct mem_cgroup *last_visited, mem_cgroup_iter_filter cond) | 872 | struct mem_cgroup *last_visited) |
882 | { | 873 | { |
883 | struct cgroup_subsys_state *prev_css, *next_css; | 874 | struct cgroup_subsys_state *prev_css, *next_css; |
884 | 875 | ||
@@ -896,31 +887,11 @@ skip_node: | |||
896 | if (next_css) { | 887 | if (next_css) { |
897 | struct mem_cgroup *mem = mem_cgroup_from_css(next_css); | 888 | struct mem_cgroup *mem = mem_cgroup_from_css(next_css); |
898 | 889 | ||
899 | switch (mem_cgroup_filter(mem, root, cond)) { | 890 | if (css_tryget(&mem->css)) |
900 | case SKIP: | 891 | return mem; |
892 | else { | ||
901 | prev_css = next_css; | 893 | prev_css = next_css; |
902 | goto skip_node; | 894 | goto skip_node; |
903 | case SKIP_TREE: | ||
904 | if (mem == root) | ||
905 | return NULL; | ||
906 | /* | ||
907 | * css_rightmost_descendant is not an optimal way to | ||
908 | * skip through a subtree (especially for imbalanced | ||
909 | * trees leaning to right) but that's what we have right | ||
910 | * now. More effective solution would be traversing | ||
911 | * right-up for first non-NULL without calling | ||
912 | * css_next_descendant_pre afterwards. | ||
913 | */ | ||
914 | prev_css = css_rightmost_descendant(next_css); | ||
915 | goto skip_node; | ||
916 | case VISIT: | ||
917 | if (css_tryget(&mem->css)) | ||
918 | return mem; | ||
919 | else { | ||
920 | prev_css = next_css; | ||
921 | goto skip_node; | ||
922 | } | ||
923 | break; | ||
924 | } | 895 | } |
925 | } | 896 | } |
926 | 897 | ||
@@ -984,7 +955,6 @@ static void mem_cgroup_iter_update(struct mem_cgroup_reclaim_iter *iter, | |||
984 | * @root: hierarchy root | 955 | * @root: hierarchy root |
985 | * @prev: previously returned memcg, NULL on first invocation | 956 | * @prev: previously returned memcg, NULL on first invocation |
986 | * @reclaim: cookie for shared reclaim walks, NULL for full walks | 957 | * @reclaim: cookie for shared reclaim walks, NULL for full walks |
987 | * @cond: filter for visited nodes, NULL for no filter | ||
988 | * | 958 | * |
989 | * Returns references to children of the hierarchy below @root, or | 959 | * Returns references to children of the hierarchy below @root, or |
990 | * @root itself, or %NULL after a full round-trip. | 960 | * @root itself, or %NULL after a full round-trip. |
@@ -997,18 +967,15 @@ static void mem_cgroup_iter_update(struct mem_cgroup_reclaim_iter *iter, | |||
997 | * divide up the memcgs in the hierarchy among all concurrent | 967 | * divide up the memcgs in the hierarchy among all concurrent |
998 | * reclaimers operating on the same zone and priority. | 968 | * reclaimers operating on the same zone and priority. |
999 | */ | 969 | */ |
1000 | struct mem_cgroup *mem_cgroup_iter_cond(struct mem_cgroup *root, | 970 | struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *root, |
1001 | struct mem_cgroup *prev, | 971 | struct mem_cgroup *prev, |
1002 | struct mem_cgroup_reclaim_cookie *reclaim, | 972 | struct mem_cgroup_reclaim_cookie *reclaim) |
1003 | mem_cgroup_iter_filter cond) | ||
1004 | { | 973 | { |
1005 | struct mem_cgroup *memcg = NULL; | 974 | struct mem_cgroup *memcg = NULL; |
1006 | struct mem_cgroup *last_visited = NULL; | 975 | struct mem_cgroup *last_visited = NULL; |
1007 | 976 | ||
1008 | if (mem_cgroup_disabled()) { | 977 | if (mem_cgroup_disabled()) |
1009 | /* first call must return non-NULL, second return NULL */ | 978 | return NULL; |
1010 | return (struct mem_cgroup *)(unsigned long)!prev; | ||
1011 | } | ||
1012 | 979 | ||
1013 | if (!root) | 980 | if (!root) |
1014 | root = root_mem_cgroup; | 981 | root = root_mem_cgroup; |
@@ -1019,9 +986,7 @@ struct mem_cgroup *mem_cgroup_iter_cond(struct mem_cgroup *root, | |||
1019 | if (!root->use_hierarchy && root != root_mem_cgroup) { | 986 | if (!root->use_hierarchy && root != root_mem_cgroup) { |
1020 | if (prev) | 987 | if (prev) |
1021 | goto out_css_put; | 988 | goto out_css_put; |
1022 | if (mem_cgroup_filter(root, root, cond) == VISIT) | 989 | return root; |
1023 | return root; | ||
1024 | return NULL; | ||
1025 | } | 990 | } |
1026 | 991 | ||
1027 | rcu_read_lock(); | 992 | rcu_read_lock(); |
@@ -1044,7 +1009,7 @@ struct mem_cgroup *mem_cgroup_iter_cond(struct mem_cgroup *root, | |||
1044 | last_visited = mem_cgroup_iter_load(iter, root, &seq); | 1009 | last_visited = mem_cgroup_iter_load(iter, root, &seq); |
1045 | } | 1010 | } |
1046 | 1011 | ||
1047 | memcg = __mem_cgroup_iter_next(root, last_visited, cond); | 1012 | memcg = __mem_cgroup_iter_next(root, last_visited); |
1048 | 1013 | ||
1049 | if (reclaim) { | 1014 | if (reclaim) { |
1050 | mem_cgroup_iter_update(iter, last_visited, memcg, seq); | 1015 | mem_cgroup_iter_update(iter, last_visited, memcg, seq); |
@@ -1055,11 +1020,7 @@ struct mem_cgroup *mem_cgroup_iter_cond(struct mem_cgroup *root, | |||
1055 | reclaim->generation = iter->generation; | 1020 | reclaim->generation = iter->generation; |
1056 | } | 1021 | } |
1057 | 1022 | ||
1058 | /* | 1023 | if (prev && !memcg) |
1059 | * We have finished the whole tree walk or no group has been | ||
1060 | * visited because filter told us to skip the root node. | ||
1061 | */ | ||
1062 | if (!memcg && (prev || (cond && !last_visited))) | ||
1063 | goto out_unlock; | 1024 | goto out_unlock; |
1064 | } | 1025 | } |
1065 | out_unlock: | 1026 | out_unlock: |
@@ -1804,14 +1765,13 @@ int mem_cgroup_select_victim_node(struct mem_cgroup *memcg) | |||
1804 | * a) it is over its soft limit | 1765 | * a) it is over its soft limit |
1805 | * b) any parent up the hierarchy is over its soft limit | 1766 | * b) any parent up the hierarchy is over its soft limit |
1806 | */ | 1767 | */ |
1807 | enum mem_cgroup_filter_t | 1768 | bool mem_cgroup_soft_reclaim_eligible(struct mem_cgroup *memcg, |
1808 | mem_cgroup_soft_reclaim_eligible(struct mem_cgroup *memcg, | ||
1809 | struct mem_cgroup *root) | 1769 | struct mem_cgroup *root) |
1810 | { | 1770 | { |
1811 | struct mem_cgroup *parent = memcg; | 1771 | struct mem_cgroup *parent = memcg; |
1812 | 1772 | ||
1813 | if (res_counter_soft_limit_excess(&memcg->res)) | 1773 | if (res_counter_soft_limit_excess(&memcg->res)) |
1814 | return VISIT; | 1774 | return true; |
1815 | 1775 | ||
1816 | /* | 1776 | /* |
1817 | * If any parent up to the root in the hierarchy is over its soft limit | 1777 | * If any parent up to the root in the hierarchy is over its soft limit |
@@ -1819,12 +1779,12 @@ mem_cgroup_soft_reclaim_eligible(struct mem_cgroup *memcg, | |||
1819 | */ | 1779 | */ |
1820 | while ((parent = parent_mem_cgroup(parent))) { | 1780 | while ((parent = parent_mem_cgroup(parent))) { |
1821 | if (res_counter_soft_limit_excess(&parent->res)) | 1781 | if (res_counter_soft_limit_excess(&parent->res)) |
1822 | return VISIT; | 1782 | return true; |
1823 | if (parent == root) | 1783 | if (parent == root) |
1824 | break; | 1784 | break; |
1825 | } | 1785 | } |
1826 | 1786 | ||
1827 | return SKIP; | 1787 | return false; |
1828 | } | 1788 | } |
1829 | 1789 | ||
1830 | static DEFINE_SPINLOCK(memcg_oom_lock); | 1790 | static DEFINE_SPINLOCK(memcg_oom_lock); |
diff --git a/mm/vmscan.c b/mm/vmscan.c index cdd300b81485..17a7134de4d7 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -2185,16 +2185,21 @@ __shrink_zone(struct zone *zone, struct scan_control *sc, bool soft_reclaim) | |||
2185 | .zone = zone, | 2185 | .zone = zone, |
2186 | .priority = sc->priority, | 2186 | .priority = sc->priority, |
2187 | }; | 2187 | }; |
2188 | struct mem_cgroup *memcg = NULL; | 2188 | struct mem_cgroup *memcg; |
2189 | mem_cgroup_iter_filter filter = (soft_reclaim) ? | ||
2190 | mem_cgroup_soft_reclaim_eligible : NULL; | ||
2191 | 2189 | ||
2192 | nr_reclaimed = sc->nr_reclaimed; | 2190 | nr_reclaimed = sc->nr_reclaimed; |
2193 | nr_scanned = sc->nr_scanned; | 2191 | nr_scanned = sc->nr_scanned; |
2194 | 2192 | ||
2195 | while ((memcg = mem_cgroup_iter_cond(root, memcg, &reclaim, filter))) { | 2193 | memcg = mem_cgroup_iter(root, NULL, &reclaim); |
2194 | do { | ||
2196 | struct lruvec *lruvec; | 2195 | struct lruvec *lruvec; |
2197 | 2196 | ||
2197 | if (soft_reclaim && | ||
2198 | !mem_cgroup_soft_reclaim_eligible(memcg, root)) { | ||
2199 | memcg = mem_cgroup_iter(root, memcg, &reclaim); | ||
2200 | continue; | ||
2201 | } | ||
2202 | |||
2198 | lruvec = mem_cgroup_zone_lruvec(zone, memcg); | 2203 | lruvec = mem_cgroup_zone_lruvec(zone, memcg); |
2199 | 2204 | ||
2200 | shrink_lruvec(lruvec, sc); | 2205 | shrink_lruvec(lruvec, sc); |
@@ -2214,7 +2219,8 @@ __shrink_zone(struct zone *zone, struct scan_control *sc, bool soft_reclaim) | |||
2214 | mem_cgroup_iter_break(root, memcg); | 2219 | mem_cgroup_iter_break(root, memcg); |
2215 | break; | 2220 | break; |
2216 | } | 2221 | } |
2217 | } | 2222 | memcg = mem_cgroup_iter(root, memcg, &reclaim); |
2223 | } while (memcg); | ||
2218 | 2224 | ||
2219 | vmpressure(sc->gfp_mask, sc->target_mem_cgroup, | 2225 | vmpressure(sc->gfp_mask, sc->target_mem_cgroup, |
2220 | sc->nr_scanned - nr_scanned, | 2226 | sc->nr_scanned - nr_scanned, |