From: Matthew Wilcox <willy@infradead.org>
To: linux-mm@kvack.org
Cc: "Matthew Wilcox" <mawilcox@microsoft.com>,
"Andrew Morton" <akpm@linux-foundation.org>,
"Kirill A . Shutemov" <kirill.shutemov@linux.intel.com>,
"Christoph Lameter" <cl@linux.com>,
"Lai Jiangshan" <jiangshanlai@gmail.com>,
"Pekka Enberg" <penberg@kernel.org>,
"Vlastimil Babka" <vbabka@suse.cz>,
"Dave Hansen" <dave.hansen@linux.intel.com>,
"Jérôme Glisse" <jglisse@redhat.com>
Subject: [PATCH v5 17/17] mm: Distinguish VMalloc pages
Date: Fri, 4 May 2018 11:33:18 -0700 [thread overview]
Message-ID: <20180504183318.14415-18-willy@infradead.org> (raw)
In-Reply-To: <20180504183318.14415-1-willy@infradead.org>
From: Matthew Wilcox <mawilcox@microsoft.com>
For diagnosing various performance and memory-leak problems, it is helpful
to be able to distinguish pages which are in use as VMalloc pages.
Unfortunately, we cannot use the page_type field in struct page, as
this is in use for mapcount by some drivers which map vmalloced pages
to userspace.
Use a special page->mapping value to distinguish VMalloc pages from
other kinds of pages. Also record a pointer to the vm_struct and the
offset within the area in struct page to help reconstruct exactly what
this page is being used for.
Signed-off-by: Matthew Wilcox <mawilcox@microsoft.com>
---
fs/proc/page.c | 2 ++
include/linux/mm_types.h | 5 +++++
include/linux/page-flags.h | 25 +++++++++++++++++++++++++
include/uapi/linux/kernel-page-flags.h | 1 +
mm/vmalloc.c | 5 ++++-
tools/vm/page-types.c | 1 +
6 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/fs/proc/page.c b/fs/proc/page.c
index 792c78a49174..fc83dae1af7b 100644
--- a/fs/proc/page.c
+++ b/fs/proc/page.c
@@ -156,6 +156,8 @@ u64 stable_page_flags(struct page *page)
u |= 1 << KPF_BALLOON;
if (PageTable(page))
u |= 1 << KPF_PGTABLE;
+ if (PageVMalloc(page))
+ u |= 1 << KPF_VMALLOC;
if (page_is_idle(page))
u |= 1 << KPF_IDLE;
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index fa05e6ca31ed..199f43b50cf4 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -146,6 +146,11 @@ struct page {
spinlock_t ptl;
#endif
};
+ struct { /* VMalloc pages */
+ struct vm_struct *vm_area;
+ unsigned long vm_offset;
+ unsigned long _vm_id; /* MAPPING_VMalloc */
+ };
/** @rcu_head: You can use this to free a page by RCU. */
struct rcu_head rcu_head;
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 901943e4754b..5232433175c1 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -699,6 +699,31 @@ PAGE_TYPE_OPS(Kmemcg, kmemcg)
*/
PAGE_TYPE_OPS(Table, table)
+/*
+ * vmalloc pages may be mapped to userspace, so we need some other way
+ * to distinguish them from other kinds of pages. Use page->mapping
+ * for this purpose. Values below 0x1000 cannot be real pointers.
+ */
+#define MAPPING_VMalloc (void *)0x440
+
+#define PAGE_MAPPING_OPS(name) \
+static __always_inline int Page##name(struct page *page) \
+{ \
+ return page->mapping == MAPPING_##name; \
+} \
+static __always_inline void __SetPage##name(struct page *page) \
+{ \
+ VM_BUG_ON_PAGE(page->mapping != NULL, page); \
+ page->mapping = MAPPING_##name; \
+} \
+static __always_inline void __ClearPage##name(struct page *page) \
+{ \
+ VM_BUG_ON_PAGE(page->mapping != MAPPING_##name, page); \
+ page->mapping = NULL; \
+}
+
+PAGE_MAPPING_OPS(VMalloc)
+
extern bool is_free_buddy_page(struct page *page);
__PAGEFLAG(Isolated, isolated, PF_ANY);
diff --git a/include/uapi/linux/kernel-page-flags.h b/include/uapi/linux/kernel-page-flags.h
index 21b9113c69da..6800968b8f47 100644
--- a/include/uapi/linux/kernel-page-flags.h
+++ b/include/uapi/linux/kernel-page-flags.h
@@ -36,5 +36,6 @@
#define KPF_ZERO_PAGE 24
#define KPF_IDLE 25
#define KPF_PGTABLE 26
+#define KPF_VMALLOC 27
#endif /* _UAPILINUX_KERNEL_PAGE_FLAGS_H */
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 5fbf27e7f956..98bc690d472d 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -1535,7 +1535,7 @@ static void __vunmap(const void *addr, int deallocate_pages)
for (i = 0; i < area->nr_pages; i++) {
struct page *page = area->pages[i];
- BUG_ON(!page);
+ __ClearPageVMalloc(page);
__free_pages(page, 0);
}
@@ -1704,6 +1704,9 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
area->nr_pages = i;
goto fail;
}
+ __SetPageVMalloc(page);
+ page->vm_area = area;
+ page->vm_offset = i;
area->pages[i] = page;
if (gfpflags_allow_blocking(gfp_mask))
cond_resched();
diff --git a/tools/vm/page-types.c b/tools/vm/page-types.c
index cce853dca691..25cc21855be4 100644
--- a/tools/vm/page-types.c
+++ b/tools/vm/page-types.c
@@ -132,6 +132,7 @@ static const char * const page_flag_names[] = {
[KPF_THP] = "t:thp",
[KPF_BALLOON] = "o:balloon",
[KPF_PGTABLE] = "g:pgtable",
+ [KPF_VMALLOC] = "V:vmalloc",
[KPF_ZERO_PAGE] = "z:zero_page",
[KPF_IDLE] = "i:idle_page",
--
2.17.0
next prev parent reply other threads:[~2018-05-04 18:33 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-05-04 18:33 [PATCH v5 00/17] Rearrange struct page Matthew Wilcox
2018-05-04 18:33 ` [PATCH v5 01/17] s390: Use _refcount for pgtables Matthew Wilcox
2018-05-04 18:33 ` [PATCH v5 02/17] mm: Split page_type out from _mapcount Matthew Wilcox
2018-05-14 14:33 ` Vlastimil Babka
2018-05-04 18:33 ` [PATCH v5 03/17] mm: Mark pages in use for page tables Matthew Wilcox
2018-05-04 18:33 ` [PATCH v5 04/17] mm: Switch s_mem and slab_cache in struct page Matthew Wilcox
2018-05-07 14:58 ` Christopher Lameter
2018-05-14 14:37 ` Vlastimil Babka
2018-05-04 18:33 ` [PATCH v5 05/17] mm: Move 'private' union within " Matthew Wilcox
2018-05-04 18:33 ` [PATCH v5 06/17] mm: Move _refcount out of struct page union Matthew Wilcox
2018-05-04 18:33 ` [PATCH v5 07/17] mm: Combine first three unions in struct page Matthew Wilcox
2018-05-14 14:42 ` Vlastimil Babka
2018-05-04 18:33 ` [PATCH v5 08/17] mm: Use page->deferred_list Matthew Wilcox
2018-05-04 18:33 ` [PATCH v5 09/17] mm: Move lru union within struct page Matthew Wilcox
2018-05-04 18:33 ` [PATCH v5 10/17] mm: Combine LRU and main union in " Matthew Wilcox
2018-05-04 18:33 ` [PATCH v5 11/17] mm: Improve struct page documentation Matthew Wilcox
2018-05-15 9:22 ` Vlastimil Babka
2018-05-04 18:33 ` [PATCH v5 12/17] mm: Add pt_mm to struct page Matthew Wilcox
2018-05-15 9:27 ` Vlastimil Babka
2018-05-15 12:23 ` Matthew Wilcox
2018-05-04 18:33 ` [PATCH v5 13/17] mm: Add hmm_data " Matthew Wilcox
2018-05-15 9:32 ` Vlastimil Babka
2018-05-15 12:40 ` Vlastimil Babka
2018-05-04 18:33 ` [PATCH v5 14/17] slab,slub: Remove rcu_head size checks Matthew Wilcox
2018-05-15 11:30 ` Vlastimil Babka
2018-05-04 18:33 ` [PATCH v5 15/17] slub: Remove kmem_cache->reserved Matthew Wilcox
2018-05-04 18:33 ` [PATCH v5 16/17] slub: Remove 'reserved' file from sysfs Matthew Wilcox
2018-05-07 15:01 ` Christopher Lameter
2018-05-04 18:33 ` Matthew Wilcox [this message]
2018-05-04 20:52 ` [PATCH v5 00/17] Rearrange struct page Andrew Morton
2018-05-04 21:25 ` Matthew Wilcox
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180504183318.14415-18-willy@infradead.org \
--to=willy@infradead.org \
--cc=akpm@linux-foundation.org \
--cc=cl@linux.com \
--cc=dave.hansen@linux.intel.com \
--cc=jglisse@redhat.com \
--cc=jiangshanlai@gmail.com \
--cc=kirill.shutemov@linux.intel.com \
--cc=linux-mm@kvack.org \
--cc=mawilcox@microsoft.com \
--cc=penberg@kernel.org \
--cc=vbabka@suse.cz \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.