Currently the pGp only shows the names of page flags, rather than
the full information including section, node, zone, last cpupid and
kasan tag. While it is not easy to parse these information manually
because there're so many flavors. Let's interpret them in pGp as well.
This patchset also includes some code cleanup in mm/slub.c.
Below is the example of the output in mm/slub.c.
- Before the patchset
[ 6155.716018] INFO: Slab 0x000000004027dd4f objects=33 used=3 fp=0x000000008cd1579c flags=0x17ffffc0010200
- After the patchset
[ 6315.235783] ERR: Slab 0x000000006d1133b9 objects=33 used=3 fp=0x000000006d0779d1 flags=0x17ffffc0010200(Node 0x0,Zone 0x2,Lastcpupid 0x1fffff,slab|head)
Yafang Shao (3):
mm, slub: use pGp to print page flags
mm, slub: don't combine pr_err with INFO
printk: dump full information of page flags in pGp
lib/vsprintf.c | 42 +++++++++++++++++++++++++++++++++++++++++-
mm/slub.c | 13 +++++++------
2 files changed, 48 insertions(+), 7 deletions(-)
--
2.17.1
As pGp has been already introduced in printk, we'd better use it to make
the output human readable.
Before this change, the output is,
[ 6155.716018] INFO: Slab 0x000000004027dd4f objects=33 used=3 fp=0x000000008cd1579c flags=0x17ffffc0010200
While after this change, the output is,
[ 8846.517809] INFO: Slab 0x00000000f42a2c60 objects=33 used=3 fp=0x0000000060d32ca8 flags=0x17ffffc0010200(slab|head)
Reviewed-by: David Hildenbrand <[email protected]>
Signed-off-by: Yafang Shao <[email protected]>
---
mm/slub.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/mm/slub.c b/mm/slub.c
index 69742ab9a21d..4b9ab267afbc 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -641,8 +641,9 @@ void print_tracking(struct kmem_cache *s, void *object)
static void print_page_info(struct page *page)
{
- pr_err("INFO: Slab 0x%p objects=%u used=%u fp=0x%p flags=0x%04lx\n",
- page, page->objects, page->inuse, page->freelist, page->flags);
+ pr_err("INFO: Slab 0x%p objects=%u used=%u fp=0x%p flags=%#lx(%pGp)\n",
+ page, page->objects, page->inuse, page->freelist,
+ page->flags, &page->flags);
}
--
2.17.1
Currently the pGp only shows the names of page flags, rather than
the full information including section, node, zone, last cpupid and
kasan tag. While it is not easy to parse these information manually
because there're so many flavors. Let's interpret them in pGp as well.
- Before the patch,
[ 6312.639698] ERR: Slab 0x000000006d1133b9 objects=33 used=3 fp=0x000000006d0779d1 flags=0x17ffffc0010200(slab|head)
- After the patch,
[ 6315.235783] ERR: Slab 0x000000006d1133b9 objects=33 used=3 fp=0x000000006d0779d1 flags=0x17ffffc0010200(Node 0x0,Zone 0x2,Lastcpupid 0x1fffff,slab|head)
Cc: David Hildenbrand <[email protected]>
Signed-off-by: Yafang Shao <[email protected]>
---
lib/vsprintf.c | 42 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 41 insertions(+), 1 deletion(-)
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 3b53c73580c5..bd809f4f1b82 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -1916,6 +1916,46 @@ char *format_flags(char *buf, char *end, unsigned long flags,
return buf;
}
+struct page_flags_layout {
+ int width;
+ int shift;
+ int mask;
+ char *name;
+};
+
+struct page_flags_layout pfl[] = {
+ {SECTIONS_WIDTH, SECTIONS_PGSHIFT, SECTIONS_MASK, "Section "},
+ {NODES_WIDTH, NODES_PGSHIFT, NODES_MASK, "Node "},
+ {ZONES_WIDTH, ZONES_PGSHIFT, ZONES_MASK, "Zone "},
+ {LAST_CPUPID_WIDTH, LAST_CPUPID_PGSHIFT, LAST_CPUPID_MASK, "Lastcpupid "},
+ {KASAN_TAG_WIDTH, KASAN_TAG_PGSHIFT, KASAN_TAG_MASK, "Kasantag "},
+};
+
+static
+char *format_layout(char *buf, char *end, unsigned long flags)
+{
+ int i;
+
+ for (i = 0; i < sizeof(pfl) / sizeof(struct page_flags_layout) && buf < end; i++) {
+ if (pfl[i].width == 0)
+ continue;
+
+ buf = string(buf, end, pfl[i].name, default_str_spec);
+
+ if (buf >= end)
+ break;
+ buf = number(buf, end, (flags >> pfl[i].shift) & pfl[i].mask,
+ default_flag_spec);
+
+ if (buf >= end)
+ break;
+ *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)
@@ -1929,7 +1969,7 @@ char *flags_string(char *buf, char *end, void *flags_ptr,
switch (fmt[1]) {
case 'p':
flags = *(unsigned long *)flags_ptr;
- /* Remove zone id */
+ buf = format_layout(buf, end, flags & ~((1UL << NR_PAGEFLAGS) - 1));
flags &= (1UL << NR_PAGEFLAGS) - 1;
names = pageflag_names;
break;
--
2.17.1
It is strange to combine "pr_err" with "INFO", so let's clean them up.
This patch is motivated by David's comment[1].
- before the patch
[ 8846.517809] INFO: Slab 0x00000000f42a2c60 objects=33 used=3 fp=0x0000000060d32ca8 flags=0x17ffffc0010200(slab|head)
- after the patch
[ 6312.639698] ERR: Slab 0x000000006d1133b9 objects=33 used=3 fp=0x000000006d0779d1 flags=0x17ffffc0010200(slab|head)
[1]. https://lore.kernel.org/linux-mm/[email protected]/#t
Cc: David Hildenbrand <[email protected]>
Signed-off-by: Yafang Shao <[email protected]>
---
mm/slub.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/mm/slub.c b/mm/slub.c
index 4b9ab267afbc..18b4474c8fa2 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -615,7 +615,7 @@ static void print_track(const char *s, struct track *t, unsigned long pr_time)
if (!t->addr)
return;
- pr_err("INFO: %s in %pS age=%lu cpu=%u pid=%d\n",
+ pr_err("ERR: %s in %pS age=%lu cpu=%u pid=%d\n",
s, (void *)t->addr, pr_time - t->when, t->cpu, t->pid);
#ifdef CONFIG_STACKTRACE
{
@@ -641,7 +641,7 @@ void print_tracking(struct kmem_cache *s, void *object)
static void print_page_info(struct page *page)
{
- pr_err("INFO: Slab 0x%p objects=%u used=%u fp=0x%p flags=%#lx(%pGp)\n",
+ pr_err("ERR: Slab 0x%p objects=%u used=%u fp=0x%p flags=%#lx(%pGp)\n",
page, page->objects, page->inuse, page->freelist,
page->flags, &page->flags);
@@ -698,7 +698,7 @@ static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p)
print_page_info(page);
- pr_err("INFO: Object 0x%p @offset=%tu fp=0x%p\n\n",
+ pr_err("ERR: Object 0x%p @offset=%tu fp=0x%p\n\n",
p, p - addr, get_freepointer(s, p));
if (s->flags & SLAB_RED_ZONE)
@@ -791,7 +791,7 @@ static int check_bytes_and_report(struct kmem_cache *s, struct page *page,
end--;
slab_bug(s, "%s overwritten", what);
- pr_err("INFO: 0x%p-0x%p @offset=%tu. First byte 0x%x instead of 0x%x\n",
+ pr_err("ERR: 0x%p-0x%p @offset=%tu. First byte 0x%x instead of 0x%x\n",
fault, end - 1, fault - addr,
fault[0], value);
print_trailer(s, page, object);
@@ -3855,7 +3855,7 @@ static void list_slab_objects(struct kmem_cache *s, struct page *page,
for_each_object(p, s, addr, page->objects) {
if (!test_bit(__obj_to_index(s, addr, p), map)) {
- pr_err("INFO: Object 0x%p @offset=%tu\n", p, p - addr);
+ pr_err("ERR: Object 0x%p @offset=%tu\n", p, p - addr);
print_tracking(s, p);
}
}
--
2.17.1
On Thu, 2021-01-28 at 10:19 +0800, Yafang Shao wrote:
> Currently the pGp only shows the names of page flags, rather than
> the full information including section, node, zone, last cpupid and
> kasan tag. While it is not easy to parse these information manually
> because there're so many flavors. Let's interpret them in pGp as well.
[]
> diff --git a/lib/vsprintf.c b/lib/vsprintf.c
[]
> @@ -1916,6 +1916,46 @@ char *format_flags(char *buf, char *end, unsigned long flags,
> ? return buf;
> ?}
>
> +struct page_flags_layout {
> + int width;
> + int shift;
> + int mask;
> + char *name;
> +};
> +
> +struct page_flags_layout pfl[] = {
static const struct page_flags_layout pfl[] = {
> + {SECTIONS_WIDTH, SECTIONS_PGSHIFT, SECTIONS_MASK, "Section "},
> + {NODES_WIDTH, NODES_PGSHIFT, NODES_MASK, "Node "},
> + {ZONES_WIDTH, ZONES_PGSHIFT, ZONES_MASK, "Zone "},
> + {LAST_CPUPID_WIDTH, LAST_CPUPID_PGSHIFT, LAST_CPUPID_MASK, "Lastcpupid "},
> + {KASAN_TAG_WIDTH, KASAN_TAG_PGSHIFT, KASAN_TAG_MASK, "Kasantag "},
> +};
> +
> +static
> +char *format_layout(char *buf, char *end, unsigned long flags)
poor name. perhaps format_page_flags
> +{
> + int i;
> +
> + for (i = 0; i < sizeof(pfl) / sizeof(struct page_flags_layout) && buf < end; i++) {
for (i = 0; i < ARRAY_SIZE(pfl) && buf < end; i++) {
> @@ -1929,7 +1969,7 @@ char *flags_string(char *buf, char *end, void *flags_ptr,
> ? switch (fmt[1]) {
> ? case 'p':
> ? flags = *(unsigned long *)flags_ptr;
> - /* Remove zone id */
> + buf = format_layout(buf, end, flags & ~((1UL << NR_PAGEFLAGS) - 1));
> ? flags &= (1UL << NR_PAGEFLAGS) - 1;
Perhaps store the bitshift into a temp and use the temp twice
foo = BIT(NR_PAGEFLAGS) - 1;
buf = format_layout(buf, end, flags & ~foo);
flags &= foo;
Hi:
On 2021/1/28 10:19, Yafang Shao wrote:
> Currently the pGp only shows the names of page flags, rather than
> the full information including section, node, zone, last cpupid and
> kasan tag. While it is not easy to parse these information manually
> because there're so many flavors. Let's interpret them in pGp as well.
>
> - Before the patch,
> [ 6312.639698] ERR: Slab 0x000000006d1133b9 objects=33 used=3 fp=0x000000006d0779d1 flags=0x17ffffc0010200(slab|head)
>
> - After the patch,
> [ 6315.235783] ERR: Slab 0x000000006d1133b9 objects=33 used=3 fp=0x000000006d0779d1 flags=0x17ffffc0010200(Node 0x0,Zone 0x2,Lastcpupid 0x1fffff,slab|head)
>
Thanks. This really helps!
> Cc: David Hildenbrand <[email protected]>
> Signed-off-by: Yafang Shao <[email protected]>
> ---
> lib/vsprintf.c | 42 +++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 41 insertions(+), 1 deletion(-)
>
> diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> index 3b53c73580c5..bd809f4f1b82 100644
> --- a/lib/vsprintf.c
> +++ b/lib/vsprintf.c
> @@ -1916,6 +1916,46 @@ char *format_flags(char *buf, char *end, unsigned long flags,
> return buf;
> }
>
> +struct page_flags_layout {
> + int width;
> + int shift;
> + int mask;
> + char *name;
Should we add const for name ?
> +};
> +
> +struct page_flags_layout pfl[] = {
Should we add static const for pfl[] as we won't change its value and use it outside this file ?
> + {SECTIONS_WIDTH, SECTIONS_PGSHIFT, SECTIONS_MASK, "Section "},
> + {NODES_WIDTH, NODES_PGSHIFT, NODES_MASK, "Node "},
> + {ZONES_WIDTH, ZONES_PGSHIFT, ZONES_MASK, "Zone "},
> + {LAST_CPUPID_WIDTH, LAST_CPUPID_PGSHIFT, LAST_CPUPID_MASK, "Lastcpupid "},
> + {KASAN_TAG_WIDTH, KASAN_TAG_PGSHIFT, KASAN_TAG_MASK, "Kasantag "},
> +};
> +
> +static
> +char *format_layout(char *buf, char *end, unsigned long flags)
> +{
> + int i;
> +
> + for (i = 0; i < sizeof(pfl) / sizeof(struct page_flags_layout) && buf < end; i++) {
I think we can use ARRAY_SIZE here.
> + if (pfl[i].width == 0)
> + continue;
> +
> + buf = string(buf, end, pfl[i].name, default_str_spec);
> +
> + if (buf >= end)
> + break;
> + buf = number(buf, end, (flags >> pfl[i].shift) & pfl[i].mask,
> + default_flag_spec);
> +
> + if (buf >= end)
> + break;
> + *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)
> @@ -1929,7 +1969,7 @@ char *flags_string(char *buf, char *end, void *flags_ptr,
> switch (fmt[1]) {
> case 'p':
> flags = *(unsigned long *)flags_ptr;
> - /* Remove zone id */
> + buf = format_layout(buf, end, flags & ~((1UL << NR_PAGEFLAGS) - 1));
> flags &= (1UL << NR_PAGEFLAGS) - 1;
> names = pageflag_names;
> break;
>
Many thanks.
On Thu, Jan 28, 2021 at 10:35 AM Joe Perches <[email protected]> wrote:
>
> On Thu, 2021-01-28 at 10:19 +0800, Yafang Shao wrote:
> > Currently the pGp only shows the names of page flags, rather than
> > the full information including section, node, zone, last cpupid and
> > kasan tag. While it is not easy to parse these information manually
> > because there're so many flavors. Let's interpret them in pGp as well.
> []
> > diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> []
> > @@ -1916,6 +1916,46 @@ char *format_flags(char *buf, char *end, unsigned long flags,
> > return buf;
> > }
> >
> > +struct page_flags_layout {
> > + int width;
> > + int shift;
> > + int mask;
> > + char *name;
> > +};
> > +
> > +struct page_flags_layout pfl[] = {
>
> static const struct page_flags_layout pfl[] = {
Sure.
>
> > + {SECTIONS_WIDTH, SECTIONS_PGSHIFT, SECTIONS_MASK, "Section "},
> > + {NODES_WIDTH, NODES_PGSHIFT, NODES_MASK, "Node "},
> > + {ZONES_WIDTH, ZONES_PGSHIFT, ZONES_MASK, "Zone "},
> > + {LAST_CPUPID_WIDTH, LAST_CPUPID_PGSHIFT, LAST_CPUPID_MASK, "Lastcpupid "},
> > + {KASAN_TAG_WIDTH, KASAN_TAG_PGSHIFT, KASAN_TAG_MASK, "Kasantag "},
> > +};
> > +
> > +static
> > +char *format_layout(char *buf, char *end, unsigned long flags)
>
> poor name. perhaps format_page_flags
>
Thanks for the suggestion.
> > +{
> > + int i;
> > +
> > + for (i = 0; i < sizeof(pfl) / sizeof(struct page_flags_layout) && buf < end; i++) {
>
> for (i = 0; i < ARRAY_SIZE(pfl) && buf < end; i++) {
>
Sure.
>
> > @@ -1929,7 +1969,7 @@ char *flags_string(char *buf, char *end, void *flags_ptr,
> > switch (fmt[1]) {
> > case 'p':
> > flags = *(unsigned long *)flags_ptr;
> > - /* Remove zone id */
> > + buf = format_layout(buf, end, flags & ~((1UL << NR_PAGEFLAGS) - 1));
> > flags &= (1UL << NR_PAGEFLAGS) - 1;
>
> Perhaps store the bitshift into a temp and use the temp twice
>
> foo = BIT(NR_PAGEFLAGS) - 1;
>
> buf = format_layout(buf, end, flags & ~foo);
> flags &= foo;
>
>
Thanks for the suggestion. I will change them all.
--
Thanks
Yafang
On Thu, Jan 28, 2021 at 10:52 AM Miaohe Lin <[email protected]> wrote:
>
> Hi:
> On 2021/1/28 10:19, Yafang Shao wrote:
> > Currently the pGp only shows the names of page flags, rather than
> > the full information including section, node, zone, last cpupid and
> > kasan tag. While it is not easy to parse these information manually
> > because there're so many flavors. Let's interpret them in pGp as well.
> >
> > - Before the patch,
> > [ 6312.639698] ERR: Slab 0x000000006d1133b9 objects=33 used=3 fp=0x000000006d0779d1 flags=0x17ffffc0010200(slab|head)
> >
> > - After the patch,
> > [ 6315.235783] ERR: Slab 0x000000006d1133b9 objects=33 used=3 fp=0x000000006d0779d1 flags=0x17ffffc0010200(Node 0x0,Zone 0x2,Lastcpupid 0x1fffff,slab|head)
> >
>
> Thanks. This really helps!
>
> > Cc: David Hildenbrand <[email protected]>
> > Signed-off-by: Yafang Shao <[email protected]>
> > ---
> > lib/vsprintf.c | 42 +++++++++++++++++++++++++++++++++++++++++-
> > 1 file changed, 41 insertions(+), 1 deletion(-)
> >
> > diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> > index 3b53c73580c5..bd809f4f1b82 100644
> > --- a/lib/vsprintf.c
> > +++ b/lib/vsprintf.c
> > @@ -1916,6 +1916,46 @@ char *format_flags(char *buf, char *end, unsigned long flags,
> > return buf;
> > }
> >
> > +struct page_flags_layout {
> > + int width;
> > + int shift;
> > + int mask;
> > + char *name;
>
> Should we add const for name ?
>
Good suggestion.
> > +};
> > +
> > +struct page_flags_layout pfl[] = {
>
> Should we add static const for pfl[] as we won't change its value and use it outside this file ?
>
Sure.
> > + {SECTIONS_WIDTH, SECTIONS_PGSHIFT, SECTIONS_MASK, "Section "},
> > + {NODES_WIDTH, NODES_PGSHIFT, NODES_MASK, "Node "},
> > + {ZONES_WIDTH, ZONES_PGSHIFT, ZONES_MASK, "Zone "},
> > + {LAST_CPUPID_WIDTH, LAST_CPUPID_PGSHIFT, LAST_CPUPID_MASK, "Lastcpupid "},
> > + {KASAN_TAG_WIDTH, KASAN_TAG_PGSHIFT, KASAN_TAG_MASK, "Kasantag "},
> > +};
> > +
> > +static
> > +char *format_layout(char *buf, char *end, unsigned long flags)
> > +{
> > + int i;
> > +
> > + for (i = 0; i < sizeof(pfl) / sizeof(struct page_flags_layout) && buf < end; i++) {
>
> I think we can use ARRAY_SIZE here.
>
Sure.
> > + if (pfl[i].width == 0)
> > + continue;
> > +
> > + buf = string(buf, end, pfl[i].name, default_str_spec);
> > +
> > + if (buf >= end)
> > + break;
> > + buf = number(buf, end, (flags >> pfl[i].shift) & pfl[i].mask,
> > + default_flag_spec);
> > +
> > + if (buf >= end)
> > + break;
> > + *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)
> > @@ -1929,7 +1969,7 @@ char *flags_string(char *buf, char *end, void *flags_ptr,
> > switch (fmt[1]) {
> > case 'p':
> > flags = *(unsigned long *)flags_ptr;
> > - /* Remove zone id */
> > + buf = format_layout(buf, end, flags & ~((1UL << NR_PAGEFLAGS) - 1));
> > flags &= (1UL << NR_PAGEFLAGS) - 1;
> > names = pageflag_names;
> > break;
> >
> Many thanks.
--
Thanks
Yafang
On 1/28/21 3:19 AM, Yafang Shao wrote:
> As pGp has been already introduced in printk, we'd better use it to make
> the output human readable.
>
> Before this change, the output is,
> [ 6155.716018] INFO: Slab 0x000000004027dd4f objects=33 used=3 fp=0x000000008cd1579c flags=0x17ffffc0010200
>
> While after this change, the output is,
> [ 8846.517809] INFO: Slab 0x00000000f42a2c60 objects=33 used=3 fp=0x0000000060d32ca8 flags=0x17ffffc0010200(slab|head)
>
> Reviewed-by: David Hildenbrand <[email protected]>
> Signed-off-by: Yafang Shao <[email protected]>
Reviewed-by: Vlastimil Babka <[email protected]>
> ---
> mm/slub.c | 5 +++--
> 1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/mm/slub.c b/mm/slub.c
> index 69742ab9a21d..4b9ab267afbc 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -641,8 +641,9 @@ void print_tracking(struct kmem_cache *s, void *object)
>
> static void print_page_info(struct page *page)
> {
> - pr_err("INFO: Slab 0x%p objects=%u used=%u fp=0x%p flags=0x%04lx\n",
> - page, page->objects, page->inuse, page->freelist, page->flags);
> + pr_err("INFO: Slab 0x%p objects=%u used=%u fp=0x%p flags=%#lx(%pGp)\n",
> + page, page->objects, page->inuse, page->freelist,
> + page->flags, &page->flags);
>
> }
>
>
On 1/28/21 3:19 AM, Yafang Shao wrote:
> It is strange to combine "pr_err" with "INFO", so let's clean them up.
> This patch is motivated by David's comment[1].
>
> - before the patch
> [ 8846.517809] INFO: Slab 0x00000000f42a2c60 objects=33 used=3 fp=0x0000000060d32ca8 flags=0x17ffffc0010200(slab|head)
>
> - after the patch
> [ 6312.639698] ERR: Slab 0x000000006d1133b9 objects=33 used=3 fp=0x000000006d0779d1 flags=0x17ffffc0010200(slab|head)
>
> [1]. https://lore.kernel.org/linux-mm/[email protected]/#t
>
> Cc: David Hildenbrand <[email protected]>
> Signed-off-by: Yafang Shao <[email protected]>
These are usually printed as part of slab_bug() with its prominent banner. In
that sense it's additional details, thus INFO. The details itself are not error,
thus ERR makes little sense imho. How about removing the prefix completely, or
just replacing with an ident to make it visually part of the BUG report.
> ---
> mm/slub.c | 10 +++++-----
> 1 file changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/mm/slub.c b/mm/slub.c
> index 4b9ab267afbc..18b4474c8fa2 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -615,7 +615,7 @@ static void print_track(const char *s, struct track *t, unsigned long pr_time)
> if (!t->addr)
> return;
>
> - pr_err("INFO: %s in %pS age=%lu cpu=%u pid=%d\n",
> + pr_err("ERR: %s in %pS age=%lu cpu=%u pid=%d\n",
> s, (void *)t->addr, pr_time - t->when, t->cpu, t->pid);
> #ifdef CONFIG_STACKTRACE
> {
> @@ -641,7 +641,7 @@ void print_tracking(struct kmem_cache *s, void *object)
>
> static void print_page_info(struct page *page)
> {
> - pr_err("INFO: Slab 0x%p objects=%u used=%u fp=0x%p flags=%#lx(%pGp)\n",
> + pr_err("ERR: Slab 0x%p objects=%u used=%u fp=0x%p flags=%#lx(%pGp)\n",
> page, page->objects, page->inuse, page->freelist,
> page->flags, &page->flags);
>
> @@ -698,7 +698,7 @@ static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p)
>
> print_page_info(page);
>
> - pr_err("INFO: Object 0x%p @offset=%tu fp=0x%p\n\n",
> + pr_err("ERR: Object 0x%p @offset=%tu fp=0x%p\n\n",
> p, p - addr, get_freepointer(s, p));
>
> if (s->flags & SLAB_RED_ZONE)
> @@ -791,7 +791,7 @@ static int check_bytes_and_report(struct kmem_cache *s, struct page *page,
> end--;
>
> slab_bug(s, "%s overwritten", what);
> - pr_err("INFO: 0x%p-0x%p @offset=%tu. First byte 0x%x instead of 0x%x\n",
> + pr_err("ERR: 0x%p-0x%p @offset=%tu. First byte 0x%x instead of 0x%x\n",
> fault, end - 1, fault - addr,
> fault[0], value);
> print_trailer(s, page, object);
> @@ -3855,7 +3855,7 @@ static void list_slab_objects(struct kmem_cache *s, struct page *page,
> for_each_object(p, s, addr, page->objects) {
>
> if (!test_bit(__obj_to_index(s, addr, p), map)) {
> - pr_err("INFO: Object 0x%p @offset=%tu\n", p, p - addr);
> + pr_err("ERR: Object 0x%p @offset=%tu\n", p, p - addr);
> print_tracking(s, p);
> }
> }
>
On 1/28/21 3:19 AM, Yafang Shao wrote:
> Currently the pGp only shows the names of page flags, rather than
> the full information including section, node, zone, last cpupid and
> kasan tag. While it is not easy to parse these information manually
> because there're so many flavors. Let's interpret them in pGp as well.
>
> - Before the patch,
> [ 6312.639698] ERR: Slab 0x000000006d1133b9 objects=33 used=3 fp=0x000000006d0779d1 flags=0x17ffffc0010200(slab|head)
>
> - After the patch,
> [ 6315.235783] ERR: Slab 0x000000006d1133b9 objects=33 used=3 fp=0x000000006d0779d1 flags=0x17ffffc0010200(Node 0x0,Zone 0x2,Lastcpupid 0x1fffff,slab|head)
node, zone could be decimal?
Thanks
>
> Cc: David Hildenbrand <[email protected]>
> Signed-off-by: Yafang Shao <[email protected]>
> ---
> lib/vsprintf.c | 42 +++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 41 insertions(+), 1 deletion(-)
>
> diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> index 3b53c73580c5..bd809f4f1b82 100644
> --- a/lib/vsprintf.c
> +++ b/lib/vsprintf.c
> @@ -1916,6 +1916,46 @@ char *format_flags(char *buf, char *end, unsigned long flags,
> return buf;
> }
>
> +struct page_flags_layout {
> + int width;
> + int shift;
> + int mask;
> + char *name;
> +};
> +
> +struct page_flags_layout pfl[] = {
> + {SECTIONS_WIDTH, SECTIONS_PGSHIFT, SECTIONS_MASK, "Section "},
> + {NODES_WIDTH, NODES_PGSHIFT, NODES_MASK, "Node "},
> + {ZONES_WIDTH, ZONES_PGSHIFT, ZONES_MASK, "Zone "},
> + {LAST_CPUPID_WIDTH, LAST_CPUPID_PGSHIFT, LAST_CPUPID_MASK, "Lastcpupid "},
> + {KASAN_TAG_WIDTH, KASAN_TAG_PGSHIFT, KASAN_TAG_MASK, "Kasantag "},
> +};
> +
> +static
> +char *format_layout(char *buf, char *end, unsigned long flags)
> +{
> + int i;
> +
> + for (i = 0; i < sizeof(pfl) / sizeof(struct page_flags_layout) && buf < end; i++) {
> + if (pfl[i].width == 0)
> + continue;
> +
> + buf = string(buf, end, pfl[i].name, default_str_spec);
> +
> + if (buf >= end)
> + break;
> + buf = number(buf, end, (flags >> pfl[i].shift) & pfl[i].mask,
> + default_flag_spec);
> +
> + if (buf >= end)
> + break;
> + *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)
> @@ -1929,7 +1969,7 @@ char *flags_string(char *buf, char *end, void *flags_ptr,
> switch (fmt[1]) {
> case 'p':
> flags = *(unsigned long *)flags_ptr;
> - /* Remove zone id */
> + buf = format_layout(buf, end, flags & ~((1UL << NR_PAGEFLAGS) - 1));
> flags &= (1UL << NR_PAGEFLAGS) - 1;
> names = pageflag_names;
> break;
>
On Thu, Jan 28, 2021 at 10:19:47AM +0800, Yafang Shao wrote:
> Currently the pGp only shows the names of page flags, rather than
> the full information including section, node, zone, last cpupid and
> kasan tag. While it is not easy to parse these information manually
> because there're so many flavors. Let's interpret them in pGp as well.
>
> - Before the patch,
> [ 6312.639698] ERR: Slab 0x000000006d1133b9 objects=33 used=3 fp=0x000000006d0779d1 flags=0x17ffffc0010200(slab|head)
>
> - After the patch,
> [ 6315.235783] ERR: Slab 0x000000006d1133b9 objects=33 used=3 fp=0x000000006d0779d1 flags=0x17ffffc0010200(Node 0x0,Zone 0x2,Lastcpupid 0x1fffff,slab|head)
> + int i;
> +
> + for (i = 0; i < sizeof(pfl) / sizeof(struct page_flags_layout) && buf < end; i++) {
'buf < end' is redundant.
> + if (pfl[i].width == 0)
> + continue;
> +
> + buf = string(buf, end, pfl[i].name, default_str_spec);
> + if (buf >= end)
> + break;
Can you rather use usual patter, i.e.
if (buf < end) {
...do something...
}
buf++; // or whatever increase should be done
Moreover, number() and string() IIRC have the proper checks embedded into them.
> + buf = number(buf, end, (flags >> pfl[i].shift) & pfl[i].mask,
> + default_flag_spec);
> + if (buf >= end)
> + break;
> + *buf = ',';
> + buf++;
Here is a very standard pattern can be used, see code around
if (buf < end)
*buf = ',';
buf++;
> + }
--
With Best Regards,
Andy Shevchenko
On Thu, Jan 28, 2021 at 10:19:44AM +0800, Yafang Shao wrote:
> Currently the pGp only shows the names of page flags, rather than
> the full information including section, node, zone, last cpupid and
> kasan tag. While it is not easy to parse these information manually
> because there're so many flavors. Let's interpret them in pGp as well.
>
> This patchset also includes some code cleanup in mm/slub.c.
>
> Below is the example of the output in mm/slub.c.
> - Before the patchset
> [ 6155.716018] INFO: Slab 0x000000004027dd4f objects=33 used=3 fp=0x000000008cd1579c flags=0x17ffffc0010200
>
> - After the patchset
> [ 6315.235783] ERR: Slab 0x000000006d1133b9 objects=33 used=3 fp=0x000000006d0779d1 flags=0x17ffffc0010200(Node 0x0,Zone 0x2,Lastcpupid 0x1fffff,slab|head)
Please, add a corresponding test cases to test_printf.c. W/o test cases NAK.
--
With Best Regards,
Andy Shevchenko
On Thu, Jan 28, 2021 at 6:35 PM Vlastimil Babka <[email protected]> wrote:
>
> On 1/28/21 3:19 AM, Yafang Shao wrote:
> > It is strange to combine "pr_err" with "INFO", so let's clean them up.
> > This patch is motivated by David's comment[1].
> >
> > - before the patch
> > [ 8846.517809] INFO: Slab 0x00000000f42a2c60 objects=33 used=3 fp=0x0000000060d32ca8 flags=0x17ffffc0010200(slab|head)
> >
> > - after the patch
> > [ 6312.639698] ERR: Slab 0x000000006d1133b9 objects=33 used=3 fp=0x000000006d0779d1 flags=0x17ffffc0010200(slab|head)
> >
> > [1]. https://lore.kernel.org/linux-mm/[email protected]/#t
> >
> > Cc: David Hildenbrand <[email protected]>
> > Signed-off-by: Yafang Shao <[email protected]>
>
> These are usually printed as part of slab_bug() with its prominent banner. In
> that sense it's additional details, thus INFO. The details itself are not error,
> thus ERR makes little sense imho. How about removing the prefix completely, or
> just replacing with an ident to make it visually part of the BUG report.
>
Thanks for the explanation. I will remove the prefix completely in the
next version.
> > ---
> > mm/slub.c | 10 +++++-----
> > 1 file changed, 5 insertions(+), 5 deletions(-)
> >
> > diff --git a/mm/slub.c b/mm/slub.c
> > index 4b9ab267afbc..18b4474c8fa2 100644
> > --- a/mm/slub.c
> > +++ b/mm/slub.c
> > @@ -615,7 +615,7 @@ static void print_track(const char *s, struct track *t, unsigned long pr_time)
> > if (!t->addr)
> > return;
> >
> > - pr_err("INFO: %s in %pS age=%lu cpu=%u pid=%d\n",
> > + pr_err("ERR: %s in %pS age=%lu cpu=%u pid=%d\n",
> > s, (void *)t->addr, pr_time - t->when, t->cpu, t->pid);
> > #ifdef CONFIG_STACKTRACE
> > {
> > @@ -641,7 +641,7 @@ void print_tracking(struct kmem_cache *s, void *object)
> >
> > static void print_page_info(struct page *page)
> > {
> > - pr_err("INFO: Slab 0x%p objects=%u used=%u fp=0x%p flags=%#lx(%pGp)\n",
> > + pr_err("ERR: Slab 0x%p objects=%u used=%u fp=0x%p flags=%#lx(%pGp)\n",
> > page, page->objects, page->inuse, page->freelist,
> > page->flags, &page->flags);
> >
> > @@ -698,7 +698,7 @@ static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p)
> >
> > print_page_info(page);
> >
> > - pr_err("INFO: Object 0x%p @offset=%tu fp=0x%p\n\n",
> > + pr_err("ERR: Object 0x%p @offset=%tu fp=0x%p\n\n",
> > p, p - addr, get_freepointer(s, p));
> >
> > if (s->flags & SLAB_RED_ZONE)
> > @@ -791,7 +791,7 @@ static int check_bytes_and_report(struct kmem_cache *s, struct page *page,
> > end--;
> >
> > slab_bug(s, "%s overwritten", what);
> > - pr_err("INFO: 0x%p-0x%p @offset=%tu. First byte 0x%x instead of 0x%x\n",
> > + pr_err("ERR: 0x%p-0x%p @offset=%tu. First byte 0x%x instead of 0x%x\n",
> > fault, end - 1, fault - addr,
> > fault[0], value);
> > print_trailer(s, page, object);
> > @@ -3855,7 +3855,7 @@ static void list_slab_objects(struct kmem_cache *s, struct page *page,
> > for_each_object(p, s, addr, page->objects) {
> >
> > if (!test_bit(__obj_to_index(s, addr, p), map)) {
> > - pr_err("INFO: Object 0x%p @offset=%tu\n", p, p - addr);
> > + pr_err("ERR: Object 0x%p @offset=%tu\n", p, p - addr);
> > print_tracking(s, p);
> > }
> > }
> >
>
--
Thanks
Yafang
On Thu, Jan 28, 2021 at 6:42 PM Vlastimil Babka <[email protected]> wrote:
>
> On 1/28/21 3:19 AM, Yafang Shao wrote:
> > Currently the pGp only shows the names of page flags, rather than
> > the full information including section, node, zone, last cpupid and
> > kasan tag. While it is not easy to parse these information manually
> > because there're so many flavors. Let's interpret them in pGp as well.
> >
> > - Before the patch,
> > [ 6312.639698] ERR: Slab 0x000000006d1133b9 objects=33 used=3 fp=0x000000006d0779d1 flags=0x17ffffc0010200(slab|head)
> >
> > - After the patch,
> > [ 6315.235783] ERR: Slab 0x000000006d1133b9 objects=33 used=3 fp=0x000000006d0779d1 flags=0x17ffffc0010200(Node 0x0,Zone 0x2,Lastcpupid 0x1fffff,slab|head)
>
> node, zone could be decimal?
Make sense to me. Will change it.
>
> >
> > Cc: David Hildenbrand <[email protected]>
> > Signed-off-by: Yafang Shao <[email protected]>
> > ---
> > lib/vsprintf.c | 42 +++++++++++++++++++++++++++++++++++++++++-
> > 1 file changed, 41 insertions(+), 1 deletion(-)
> >
> > diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> > index 3b53c73580c5..bd809f4f1b82 100644
> > --- a/lib/vsprintf.c
> > +++ b/lib/vsprintf.c
> > @@ -1916,6 +1916,46 @@ char *format_flags(char *buf, char *end, unsigned long flags,
> > return buf;
> > }
> >
> > +struct page_flags_layout {
> > + int width;
> > + int shift;
> > + int mask;
> > + char *name;
> > +};
> > +
> > +struct page_flags_layout pfl[] = {
> > + {SECTIONS_WIDTH, SECTIONS_PGSHIFT, SECTIONS_MASK, "Section "},
> > + {NODES_WIDTH, NODES_PGSHIFT, NODES_MASK, "Node "},
> > + {ZONES_WIDTH, ZONES_PGSHIFT, ZONES_MASK, "Zone "},
> > + {LAST_CPUPID_WIDTH, LAST_CPUPID_PGSHIFT, LAST_CPUPID_MASK, "Lastcpupid "},
> > + {KASAN_TAG_WIDTH, KASAN_TAG_PGSHIFT, KASAN_TAG_MASK, "Kasantag "},
> > +};
> > +
> > +static
> > +char *format_layout(char *buf, char *end, unsigned long flags)
> > +{
> > + int i;
> > +
> > + for (i = 0; i < sizeof(pfl) / sizeof(struct page_flags_layout) && buf < end; i++) {
> > + if (pfl[i].width == 0)
> > + continue;
> > +
> > + buf = string(buf, end, pfl[i].name, default_str_spec);
> > +
> > + if (buf >= end)
> > + break;
> > + buf = number(buf, end, (flags >> pfl[i].shift) & pfl[i].mask,
> > + default_flag_spec);
> > +
> > + if (buf >= end)
> > + break;
> > + *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)
> > @@ -1929,7 +1969,7 @@ char *flags_string(char *buf, char *end, void *flags_ptr,
> > switch (fmt[1]) {
> > case 'p':
> > flags = *(unsigned long *)flags_ptr;
> > - /* Remove zone id */
> > + buf = format_layout(buf, end, flags & ~((1UL << NR_PAGEFLAGS) - 1));
> > flags &= (1UL << NR_PAGEFLAGS) - 1;
> > names = pageflag_names;
> > break;
> >
>
--
Thanks
Yafang
On Thu, Jan 28, 2021 at 8:11 PM Andy Shevchenko
<[email protected]> wrote:
>
> On Thu, Jan 28, 2021 at 10:19:47AM +0800, Yafang Shao wrote:
> > Currently the pGp only shows the names of page flags, rather than
> > the full information including section, node, zone, last cpupid and
> > kasan tag. While it is not easy to parse these information manually
> > because there're so many flavors. Let's interpret them in pGp as well.
> >
> > - Before the patch,
> > [ 6312.639698] ERR: Slab 0x000000006d1133b9 objects=33 used=3 fp=0x000000006d0779d1 flags=0x17ffffc0010200(slab|head)
> >
> > - After the patch,
> > [ 6315.235783] ERR: Slab 0x000000006d1133b9 objects=33 used=3 fp=0x000000006d0779d1 flags=0x17ffffc0010200(Node 0x0,Zone 0x2,Lastcpupid 0x1fffff,slab|head)
>
> > + int i;
> > +
> > + for (i = 0; i < sizeof(pfl) / sizeof(struct page_flags_layout) && buf < end; i++) {
>
> 'buf < end' is redundant.
>
Thanks for pointing this out.
> > + if (pfl[i].width == 0)
> > + continue;
> > +
> > + buf = string(buf, end, pfl[i].name, default_str_spec);
>
> > + if (buf >= end)
> > + break;
>
> Can you rather use usual patter, i.e.
>
> if (buf < end) {
> ...do something...
> }
> buf++; // or whatever increase should be done
>
> Moreover, number() and string() IIRC have the proper checks embedded into them.
>
I will take a look at the detail in these two functions.
> > + buf = number(buf, end, (flags >> pfl[i].shift) & pfl[i].mask,
> > + default_flag_spec);
>
> > + if (buf >= end)
> > + break;
> > + *buf = ',';
> > + buf++;
>
> Here is a very standard pattern can be used, see code around
>
> if (buf < end)
> *buf = ',';
> buf++;
>
> > + }
>
Thanks for the explanation.
I will change it as you suggested.
--
Thanks
Yafang
On Thu, Jan 28, 2021 at 8:12 PM Andy Shevchenko
<[email protected]> wrote:
>
> On Thu, Jan 28, 2021 at 10:19:44AM +0800, Yafang Shao wrote:
> > Currently the pGp only shows the names of page flags, rather than
> > the full information including section, node, zone, last cpupid and
> > kasan tag. While it is not easy to parse these information manually
> > because there're so many flavors. Let's interpret them in pGp as well.
> >
> > This patchset also includes some code cleanup in mm/slub.c.
> >
> > Below is the example of the output in mm/slub.c.
> > - Before the patchset
> > [ 6155.716018] INFO: Slab 0x000000004027dd4f objects=33 used=3 fp=0x000000008cd1579c flags=0x17ffffc0010200
> >
> > - After the patchset
> > [ 6315.235783] ERR: Slab 0x000000006d1133b9 objects=33 used=3 fp=0x000000006d0779d1 flags=0x17ffffc0010200(Node 0x0,Zone 0x2,Lastcpupid 0x1fffff,slab|head)
>
>
> Please, add a corresponding test cases to test_printf.c. W/o test cases NAK.
>
Sure. Will add the test cases in the next version.
--
Thanks
Yafang
On Thu, Jan 28, 2021 at 09:18:24PM +0800, Yafang Shao wrote:
> On Thu, Jan 28, 2021 at 8:11 PM Andy Shevchenko
> <[email protected]> wrote:
...
> Thanks for the explanation.
> I will change it as you suggested.
You are welcome!
Just note, that kasprintf() should work for this as well as for the rest
printf() cases. That's why it's very important to return proper buffer pointer.
Also read `man snprintf(3)` RETURN VALUE section to understand it.
--
With Best Regards,
Andy Shevchenko
On Thu, 28 Jan 2021, Yafang Shao wrote:
> As pGp has been already introduced in printk, we'd better use it to make
> the output human readable.
>
> Before this change, the output is,
> [ 6155.716018] INFO: Slab 0x000000004027dd4f objects=33 used=3 fp=0x000000008cd1579c flags=0x17ffffc0010200
>
> While after this change, the output is,
> [ 8846.517809] INFO: Slab 0x00000000f42a2c60 objects=33 used=3 fp=0x0000000060d32ca8 flags=0x17ffffc0010200(slab|head)
>
> Reviewed-by: David Hildenbrand <[email protected]>
> Signed-off-by: Yafang Shao <[email protected]>
Acked-by: David Rientjes <[email protected]>
On Thu, Jan 28, 2021 at 10:50 PM Andy Shevchenko
<[email protected]> wrote:
>
> On Thu, Jan 28, 2021 at 09:18:24PM +0800, Yafang Shao wrote:
> > On Thu, Jan 28, 2021 at 8:11 PM Andy Shevchenko
> > <[email protected]> wrote:
>
> ...
>
> > Thanks for the explanation.
> > I will change it as you suggested.
>
> You are welcome!
>
> Just note, that kasprintf() should work for this as well as for the rest
> printf() cases. That's why it's very important to return proper buffer pointer.
>
> Also read `man snprintf(3)` RETURN VALUE section to understand it.
>
Thanks for the information. I will take a look at it.
--
Thanks
Yafang