2023-01-30 04:25:46

by Hyeonggon Yoo

[permalink] [raw]
Subject: [PATCH mm-unstable v4 0/3] mm, printk: introduce new format for page_type

RFC v3:
https://lore.kernel.org/lkml/[email protected]

This series was originally part of "move PG_slab to page_type" series,
but printk format implementation for page_type is separated to this series.

RFC v3 -> v4:
- dropped patch 1 ("mm/hwpoison: remove MF_MSG_SLAB from action_page_types")
and patch 2 ("mm: move PG_slab flag to page_type") from previous
spin as they are planned as separate series

- adjusted comments from Andy Shevchenko [1] and Petr Mladek [2]

- added patch 1 ("mmflags.h: use less error prone method to define pageflag_names")
for consistency with patch 2 ("mm, printk: introduce new format %pGt for page_type"),
as suggested by Andy Shevchenko [1]

[1] https://lore.kernel.org/lkml/[email protected]/
[2] https://lore.kernel.org/lkml/Y6HSutM8pmoKxQWp@alley/

Based on mm-unstable (ede43f2956cc "kasan: fix Oops due to missing calls
to kasan_arch_is_rea()") as there are recent changes in mmflags.h.

Hyeonggon Yoo (3):
mmflags.h: use less error prone method to define pageflag_names
mm, printk: introduce new format %pGt for page_type
mm/debug: use %pGt to display page_type in dump_page()

Documentation/core-api/printk-formats.rst | 16 ++--
include/linux/page-flags.h | 7 +-
include/trace/events/mmflags.h | 93 +++++++++++++----------
lib/test_printf.c | 26 +++++++
lib/vsprintf.c | 21 +++++
mm/debug.c | 7 ++
mm/internal.h | 1 +
7 files changed, 124 insertions(+), 47 deletions(-)

--
2.39.1



2023-01-30 04:25:51

by Hyeonggon Yoo

[permalink] [raw]
Subject: [PATCH mm-unstable v4 1/3] mmflags.h: use less error prone method to define pageflag_names

As suggested by Andy Shevchenko, use helper macro to decrease chances
of typo when defining pageflag_names.

Link: https://lore.kernel.org/lkml/[email protected]
Signed-off-by: Hyeonggon Yoo <[email protected]>
---
include/trace/events/mmflags.h | 85 ++++++++++++++++++----------------
1 file changed, 44 insertions(+), 41 deletions(-)

diff --git a/include/trace/events/mmflags.h b/include/trace/events/mmflags.h
index 9db52bc4ce19..f453babe29b3 100644
--- a/include/trace/events/mmflags.h
+++ b/include/trace/events/mmflags.h
@@ -67,71 +67,74 @@
) : "none"

#ifdef CONFIG_MMU
-#define IF_HAVE_PG_MLOCK(flag,string) ,{1UL << flag, string}
+#define IF_HAVE_PG_MLOCK(_name) ,{1UL << PG_##_name, __stringify(_name)}
#else
-#define IF_HAVE_PG_MLOCK(flag,string)
+#define IF_HAVE_PG_MLOCK(_name)
#endif

#ifdef CONFIG_ARCH_USES_PG_UNCACHED
-#define IF_HAVE_PG_UNCACHED(flag,string) ,{1UL << flag, string}
+#define IF_HAVE_PG_UNCACHED(_name) ,{1UL << PG_##_name, __stringify(_name)}
#else
-#define IF_HAVE_PG_UNCACHED(flag,string)
+#define IF_HAVE_PG_UNCACHED(_name)
#endif

#ifdef CONFIG_MEMORY_FAILURE
-#define IF_HAVE_PG_HWPOISON(flag,string) ,{1UL << flag, string}
+#define IF_HAVE_PG_HWPOISON(_name) ,{1UL << PG_##_name, __stringify(_name)}
#else
-#define IF_HAVE_PG_HWPOISON(flag,string)
+#define IF_HAVE_PG_HWPOISON(_name)
#endif

#if defined(CONFIG_PAGE_IDLE_FLAG) && defined(CONFIG_64BIT)
-#define IF_HAVE_PG_IDLE(flag,string) ,{1UL << flag, string}
+#define IF_HAVE_PG_IDLE(_name) ,{1UL << PG_##_name, __stringify(_name)}
#else
-#define IF_HAVE_PG_IDLE(flag,string)
+#define IF_HAVE_PG_IDLE(_name)
#endif

#ifdef CONFIG_ARCH_USES_PG_ARCH_X
-#define IF_HAVE_PG_ARCH_X(flag,string) ,{1UL << flag, string}
+#define IF_HAVE_PG_ARCH_X(_name) ,{1UL << PG_##_name, __stringify(_name)}
#else
-#define IF_HAVE_PG_ARCH_X(flag,string)
+#define IF_HAVE_PG_ARCH_X(_name)
#endif

#ifdef CONFIG_KASAN_HW_TAGS
-#define IF_HAVE_PG_SKIP_KASAN_POISON(flag,string) ,{1UL << flag, string}
+#define IF_HAVE_PG_SKIP_KASAN_POISON(_name) \
+ ,{1UL << PG_##_name, __stringify(_name)}
#else
-#define IF_HAVE_PG_SKIP_KASAN_POISON(flag,string)
+#define IF_HAVE_PG_SKIP_KASAN_POISON(_name)
#endif

+#define DEF_PAGEFLAG_NAME(_name) { 1UL << PG_##_name, __stringify(_name) }
+
#define __def_pageflag_names \
- {1UL << PG_locked, "locked" }, \
- {1UL << PG_waiters, "waiters" }, \
- {1UL << PG_error, "error" }, \
- {1UL << PG_referenced, "referenced" }, \
- {1UL << PG_uptodate, "uptodate" }, \
- {1UL << PG_dirty, "dirty" }, \
- {1UL << PG_lru, "lru" }, \
- {1UL << PG_active, "active" }, \
- {1UL << PG_workingset, "workingset" }, \
- {1UL << PG_slab, "slab" }, \
- {1UL << PG_owner_priv_1, "owner_priv_1" }, \
- {1UL << PG_arch_1, "arch_1" }, \
- {1UL << PG_reserved, "reserved" }, \
- {1UL << PG_private, "private" }, \
- {1UL << PG_private_2, "private_2" }, \
- {1UL << PG_writeback, "writeback" }, \
- {1UL << PG_head, "head" }, \
- {1UL << PG_mappedtodisk, "mappedtodisk" }, \
- {1UL << PG_reclaim, "reclaim" }, \
- {1UL << PG_swapbacked, "swapbacked" }, \
- {1UL << PG_unevictable, "unevictable" } \
-IF_HAVE_PG_MLOCK(PG_mlocked, "mlocked" ) \
-IF_HAVE_PG_UNCACHED(PG_uncached, "uncached" ) \
-IF_HAVE_PG_HWPOISON(PG_hwpoison, "hwpoison" ) \
-IF_HAVE_PG_IDLE(PG_young, "young" ) \
-IF_HAVE_PG_IDLE(PG_idle, "idle" ) \
-IF_HAVE_PG_ARCH_X(PG_arch_2, "arch_2" ) \
-IF_HAVE_PG_ARCH_X(PG_arch_3, "arch_3" ) \
-IF_HAVE_PG_SKIP_KASAN_POISON(PG_skip_kasan_poison, "skip_kasan_poison")
+ DEF_PAGEFLAG_NAME(locked), \
+ DEF_PAGEFLAG_NAME(waiters), \
+ DEF_PAGEFLAG_NAME(error), \
+ DEF_PAGEFLAG_NAME(referenced), \
+ DEF_PAGEFLAG_NAME(uptodate), \
+ DEF_PAGEFLAG_NAME(dirty), \
+ DEF_PAGEFLAG_NAME(lru), \
+ DEF_PAGEFLAG_NAME(active), \
+ DEF_PAGEFLAG_NAME(workingset), \
+ DEF_PAGEFLAG_NAME(slab), \
+ DEF_PAGEFLAG_NAME(owner_priv_1), \
+ DEF_PAGEFLAG_NAME(arch_1), \
+ DEF_PAGEFLAG_NAME(reserved), \
+ DEF_PAGEFLAG_NAME(private), \
+ DEF_PAGEFLAG_NAME(private_2), \
+ DEF_PAGEFLAG_NAME(writeback), \
+ DEF_PAGEFLAG_NAME(head), \
+ DEF_PAGEFLAG_NAME(mappedtodisk), \
+ DEF_PAGEFLAG_NAME(reclaim), \
+ DEF_PAGEFLAG_NAME(swapbacked), \
+ DEF_PAGEFLAG_NAME(unevictable) \
+IF_HAVE_PG_MLOCK(mlocked) \
+IF_HAVE_PG_UNCACHED(uncached) \
+IF_HAVE_PG_HWPOISON(hwpoison) \
+IF_HAVE_PG_IDLE(idle) \
+IF_HAVE_PG_IDLE(young) \
+IF_HAVE_PG_ARCH_X(arch_2) \
+IF_HAVE_PG_ARCH_X(arch_3) \
+IF_HAVE_PG_SKIP_KASAN_POISON(skip_kasan_poison)

#define show_page_flags(flags) \
(flags) ? __print_flags(flags, "|", \
--
2.39.1


2023-01-30 04:26:20

by Hyeonggon Yoo

[permalink] [raw]
Subject: [PATCH mm-unstable v4 2/3] mm, printk: introduce new format %pGt for page_type

%pGp format is used to display 'flags' field of a struct page.
However, some page flags (i.e. PG_buddy, see page-flags.h for more details)
are stored in page_type field. To display human-readable output of
page_type, introduce %pGt format.

It is important to note the meaning of bits are different in page_type.
if page_type is 0xffffffff, no flags are set. Setting PG_buddy (0x00000080)
flag results in a page_type of 0xffffff7f. Clearing a bit actually means
setting a flag. Bits in page_type are inverted when displaying type names.

Only values for which page_type_has_type() returns true are considered
as page_type, to avoid confusion with mapcount values. if it returns false,
only raw values are displayed and not page type names.

Signed-off-by: Hyeonggon Yoo <[email protected]>
---
Documentation/core-api/printk-formats.rst | 16 +++++++++-----
include/linux/page-flags.h | 7 +++++-
include/trace/events/mmflags.h | 8 +++++++
lib/test_printf.c | 26 +++++++++++++++++++++++
lib/vsprintf.c | 21 ++++++++++++++++++
mm/debug.c | 5 +++++
mm/internal.h | 1 +
7 files changed, 78 insertions(+), 6 deletions(-)

diff --git a/Documentation/core-api/printk-formats.rst b/Documentation/core-api/printk-formats.rst
index dbe1aacc79d0..dfe7e75a71de 100644
--- a/Documentation/core-api/printk-formats.rst
+++ b/Documentation/core-api/printk-formats.rst
@@ -575,20 +575,26 @@ 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 0xffffff7f(buddy)
%pGg GFP_USER|GFP_DMA32|GFP_NOWARN
%pGv read|exec|mayread|maywrite|mayexec|denywrite

For printing flags bitfields as a collection of symbolic constants that
would construct the value. The type of flags is given by the third
-character. Currently supported are [p]age flags, [v]ma_flags (both
-expect ``unsigned long *``) and [g]fp_flags (expects ``gfp_t *``). The flag
-names and print order depends on the particular type.
+character. Currently supported are:
+
+ - p - [p]age flags, expects value of type (``unsigned long *``)
+ - t - page [t]ype, expects value of type (``unsigned int *``)
+ - v - [v]ma_flags, expects value of type (``unsigned long *``)
+ - g - [g]fp_flags, expects value of type (``gfp_t *``)
+
+The flag names and print order depends on the particular type.

Note that this format should not be used directly in the
:c:func:`TP_printk()` part of a tracepoint. Instead, use the show_*_flags()
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index a7e3a3405520..57287102c5bd 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -926,9 +926,14 @@ static inline bool is_page_hwpoison(struct page *page)
#define PageType(page, flag) \
((page->page_type & (PAGE_TYPE_BASE | flag)) == PAGE_TYPE_BASE)

+static inline int page_type_has_type(unsigned int page_type)
+{
+ return (int)page_type < PAGE_MAPCOUNT_RESERVE;
+}
+
static inline int page_has_type(struct page *page)
{
- return (int)page->page_type < PAGE_MAPCOUNT_RESERVE;
+ return page_type_has_type(page->page_type);
}

#define PAGE_TYPE_OPS(uname, lname) \
diff --git a/include/trace/events/mmflags.h b/include/trace/events/mmflags.h
index f453babe29b3..b28218b7998e 100644
--- a/include/trace/events/mmflags.h
+++ b/include/trace/events/mmflags.h
@@ -141,6 +141,14 @@ IF_HAVE_PG_SKIP_KASAN_POISON(skip_kasan_poison)
__def_pageflag_names \
) : "none"

+#define DEF_PAGETYPE_NAME(_name) { PG_##_name, __stringify(_name) }
+
+#define __def_pagetype_names \
+ DEF_PAGETYPE_NAME(offline), \
+ DEF_PAGETYPE_NAME(guard), \
+ DEF_PAGETYPE_NAME(table), \
+ DEF_PAGETYPE_NAME(buddy)
+
#if defined(CONFIG_X86)
#define __VM_ARCH_SPECIFIC_1 {VM_PAT, "pat" }
#elif defined(CONFIG_PPC)
diff --git a/lib/test_printf.c b/lib/test_printf.c
index 46b4e6c414a3..7677ebccf3c3 100644
--- a/lib/test_printf.c
+++ b/lib/test_printf.c
@@ -642,12 +642,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)
@@ -687,6 +701,18 @@ flags(void)
gfp |= __GFP_HIGH;
test(cmp_buffer, "%pGg", &gfp);

+ page_type = ~0;
+ page_type_test(page_type, "", cmp_buffer);
+
+ page_type = 10;
+ page_type_test(page_type, "", cmp_buffer);
+
+ page_type = ~PG_buddy;
+ page_type_test(page_type, "buddy", cmp_buffer);
+
+ page_type = ~(PG_table | PG_buddy);
+ page_type_test(page_type, "table|buddy", cmp_buffer);
+
kfree(cmp_buffer);
}

diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index be71a03c936a..fbe320b5e89f 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -2052,6 +2052,25 @@ 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)
+{
+ 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)
@@ -2065,6 +2084,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 96d594e16292..01cf0435723b 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}
diff --git a/mm/internal.h b/mm/internal.h
index 90bb2078444c..11c3258809a9 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -802,6 +802,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[];

--
2.39.1


2023-01-30 04:26:20

by Hyeonggon Yoo

[permalink] [raw]
Subject: [PATCH mm-unstable v4 3/3] mm/debug: use %pGt to display page_type in dump_page()

Some page flags are stored in page_type rather than ->flags field.
Use newly introduced page type %pGt in dump_page().

Below are some examples:

page:00000000da7184dd refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x101cb3
flags: 0x2ffff0000000000(node=0|zone=2|lastcpupid=0xffff)
page_type: 0xffffffff()
raw: 02ffff0000000000 0000000000000000 dead000000000122 0000000000000000
raw: 0000000000000000 0000000000000000 00000001ffffffff 0000000000000000
page dumped because: newly allocated page

page:00000000da7184dd refcount:0 mapcount:-128 mapping:0000000000000000 index:0x0 pfn:0x101cb3
flags: 0x2ffff0000000000(node=0|zone=2|lastcpupid=0xffff)
page_type: 0xffffff7f(buddy)
raw: 02ffff0000000000 ffff88813fff8e80 ffff88813fff8e80 0000000000000000
raw: 0000000000000000 0000000000000000 00000000ffffff7f 0000000000000000
page dumped because: freed page

page:0000000042202316 refcount:3 mapcount:2 mapping:0000000000000000 index:0x7f634722a pfn:0x11994e
memcg:ffff888100135000
anon flags: 0x2ffff0000080024(uptodate|active|swapbacked|node=0|zone=2|lastcpupid=0xffff)
page_type: 0x1()
raw: 02ffff0000080024 0000000000000000 dead000000000122 ffff8881193398f1
raw: 00000007f634722a 0000000000000000 0000000300000001 ffff888100135000
page dumped because: user-mapped page

Signed-off-by: Hyeonggon Yoo <[email protected]>
---
mm/debug.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/mm/debug.c b/mm/debug.c
index 01cf0435723b..c7b228097bd9 100644
--- a/mm/debug.c
+++ b/mm/debug.c
@@ -120,6 +120,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);
--
2.39.1


2023-01-30 12:36:03

by Andy Shevchenko

[permalink] [raw]
Subject: Re: [PATCH mm-unstable v4 1/3] mmflags.h: use less error prone method to define pageflag_names

On Mon, Jan 30, 2023 at 01:25:12PM +0900, Hyeonggon Yoo wrote:
> As suggested by Andy Shevchenko, use helper macro to decrease chances
> of typo when defining pageflag_names.

Suggested-by: ? :-)

> Link: https://lore.kernel.org/lkml/[email protected]
> Signed-off-by: Hyeonggon Yoo <[email protected]>

LGTM, thank you!
Reviewed-by: Andy Shevchenko <[email protected]>

--
With Best Regards,
Andy Shevchenko



2023-01-31 08:38:13

by Hyeonggon Yoo

[permalink] [raw]
Subject: Re: [PATCH mm-unstable v4 1/3] mmflags.h: use less error prone method to define pageflag_names

On Mon, Jan 30, 2023 at 02:35:52PM +0200, Andy Shevchenko wrote:
> On Mon, Jan 30, 2023 at 01:25:12PM +0900, Hyeonggon Yoo wrote:
> > As suggested by Andy Shevchenko, use helper macro to decrease chances
> > of typo when defining pageflag_names.
>
> Suggested-by: ? :-)

oh, yeah I only wrote in changelog forgot to add the tag.
I think Andrew will kindly add that when picking this series up?

> > Link: https://lore.kernel.org/lkml/[email protected]
> > Signed-off-by: Hyeonggon Yoo <[email protected]>
>
> LGTM, thank you!
> Reviewed-by: Andy Shevchenko <[email protected]>

Thank you a lot!

> --
> With Best Regards,
> Andy Shevchenko

Best Regards,
Hyeonggon

2023-01-31 21:09:48

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH mm-unstable v4 1/3] mmflags.h: use less error prone method to define pageflag_names

On Tue, 31 Jan 2023 17:38:02 +0900 Hyeonggon Yoo <[email protected]> wrote:

> On Mon, Jan 30, 2023 at 02:35:52PM +0200, Andy Shevchenko wrote:
> > On Mon, Jan 30, 2023 at 01:25:12PM +0900, Hyeonggon Yoo wrote:
> > > As suggested by Andy Shevchenko, use helper macro to decrease chances
> > > of typo when defining pageflag_names.
> >
> > Suggested-by: ? :-)
>
> oh, yeah I only wrote in changelog forgot to add the tag.
> I think Andrew will kindly add that when picking this series up?

Sure.

We're at -rc6 so I'm slowing down on the features and cleanups. I'll
probably park this series for the next -rc cycle.

2023-02-01 12:14:58

by Hyeonggon Yoo

[permalink] [raw]
Subject: Re: [PATCH mm-unstable v4 1/3] mmflags.h: use less error prone method to define pageflag_names

On Tue, Jan 31, 2023 at 01:09:40PM -0800, Andrew Morton wrote:
> On Tue, 31 Jan 2023 17:38:02 +0900 Hyeonggon Yoo <[email protected]> wrote:
>
> > On Mon, Jan 30, 2023 at 02:35:52PM +0200, Andy Shevchenko wrote:
> > > On Mon, Jan 30, 2023 at 01:25:12PM +0900, Hyeonggon Yoo wrote:
> > > > As suggested by Andy Shevchenko, use helper macro to decrease chances
> > > > of typo when defining pageflag_names.
> > >
> > > Suggested-by: ? :-)
> >
> > oh, yeah I only wrote in changelog forgot to add the tag.
> > I think Andrew will kindly add that when picking this series up?
>
> Sure.

Thanks ;)

> We're at -rc6 so I'm slowing down on the features and cleanups. I'll
> probably park this series for the next -rc cycle.

No problem!

2023-03-03 19:51:04

by Petr Mladek

[permalink] [raw]
Subject: Re: [PATCH mm-unstable v4 2/3] mm, printk: introduce new format %pGt for page_type

On Mon 2023-01-30 13:25:13, Hyeonggon Yoo wrote:
> %pGp format is used to display 'flags' field of a struct page.
> However, some page flags (i.e. PG_buddy, see page-flags.h for more details)
> are stored in page_type field. To display human-readable output of
> page_type, introduce %pGt format.
>
> It is important to note the meaning of bits are different in page_type.
> if page_type is 0xffffffff, no flags are set. Setting PG_buddy (0x00000080)
> flag results in a page_type of 0xffffff7f. Clearing a bit actually means
> setting a flag. Bits in page_type are inverted when displaying type names.
>
> Only values for which page_type_has_type() returns true are considered
> as page_type, to avoid confusion with mapcount values. if it returns false,
> only raw values are displayed and not page type names.
>
> Signed-off-by: Hyeonggon Yoo <[email protected]>

Reviewed-by: Petr Mladek <[email protected]> # for vsprintf part

I am sorry for the late review. It has somehow fallen through cracks.

Best Regards,
Petr