[Devel] [PATCH rh7 v2 1/3] memcg: add page_cgroup_ino helper
Vladimir Davydov
vdavydov at parallels.com
Mon May 18 04:33:32 PDT 2015
Hwpoison allows to filter pages by memory cgroup ino. To ahieve that, it
calls try_get_mem_cgroup_from_page(), then mem_cgroup_css(), and finally
extracts the inode number from the cgroup returned. This looks bulky.
Since in the next patch I need to get the ino of the memory cgroup a
page is charged to too, in this patch I introduce the page_cgroup_ino()
helper.
Note that page_cgroup_ino() only considers those pages that are charged
to mem_cgroup->res (i.e. page_cgroup->mem_cgroup != NULL), and for
others it returns 0, while try_get_mem_cgroup_page(), used by hwpoison
before, may extract the cgroup from a swapcache readahead page too.
Ignoring swapcache readahead pages allows to call page_cgroup_ino() on
unlocked pages, which is nice. Hwpoison users will hardly see any
difference.
Signed-off-by: Vladimir Davydov <vdavydov at parallels.com>
---
include/linux/memcontrol.h | 3 +++
mm/hwpoison-inject.c | 3 ---
mm/memcontrol.c | 22 ++++++++++++++++++++++
mm/memory-failure.c | 18 +-----------------
4 files changed, 26 insertions(+), 20 deletions(-)
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 675b4c517200..5507be5af34f 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -200,6 +200,9 @@ void mem_cgroup_split_huge_fixup(struct page *head);
bool mem_cgroup_bad_page_check(struct page *page);
void mem_cgroup_print_bad_page(struct page *page);
#endif
+
+unsigned long page_cgroup_ino(struct page *page);
+
#else /* CONFIG_MEMCG */
struct mem_cgroup;
diff --git a/mm/hwpoison-inject.c b/mm/hwpoison-inject.c
index 3a61efc518d5..bd580f803f5c 100644
--- a/mm/hwpoison-inject.c
+++ b/mm/hwpoison-inject.c
@@ -44,12 +44,9 @@ static int hwpoison_inject(void *data, u64 val)
/*
* do a racy check with elevated page count, to make sure PG_hwpoison
* will only be set for the targeted owner (or on a free page).
- * We temporarily take page lock for try_get_mem_cgroup_from_page().
* memory_failure() will redo the check reliably inside page lock.
*/
- lock_page(hpage);
err = hwpoison_filter(hpage);
- unlock_page(hpage);
if (err)
return 0;
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index e772a06b3f10..9dda309b8fae 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2877,6 +2877,28 @@ struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page)
return memcg;
}
+/**
+ * page_cgroup_ino - return inode number of page's memcg
+ * @page: the page
+ *
+ * Look up the memory cgroup @page is charged to and return its inode number.
+ * It is safe to call this function without taking a reference to the page.
+ */
+unsigned long page_cgroup_ino(struct page *page)
+{
+ struct mem_cgroup *memcg;
+ struct page_cgroup *pc;
+ unsigned long ino = 0;
+
+ pc = lookup_page_cgroup(page);
+ lock_page_cgroup(pc);
+ memcg = pc->mem_cgroup;
+ if (PageCgroupUsed(pc) && memcg)
+ ino = memcg->css.cgroup->dentry->d_inode->i_ino;
+ unlock_page_cgroup(pc);
+ return ino;
+}
+
static void __mem_cgroup_commit_charge(struct mem_cgroup *memcg,
struct page *page,
unsigned int nr_pages,
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 06f8d308c88f..b3b1a2d073f7 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -133,26 +133,10 @@ u64 hwpoison_filter_memcg;
EXPORT_SYMBOL_GPL(hwpoison_filter_memcg);
static int hwpoison_filter_task(struct page *p)
{
- struct mem_cgroup *mem;
- struct cgroup_subsys_state *css;
- unsigned long ino;
-
if (!hwpoison_filter_memcg)
return 0;
- mem = try_get_mem_cgroup_from_page(p);
- if (!mem)
- return -EINVAL;
-
- css = mem_cgroup_css(mem);
- /* root_mem_cgroup has NULL dentries */
- if (!css->cgroup->dentry)
- return -EINVAL;
-
- ino = css->cgroup->dentry->d_inode->i_ino;
- css_put(css);
-
- if (ino != hwpoison_filter_memcg)
+ if (page_cgroup_ino(p) != hwpoison_filter_memcg)
return -EINVAL;
return 0;
--
1.7.10.4
More information about the Devel
mailing list