Structure of kernel printing and debugging, from the ground up.
KERN_SOH_ASCII
is prepended to string passed to printk()
.
#define KERN_SOH "\001" /* ASCII Start Of Header */ #define KERN_SOH_ASCII '\001' #define KERN_EMERG KERN_SOH "0" /* system is unusable */ #define KERN_ALERT KERN_SOH "1" /* action must be taken immediately */ #define KERN_CRIT KERN_SOH "2" /* critical conditions */ #define KERN_ERR KERN_SOH "3" /* error conditions */ #define KERN_WARNING KERN_SOH "4" /* warning conditions */ #define KERN_NOTICE KERN_SOH "5" /* normal but significant condition */ #define KERN_INFO KERN_SOH "6" /* informational */ #define KERN_DEBUG KERN_SOH "7" /* debug-level messages */ #define KERN_DEFAULT KERN_SOH "d" /* the default kernel loglevel */ /* * Annotation for a "continued" line of log printout (only done after a * line that had no enclosing \n). Only to be used by core/arch code * during early bootup (a continued line is not SMP-safe otherwise). */ #define KERN_CONT KERN_SOH "c"
Remember to skip leading KERN_SOH_ASCII
:
static inline int printk_get_level(const char *buffer) { if (buffer[0] == KERN_SOH_ASCII && buffer[1]) { switch (buffer[1]) { case '0' ... '7': case 'd': /* KERN_DEFAULT */ case 'c': /* KERN_CONT */ return buffer[1]; } } return 0; }
Unconditional printing at all log levels.
#define pr_emerg(fmt, ...) \ printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__) #define pr_alert(fmt, ...) \ printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__) #define pr_crit(fmt, ...) \ printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__) #define pr_err(fmt, ...) \ printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__) #define pr_warning(fmt, ...) \ printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__) #define pr_warn pr_warning #define pr_notice(fmt, ...) \ printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__) #define pr_info(fmt, ...) \ printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__) /* * Like KERN_CONT, pr_cont() should only be used when continuing * a line with no newline ('\n') enclosed. Otherwise it defaults * back to KERN_DEFAULT. */ #define pr_cont(fmt, ...) \ printk(KERN_CONT fmt, ##__VA_ARGS__)
/* If you are writing a driver, please use dev_dbg instead */
#ifndef dev_fmt #define dev_fmt(fmt) fmt #endif #ifdef CONFIG_PRINTK __printf(3, 0) int dev_vprintk_emit(int level, const struct device *dev, const char *fmt, va_list args); __printf(3, 4) int dev_printk_emit(int level, const struct device *dev, const char *fmt, ...); __printf(3, 4) void dev_printk(const char *level, const struct device *dev, const char *fmt, ...); __printf(2, 3) void _dev_emerg(const struct device *dev, const char *fmt, ...); __printf(2, 3) void _dev_alert(const struct device *dev, const char *fmt, ...); __printf(2, 3) void _dev_crit(const struct device *dev, const char *fmt, ...); __printf(2, 3) void _dev_err(const struct device *dev, const char *fmt, ...); __printf(2, 3) void _dev_warn(const struct device *dev, const char *fmt, ...); __printf(2, 3) void _dev_notice(const struct device *dev, const char *fmt, ...); __printf(2, 3) void _dev_info(const struct device *dev, const char *fmt, ...); #else ... snip ... #endif #define dev_emerg(dev, fmt, ...) \ _dev_emerg(dev, dev_fmt(fmt), ##__VA_ARGS__) #define dev_crit(dev, fmt, ...) \ _dev_crit(dev, dev_fmt(fmt), ##__VA_ARGS__) #define dev_alert(dev, fmt, ...) \ _dev_alert(dev, dev_fmt(fmt), ##__VA_ARGS__) #define dev_err(dev, fmt, ...) \ _dev_err(dev, dev_fmt(fmt), ##__VA_ARGS__) #define dev_warn(dev, fmt, ...) \ _dev_warn(dev, dev_fmt(fmt), ##__VA_ARGS__) #define dev_notice(dev, fmt, ...) \ _dev_notice(dev, dev_fmt(fmt), ##__VA_ARGS__) #define dev_info(dev, fmt, ...) \ _dev_info(dev, dev_fmt(fmt), ##__VA_ARGS__)
void dev_printk(const char *level, const struct device *dev, const char *fmt, ...) { struct va_format vaf; va_list args; va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; __dev_printk(level, dev, &vaf); va_end(args); } EXPORT_SYMBOL(dev_printk);
static void __dev_printk(const char *level, const struct device *dev, struct va_format *vaf) { if (dev) dev_printk_emit(level[1] - '0', dev, "%s %s: %pV", dev_driver_string(dev), dev_name(dev), vaf); else printk("%s(NULL device *): %pV", level, vaf); }
int dev_printk_emit(int level, const struct device *dev, const char *fmt, ...) { va_list args; int r; va_start(args, fmt); r = dev_vprintk_emit(level, dev, fmt, args); va_end(args); return r; } EXPORT_SYMBOL(dev_printk_emit);
int dev_vprintk_emit(int level, const struct device *dev, const char *fmt, va_list args) { char hdr[128]; size_t hdrlen; hdrlen = create_syslog_header(dev, hdr, sizeof(hdr)); return vprintk_emit(0, level, hdrlen ? hdr : NULL, hdrlen, fmt, args); }
#define define_netdev_printk_level(func, level) \ void func(const struct net_device *dev, const char *fmt, ...) \ { \ struct va_format vaf; \ va_list args; \ \ va_start(args, fmt); \ \ vaf.fmt = fmt; \ vaf.va = &args; \ \ __netdev_printk(level, dev, &vaf); \ \ va_end(args); \ } \ EXPORT_SYMBOL(func); define_netdev_printk_level(netdev_emerg, KERN_EMERG); define_netdev_printk_level(netdev_alert, KERN_ALERT); define_netdev_printk_level(netdev_crit, KERN_CRIT); define_netdev_printk_level(netdev_err, KERN_ERR); define_netdev_printk_level(netdev_warn, KERN_WARNING); define_netdev_printk_level(netdev_notice, KERN_NOTICE); define_netdev_printk_level(netdev_info, KERN_INFO);
void netdev_printk(const char *level, const struct net_device *dev, const char *format, ...) { struct va_format vaf; va_list args; va_start(args, format); vaf.fmt = format; vaf.va = &args; __netdev_printk(level, dev, &vaf); va_end(args); } EXPORT_SYMBOL(netdev_printk);
static void __netdev_printk(const char *level, const struct net_device *dev, struct va_format *vaf) { if (dev && dev->dev.parent) { dev_printk_emit(level[1] - '0', dev->dev.parent, "%s %s %s%s: %pV", dev_driver_string(dev->dev.parent), dev_name(dev->dev.parent), netdev_name(dev), netdev_reg_state(dev), vaf); } else if (dev) { printk("%s%s%s: %pV", level, netdev_name(dev), netdev_reg_state(dev), vaf); } else { printk("%s(NULL net_device): %pV", level, vaf); } }
… coming …