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 <vdavy...@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 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel