diff options
author | Petr Mladek <pmladek@suse.com> | 2021-04-27 14:31:38 +0200 |
---|---|---|
committer | Petr Mladek <pmladek@suse.com> | 2021-04-27 14:31:38 +0200 |
commit | da34b03fbd0a6e58770d5fe00830674633a57d60 (patch) | |
tree | ccb97e2c2b0ae6421c5d79c25e8b8869006ce6d1 /lib/vsprintf.c | |
parent | lib/vsprintf.c: remove leftover 'f' and 'F' cases from bstr_printf() (diff) | |
parent | vsprintf: dump full information of page flags in pGp (diff) | |
download | linux-da34b03fbd0a6e58770d5fe00830674633a57d60.tar.xz linux-da34b03fbd0a6e58770d5fe00830674633a57d60.zip |
Merge branch 'for-5.13-vsprintf-pgp' into for-linus
Diffstat (limited to 'lib/vsprintf.c')
-rw-r--r-- | lib/vsprintf.c | 66 |
1 files changed, 61 insertions, 5 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 7caf619ee9c2..6c56c62fd9a5 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1916,6 +1916,66 @@ char *format_flags(char *buf, char *end, unsigned long flags, return buf; } +struct page_flags_fields { + int width; + int shift; + int mask; + const struct printf_spec *spec; + const char *name; +}; + +static const struct page_flags_fields pff[] = { + {SECTIONS_WIDTH, SECTIONS_PGSHIFT, SECTIONS_MASK, + &default_dec_spec, "section"}, + {NODES_WIDTH, NODES_PGSHIFT, NODES_MASK, + &default_dec_spec, "node"}, + {ZONES_WIDTH, ZONES_PGSHIFT, ZONES_MASK, + &default_dec_spec, "zone"}, + {LAST_CPUPID_WIDTH, LAST_CPUPID_PGSHIFT, LAST_CPUPID_MASK, + &default_flag_spec, "lastcpupid"}, + {KASAN_TAG_WIDTH, KASAN_TAG_PGSHIFT, KASAN_TAG_MASK, + &default_flag_spec, "kasantag"}, +}; + +static +char *format_page_flags(char *buf, char *end, unsigned long flags) +{ + unsigned long main_flags = flags & (BIT(NR_PAGEFLAGS) - 1); + bool append = false; + int i; + + /* Page flags from the main area. */ + if (main_flags) { + buf = format_flags(buf, end, main_flags, pageflag_names); + append = true; + } + + /* Page flags from the fields area */ + for (i = 0; i < ARRAY_SIZE(pff); i++) { + /* Skip undefined fields. */ + if (!pff[i].width) + continue; + + /* Format: Flag Name + '=' (equals sign) + Number + '|' (separator) */ + if (append) { + if (buf < end) + *buf = '|'; + buf++; + } + + buf = string(buf, end, pff[i].name, default_str_spec); + if (buf < end) + *buf = '='; + buf++; + buf = number(buf, end, (flags >> pff[i].shift) & pff[i].mask, + *pff[i].spec); + + append = true; + } + + return buf; +} + static noinline_for_stack char *flags_string(char *buf, char *end, void *flags_ptr, struct printf_spec spec, const char *fmt) @@ -1928,11 +1988,7 @@ char *flags_string(char *buf, char *end, void *flags_ptr, switch (fmt[1]) { case 'p': - flags = *(unsigned long *)flags_ptr; - /* Remove zone id */ - flags &= (1UL << NR_PAGEFLAGS) - 1; - names = pageflag_names; - break; + return format_page_flags(buf, end, *(unsigned long *)flags_ptr); case 'v': flags = *(unsigned long *)flags_ptr; names = vmaflag_names; |