Skip to contentSkip to conversation

memcg: add support for hwpoison testing

RFC PATCH In review Wu Fengguang 3 participants 15 messages Aug 31, 2009 – Sep 2, 2009

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

cover memcg: add support for hwpoison testing

Hi all,

In hardware poison testing, we want to inject hwpoison errors to pages of a collection of selected tasks, so that random tasks (eg. init) won't be killed in stress tests and lead to test failure.

Memory cgroup provides an ideal tool for tracking and testing these target process pages. All we have to do is to
- export the memory cgroup id via cgroupfs
- export two functions/structs for hwpoison_inject.c

This might be an unexpected usage of memory cgroup. The last patch and this script demonstrates how the exported interfaces are to be used to limit the scope of hwpoison injection.

	test -d /cgroup/hwpoison && rmdir /cgroup/hwpoison
	mkdir /cgroup/hwpoison

	usemem -m 100 -s 100 &   # eat 100MB and sleep 100s
	echo `pidof usemem` > /cgroup/hwpoison/tasks

==> memcg_id=$(</cgroup/hwpoison/memory.id)
==> echo $memcg_id > /debug/hwpoison/corrupt-filter-memcg

	# hwpoison all pfn
	pfn=0
	while true
	do      
		let pfn=pfn+1
		echo $pfn > /debug/hwpoison/corrupt-pfn
		if [ $? -ne 0 ]; then
			break
		fi
	done

Comments are welcome, thanks!

Cheers,
Fengguang

Signature · 5 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>
#2 lore raw

RFC PATCH 2/4 memcg: rename and export try_get_mem_cgroup_from_page()

The hwpoison injection code need to get the mem_cgroup from arbitrary page in order to check its css_id.

---
 include/linux/memcontrol.h |    6 ++++++
 mm/memcontrol.c            |   12 +++++-------
 2 files changed, 11 insertions(+), 7 deletions(-)
mm/memcontrol.c +5 -7
@@ -1385,25 +1385,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();
@@ -1415,6 +1412,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
@@ -1749,7 +1747,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;
Signature · 5 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>
#1 lore raw

RFC PATCH 1/4 memcg: show memory.id in cgroupfs

In reply to Wu Fengguang

The hwpoison test suite need to selectively inject hwpoison to some targeted task pages, and must not kill important system processes such as init.

The memory cgroup serves this purpose well. We can put the target processes under the control of a memory cgroup, tell the hwpoison injection code the id of that memory cgroup so that it will only poison pages associated with it.

---
 mm/memcontrol.c |    9 +++++++++
 1 file changed, 9 insertions(+)
mm/memcontrol.c +9 -0
@@ -2510,6 +2510,11 @@ mem_cgroup_get_recursive_idx_stat(struct
 	*val = d.val;
 }
 
+static u64 mem_cgroup_id_read(struct cgroup *cont, struct cftype *cft)
+{
+	return css_id(cgroup_subsys_state(cont, mem_cgroup_subsys_id));
+}
+
 static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft)
 {
 	struct mem_cgroup *mem = mem_cgroup_from_cont(cont);
@@ -2842,6 +2847,10 @@ static int mem_cgroup_swappiness_write(s
 
 static struct cftype mem_cgroup_files[] = {
 	{
+		.name = "id",
+		.read_u64 = mem_cgroup_id_read,
+	},
+	{
 		.name = "usage_in_bytes",
 		.private = MEMFILE_PRIVATE(_MEM, RES_USAGE),
 		.read_u64 = mem_cgroup_read,
Signature · 5 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>
#4 lore raw

RFC PATCH 4/4 HWPOISON: memory cgroup based hwpoison injection filtering

In reply to Wu Fengguang
---
 mm/hwpoison-inject.c |   37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)
mm/hwpoison-inject.c +37 -0
@@ -5,10 +5,13 @@
 #include <linux/mm.h>
 #include <linux/bootmem.h>
 #include <linux/pagemap.h>
+#include <linux/page_cgroup.h>
+#include <linux/cgroup.h>
 #include "internal.h"
 
 static struct dentry *hwpoison_dir;
 
+static u32 hwpoison_filter_memcg;
 static u32 hwpoison_filter_dev_major = ~0U;
 static u32 hwpoison_filter_dev_minor = ~0U;
 static u64 hwpoison_filter_flags_mask;
@@ -53,8 +56,37 @@ static int hwpoison_filter_dev(struct pa
 	return 0;
 }
 
+static int hwpoison_filter_cg(struct page *p)
+{
+	struct mem_cgroup *mem;
+	struct cgroup_subsys_state *css;
+	int ret;
+
+	if (!hwpoison_filter_memcg)
+		return 0;
+
+	mem = try_get_mem_cgroup_from_page(p);
+	if (!mem)
+		return -EINVAL;
+
+	css = mem_cgroup_css(mem);
+	if (!css)
+		return -EINVAL;
+
+	if (css_id(css) != hwpoison_filter_memcg)
+		ret = -EINVAL;
+	else
+		ret = 0;
+
+	css_put(css);
+	return ret;
+}
+
 static int hwpoison_filter(struct page *p)
 {
+	if (hwpoison_filter_cg(p))
+		return 1;
+
 	if (hwpoison_filter_dev(p))
 		return -EINVAL;
 
@@ -119,6 +151,11 @@ static int pfn_inject_init(void)
 	if (!dentry)
 		goto fail;
 
+	dentry = debugfs_create_u32("corrupt-filter-memcg", 0600,
+				    hwpoison_dir, &hwpoison_filter_memcg);
+	if (!dentry)
+		goto fail;
+
 	dentry = debugfs_create_u32("corrupt-filter-dev-major", 0600,
 				    hwpoison_dir, &hwpoison_filter_dev_major);
 	if (!dentry)
Signature · 5 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

RFC PATCH 3/4 memcg: add accessor to mem_cgroup.css

In reply to Wu Fengguang

So that one can check its cgroup id and free the reference count grabbed by try_get_mem_cgroup_from_page().

---
 include/linux/memcontrol.h |    7 +++++++
 mm/memcontrol.c            |    6 ++++++
 2 files changed, 13 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 +6 -0
@@ -282,6 +282,12 @@ mem_cgroup_zoneinfo(struct mem_cgroup *m
 	return &mem->info.nodeinfo[nid]->zoneinfo[zid];
 }
 
+struct cgroup_subsys_state *mem_cgroup_css(struct mem_cgroup *mem)
+{
+	return &mem->css;
+}
+EXPORT_SYMBOL(mem_cgroup_css);
+
 static struct mem_cgroup_per_zone *
 page_cgroup_zoneinfo(struct page_cgroup *pc)
 {
Signature · 5 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>
#5 lore raw
In reply to Wu Fengguang
Quoted 35 lines · Wu Fengguang

Hi all,

In hardware poison testing, we want to inject hwpoison errors to pages of a collection of selected tasks, so that random tasks (eg. init) won't be killed in stress tests and lead to test failure.

Memory cgroup provides an ideal tool for tracking and testing these target process pages. All we have to do is to
- export the memory cgroup id via cgroupfs
- export two functions/structs for hwpoison_inject.c

This might be an unexpected usage of memory cgroup. The last patch and this script demonstrates how the exported interfaces are to be used to limit the scope of hwpoison injection.

	test -d /cgroup/hwpoison && rmdir /cgroup/hwpoison
	mkdir /cgroup/hwpoison

	usemem -m 100 -s 100 &   # eat 100MB and sleep 100s
	echo `pidof usemem` > /cgroup/hwpoison/tasks

==> memcg_id=$(</cgroup/hwpoison/memory.id)
==> echo $memcg_id > /debug/hwpoison/corrupt-filter-memcg

	# hwpoison all pfn
	pfn=0
	while true
	do      
		let pfn=pfn+1
		echo $pfn > /debug/hwpoison/corrupt-pfn
		if [ $? -ne 0 ]; then
			break
		fi
	done
Quoted 2 lines

Comments are welcome, thanks!

I took a quick look and the patches seem OKAY to me, but I have question, can't we do all of this from user space? The bits about id export and import the ids look like they can be replaced by names in user space.

Quoted 4 lines

Cheers,
Fengguang

Signature · 7 lines
	Balbir

--
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>
#6 lore raw
Quoted 37 lines · Balbir Singh
Quoted 35 lines · Wu Fengguang

Hi all,

In hardware poison testing, we want to inject hwpoison errors to pages of a collection of selected tasks, so that random tasks (eg. init) won't be killed in stress tests and lead to test failure.

Memory cgroup provides an ideal tool for tracking and testing these target process pages. All we have to do is to
- export the memory cgroup id via cgroupfs
- export two functions/structs for hwpoison_inject.c

This might be an unexpected usage of memory cgroup. The last patch and this script demonstrates how the exported interfaces are to be used to limit the scope of hwpoison injection.

	test -d /cgroup/hwpoison && rmdir /cgroup/hwpoison
	mkdir /cgroup/hwpoison

	usemem -m 100 -s 100 &   # eat 100MB and sleep 100s
	echo `pidof usemem` > /cgroup/hwpoison/tasks

==> memcg_id=$(</cgroup/hwpoison/memory.id)
==> echo $memcg_id > /debug/hwpoison/corrupt-filter-memcg

	# hwpoison all pfn
	pfn=0
	while true
	do      
		let pfn=pfn+1
		echo $pfn > /debug/hwpoison/corrupt-pfn
		if [ $? -ne 0 ]; then
			break
		fi
	done
Quoted 7 lines
Quoted 2 lines

Comments are welcome, thanks!

I took a quick look and the patches seem OKAY to me, but I have question, can't we do all of this from user space? The bits about id export and import the ids look like they can be replaced by names in user space.

You mean to match by cgrp->dentry->d_name.name in kernel hwpoison_inject.c and do this in user space?

DIR_NAME=hwpoison
mkdir /cgroup/$DIR_NAME
echo $DIR_NAME > /debug/hwpoison/corrupt-filter-memcg

Looks like a good idea!

Thanks,
Fengguang

#7 lore raw
In reply to Wu Fengguang
Quoted 24 lines · On Mon, 31 Aug 2009 18:26:40 +0800 Wu Fengguang <[email protected]> wrote:

Hi all,

In hardware poison testing, we want to inject hwpoison errors to pages of a collection of selected tasks, so that random tasks (eg. init) won't be killed in stress tests and lead to test failure.

Memory cgroup provides an ideal tool for tracking and testing these target process pages. All we have to do is to
- export the memory cgroup id via cgroupfs
- export two functions/structs for hwpoison_inject.c

This might be an unexpected usage of memory cgroup. The last patch and this script demonstrates how the exported interfaces are to be used to limit the scope of hwpoison injection.

	test -d /cgroup/hwpoison && rmdir /cgroup/hwpoison
	mkdir /cgroup/hwpoison

	usemem -m 100 -s 100 &   # eat 100MB and sleep 100s
	echo `pidof usemem` > /cgroup/hwpoison/tasks

==> memcg_id=$(</cgroup/hwpoison/memory.id)
==> echo $memcg_id > /debug/hwpoison/corrupt-filter-memcg

Quoted 11 lines
	# hwpoison all pfn
	pfn=0
	while true
	do      
		let pfn=pfn+1
		echo $pfn > /debug/hwpoison/corrupt-pfn
		if [ $? -ne 0 ]; then
			break
		fi
	done

I don't like this.

1. plz put all under CONFIG_DEBUG_HWPOISON or some
2. plz don't export memcg's id. you can do it without it.
3. If I was you, just adds following file

memory.hwpoison_test
Then, if you allow test
#echo 1 > memory.hwpoison_test

4. I can't understand why you need this. I wonder you can get pfn via /proc/<pid>/????. And this may insert HWPOISON to page-cache of shared library and "unexpected" process will be poisoned.

Thanks,
-Kame

Quoted 12 lines

Comments are welcome, thanks!

Cheers,
Fengguang

Signature · 5 lines
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

--
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>

#8 lore raw
Quoted 39 lines · KAMEZAWA Hiroyuki
Quoted 24 lines · On Mon, 31 Aug 2009 18:26:40 +0800 Wu Fengguang <[email protected]> wrote:

Hi all,

In hardware poison testing, we want to inject hwpoison errors to pages of a collection of selected tasks, so that random tasks (eg. init) won't be killed in stress tests and lead to test failure.

Memory cgroup provides an ideal tool for tracking and testing these target process pages. All we have to do is to
- export the memory cgroup id via cgroupfs
- export two functions/structs for hwpoison_inject.c

This might be an unexpected usage of memory cgroup. The last patch and this script demonstrates how the exported interfaces are to be used to limit the scope of hwpoison injection.

	test -d /cgroup/hwpoison && rmdir /cgroup/hwpoison
	mkdir /cgroup/hwpoison

	usemem -m 100 -s 100 &   # eat 100MB and sleep 100s
	echo `pidof usemem` > /cgroup/hwpoison/tasks

==> memcg_id=$(</cgroup/hwpoison/memory.id)
==> echo $memcg_id > /debug/hwpoison/corrupt-filter-memcg

Quoted 11 lines
	# hwpoison all pfn
	pfn=0
	while true
	do      
		let pfn=pfn+1
		echo $pfn > /debug/hwpoison/corrupt-pfn
		if [ $? -ne 0 ]; then
			break
		fi
	done
Quoted 4 lines

I don't like this.

1. plz put all under CONFIG_DEBUG_HWPOISON or some
2. plz don't export memcg's id. you can do it without it.

No problem.

My intention was, as memcg users grow in future, the export of memcg functions and maybe its id will be generally useful then.

Matching by memcg dir name is acceptable for our case, however won't be suitable for general use: there are file name uniqueness, string escaping and efficiency issues.

Quoted 5 lines

3. If I was you, just adds following file

memory.hwpoison_test
Then, if you allow test
#echo 1 > memory.hwpoison_test

No that would look ugly in the long term. I'd rather go for dir name matching for now.

Quoted 3 lines

4. I can't understand why you need this. I wonder you can get pfn via /proc/<pid>/????. And this may insert HWPOISON to page-cache of shared library and "unexpected" process will be poisoned.

Sorry I should have explained this. It's mainly for correctness. When a user space tool queries the task PFNs in /proc/pid/pagemap and then send to /debug/hwpoison/corrupt-pfn, there is a racy window that the page could be reclaimed and allocated by some one else. It would be awkward to try to pin the pages in user space. So we need the guarantees provided by /debug/hwpoison/corrupt-filter-memcg, which will be checked inside the page lock with elevated reference count.

Thanks,
Fengguang

--
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>

#9 lore raw
Quoted 4 lines · On Tue, 1 Sep 2009 10:25:14 +0800 Wu Fengguang <[email protected]> wrote:
Quoted 3 lines

4. I can't understand why you need this. I wonder you can get pfn via /proc/<pid>/????. And this may insert HWPOISON to page-cache of shared library and "unexpected" process will be poisoned.

Quoted 8 lines

Sorry I should have explained this. It's mainly for correctness. When a user space tool queries the task PFNs in /proc/pid/pagemap and then send to /debug/hwpoison/corrupt-pfn, there is a racy window that the page could be reclaimed and allocated by some one else. It would be awkward to try to pin the pages in user space. So we need the guarantees provided by /debug/hwpoison/corrupt-filter-memcg, which will be checked inside the page lock with elevated reference count.

memcg never holds refcnt for a page and the kernel::vmscan.c can reclaim any pages under memcg whithout checking anything related to memcg. *And*, your code has no "pin" code.
This patch sed does no jobs for your concern.

I recommend you to add
/debug/hwpoizon/pin-pfn

Then,
echo pfn > /debug/hwpoizon/pin-pfn
# add pfn for hwpoison debug's watch list. and elevate refcnt check 'pfn' is still used.
echo pfn > /debug/hwpoison/corrupt-pfn

	# check 'watch list' and make it corrupt and release refcnt.
or some.

memcg is not for pinning a page and never do such.

Thanks,
-Kame

#10 lore raw
Quoted 15 lines · KAMEZAWA Hiroyuki
Quoted 4 lines · On Tue, 1 Sep 2009 10:25:14 +0800 Wu Fengguang <[email protected]> wrote:
Quoted 3 lines

4. I can't understand why you need this. I wonder you can get pfn via /proc/<pid>/????. And this may insert HWPOISON to page-cache of shared library and "unexpected" process will be poisoned.

Quoted 8 lines

Sorry I should have explained this. It's mainly for correctness. When a user space tool queries the task PFNs in /proc/pid/pagemap and then send to /debug/hwpoison/corrupt-pfn, there is a racy window that the page could be reclaimed and allocated by some one else. It would be awkward to try to pin the pages in user space. So we need the guarantees provided by /debug/hwpoison/corrupt-filter-memcg, which will be checked inside the page lock with elevated reference count.

Quoted 4 lines

memcg never holds refcnt for a page and the kernel::vmscan.c can reclaim any pages under memcg whithout checking anything related to memcg. *And*, your code has no "pin" code.
This patch sed does no jobs for your concern.

We grabbed page here, which is not in the scope of this patchset:

        static int try_memory_failure(unsigned long pfn)
        {      
                struct page *p;
                int res = -EINVAL;

                if (!pfn_valid(pfn))
                        return res;

                p = pfn_to_page(pfn);
                if (!get_page_unless_zero(compound_head(p)))
                        return res;

                lock_page_nosync(compound_head(p));

                if (hwpoison_filter(p))
                        goto out;

                res = __memory_failure(pfn, 18,
                                       MEMORY_FAILURE_FLAG_COUNTED |
                                       MEMORY_FAILURE_FLAG_LOCKED);
        out:
                unlock_page(p);
                return res;
        }
Quoted 10 lines

I recommend you to add
/debug/hwpoizon/pin-pfn

Then,
echo pfn > /debug/hwpoizon/pin-pfn
# add pfn for hwpoison debug's watch list. and elevate refcnt check 'pfn' is still used.
echo pfn > /debug/hwpoison/corrupt-pfn

	# check 'watch list' and make it corrupt and release refcnt.
or some.

Looks like a good alternative. At least no more memcg dependency..

Cheers,
Fengguang

--
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>

#11 lore raw
Quoted 40 lines · On Tue, 1 Sep 2009 14:46:52 +0800 Wu Fengguang <[email protected]> wrote:
Quoted 15 lines · KAMEZAWA Hiroyuki
Quoted 4 lines · On Tue, 1 Sep 2009 10:25:14 +0800 Wu Fengguang <[email protected]> wrote:
Quoted 3 lines

4. I can't understand why you need this. I wonder you can get pfn via /proc/<pid>/????. And this may insert HWPOISON to page-cache of shared library and "unexpected" process will be poisoned.

Quoted 8 lines

Sorry I should have explained this. It's mainly for correctness. When a user space tool queries the task PFNs in /proc/pid/pagemap and then send to /debug/hwpoison/corrupt-pfn, there is a racy window that the page could be reclaimed and allocated by some one else. It would be awkward to try to pin the pages in user space. So we need the guarantees provided by /debug/hwpoison/corrupt-filter-memcg, which will be checked inside the page lock with elevated reference count.

Quoted 4 lines

memcg never holds refcnt for a page and the kernel::vmscan.c can reclaim any pages under memcg whithout checking anything related to memcg. *And*, your code has no "pin" code.
This patch sed does no jobs for your concern.

We grabbed page here, which is not in the scope of this patchset:

        static int try_memory_failure(unsigned long pfn)
        {      
                struct page *p;
                int res = -EINVAL;

                if (!pfn_valid(pfn))
                        return res;

                p = pfn_to_page(pfn);
                if (!get_page_unless_zero(compound_head(p)))
                        return res;

                lock_page_nosync(compound_head(p));

                if (hwpoison_filter(p))
                        goto out;
Quoted 7 lines
                res = __memory_failure(pfn, 18,
                                       MEMORY_FAILURE_FLAG_COUNTED |
                                       MEMORY_FAILURE_FLAG_LOCKED);
        out:
                unlock_page(p);
                return res;
        }

Hmm. maybe off-topic but why lock_page() is necessary ?

Quoted 11 lines
Quoted 10 lines

I recommend you to add
/debug/hwpoizon/pin-pfn

Then,
echo pfn > /debug/hwpoizon/pin-pfn
# add pfn for hwpoison debug's watch list. and elevate refcnt check 'pfn' is still used.
echo pfn > /debug/hwpoison/corrupt-pfn

	# check 'watch list' and make it corrupt and release refcnt.
or some.
Quoted 2 lines

Looks like a good alternative. At least no more memcg dependency..

My point is that memcg can show 'owner' of pages but the page may be shared with something important task _and_ if a task is migrated, its pages' memcg information is not updated now. Then, you can kill a task which is not in memcg.

Then, I don't recommend to use memcg. I think you'll see too much pitfalls.

Thanks,
-Kame

#12 lore raw
Quoted 51 lines · KAMEZAWA Hiroyuki
Quoted 40 lines · On Tue, 1 Sep 2009 14:46:52 +0800 Wu Fengguang <[email protected]> wrote:
Quoted 15 lines · KAMEZAWA Hiroyuki
Quoted 4 lines · On Tue, 1 Sep 2009 10:25:14 +0800 Wu Fengguang <[email protected]> wrote:
Quoted 3 lines

4. I can't understand why you need this. I wonder you can get pfn via /proc/<pid>/????. And this may insert HWPOISON to page-cache of shared library and "unexpected" process will be poisoned.

Quoted 8 lines

Sorry I should have explained this. It's mainly for correctness. When a user space tool queries the task PFNs in /proc/pid/pagemap and then send to /debug/hwpoison/corrupt-pfn, there is a racy window that the page could be reclaimed and allocated by some one else. It would be awkward to try to pin the pages in user space. So we need the guarantees provided by /debug/hwpoison/corrupt-filter-memcg, which will be checked inside the page lock with elevated reference count.

Quoted 4 lines

memcg never holds refcnt for a page and the kernel::vmscan.c can reclaim any pages under memcg whithout checking anything related to memcg. *And*, your code has no "pin" code.
This patch sed does no jobs for your concern.

We grabbed page here, which is not in the scope of this patchset:

        static int try_memory_failure(unsigned long pfn)
        {      
                struct page *p;
                int res = -EINVAL;

                if (!pfn_valid(pfn))
                        return res;

                p = pfn_to_page(pfn);
                if (!get_page_unless_zero(compound_head(p)))
                        return res;

                lock_page_nosync(compound_head(p));

                if (hwpoison_filter(p))
                        goto out;
Quoted 7 lines
                res = __memory_failure(pfn, 18,
                                       MEMORY_FAILURE_FLAG_COUNTED |
                                       MEMORY_FAILURE_FLAG_LOCKED);
        out:
                unlock_page(p);
                return res;
        }
Quoted 1 line

Hmm. maybe off-topic but why lock_page() is necessary ?

Because we also have filter for testing page flags, which requires lock_page() to be correct.

Quoted 12 lines
Quoted 12 lines
Quoted 11 lines

I recommend you to add
/debug/hwpoizon/pin-pfn

Then,
echo pfn > /debug/hwpoizon/pin-pfn
# add pfn for hwpoison debug's watch list. and elevate refcnt check 'pfn' is still used.
echo pfn > /debug/hwpoison/corrupt-pfn

	# check 'watch list' and make it corrupt and release refcnt.
or some.
Quoted 7 lines
Quoted 2 lines

Looks like a good alternative. At least no more memcg dependency..

My point is that memcg can show 'owner' of pages but the page may be shared with something important task _and_ if a task is migrated, its pages' memcg information is not updated now. Then, you can kill a task which is not in memcg.

Ah thanks! I'm not aware of that tricky fact, and it does make a very good reason not to use memcg, although I guess locked page won't be migrated.

Quoted 2 lines

Then, I don't recommend to use memcg. I think you'll see too much pitfalls.

Thanks,
Fengguang

--
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>

#13 lore raw
Quoted 9 lines · Wu Fengguang
Quoted 4 lines

My point is that memcg can show 'owner' of pages but the page may be shared with something important task _and_ if a task is migrated, its pages' memcg information is not updated now. Then, you can kill a task which is not in memcg.

Ah thanks! I'm not aware of that tricky fact, and it does make a very good reason not to use memcg, although I guess locked page won't be migrated.

I think what Kamezawa-San is pointing to is that the task can migrate, leaving behind the page in the memcg and poisioning those pages can kill a task outside the memcg.

Signature · 1 line
	Balbir
#14 lore raw
Quoted 7 lines · Balbir Singh
Quoted 5 lines · Wu Fengguang
Quoted 4 lines

My point is that memcg can show 'owner' of pages but the page may be shared with something important task _and_ if a task is migrated, its pages' memcg information is not updated now. Then, you can kill a task which is not in memcg.

Quoted 8 lines
Quoted 4 lines

Ah thanks! I'm not aware of that tricky fact, and it does make a very good reason not to use memcg, although I guess locked page won't be migrated.

I think what Kamezawa-San is pointing to is that the task can migrate, leaving behind the page in the memcg and poisioning those pages can kill a task outside the memcg.

Yeah Kame's words reminded me of the memcg goal: it may not have to track task pages 100% accurately for all the tricky racy windows/cases. So could be risky to use memcg for hwpoison testing.

Otherwise I felt like using memcg for hwpoison testing because the exported things are not that bad, and our hwpoison stress testing efforts may also be very good exercises to some aspects of memcg ;)

Back to the page sharing problem. For hwpoison testing, it is acceptable for the test program and the init process to share _clean_ libc.so pages. Because the hwpoison of such pages can be recovered gracefully by simply unmap and drop the hwpoisoned ones.

But if two tasks share some dirty pages (eg. shmem), then it could be killing more tasks than expected. However
- this is a general problem independent the use of memcg
- could be avoided by checking page dirtiness and map count
- our test schemes simply won't try to create such insane conditions (It will include both tasks as the target.)

btw, hwpoison testing also allows "mis-killing" of no-owner pages (ie. newly freed pages by the target task in some racy windows) which won't affect the test correctness.

Thanks,
Fengguang

--
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>