diff options
author | Joe Perches <joe@perches.com> | 2012-09-12 23:11:29 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-09-17 09:08:30 -0400 |
commit | 798efc60e4276825df34af0e91ecbe0781237834 (patch) | |
tree | 8ccec7118a7a76f5731fecb8507643c44936eb49 | |
parent | 8f949b9a7e0bac3a9c3c29dc27c476a87e21db3e (diff) |
dev_dbg/dynamic_debug: Update to use printk_emit, optimize stack
commit c4e00daaa9
("driver-core: extend dev_printk() to pass structured data")
changed __dev_printk and broke dynamic-debug's ability to control the
dynamic prefix of dev_dbg(dev,..).
commit af7f2158fd
("drivers-core: make structured logging play nice with dynamic-debug")
made a minimal correction.
The current dynamic debug code uses up to 3 recursion levels via %pV.
This can consume quite a bit of stack. Directly call printk_emit to
reduce the recursion depth.
These changes include:
dev_dbg:
o Create and use function create_syslog_header to format the syslog
header for printk_emit uses.
o Call create_syslog_header and neaten __dev_printk
o Make __dev_printk static not global
o Remove include header declaration of __dev_printk
o Remove now unused EXPORT_SYMBOL() of __dev_printk
o Whitespace neatening
dynamic_dev_dbg:
o Remove KERN_DEBUG from dynamic_emit_prefix
o Call create_syslog_header and printk_emit
o Whitespace neatening
Signed-off-by: Joe Perches <joe@perches.com>
Acked-by: David S. Miller <davem@davemloft.net>
Tested-by: Jim Cromie <jim.cromie@gmail.com>
Acked-by: Jason Baron <jbaron@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/base/core.c | 64 | ||||
-rw-r--r-- | include/linux/device.h | 8 | ||||
-rw-r--r-- | lib/dynamic_debug.c | 39 |
3 files changed, 67 insertions, 44 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index 91478bd35418..d325b9dab3ff 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -1865,26 +1865,19 @@ void device_shutdown(void) | |||
1865 | */ | 1865 | */ |
1866 | 1866 | ||
1867 | #ifdef CONFIG_PRINTK | 1867 | #ifdef CONFIG_PRINTK |
1868 | int __dev_printk(const char *level, const struct device *dev, | 1868 | int create_syslog_header(const struct device *dev, char *hdr, size_t hdrlen) |
1869 | struct va_format *vaf) | ||
1870 | { | 1869 | { |
1871 | char dict[128]; | ||
1872 | const char *level_extra = ""; | ||
1873 | size_t dictlen = 0; | ||
1874 | const char *subsys; | 1870 | const char *subsys; |
1875 | 1871 | size_t pos = 0; | |
1876 | if (!dev) | ||
1877 | return printk("%s(NULL device *): %pV", level, vaf); | ||
1878 | 1872 | ||
1879 | if (dev->class) | 1873 | if (dev->class) |
1880 | subsys = dev->class->name; | 1874 | subsys = dev->class->name; |
1881 | else if (dev->bus) | 1875 | else if (dev->bus) |
1882 | subsys = dev->bus->name; | 1876 | subsys = dev->bus->name; |
1883 | else | 1877 | else |
1884 | goto skip; | 1878 | return 0; |
1885 | 1879 | ||
1886 | dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen, | 1880 | pos += snprintf(hdr + pos, hdrlen - pos, "SUBSYSTEM=%s", subsys); |
1887 | "SUBSYSTEM=%s", subsys); | ||
1888 | 1881 | ||
1889 | /* | 1882 | /* |
1890 | * Add device identifier DEVICE=: | 1883 | * Add device identifier DEVICE=: |
@@ -1900,32 +1893,41 @@ int __dev_printk(const char *level, const struct device *dev, | |||
1900 | c = 'b'; | 1893 | c = 'b'; |
1901 | else | 1894 | else |
1902 | c = 'c'; | 1895 | c = 'c'; |
1903 | dictlen++; | 1896 | pos++; |
1904 | dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen, | 1897 | pos += snprintf(hdr + pos, hdrlen - pos, |
1905 | "DEVICE=%c%u:%u", | 1898 | "DEVICE=%c%u:%u", |
1906 | c, MAJOR(dev->devt), MINOR(dev->devt)); | 1899 | c, MAJOR(dev->devt), MINOR(dev->devt)); |
1907 | } else if (strcmp(subsys, "net") == 0) { | 1900 | } else if (strcmp(subsys, "net") == 0) { |
1908 | struct net_device *net = to_net_dev(dev); | 1901 | struct net_device *net = to_net_dev(dev); |
1909 | 1902 | ||
1910 | dictlen++; | 1903 | pos++; |
1911 | dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen, | 1904 | pos += snprintf(hdr + pos, hdrlen - pos, |
1912 | "DEVICE=n%u", net->ifindex); | 1905 | "DEVICE=n%u", net->ifindex); |
1913 | } else { | 1906 | } else { |
1914 | dictlen++; | 1907 | pos++; |
1915 | dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen, | 1908 | pos += snprintf(hdr + pos, hdrlen - pos, |
1916 | "DEVICE=+%s:%s", subsys, dev_name(dev)); | 1909 | "DEVICE=+%s:%s", subsys, dev_name(dev)); |
1917 | } | 1910 | } |
1918 | skip: | ||
1919 | if (level[2]) | ||
1920 | level_extra = &level[2]; /* skip past KERN_SOH "L" */ | ||
1921 | 1911 | ||
1922 | return printk_emit(0, level[1] - '0', | 1912 | return pos; |
1923 | dictlen ? dict : NULL, dictlen, | 1913 | } |
1924 | "%s %s: %s%pV", | 1914 | EXPORT_SYMBOL(create_syslog_header); |
1925 | dev_driver_string(dev), dev_name(dev), | 1915 | |
1926 | level_extra, vaf); | 1916 | static int __dev_printk(const char *level, const struct device *dev, |
1917 | struct va_format *vaf) | ||
1918 | { | ||
1919 | char hdr[128]; | ||
1920 | size_t hdrlen; | ||
1921 | |||
1922 | if (!dev) | ||
1923 | return printk("%s(NULL device *): %pV", level, vaf); | ||
1924 | |||
1925 | hdrlen = create_syslog_header(dev, hdr, sizeof(hdr)); | ||
1926 | |||
1927 | return printk_emit(0, level[1] - '0', hdrlen ? hdr : NULL, hdrlen, | ||
1928 | "%s %s: %pV", | ||
1929 | dev_driver_string(dev), dev_name(dev), vaf); | ||
1927 | } | 1930 | } |
1928 | EXPORT_SYMBOL(__dev_printk); | ||
1929 | 1931 | ||
1930 | int dev_printk(const char *level, const struct device *dev, | 1932 | int dev_printk(const char *level, const struct device *dev, |
1931 | const char *fmt, ...) | 1933 | const char *fmt, ...) |
@@ -1940,6 +1942,7 @@ int dev_printk(const char *level, const struct device *dev, | |||
1940 | vaf.va = &args; | 1942 | vaf.va = &args; |
1941 | 1943 | ||
1942 | r = __dev_printk(level, dev, &vaf); | 1944 | r = __dev_printk(level, dev, &vaf); |
1945 | |||
1943 | va_end(args); | 1946 | va_end(args); |
1944 | 1947 | ||
1945 | return r; | 1948 | return r; |
@@ -1959,6 +1962,7 @@ int func(const struct device *dev, const char *fmt, ...) \ | |||
1959 | vaf.va = &args; \ | 1962 | vaf.va = &args; \ |
1960 | \ | 1963 | \ |
1961 | r = __dev_printk(kern_level, dev, &vaf); \ | 1964 | r = __dev_printk(kern_level, dev, &vaf); \ |
1965 | \ | ||
1962 | va_end(args); \ | 1966 | va_end(args); \ |
1963 | \ | 1967 | \ |
1964 | return r; \ | 1968 | return r; \ |
diff --git a/include/linux/device.h b/include/linux/device.h index 378a27c1d1af..a1443b48ed4b 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -895,12 +895,12 @@ extern const char *dev_driver_string(const struct device *dev); | |||
895 | 895 | ||
896 | #ifdef CONFIG_PRINTK | 896 | #ifdef CONFIG_PRINTK |
897 | 897 | ||
898 | extern int __dev_printk(const char *level, const struct device *dev, | 898 | extern int create_syslog_header(const struct device *dev, |
899 | struct va_format *vaf); | 899 | char *hdr, size_t hdrlen); |
900 | |||
900 | extern __printf(3, 4) | 901 | extern __printf(3, 4) |
901 | int dev_printk(const char *level, const struct device *dev, | 902 | int dev_printk(const char *level, const struct device *dev, |
902 | const char *fmt, ...) | 903 | const char *fmt, ...); |
903 | ; | ||
904 | extern __printf(2, 3) | 904 | extern __printf(2, 3) |
905 | int dev_emerg(const struct device *dev, const char *fmt, ...); | 905 | int dev_emerg(const struct device *dev, const char *fmt, ...); |
906 | extern __printf(2, 3) | 906 | extern __printf(2, 3) |
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index 7ca29a0a3019..29ff2e4cfb75 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c | |||
@@ -521,25 +521,25 @@ static char *dynamic_emit_prefix(const struct _ddebug *desc, char *buf) | |||
521 | int pos_after_tid; | 521 | int pos_after_tid; |
522 | int pos = 0; | 522 | int pos = 0; |
523 | 523 | ||
524 | pos += snprintf(buf + pos, remaining(pos), "%s", KERN_DEBUG); | 524 | *buf = '\0'; |
525 | |||
525 | if (desc->flags & _DPRINTK_FLAGS_INCL_TID) { | 526 | if (desc->flags & _DPRINTK_FLAGS_INCL_TID) { |
526 | if (in_interrupt()) | 527 | if (in_interrupt()) |
527 | pos += snprintf(buf + pos, remaining(pos), "%s ", | 528 | pos += snprintf(buf + pos, remaining(pos), "<intr> "); |
528 | "<intr>"); | ||
529 | else | 529 | else |
530 | pos += snprintf(buf + pos, remaining(pos), "[%d] ", | 530 | pos += snprintf(buf + pos, remaining(pos), "[%d] ", |
531 | task_pid_vnr(current)); | 531 | task_pid_vnr(current)); |
532 | } | 532 | } |
533 | pos_after_tid = pos; | 533 | pos_after_tid = pos; |
534 | if (desc->flags & _DPRINTK_FLAGS_INCL_MODNAME) | 534 | if (desc->flags & _DPRINTK_FLAGS_INCL_MODNAME) |
535 | pos += snprintf(buf + pos, remaining(pos), "%s:", | 535 | pos += snprintf(buf + pos, remaining(pos), "%s:", |
536 | desc->modname); | 536 | desc->modname); |
537 | if (desc->flags & _DPRINTK_FLAGS_INCL_FUNCNAME) | 537 | if (desc->flags & _DPRINTK_FLAGS_INCL_FUNCNAME) |
538 | pos += snprintf(buf + pos, remaining(pos), "%s:", | 538 | pos += snprintf(buf + pos, remaining(pos), "%s:", |
539 | desc->function); | 539 | desc->function); |
540 | if (desc->flags & _DPRINTK_FLAGS_INCL_LINENO) | 540 | if (desc->flags & _DPRINTK_FLAGS_INCL_LINENO) |
541 | pos += snprintf(buf + pos, remaining(pos), "%d:", | 541 | pos += snprintf(buf + pos, remaining(pos), "%d:", |
542 | desc->lineno); | 542 | desc->lineno); |
543 | if (pos - pos_after_tid) | 543 | if (pos - pos_after_tid) |
544 | pos += snprintf(buf + pos, remaining(pos), " "); | 544 | pos += snprintf(buf + pos, remaining(pos), " "); |
545 | if (pos >= PREFIX_SIZE) | 545 | if (pos >= PREFIX_SIZE) |
@@ -559,9 +559,13 @@ int __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...) | |||
559 | BUG_ON(!fmt); | 559 | BUG_ON(!fmt); |
560 | 560 | ||
561 | va_start(args, fmt); | 561 | va_start(args, fmt); |
562 | |||
562 | vaf.fmt = fmt; | 563 | vaf.fmt = fmt; |
563 | vaf.va = &args; | 564 | vaf.va = &args; |
564 | res = printk("%s%pV", dynamic_emit_prefix(descriptor, buf), &vaf); | 565 | |
566 | res = printk(KERN_DEBUG "%s%pV", | ||
567 | dynamic_emit_prefix(descriptor, buf), &vaf); | ||
568 | |||
565 | va_end(args); | 569 | va_end(args); |
566 | 570 | ||
567 | return res; | 571 | return res; |
@@ -574,15 +578,30 @@ int __dynamic_dev_dbg(struct _ddebug *descriptor, | |||
574 | struct va_format vaf; | 578 | struct va_format vaf; |
575 | va_list args; | 579 | va_list args; |
576 | int res; | 580 | int res; |
577 | char buf[PREFIX_SIZE]; | ||
578 | 581 | ||
579 | BUG_ON(!descriptor); | 582 | BUG_ON(!descriptor); |
580 | BUG_ON(!fmt); | 583 | BUG_ON(!fmt); |
581 | 584 | ||
582 | va_start(args, fmt); | 585 | va_start(args, fmt); |
586 | |||
583 | vaf.fmt = fmt; | 587 | vaf.fmt = fmt; |
584 | vaf.va = &args; | 588 | vaf.va = &args; |
585 | res = __dev_printk(dynamic_emit_prefix(descriptor, buf), dev, &vaf); | 589 | |
590 | if (!dev) { | ||
591 | res = printk(KERN_DEBUG "(NULL device *): %pV", &vaf); | ||
592 | } else { | ||
593 | char buf[PREFIX_SIZE]; | ||
594 | char dict[128]; | ||
595 | size_t dictlen; | ||
596 | |||
597 | dictlen = create_syslog_header(dev, dict, sizeof(dict)); | ||
598 | |||
599 | res = printk_emit(0, 7, dictlen ? dict : NULL, dictlen, | ||
600 | "%s%s %s: %pV", | ||
601 | dynamic_emit_prefix(descriptor, buf), | ||
602 | dev_driver_string(dev), dev_name(dev), &vaf); | ||
603 | } | ||
604 | |||
586 | va_end(args); | 605 | va_end(args); |
587 | 606 | ||
588 | return res; | 607 | return res; |