Skip to contentSkip to conversation

memcg: rename and export try_get_mem_cgroup_from_page()

PATCH In review Wu Fengguang 2 participants 5 messages Sep 11, 2009 – Sep 12, 2009

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/2 memcg: rename and export try_get_mem_cgroup_from_page()

So that the hwpoison injector can get mem_cgroup for arbitrary page and thus know whether it is owned by some mem_cgroup task(s).

Background:

The hwpoison test suite need to inject hwpoison to a collection of selected task pages, and must not touch pages not owned by these pages and thus kill important system processes such as init. (But it's OK to mis-hwpoison free/unowned pages as well as shared clean pages. Mis-hwpoison of shared dirty pages will kill all tasks, so the test suite will target all or non of such tasks in the first place.)

The memory cgroup serves this purpose well. We can put the target processes under the control of a memory cgroup, and tell the hwpoison injection code to only kill pages associated with some active memory cgroup.

The prerequsite for doing hwpoison stress tests with mem_cgroup is, the mem_cgroup code tracks task pages _accurately_ (unless page is locked). Which we believe is/should be true.

The benifits are simplification of hwpoison injector code. Also the mem_cgroup code will automatically be tested by hwpoison test cases.

CC KOSAKI Motohiro <[email protected]>
CC Hugh Dickins <[email protected]>
CC Daisuke Nishimura <[email protected]>
CC Balbir Singh <[email protected]>
CC KAMEZAWA Hiroyuki <[email protected]>
---
 include/linux/memcontrol.h |    6 ++++++
 mm/memcontrol.c            |   12 +++++-------
 2 files changed, 11 insertions(+), 7 deletions(-)
mm/memcontrol.c +5 -7
@@ -1389,25 +1389,22 @@ static struct mem_cgroup *mem_cgroup_loo
 	return container_of(css, struct mem_cgroup, css);
 }
 
-static struct mem_cgroup *try_get_mem_cgroup_from_swapcache(struct page *page)
+struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page)
 {
-	struct mem_cgroup *mem;
+	struct mem_cgroup *mem = NULL;
 	struct page_cgroup *pc;
 	unsigned short id;
 	swp_entry_t ent;
 
 	VM_BUG_ON(!PageLocked(page));
 
-	if (!PageSwapCache(page))
-		return NULL;
-
 	pc = lookup_page_cgroup(page);
 	lock_page_cgroup(pc);
 	if (PageCgroupUsed(pc)) {
 		mem = pc->mem_cgroup;
 		if (mem && !css_tryget(&mem->css))
 			mem = NULL;
-	} else {
+	} else if (PageSwapCache(page)) {
 		ent.val = page_private(page);
 		id = lookup_swap_cgroup(ent);
 		rcu_read_lock();
@@ -1419,6 +1416,7 @@ static struct mem_cgroup *try_get_mem_cg
 	unlock_page_cgroup(pc);
 	return mem;
 }
+EXPORT_SYMBOL(try_get_mem_cgroup_from_page);
 
 /*
  * commit a charge got by __mem_cgroup_try_charge() and makes page_cgroup to be
@@ -1753,7 +1751,7 @@ int mem_cgroup_try_charge_swapin(struct 
 	 */
 	if (!PageSwapCache(page))
 		return 0;
-	mem = try_get_mem_cgroup_from_swapcache(page);
+	mem = try_get_mem_cgroup_from_page(page);
 	if (!mem)
 		goto charge_cur_mm;
 	*ptr = mem;
include/linux/memcontrol.h +6 -0
@@ -68,6 +68,7 @@ extern unsigned long mem_cgroup_isolate_
 extern void mem_cgroup_out_of_memory(struct mem_cgroup *mem, gfp_t gfp_mask);
 int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem);
 
+extern struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page);
 extern struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p);
 
 static inline
@@ -189,6 +190,11 @@ mem_cgroup_move_lists(struct page *page,
 {
 }
 
+static inline struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page)
+{
+	return NULL;
+}
+
 static inline int mm_match_cgroup(struct mm_struct *mm, struct mem_cgroup *mem)
 {
 	return 1;

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#1 lore raw

PATCH 2/2 memcg: add accessor to mem_cgroup.css

So that an outside user can free the reference count grabbed by try_get_mem_cgroup_from_page().

CC KOSAKI Motohiro <[email protected]>
CC Hugh Dickins <[email protected]>
CC Daisuke Nishimura <[email protected]>
CC Balbir Singh <[email protected]>
CC KAMEZAWA Hiroyuki <[email protected]>
---
 include/linux/memcontrol.h |    7 +++++++
 mm/memcontrol.c            |    8 ++++++++
 2 files changed, 15 insertions(+)
include/linux/memcontrol.h +7 -0
@@ -81,6 +81,8 @@ int mm_match_cgroup(const struct mm_stru
 	return cgroup == mem;
 }
 
+extern struct cgroup_subsys_state *mem_cgroup_css(struct mem_cgroup *mem);
+
 extern int
 mem_cgroup_prepare_migration(struct page *page, struct mem_cgroup **ptr);
 extern void mem_cgroup_end_migration(struct mem_cgroup *mem,
@@ -206,6 +208,11 @@ static inline int task_in_mem_cgroup(str
 	return 1;
 }
 
+static inline struct cgroup_subsys_state *mem_cgroup_css(struct mem_cgroup *mem)
+{
+	return NULL;
+}
+
 static inline int
 mem_cgroup_prepare_migration(struct page *page, struct mem_cgroup **ptr)
 {
mm/memcontrol.c +8 -0
@@ -282,6 +282,14 @@ mem_cgroup_zoneinfo(struct mem_cgroup *m
 	return &mem->info.nodeinfo[nid]->zoneinfo[zid];
 }
 
+#ifdef CONFIG_HWPOISON_INJECT /* for now, only user is hwpoison injector */
+struct cgroup_subsys_state *mem_cgroup_css(struct mem_cgroup *mem)
+{
+	return &mem->css;
+}
+EXPORT_SYMBOL(mem_cgroup_css);
+#endif
+
 static struct mem_cgroup_per_zone *
 page_cgroup_zoneinfo(struct page_cgroup *pc)
 {

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

Acked-by on v1 2/2
#2 lore raw

Re: [PATCH 2/2] memcg: add accessor to mem_cgroup.css

Quoted 3 lines · Wu Fengguang

So that an outside user can free the reference count grabbed by try_get_mem_cgroup_from_page().

While no heavy caller for this, I(we) would like to hide mem_cgroup under memcontrol.c
Personally, I like no #ifdef for this easy code ;)

Quoted 55 lines
CC KOSAKI Motohiro <[email protected]>
CC Hugh Dickins <[email protected]>
CC Daisuke Nishimura <[email protected]>
CC Balbir Singh <[email protected]>
CC KAMEZAWA Hiroyuki <[email protected]>
---
 include/linux/memcontrol.h |    7 +++++++
 mm/memcontrol.c            |    8 ++++++++
 2 files changed, 15 insertions(+)

--- linux-mm.orig/include/linux/memcontrol.h 2009-09-11 18:16:55.000000000
+0800
+++ linux-mm/include/linux/memcontrol.h 2009-09-11 18:16:56.000000000
+0800

include/linux/memcontrol.h +2 -0
@@ -81,6 +81,8 @@ int mm_match_cgroup(const struct mm_stru
 	return cgroup == mem;
 }
 
+extern struct cgroup_subsys_state *mem_cgroup_css(struct mem_cgroup
 *mem);
+
 extern int
 mem_cgroup_prepare_migration(struct page *page, struct mem_cgroup **ptr);

extern void mem_cgroup_end_migration(struct mem_cgroup *mem,

include/linux/memcontrol.h +5 -0
@@ -206,6 +208,11 @@ static inline int task_in_mem_cgroup(str
 	return 1;
 }
 
+static inline struct cgroup_subsys_state *mem_cgroup_css(struct
 mem_cgroup *mem)
+{
+	return NULL;
+}
+
 static inline int
 mem_cgroup_prepare_migration(struct page *page, struct mem_cgroup **ptr)

{

mm/memcontrol.c +8 -0
@@ -282,6 +282,14 @@ mem_cgroup_zoneinfo(struct mem_cgroup *m
 	return &mem->info.nodeinfo[nid]->zoneinfo[zid];
 }
 
+#ifdef CONFIG_HWPOISON_INJECT /* for now, only user is hwpoison injector
 */
+struct cgroup_subsys_state *mem_cgroup_css(struct mem_cgroup *mem)
+{
+	return &mem->css;
+}
+EXPORT_SYMBOL(mem_cgroup_css);
+#endif
+
 static struct mem_cgroup_per_zone *
 page_cgroup_zoneinfo(struct page_cgroup *pc)
Quoted 2 lines

{

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#3 lore raw
In reply to Wu Fengguang

[add CC to new Hugh; will update CC inside patch]

Hi Kame and Balbir,

After your previous reviews, I tried out the pin-pfn idea. It resulted in many code in both kernel and user space tools. So I (and Andi) decided that the complexity of tracking pin states is not worth it. It would be best to reuse the memcg functionalities for testing hwpoison. It is particular handy for some fork storm tests.

The change since the initial post is
- don't export the memcg id. we don't need it indeed, and can simply try to hwpoison *all* memcg tracked pages.
- generate mem_cgroup_css() code only for CONFIG_HWPOISON_INJECT

Thus no user visible changes and no extra code when hwpoison is disabled.

Thanks,
Fengguang

Quoted 95 lines · Wu Fengguang

So that the hwpoison injector can get mem_cgroup for arbitrary page and thus know whether it is owned by some mem_cgroup task(s).

Background:

The hwpoison test suite need to inject hwpoison to a collection of selected task pages, and must not touch pages not owned by these pages and thus kill important system processes such as init. (But it's OK to mis-hwpoison free/unowned pages as well as shared clean pages. Mis-hwpoison of shared dirty pages will kill all tasks, so the test suite will target all or non of such tasks in the first place.)

The memory cgroup serves this purpose well. We can put the target processes under the control of a memory cgroup, and tell the hwpoison injection code to only kill pages associated with some active memory cgroup.

The prerequsite for doing hwpoison stress tests with mem_cgroup is, the mem_cgroup code tracks task pages _accurately_ (unless page is locked). Which we believe is/should be true.

The benifits are simplification of hwpoison injector code. Also the mem_cgroup code will automatically be tested by hwpoison test cases.

CC KOSAKI Motohiro <[email protected]>
CC Hugh Dickins <[email protected]>
CC Daisuke Nishimura <[email protected]>
CC Balbir Singh <[email protected]>
CC KAMEZAWA Hiroyuki <[email protected]>
---
 include/linux/memcontrol.h |    6 ++++++
 mm/memcontrol.c            |   12 +++++-------
 2 files changed, 11 insertions(+), 7 deletions(-)
mm/memcontrol.c +5 -7
@@ -1389,25 +1389,22 @@ static struct mem_cgroup *mem_cgroup_loo
 	return container_of(css, struct mem_cgroup, css);
 }
 
-static struct mem_cgroup *try_get_mem_cgroup_from_swapcache(struct page *page)
+struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page)
 {
-	struct mem_cgroup *mem;
+	struct mem_cgroup *mem = NULL;
 	struct page_cgroup *pc;
 	unsigned short id;
 	swp_entry_t ent;
 
 	VM_BUG_ON(!PageLocked(page));
 
-	if (!PageSwapCache(page))
-		return NULL;
-
 	pc = lookup_page_cgroup(page);
 	lock_page_cgroup(pc);
 	if (PageCgroupUsed(pc)) {
 		mem = pc->mem_cgroup;
 		if (mem && !css_tryget(&mem->css))
 			mem = NULL;
-	} else {
+	} else if (PageSwapCache(page)) {
 		ent.val = page_private(page);
 		id = lookup_swap_cgroup(ent);
 		rcu_read_lock();
@@ -1419,6 +1416,7 @@ static struct mem_cgroup *try_get_mem_cg
 	unlock_page_cgroup(pc);
 	return mem;
 }
+EXPORT_SYMBOL(try_get_mem_cgroup_from_page);
 
 /*
  * commit a charge got by __mem_cgroup_try_charge() and makes page_cgroup to be
@@ -1753,7 +1751,7 @@ int mem_cgroup_try_charge_swapin(struct 
 	 */
 	if (!PageSwapCache(page))
 		return 0;
-	mem = try_get_mem_cgroup_from_swapcache(page);
+	mem = try_get_mem_cgroup_from_page(page);
 	if (!mem)
 		goto charge_cur_mm;
 	*ptr = mem;
include/linux/memcontrol.h +1 -0
@@ -68,6 +68,7 @@ extern unsigned long mem_cgroup_isolate_
 extern void mem_cgroup_out_of_memory(struct mem_cgroup *mem, gfp_t gfp_mask);
 int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem);
 
+extern struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page);
 extern struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p);
 
 static inline
@@ -189,6 +190,11 @@ mem_cgroup_move_lists(struct page *page,
 {

include/linux/memcontrol.h mem_cgroup_move_lists(struct page *page, · line 200

Quoted 10 lines
include/linux/memcontrol.h +5 -0
 }
 
+static inline struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page)
+{
+	return NULL;
+}
+
 static inline int mm_match_cgroup(struct mm_struct *mm, struct mem_cgroup *mem)
 {
 	return 1;

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

Acked-by on v1 1/2
#4 lore raw
In reply to Wu Fengguang
Quoted 3 lines · Wu Fengguang

So that the hwpoison injector can get mem_cgroup for arbitrary page and thus know whether it is owned by some mem_cgroup task(s).

I have no strong objections to these 2 patches.

But it's in merge-window. I recommend you to repost again with codes for caller(hwpoison itself).

-Kame

So if you

Quoted 109 lines

Background:

The hwpoison test suite need to inject hwpoison to a collection of selected task pages, and must not touch pages not owned by these pages and thus kill important system processes such as init. (But it's OK to mis-hwpoison free/unowned pages as well as shared clean pages. Mis-hwpoison of shared dirty pages will kill all tasks, so the test suite will target all or non of such tasks in the first place.)

The memory cgroup serves this purpose well. We can put the target processes under the control of a memory cgroup, and tell the hwpoison injection code to only kill pages associated with some active memory cgroup.

The prerequsite for doing hwpoison stress tests with mem_cgroup is, the mem_cgroup code tracks task pages _accurately_ (unless page is locked). Which we believe is/should be true.

The benifits are simplification of hwpoison injector code. Also the mem_cgroup code will automatically be tested by hwpoison test cases.

CC KOSAKI Motohiro <[email protected]>
CC Hugh Dickins <[email protected]>
CC Daisuke Nishimura <[email protected]>
CC Balbir Singh <[email protected]>
CC KAMEZAWA Hiroyuki <[email protected]>
---
 include/linux/memcontrol.h |    6 ++++++
 mm/memcontrol.c            |   12 +++++-------
 2 files changed, 11 insertions(+), 7 deletions(-)
mm/memcontrol.c +3 -6
@@ -1389,25 +1389,22 @@ static struct mem_cgroup *mem_cgroup_loo
 	return container_of(css, struct mem_cgroup, css);
 }
 
-static struct mem_cgroup *try_get_mem_cgroup_from_swapcache(struct page
 *page)
+struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page)
 {
-	struct mem_cgroup *mem;
+	struct mem_cgroup *mem = NULL;
 	struct page_cgroup *pc;
 	unsigned short id;
 	swp_entry_t ent;
 
 	VM_BUG_ON(!PageLocked(page));
 
-	if (!PageSwapCache(page))
-		return NULL;
-
 	pc = lookup_page_cgroup(page);
 	lock_page_cgroup(pc);
 	if (PageCgroupUsed(pc)) {
 		mem = pc->mem_cgroup;
 		if (mem && !css_tryget(&mem->css))
 			mem = NULL;
-	} else {
+	} else if (PageSwapCache(page)) {
 		ent.val = page_private(page);
 		id = lookup_swap_cgroup(ent);
mm/memcontrol.c +1 -0
 		rcu_read_lock();
@@ -1419,6 +1416,7 @@ static struct mem_cgroup *try_get_mem_cg
 	unlock_page_cgroup(pc);
 	return mem;
 }
+EXPORT_SYMBOL(try_get_mem_cgroup_from_page);
 
 /*
  * commit a charge got by __mem_cgroup_try_charge() and makes page_cgroup

to be

mm/memcontrol.c +5 -2
@@ -1753,7 +1751,7 @@ int mem_cgroup_try_charge_swapin(struct
 	 */
 	if (!PageSwapCache(page))
 		return 0;
-	mem = try_get_mem_cgroup_from_swapcache(page);
+	mem = try_get_mem_cgroup_from_page(page);
 	if (!mem)
 		goto charge_cur_mm;
 	*ptr = mem;
--- linux-mm.orig/include/linux/memcontrol.h	2009-09-11 18:51:13.000000000
+0800
+++ linux-mm/include/linux/memcontrol.h	2009-09-11 18:52:14.000000000
+0800
@@ -68,6 +68,7 @@ extern unsigned long mem_cgroup_isolate_
 extern void mem_cgroup_out_of_memory(struct mem_cgroup *mem, gfp_t
 gfp_mask);
 int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup
 *mem);
 
+extern struct mem_cgroup *try_get_mem_cgroup_from_page(struct page
 *page);

extern struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p);

static inline

mm/memcontrol.c +5 -0
@@ -189,6 +190,11 @@ mem_cgroup_move_lists(struct page *page,
 {
 }
 
+static inline struct mem_cgroup *try_get_mem_cgroup_from_page(struct page
 *page)
+{
+	return NULL;
+}
+
 static inline int mm_match_cgroup(struct mm_struct *mm, struct mem_cgroup
 *mem)
Quoted 3 lines

{
return 1;

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>