diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/test_printf.c | 53 | ||||
-rw-r--r-- | lib/vsprintf.c | 75 |
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 | ||
413 | static void __init | 416 | static void __init |
417 | flags(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 | |||
465 | static void __init | ||
414 | test_pointer(void) | 466 | test_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 | ||
433 | static int __init | 486 | static 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 | ||
1412 | static | ||
1413 | char *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 | |||
1449 | static noinline_for_stack | ||
1450 | char *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 | |||
1410 | int kptr_restrict __read_mostly; | 1478 | int 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) { |