summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/test_printf.c53
-rw-r--r--lib/vsprintf.c75
2 files changed, 128 insertions, 0 deletions
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) {