Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c4e00daa authored by Kay Sievers's avatar Kay Sievers Committed by Greg Kroah-Hartman
Browse files

driver-core: extend dev_printk() to pass structured data



Extends dev_printk() to attach a dictionary with a device identifier
and the driver core subsystem name to logged messages, which makes
dev_prink() reliable machine-readable. In addition to the printed
plain text message, it creates these properties:
    SUBSYSTEM=     - the driver-core subsytem name
    DEVICE=
      b12:8        - block dev_t
      c127:3       - char dev_t
      n8           - netdev ifindex
      +sound:card0 - subsystem:devname

Tested-by: default avatarWilliam Douglas <william.douglas@intel.com>
Signed-off-by: default avatarKay Sievers <kay@vrfy.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent e11fea92
Loading
Loading
Loading
Loading
+49 −3
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <linux/mutex.h>
#include <linux/async.h>
#include <linux/pm_runtime.h>
#include <linux/netdevice.h>

#include "base.h"
#include "power/power.h"
@@ -1843,15 +1844,60 @@ void device_shutdown(void)
 */

#ifdef CONFIG_PRINTK

int __dev_printk(const char *level, const struct device *dev,
		 struct va_format *vaf)
{
	char dict[128];
	size_t dictlen = 0;
	const char *subsys;

	if (!dev)
		return printk("%s(NULL device *): %pV", level, vaf);

	return printk("%s%s %s: %pV",
		      level, dev_driver_string(dev), dev_name(dev), vaf);
	if (dev->class)
		subsys = dev->class->name;
	else if (dev->bus)
		subsys = dev->bus->name;
	else
		goto skip;

	dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen,
			    "SUBSYSTEM=%s", subsys);

	/*
	 * Add device identifier DEVICE=:
	 *   b12:8         block dev_t
	 *   c127:3        char dev_t
	 *   n8            netdev ifindex
	 *   +sound:card0  subsystem:devname
	 */
	if (MAJOR(dev->devt)) {
		char c;

		if (strcmp(subsys, "block") == 0)
			c = 'b';
		else
			c = 'c';
		dictlen++;
		dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen,
				   "DEVICE=%c%u:%u",
				   c, MAJOR(dev->devt), MINOR(dev->devt));
	} else if (strcmp(subsys, "net") == 0) {
		struct net_device *net = to_net_dev(dev);

		dictlen++;
		dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen,
				    "DEVICE=n%u", net->ifindex);
	} else {
		dictlen++;
		dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen,
				    "DEVICE=+%s:%s", subsys, dev_name(dev));
	}
skip:
	return printk_emit(0, level[1] - '0',
			   dictlen ? dict : NULL, dictlen,
			   "%s %s: %pV",
			   dev_driver_string(dev), dev_name(dev), vaf);
}
EXPORT_SYMBOL(__dev_printk);