summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/printk-formats.txt18
-rw-r--r--lib/test_printf.c53
-rw-r--r--lib/vsprintf.c75
-rw-r--r--mm/debug.c34
-rw-r--r--mm/internal.h6
5 files changed, 172 insertions, 14 deletions
diff --git a/Documentation/printk-formats.txt b/Documentation/printk-formats.txt
index 5d1128bf0282..5962949944fd 100644
--- a/Documentation/printk-formats.txt
+++ b/Documentation/printk-formats.txt
@@ -298,6 +298,24 @@ bitmap and its derivatives such as cpumask and nodemask:
298 298
299 Passed by reference. 299 Passed by reference.
300 300
301Flags bitfields such as page flags, gfp_flags:
302
303 %pGp referenced|uptodate|lru|active|private
304 %pGg GFP_USER|GFP_DMA32|GFP_NOWARN
305 %pGv read|exec|mayread|maywrite|mayexec|denywrite
306
307 For printing flags bitfields as a collection of symbolic constants that
308 would construct the value. The type of flags is given by the third
309 character. Currently supported are [p]age flags, [v]ma_flags (both
310 expect unsigned long *) and [g]fp_flags (expects gfp_t *). The flag
311 names and print order depends on the particular type.
312
313 Note that this format should not be used directly in TP_printk() part
314 of a tracepoint. Instead, use the show_*_flags() functions from
315 <trace/events/mmflags.h>.
316
317 Passed by reference.
318
301Network device features: 319Network device features:
302 320
303 %pNF 0x000000000000c000 321 %pNF 0x000000000000c000
diff --git a/lib/test_printf.c b/lib/test_printf.c
index 4f6ae60433bc..563f10e6876a 100644
--- a/lib/test_printf.c
+++ b/lib/test_printf.c
@@ -17,6 +17,9 @@
17#include <linux/socket.h> 17#include <linux/socket.h>
18#include <linux/in.h> 18#include <linux/in.h>
19 19
20#include <linux/gfp.h>
21#include <linux/mm.h>
22
20#define BUF_SIZE 256 23#define BUF_SIZE 256
21#define PAD_SIZE 16 24#define PAD_SIZE 16
22#define FILL_CHAR '$' 25#define FILL_CHAR '$'
@@ -411,6 +414,55 @@ netdev_features(void)
411} 414}
412 415
413static void __init 416static void __init
417flags(void)
418{
419 unsigned long flags;
420 gfp_t gfp;
421 char *cmp_buffer;
422
423 flags = 0;
424 test("", "%pGp", &flags);
425
426 /* Page flags should filter the zone id */
427 flags = 1UL << NR_PAGEFLAGS;
428 test("", "%pGp", &flags);
429
430 flags |= 1UL << PG_uptodate | 1UL << PG_dirty | 1UL << PG_lru
431 | 1UL << PG_active | 1UL << PG_swapbacked;
432 test("uptodate|dirty|lru|active|swapbacked", "%pGp", &flags);
433
434
435 flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC
436 | VM_DENYWRITE;
437 test("read|exec|mayread|maywrite|mayexec|denywrite", "%pGv", &flags);
438
439 gfp = GFP_TRANSHUGE;
440 test("GFP_TRANSHUGE", "%pGg", &gfp);
441
442 gfp = GFP_ATOMIC|__GFP_DMA;
443 test("GFP_ATOMIC|GFP_DMA", "%pGg", &gfp);
444
445 gfp = __GFP_ATOMIC;
446 test("__GFP_ATOMIC", "%pGg", &gfp);
447
448 cmp_buffer = kmalloc(BUF_SIZE, GFP_KERNEL);
449 if (!cmp_buffer)
450 return;
451
452 /* Any flags not translated by the table should remain numeric */
453 gfp = ~__GFP_BITS_MASK;
454 snprintf(cmp_buffer, BUF_SIZE, "%#lx", (unsigned long) gfp);
455 test(cmp_buffer, "%pGg", &gfp);
456
457 snprintf(cmp_buffer, BUF_SIZE, "__GFP_ATOMIC|%#lx",
458 (unsigned long) gfp);
459 gfp |= __GFP_ATOMIC;
460 test(cmp_buffer, "%pGg", &gfp);
461
462 kfree(cmp_buffer);
463}
464
465static void __init
414test_pointer(void) 466test_pointer(void)
415{ 467{
416 plain(); 468 plain();
@@ -428,6 +480,7 @@ test_pointer(void)
428 struct_clk(); 480 struct_clk();
429 bitmap(); 481 bitmap();
430 netdev_features(); 482 netdev_features();
483 flags();
431} 484}
432 485
433static int __init 486static int __init
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index f44e178e6ede..525c8e19bda2 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -35,6 +35,8 @@
35#include <linux/blkdev.h> 35#include <linux/blkdev.h>
36#endif 36#endif
37 37
38#include "../mm/internal.h" /* For the trace_print_flags arrays */
39
38#include <asm/page.h> /* for PAGE_SIZE */ 40#include <asm/page.h> /* for PAGE_SIZE */
39#include <asm/sections.h> /* for dereference_function_descriptor() */ 41#include <asm/sections.h> /* for dereference_function_descriptor() */
40#include <asm/byteorder.h> /* cpu_to_le16 */ 42#include <asm/byteorder.h> /* cpu_to_le16 */
@@ -1407,6 +1409,72 @@ char *clock(char *buf, char *end, struct clk *clk, struct printf_spec spec,
1407 } 1409 }
1408} 1410}
1409 1411
1412static
1413char *format_flags(char *buf, char *end, unsigned long flags,
1414 const struct trace_print_flags *names)
1415{
1416 unsigned long mask;
1417 const struct printf_spec strspec = {
1418 .field_width = -1,
1419 .precision = -1,
1420 };
1421 const struct printf_spec numspec = {
1422 .flags = SPECIAL|SMALL,
1423 .field_width = -1,
1424 .precision = -1,
1425 .base = 16,
1426 };
1427
1428 for ( ; flags && names->name; names++) {
1429 mask = names->mask;
1430 if ((flags & mask) != mask)
1431 continue;
1432
1433 buf = string(buf, end, names->name, strspec);
1434
1435 flags &= ~mask;
1436 if (flags) {
1437 if (buf < end)
1438 *buf = '|';
1439 buf++;
1440 }
1441 }
1442
1443 if (flags)
1444 buf = number(buf, end, flags, numspec);
1445
1446 return buf;
1447}
1448
1449static noinline_for_stack
1450char *flags_string(char *buf, char *end, void *flags_ptr, const char *fmt)
1451{
1452 unsigned long flags;
1453 const struct trace_print_flags *names;
1454
1455 switch (fmt[1]) {
1456 case 'p':
1457 flags = *(unsigned long *)flags_ptr;
1458 /* Remove zone id */
1459 flags &= (1UL << NR_PAGEFLAGS) - 1;
1460 names = pageflag_names;
1461 break;
1462 case 'v':
1463 flags = *(unsigned long *)flags_ptr;
1464 names = vmaflag_names;
1465 break;
1466 case 'g':
1467 flags = *(gfp_t *)flags_ptr;
1468 names = gfpflag_names;
1469 break;
1470 default:
1471 WARN_ONCE(1, "Unsupported flags modifier: %c\n", fmt[1]);
1472 return buf;
1473 }
1474
1475 return format_flags(buf, end, flags, names);
1476}
1477
1410int kptr_restrict __read_mostly; 1478int kptr_restrict __read_mostly;
1411 1479
1412/* 1480/*
@@ -1495,6 +1563,11 @@ int kptr_restrict __read_mostly;
1495 * - 'Cn' For a clock, it prints the name (Common Clock Framework) or address 1563 * - 'Cn' For a clock, it prints the name (Common Clock Framework) or address
1496 * (legacy clock framework) of the clock 1564 * (legacy clock framework) of the clock
1497 * - 'Cr' For a clock, it prints the current rate of the clock 1565 * - 'Cr' For a clock, it prints the current rate of the clock
1566 * - 'G' For flags to be printed as a collection of symbolic strings that would
1567 * construct the specific value. Supported flags given by option:
1568 * p page flags (see struct page) given as pointer to unsigned long
1569 * g gfp flags (GFP_* and __GFP_*) given as pointer to gfp_t
1570 * v vma flags (VM_*) given as pointer to unsigned long
1498 * 1571 *
1499 * ** Please update also Documentation/printk-formats.txt when making changes ** 1572 * ** Please update also Documentation/printk-formats.txt when making changes **
1500 * 1573 *
@@ -1648,6 +1721,8 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
1648 return bdev_name(buf, end, ptr, spec, fmt); 1721 return bdev_name(buf, end, ptr, spec, fmt);
1649#endif 1722#endif
1650 1723
1724 case 'G':
1725 return flags_string(buf, end, ptr, fmt);
1651 } 1726 }
1652 spec.flags |= SMALL; 1727 spec.flags |= SMALL;
1653 if (spec.field_width == -1) { 1728 if (spec.field_width == -1) {
diff --git a/mm/debug.c b/mm/debug.c
index 410af904a7d5..0328fd377545 100644
--- a/mm/debug.c
+++ b/mm/debug.c
@@ -11,12 +11,21 @@
11#include <linux/memcontrol.h> 11#include <linux/memcontrol.h>
12#include <trace/events/mmflags.h> 12#include <trace/events/mmflags.h>
13 13
14static const struct trace_print_flags pageflag_names[] = { 14#include "internal.h"
15 __def_pageflag_names 15
16const struct trace_print_flags pageflag_names[] = {
17 __def_pageflag_names,
18 {0, NULL}
19};
20
21const struct trace_print_flags gfpflag_names[] = {
22 __def_gfpflag_names,
23 {0, NULL}
16}; 24};
17 25
18static const struct trace_print_flags gfpflag_names[] = { 26const struct trace_print_flags vmaflag_names[] = {
19 __def_gfpflag_names 27 __def_vmaflag_names,
28 {0, NULL}
20}; 29};
21 30
22static void dump_flags(unsigned long flags, 31static void dump_flags(unsigned long flags,
@@ -58,14 +67,15 @@ void dump_page_badflags(struct page *page, const char *reason,
58 if (PageCompound(page)) 67 if (PageCompound(page))
59 pr_cont(" compound_mapcount: %d", compound_mapcount(page)); 68 pr_cont(" compound_mapcount: %d", compound_mapcount(page));
60 pr_cont("\n"); 69 pr_cont("\n");
61 BUILD_BUG_ON(ARRAY_SIZE(pageflag_names) != __NR_PAGEFLAGS); 70 BUILD_BUG_ON(ARRAY_SIZE(pageflag_names) != __NR_PAGEFLAGS + 1);
62 dump_flags(page->flags, pageflag_names, ARRAY_SIZE(pageflag_names)); 71 dump_flags(page->flags, pageflag_names,
72 ARRAY_SIZE(pageflag_names) - 1);
63 if (reason) 73 if (reason)
64 pr_alert("page dumped because: %s\n", reason); 74 pr_alert("page dumped because: %s\n", reason);
65 if (page->flags & badflags) { 75 if (page->flags & badflags) {
66 pr_alert("bad because of flags:\n"); 76 pr_alert("bad because of flags:\n");
67 dump_flags(page->flags & badflags, 77 dump_flags(page->flags & badflags, pageflag_names,
68 pageflag_names, ARRAY_SIZE(pageflag_names)); 78 ARRAY_SIZE(pageflag_names) - 1);
69 } 79 }
70#ifdef CONFIG_MEMCG 80#ifdef CONFIG_MEMCG
71 if (page->mem_cgroup) 81 if (page->mem_cgroup)
@@ -81,10 +91,6 @@ EXPORT_SYMBOL(dump_page);
81 91
82#ifdef CONFIG_DEBUG_VM 92#ifdef CONFIG_DEBUG_VM
83 93
84static const struct trace_print_flags vmaflag_names[] = {
85 __def_vmaflag_names
86};
87
88void dump_vma(const struct vm_area_struct *vma) 94void dump_vma(const struct vm_area_struct *vma)
89{ 95{
90 pr_emerg("vma %p start %p end %p\n" 96 pr_emerg("vma %p start %p end %p\n"
@@ -96,7 +102,7 @@ void dump_vma(const struct vm_area_struct *vma)
96 (unsigned long)pgprot_val(vma->vm_page_prot), 102 (unsigned long)pgprot_val(vma->vm_page_prot),
97 vma->anon_vma, vma->vm_ops, vma->vm_pgoff, 103 vma->anon_vma, vma->vm_ops, vma->vm_pgoff,
98 vma->vm_file, vma->vm_private_data); 104 vma->vm_file, vma->vm_private_data);
99 dump_flags(vma->vm_flags, vmaflag_names, ARRAY_SIZE(vmaflag_names)); 105 dump_flags(vma->vm_flags, vmaflag_names, ARRAY_SIZE(vmaflag_names) - 1);
100} 106}
101EXPORT_SYMBOL(dump_vma); 107EXPORT_SYMBOL(dump_vma);
102 108
@@ -168,7 +174,7 @@ void dump_mm(const struct mm_struct *mm)
168 ); 174 );
169 175
170 dump_flags(mm->def_flags, vmaflag_names, 176 dump_flags(mm->def_flags, vmaflag_names,
171 ARRAY_SIZE(vmaflag_names)); 177 ARRAY_SIZE(vmaflag_names) - 1);
172} 178}
173 179
174#endif /* CONFIG_DEBUG_VM */ 180#endif /* CONFIG_DEBUG_VM */
diff --git a/mm/internal.h b/mm/internal.h
index a38a21ebddb4..6636e1d3ecf0 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -14,6 +14,7 @@
14#include <linux/fs.h> 14#include <linux/fs.h>
15#include <linux/mm.h> 15#include <linux/mm.h>
16#include <linux/pagemap.h> 16#include <linux/pagemap.h>
17#include <linux/tracepoint-defs.h>
17 18
18/* 19/*
19 * The set of flags that only affect watermark checking and reclaim 20 * The set of flags that only affect watermark checking and reclaim
@@ -466,4 +467,9 @@ static inline void try_to_unmap_flush_dirty(void)
466} 467}
467 468
468#endif /* CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH */ 469#endif /* CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH */
470
471extern const struct trace_print_flags pageflag_names[];
472extern const struct trace_print_flags vmaflag_names[];
473extern const struct trace_print_flags gfpflag_names[];
474
469#endif /* __MM_INTERNAL_H */ 475#endif /* __MM_INTERNAL_H */