summaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
authorMichal Hocko <mhocko@suse.cz>2013-09-12 18:13:26 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-12 18:38:00 -0400
commitde57780dc659f95b17ccb649f003278dde0b5b86 (patch)
treed2493cc412c16946f3ead9158a61b26dd1f0c45a /include/linux
parenta5b7c87f92076352dbff2fe0423ec255e1c9a71b (diff)
memcg: enhance memcg iterator to support predicates
The caller of the iterator might know that some nodes or even subtrees should be skipped but there is no way to tell iterators about that so the only choice left is to let iterators to visit each node and do the selection outside of the iterating code. This, however, doesn't scale well with hierarchies with many groups where only few groups are interesting. This patch adds mem_cgroup_iter_cond variant of the iterator with a callback which gets called for every visited node. There are three possible ways how the callback can influence the walk. Either the node is visited, it is skipped but the tree walk continues down the tree or the whole subtree of the current group is skipped. [hughd@google.com: fix memcg-less page reclaim] Signed-off-by: Michal Hocko <mhocko@suse.cz> Cc: Balbir Singh <bsingharora@gmail.com> Cc: Glauber Costa <glommer@openvz.org> Cc: Greg Thelen <gthelen@google.com> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: Michel Lespinasse <walken@google.com> Cc: Tejun Heo <tj@kernel.org> Cc: Ying Han <yinghan@google.com> Signed-off-by: Hugh Dickins <hughd@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/memcontrol.h49
1 files changed, 43 insertions, 6 deletions
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index d8dd6560621b..d4d1f9b0dbba 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -41,6 +41,23 @@ struct mem_cgroup_reclaim_cookie {
41 unsigned int generation; 41 unsigned int generation;
42}; 42};
43 43
44enum mem_cgroup_filter_t {
45 VISIT, /* visit current node */
46 SKIP, /* skip the current node and continue traversal */
47 SKIP_TREE, /* skip the whole subtree and continue traversal */
48};
49
50/*
51 * mem_cgroup_filter_t predicate might instruct mem_cgroup_iter_cond how to
52 * iterate through the hierarchy tree. Each tree element is checked by the
53 * predicate before it is returned by the iterator. If a filter returns
54 * SKIP or SKIP_TREE then the iterator code continues traversal (with the
55 * next node down the hierarchy or the next node that doesn't belong under the
56 * memcg's subtree).
57 */
58typedef enum mem_cgroup_filter_t
59(*mem_cgroup_iter_filter)(struct mem_cgroup *memcg, struct mem_cgroup *root);
60
44#ifdef CONFIG_MEMCG 61#ifdef CONFIG_MEMCG
45/* 62/*
46 * All "charge" functions with gfp_mask should use GFP_KERNEL or 63 * All "charge" functions with gfp_mask should use GFP_KERNEL or
@@ -108,9 +125,18 @@ mem_cgroup_prepare_migration(struct page *page, struct page *newpage,
108extern void mem_cgroup_end_migration(struct mem_cgroup *memcg, 125extern void mem_cgroup_end_migration(struct mem_cgroup *memcg,
109 struct page *oldpage, struct page *newpage, bool migration_ok); 126 struct page *oldpage, struct page *newpage, bool migration_ok);
110 127
111struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *, 128struct mem_cgroup *mem_cgroup_iter_cond(struct mem_cgroup *root,
112 struct mem_cgroup *, 129 struct mem_cgroup *prev,
113 struct mem_cgroup_reclaim_cookie *); 130 struct mem_cgroup_reclaim_cookie *reclaim,
131 mem_cgroup_iter_filter cond);
132
133static inline struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *root,
134 struct mem_cgroup *prev,
135 struct mem_cgroup_reclaim_cookie *reclaim)
136{
137 return mem_cgroup_iter_cond(root, prev, reclaim, NULL);
138}
139
114void mem_cgroup_iter_break(struct mem_cgroup *, struct mem_cgroup *); 140void mem_cgroup_iter_break(struct mem_cgroup *, struct mem_cgroup *);
115 141
116/* 142/*
@@ -180,7 +206,8 @@ static inline void mem_cgroup_dec_page_stat(struct page *page,
180 mem_cgroup_update_page_stat(page, idx, -1); 206 mem_cgroup_update_page_stat(page, idx, -1);
181} 207}
182 208
183bool mem_cgroup_soft_reclaim_eligible(struct mem_cgroup *memcg, 209enum mem_cgroup_filter_t
210mem_cgroup_soft_reclaim_eligible(struct mem_cgroup *memcg,
184 struct mem_cgroup *root); 211 struct mem_cgroup *root);
185 212
186void __mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx); 213void __mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx);
@@ -295,6 +322,15 @@ static inline void mem_cgroup_end_migration(struct mem_cgroup *memcg,
295 struct page *oldpage, struct page *newpage, bool migration_ok) 322 struct page *oldpage, struct page *newpage, bool migration_ok)
296{ 323{
297} 324}
325static inline struct mem_cgroup *
326mem_cgroup_iter_cond(struct mem_cgroup *root,
327 struct mem_cgroup *prev,
328 struct mem_cgroup_reclaim_cookie *reclaim,
329 mem_cgroup_iter_filter cond)
330{
331 /* first call must return non-NULL, second return NULL */
332 return (struct mem_cgroup *)(unsigned long)!prev;
333}
298 334
299static inline struct mem_cgroup * 335static inline struct mem_cgroup *
300mem_cgroup_iter(struct mem_cgroup *root, 336mem_cgroup_iter(struct mem_cgroup *root,
@@ -358,10 +394,11 @@ static inline void mem_cgroup_dec_page_stat(struct page *page,
358} 394}
359 395
360static inline 396static inline
361bool mem_cgroup_soft_reclaim_eligible(struct mem_cgroup *memcg, 397enum mem_cgroup_filter_t
398mem_cgroup_soft_reclaim_eligible(struct mem_cgroup *memcg,
362 struct mem_cgroup *root) 399 struct mem_cgroup *root)
363{ 400{
364 return false; 401 return VISIT;
365} 402}
366 403
367static inline void mem_cgroup_split_huge_fixup(struct page *head) 404static inline void mem_cgroup_split_huge_fixup(struct page *head)