diff mbox series

[RFC,v2,3/3] mm, printk: introduce new format %pGt for page_type

Message ID 20221106140355.294845-4-42.hyeyoo@gmail.com (mailing list archive)
State New
Headers show
Series move PG_slab to page_type | expand

Commit Message

Hyeonggon Yoo Nov. 6, 2022, 2:03 p.m. UTC
dump_page() uses %pGp format to print 'flags' field of struct page.
As some page flags (e.g. PG_buddy, see page-flags.h for more details)
are set in page_type field, introduce %pGt format which provides
human readable output of page_type. And use it in dump_page().

Note that the sense of bits are different in page_type. if page_type is
0xffffffff, no flags are set. if PG_slab (0x00100000) flag is set,
page_type is 0xffefffff. Clearing a bit means we set the bit. Bits in
page_type are inverted when printing type names.

Below is examples of dump_page(). One is just after alloc_pages() and
the other is after __SetPageSlab().

[    1.814728] page:ffffea000415e200 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x105788
[    1.815961] flags: 0x17ffffc0000000(node=0|zone=2|lastcpupid=0x1fffff)
[    1.816443] page_type: 0xffffffff()
[    1.816704] raw: 0017ffffc0000000 0000000000000000 dead000000000122 0000000000000000
[    1.817291] raw: 0000000000000000 0000000000000000 00000001ffffffff 0000000000000000
[    1.817870] page dumped because: Before __SetPageSlab()

[    1.818258] page:ffffea000415e200 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x105788
[    1.818857] flags: 0x17ffffc0000000(node=0|zone=2|lastcpupid=0x1fffff)
[    1.819250] page_type: 0xffefffff(slab)
[    1.819483] raw: 0017ffffc0000000 0000000000000000 dead000000000122 0000000000000000
[    1.819947] raw: 0000000000000000 0000000000000000 00000001ffefffff 0000000000000000
[    1.820410] page dumped because: After __SetPageSlab()

Cc: Petr Mladek <pmladek@suse.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Sergey Senozhatsky <senozhatsky@chromium.org>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: linux-doc@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-mm@kvack.org
Signed-off-by: Hyeonggon Yoo <42.hyeyoo@gmail.com>
---
 Documentation/core-api/printk-formats.rst |  3 ++-
 lib/test_printf.c                         | 23 ++++++++++++++++++++++
 lib/vsprintf.c                            | 24 +++++++++++++++++++++++
 mm/debug.c                                |  7 +++++++
 mm/internal.h                             |  1 +
 5 files changed, 57 insertions(+), 1 deletion(-)

Comments

Joe Perches Nov. 6, 2022, 6:04 p.m. UTC | #1
On Sun, 2022-11-06 at 23:03 +0900, Hyeonggon Yoo wrote:
> dump_page() uses %pGp format to print 'flags' field of struct page.
> As some page flags (e.g. PG_buddy, see page-flags.h for more details)
> are set in page_type field, introduce %pGt format which provides
> human readable output of page_type. And use it in dump_page().
[]
> diff --git a/lib/vsprintf.c b/lib/vsprintf.c
[]
> @@ -2056,6 +2056,28 @@ char *format_page_flags(char *buf, char *end, unsigned long flags)
>  	return buf;
>  }
>  
> +static

noinline_for_stack ?

> +char *format_page_type(char *buf, char *end, unsigned int page_type)
> +{
> +	if (!(page_type & PAGE_TYPE_BASE))
> +		return string(buf, end, "no type for user-mapped page", default_str_spec);

Might be better with something like '%pGt: no type..."
Andy Shevchenko Nov. 7, 2022, 11:18 a.m. UTC | #2
On Sun, Nov 06, 2022 at 11:03:55PM +0900, Hyeonggon Yoo wrote:
> dump_page() uses %pGp format to print 'flags' field of struct page.
> As some page flags (e.g. PG_buddy, see page-flags.h for more details)
> are set in page_type field, introduce %pGt format which provides
> human readable output of page_type. And use it in dump_page().
> 
> Note that the sense of bits are different in page_type. if page_type is
> 0xffffffff, no flags are set. if PG_slab (0x00100000) flag is set,
> page_type is 0xffefffff. Clearing a bit means we set the bit. Bits in
> page_type are inverted when printing type names.
> 
> Below is examples of dump_page(). One is just after alloc_pages() and
> the other is after __SetPageSlab().
> 
> [    1.814728] page:ffffea000415e200 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x105788
> [    1.815961] flags: 0x17ffffc0000000(node=0|zone=2|lastcpupid=0x1fffff)

> [    1.816443] page_type: 0xffffffff()

Why do we have empty parentheses? I would expect either something there, or no
parentheses at all.

> [    1.816704] raw: 0017ffffc0000000 0000000000000000 dead000000000122 0000000000000000
> [    1.817291] raw: 0000000000000000 0000000000000000 00000001ffffffff 0000000000000000
> [    1.817870] page dumped because: Before __SetPageSlab()
> 
> [    1.818258] page:ffffea000415e200 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x105788
> [    1.818857] flags: 0x17ffffc0000000(node=0|zone=2|lastcpupid=0x1fffff)
> [    1.819250] page_type: 0xffefffff(slab)
> [    1.819483] raw: 0017ffffc0000000 0000000000000000 dead000000000122 0000000000000000
> [    1.819947] raw: 0000000000000000 0000000000000000 00000001ffefffff 0000000000000000
> [    1.820410] page dumped because: After __SetPageSlab()

> Cc: Petr Mladek <pmladek@suse.com>
> Cc: Steven Rostedt <rostedt@goodmis.org>
> Cc: Sergey Senozhatsky <senozhatsky@chromium.org>
> Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk>
> Cc: Jonathan Corbet <corbet@lwn.net>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: linux-doc@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Cc: linux-mm@kvack.org

Can you utilize --cc parameter next time and avoid polluting commit message
with this? We have archives where anybody can check this (and usually maintainers
add a Link tag for that purpose).

...

> +	%pGt	0xffefffff(slab)

No space before ( ?

...

> +static
> +char *format_page_type(char *buf, char *end, unsigned int page_type)
> +{
> +	if (!(page_type & PAGE_TYPE_BASE))
> +		return string(buf, end, "no type for user-mapped page", default_str_spec);

It's too long, can we make it shorten?

> +	buf = number(buf, end, page_type, default_flag_spec);
> +
> +	if (buf < end)
> +		*buf = '(';
> +	buf++;

> +	if (page_type_has_type(page_type))

This should be check for the entire function.

> +		buf = format_flags(buf, end, ~page_type, pagetype_names);
> +
> +	if (buf < end)
> +		*buf = ')';
> +	buf++;
> +
> +	return buf;
> +}

...

> @@ -36,6 +36,11 @@ const struct trace_print_flags pageflag_names[] = {
>  	{0, NULL}
>  };
>  
> +const struct trace_print_flags pagetype_names[] = {
> +	__def_pagetype_names,


> +	{0, NULL}

Hmm... I see it's already done like this above, but {}  would suffice, why not
to convert the rest first to the {} and use it here?

> +};

...

>  	pr_warn("%sflags: %pGp%s\n", type, &head->flags,
>  		page_cma ? " CMA" : "");
> +	pr_warn("page_type: %pGt\n", &head->page_type);
> +
>  	print_hex_dump(KERN_WARNING, "raw: ", DUMP_PREFIX_NONE, 32,
>  			sizeof(unsigned long), page,
>  			sizeof(struct page), false);
> diff --git a/mm/internal.h b/mm/internal.h
> index cb4c663a714e..956eaa9f12c0 100644
> --- a/mm/internal.h
> +++ b/mm/internal.h
> @@ -773,6 +773,7 @@ static inline void flush_tlb_batched_pending(struct mm_struct *mm)
>  #endif /* CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH */
>  
>  extern const struct trace_print_flags pageflag_names[];
> +extern const struct trace_print_flags pagetype_names[];
>  extern const struct trace_print_flags vmaflag_names[];
>  extern const struct trace_print_flags gfpflag_names[];

I would split this to a separate change, but it's up to PRINTK maintainers.
Petr Mladek Nov. 7, 2022, 2:20 p.m. UTC | #3
On Mon 2022-11-07 13:18:52, Andy Shevchenko wrote:
> On Sun, Nov 06, 2022 at 11:03:55PM +0900, Hyeonggon Yoo wrote:
> > dump_page() uses %pGp format to print 'flags' field of struct page.
> > As some page flags (e.g. PG_buddy, see page-flags.h for more details)
> > are set in page_type field, introduce %pGt format which provides
> > human readable output of page_type. And use it in dump_page().
> > 
> > Note that the sense of bits are different in page_type. if page_type is
> > 0xffffffff, no flags are set. if PG_slab (0x00100000) flag is set,
> > page_type is 0xffefffff. Clearing a bit means we set the bit. Bits in
> > page_type are inverted when printing type names.
> > 
> > Below is examples of dump_page(). One is just after alloc_pages() and
> > the other is after __SetPageSlab().
> > 
> > [    1.814728] page:ffffea000415e200 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x105788
> > [    1.815961] flags: 0x17ffffc0000000(node=0|zone=2|lastcpupid=0x1fffff)
> 
> > [    1.816443] page_type: 0xffffffff()
> 
> Why do we have empty parentheses? I would expect either something there, or no
> parentheses at all.

This looks fine. format_page_flags() does the same for %pGp.

> ...
> 
> > +	%pGt	0xffefffff(slab)
> 
> No space before ( ?

Also looks fine. %pGp does the same.

> ...
> 
> > +static
> > +char *format_page_type(char *buf, char *end, unsigned int page_type)
> > +{
> > +	if (!(page_type & PAGE_TYPE_BASE))
> > +		return string(buf, end, "no type for user-mapped page", default_str_spec);
> 
> It's too long, can we make it shorten?

I wonder if it would help to write the value. Something like:

      page_type: 0x0ace5768(no type)

That said. I am not familiar with the page types and am not sure
about the semantic of this value. MM people should decide what they
want to see in this case.

> ...
> 
> >  	pr_warn("%sflags: %pGp%s\n", type, &head->flags,
> >  		page_cma ? " CMA" : "");
> > +	pr_warn("page_type: %pGt\n", &head->page_type);
> > +
> >  	print_hex_dump(KERN_WARNING, "raw: ", DUMP_PREFIX_NONE, 32,
> >  			sizeof(unsigned long), page,
> >  			sizeof(struct page), false);
> > diff --git a/mm/internal.h b/mm/internal.h
> > index cb4c663a714e..956eaa9f12c0 100644
> > --- a/mm/internal.h
> > +++ b/mm/internal.h
> > @@ -773,6 +773,7 @@ static inline void flush_tlb_batched_pending(struct mm_struct *mm)
> >  #endif /* CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH */
> >  
> >  extern const struct trace_print_flags pageflag_names[];
> > +extern const struct trace_print_flags pagetype_names[];
> >  extern const struct trace_print_flags vmaflag_names[];
> >  extern const struct trace_print_flags gfpflag_names[];
> 
> I would split this to a separate change, but it's up to PRINTK maintainers.

I guess that you are talking about the line:

+	pr_warn("page_type: %pGt\n", &head->page_type);


Yes, it would be better to have implementation of %pGt modifier
in one patch and add the user in another one.

Best Regards,
Petr
Andy Shevchenko Nov. 7, 2022, 2:41 p.m. UTC | #4
On Mon, Nov 07, 2022 at 03:20:34PM +0100, Petr Mladek wrote:
> On Mon 2022-11-07 13:18:52, Andy Shevchenko wrote:
> > On Sun, Nov 06, 2022 at 11:03:55PM +0900, Hyeonggon Yoo wrote:
> > > dump_page() uses %pGp format to print 'flags' field of struct page.

...

> > > [    1.816443] page_type: 0xffffffff()
> > 
> > Why do we have empty parentheses? I would expect either something there, or no
> > parentheses at all.
> 
> This looks fine. format_page_flags() does the same for %pGp.

...

> > > +	%pGt	0xffefffff(slab)
> > 
> > No space before ( ?
> 
> Also looks fine. %pGp does the same.

Maybe we can modify them before or after this change?
Hyeonggon Yoo Nov. 9, 2022, 6:04 a.m. UTC | #5
On Mon, Nov 07, 2022 at 03:20:34PM +0100, Petr Mladek wrote:
> On Mon 2022-11-07 13:18:52, Andy Shevchenko wrote:
> > On Sun, Nov 06, 2022 at 11:03:55PM +0900, Hyeonggon Yoo wrote:
> > > dump_page() uses %pGp format to print 'flags' field of struct page.
> > > As some page flags (e.g. PG_buddy, see page-flags.h for more details)
> > > are set in page_type field, introduce %pGt format which provides
> > > human readable output of page_type. And use it in dump_page().
> > > 
> > > Note that the sense of bits are different in page_type. if page_type is
> > > 0xffffffff, no flags are set. if PG_slab (0x00100000) flag is set,
> > > page_type is 0xffefffff. Clearing a bit means we set the bit. Bits in
> > > page_type are inverted when printing type names.
> > > 
> > > Below is examples of dump_page(). One is just after alloc_pages() and
> > > the other is after __SetPageSlab().
> > > 
> > > [    1.814728] page:ffffea000415e200 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x105788
> > > [    1.815961] flags: 0x17ffffc0000000(node=0|zone=2|lastcpupid=0x1fffff)
> > 
> > > [    1.816443] page_type: 0xffffffff()
> > 


Thank you both for looking at this! :-)

> > Why do we have empty parentheses? I would expect either something there, or no
> > parentheses at all.
> 
> This looks fine. format_page_flags() does the same for %pGp.
> 
> > ...
> > 
> > > +	%pGt	0xffefffff(slab)
> > 
> > No space before ( ?
> 
> Also looks fine. %pGp does the same.
> 
> > ...
> > 
> > > +static
> > > +char *format_page_type(char *buf, char *end, unsigned int page_type)
> > > +{
> > > +	if (!(page_type & PAGE_TYPE_BASE))
> > > +		return string(buf, end, "no type for user-mapped page", default_str_spec);
> > 
> > It's too long, can we make it shorten?
> 
> I wonder if it would help to write the value. Something like:
> 
>       page_type: 0x0ace5768(no type)
>
> That said. I am not familiar with the page types and am not sure
> about the semantic of this value. MM people should decide what they
> want to see in this case.

Hmm, then for consistency let's try:

- 0xffefffff(slab)
- 0xffffffff()
- 0x0ace5768()

this way.

> > ...
> > 
> > >  	pr_warn("%sflags: %pGp%s\n", type, &head->flags,
> > >  		page_cma ? " CMA" : "");
> > > +	pr_warn("page_type: %pGt\n", &head->page_type);
> > > +
> > >  	print_hex_dump(KERN_WARNING, "raw: ", DUMP_PREFIX_NONE, 32,
> > >  			sizeof(unsigned long), page,
> > >  			sizeof(struct page), false);
> > > diff --git a/mm/internal.h b/mm/internal.h
> > > index cb4c663a714e..956eaa9f12c0 100644
> > > --- a/mm/internal.h
> > > +++ b/mm/internal.h
> > > @@ -773,6 +773,7 @@ static inline void flush_tlb_batched_pending(struct mm_struct *mm)
> > >  #endif /* CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH */
> > >  
> > >  extern const struct trace_print_flags pageflag_names[];
> > > +extern const struct trace_print_flags pagetype_names[];
> > >  extern const struct trace_print_flags vmaflag_names[];
> > >  extern const struct trace_print_flags gfpflag_names[];
> > 
> > I would split this to a separate change, but it's up to PRINTK maintainers.
> 
> I guess that you are talking about the line:
> 
> +	pr_warn("page_type: %pGt\n", &head->page_type);
> 
> 
> Yes, it would be better to have implementation of %pGt modifier
> in one patch and add the user in another one.

Sounds reasonable.
Will split its caller into another patch next to this one.
Hyeonggon Yoo Nov. 9, 2022, 6:14 a.m. UTC | #6
On Sun, Nov 06, 2022 at 10:04:25AM -0800, Joe Perches wrote:
> On Sun, 2022-11-06 at 23:03 +0900, Hyeonggon Yoo wrote:
> > dump_page() uses %pGp format to print 'flags' field of struct page.
> > As some page flags (e.g. PG_buddy, see page-flags.h for more details)
> > are set in page_type field, introduce %pGt format which provides
> > human readable output of page_type. And use it in dump_page().
> []
> > diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> []
> > @@ -2056,6 +2056,28 @@ char *format_page_flags(char *buf, char *end, unsigned long flags)
> >  	return buf;
> >  }
> >  
> > +static

Thanks for looking at this.

> 
> noinline_for_stack ?

May I ask why,
Does it have issues related to stack consumption?
To Be Honest I'm a bit unsure what is purpose of this attribute.

> > +char *format_page_type(char *buf, char *end, unsigned int page_type)
> > +{
> > +	if (!(page_type & PAGE_TYPE_BASE))
> > +		return string(buf, end, "no type for user-mapped page", default_str_spec);
> 
> Might be better with something like '%pGt: no type..."

Will try something like "0x32()" when it has no type because it is
mapped to userspace.
Petr Mladek Nov. 9, 2022, 8:13 a.m. UTC | #7
On Wed 2022-11-09 15:14:05, Hyeonggon Yoo wrote:
> On Sun, Nov 06, 2022 at 10:04:25AM -0800, Joe Perches wrote:
> > On Sun, 2022-11-06 at 23:03 +0900, Hyeonggon Yoo wrote:
> > > dump_page() uses %pGp format to print 'flags' field of struct page.
> > > As some page flags (e.g. PG_buddy, see page-flags.h for more details)
> > > are set in page_type field, introduce %pGt format which provides
> > > human readable output of page_type. And use it in dump_page().
> > []
> > > diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> > []
> > > @@ -2056,6 +2056,28 @@ char *format_page_flags(char *buf, char *end, unsigned long flags)
> > >  	return buf;
> > >  }
> > >  
> > > +static
> 
> Thanks for looking at this.
> 
> > 
> > noinline_for_stack ?

Honestly, I do not like much adding this without numbers. It has been added
to some functions in vsprintf.c long time ago because it reduced
the stack usage. But I think that it is a compiler and an architecture
specific. And it is not clear if it would really help in this
particular case.

Feel free to omit it.

Best Regards,
Petr
diff mbox series

Patch

diff --git a/Documentation/core-api/printk-formats.rst b/Documentation/core-api/printk-formats.rst
index dbe1aacc79d0..582e965508eb 100644
--- a/Documentation/core-api/printk-formats.rst
+++ b/Documentation/core-api/printk-formats.rst
@@ -575,12 +575,13 @@  The field width is passed by value, the bitmap is passed by reference.
 Helper macros cpumask_pr_args() and nodemask_pr_args() are available to ease
 printing cpumask and nodemask.
 
-Flags bitfields such as page flags, gfp_flags
+Flags bitfields such as page flags, page_type, gfp_flags
 ---------------------------------------------
 
 ::
 
 	%pGp	0x17ffffc0002036(referenced|uptodate|lru|active|private|node=0|zone=2|lastcpupid=0x1fffff)
+	%pGt	0xffefffff(slab)
 	%pGg	GFP_USER|GFP_DMA32|GFP_NOWARN
 	%pGv	read|exec|mayread|maywrite|mayexec|denywrite
 
diff --git a/lib/test_printf.c b/lib/test_printf.c
index fe13de1bed5f..6b778a8ea44c 100644
--- a/lib/test_printf.c
+++ b/lib/test_printf.c
@@ -654,12 +654,26 @@  page_flags_test(int section, int node, int zone, int last_cpupid,
 	test(cmp_buf, "%pGp", &flags);
 }
 
+static void __init page_type_test(unsigned int page_type, const char *name,
+				  char *cmp_buf)
+{
+	unsigned long size;
+
+	size = scnprintf(cmp_buf, BUF_SIZE, "%#x(", page_type);
+	if (page_type_has_type(page_type))
+		size += scnprintf(cmp_buf + size, BUF_SIZE - size, "%s", name);
+
+	snprintf(cmp_buf + size, BUF_SIZE - size, ")");
+	test(cmp_buf, "%pGt", &page_type);
+}
+
 static void __init
 flags(void)
 {
 	unsigned long flags;
 	char *cmp_buffer;
 	gfp_t gfp;
+	unsigned int page_type;
 
 	cmp_buffer = kmalloc(BUF_SIZE, GFP_KERNEL);
 	if (!cmp_buffer)
@@ -699,6 +713,15 @@  flags(void)
 	gfp |= __GFP_HIGH;
 	test(cmp_buffer, "%pGg", &gfp);
 
+	page_type = ~0;
+	page_type_test(page_type, "", cmp_buffer);
+
+	page_type = ~PG_slab;
+	page_type_test(page_type, "slab", cmp_buffer);
+
+	page_type = ~(PG_slab | PG_table | PG_buddy);
+	page_type_test(page_type, "slab|table|buddy", cmp_buffer);
+
 	kfree(cmp_buffer);
 }
 
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 24f37bab8bc1..d855b40e5cfd 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -2056,6 +2056,28 @@  char *format_page_flags(char *buf, char *end, unsigned long flags)
 	return buf;
 }
 
+static
+char *format_page_type(char *buf, char *end, unsigned int page_type)
+{
+	if (!(page_type & PAGE_TYPE_BASE))
+		return string(buf, end, "no type for user-mapped page", default_str_spec);
+
+	buf = number(buf, end, page_type, default_flag_spec);
+
+	if (buf < end)
+		*buf = '(';
+	buf++;
+
+	if (page_type_has_type(page_type))
+		buf = format_flags(buf, end, ~page_type, pagetype_names);
+
+	if (buf < end)
+		*buf = ')';
+	buf++;
+
+	return buf;
+}
+
 static noinline_for_stack
 char *flags_string(char *buf, char *end, void *flags_ptr,
 		   struct printf_spec spec, const char *fmt)
@@ -2069,6 +2091,8 @@  char *flags_string(char *buf, char *end, void *flags_ptr,
 	switch (fmt[1]) {
 	case 'p':
 		return format_page_flags(buf, end, *(unsigned long *)flags_ptr);
+	case 't':
+		return format_page_type(buf, end, *(unsigned int *)flags_ptr);
 	case 'v':
 		flags = *(unsigned long *)flags_ptr;
 		names = vmaflag_names;
diff --git a/mm/debug.c b/mm/debug.c
index 0fd15ba70d16..bb7f2278abc5 100644
--- a/mm/debug.c
+++ b/mm/debug.c
@@ -36,6 +36,11 @@  const struct trace_print_flags pageflag_names[] = {
 	{0, NULL}
 };
 
+const struct trace_print_flags pagetype_names[] = {
+	__def_pagetype_names,
+	{0, NULL}
+};
+
 const struct trace_print_flags gfpflag_names[] = {
 	__def_gfpflag_names,
 	{0, NULL}
@@ -114,6 +119,8 @@  static void __dump_page(struct page *page)
 
 	pr_warn("%sflags: %pGp%s\n", type, &head->flags,
 		page_cma ? " CMA" : "");
+	pr_warn("page_type: %pGt\n", &head->page_type);
+
 	print_hex_dump(KERN_WARNING, "raw: ", DUMP_PREFIX_NONE, 32,
 			sizeof(unsigned long), page,
 			sizeof(struct page), false);
diff --git a/mm/internal.h b/mm/internal.h
index cb4c663a714e..956eaa9f12c0 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -773,6 +773,7 @@  static inline void flush_tlb_batched_pending(struct mm_struct *mm)
 #endif /* CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH */
 
 extern const struct trace_print_flags pageflag_names[];
+extern const struct trace_print_flags pagetype_names[];
 extern const struct trace_print_flags vmaflag_names[];
 extern const struct trace_print_flags gfpflag_names[];