Commit 74caba7f authored by John Ogness's avatar John Ogness Committed by Petr Mladek
Browse files

printk: move dictionary keys to dev_printk_info



Dictionaries are only used for SUBSYSTEM and DEVICE properties. The
current implementation stores the property names each time they are
used. This requires more space than otherwise necessary. Also,
because the dictionary entries are currently considered optional,
it cannot be relied upon that they are always available, even if the
writer wanted to store them. These issues will increase should new
dictionary properties be introduced.

Rather than storing the subsystem and device properties in the
dict ring, introduce a struct dev_printk_info with separate fields
to store only the property values. Embed this struct within the
struct printk_info to provide guaranteed availability.

Signed-off-by: default avatarJohn Ogness <john.ogness@linutronix.de>
Reviewed-by: default avatarPetr Mladek <pmladek@suse.com>
Signed-off-by: default avatarPetr Mladek <pmladek@suse.com>
Link: https://lore.kernel.org/r/87mu1jl6ne.fsf@jogness.linutronix.de
parent cfe2790b
Loading
Loading
Loading
Loading
+33 −40
Original line number Diff line number Diff line
@@ -172,13 +172,13 @@ end

define dump_record
	set var $desc = $arg0
	if ($argc > 1)
		set var $prev_flags = $arg1
	set var $info = $arg1
	if ($argc > 2)
		set var $prev_flags = $arg2
	else
		set var $prev_flags = 0
	end

	set var $info = &$desc->info
	set var $prefix = 1
	set var $newline = 1

@@ -237,44 +237,36 @@ define dump_record

	# handle dictionary data

	set var $begin = $desc->dict_blk_lpos.begin % (1U << prb->dict_data_ring.size_bits)
	set var $next = $desc->dict_blk_lpos.next % (1U << prb->dict_data_ring.size_bits)

	# handle data-less record
	if ($begin & 1)
		set var $dict_len = 0
		set var $dict = ""
	set var $dict = &$info->dev_info.subsystem[0]
	set var $dict_len = sizeof($info->dev_info.subsystem)
	if ($dict[0] != '\0')
		printf " SUBSYSTEM="
		set var $idx = 0
		while ($idx < $dict_len)
			set var $c = $dict[$idx]
			if ($c == '\0')
				loop_break
			else
		# handle wrapping data block
		if ($begin > $next)
			set var $begin = 0
		end

		# skip over descriptor id
		set var $begin = $begin + sizeof(long)

		# handle truncated message
		if ($next - $begin < $info->dict_len)
			set var $dict_len = $next - $begin
				if ($c < ' ' || $c >= 127 || $c == '\\')
					printf "\\x%02x", $c
				else
			set var $dict_len = $info->dict_len
					printf "%c", $c
				end

		set var $dict = &prb->dict_data_ring.data[$begin]
			end
			set var $idx = $idx + 1
		end
		printf "\n"
	end

	if ($dict_len > 0)
	set var $dict = &$info->dev_info.device[0]
	set var $dict_len = sizeof($info->dev_info.device)
	if ($dict[0] != '\0')
		printf " DEVICE="
		set var $idx = 0
		set var $line = 1
		while ($idx < $dict_len)
			if ($line)
				printf " "
				set var $line = 0
			end
			set var $c = $dict[$idx]
			if ($c == '\0')
				printf "\n"
				set var $line = 1
				loop_break
			else
				if ($c < ' ' || $c >= 127 || $c == '\\')
					printf "\\x%02x", $c
@@ -288,10 +280,10 @@ define dump_record
	end
end
document dump_record
	Dump a single record. The first parameter is the descriptor
	sequence number, the second is optional and specifies the
	previous record's flags, used for properly formatting
	continued lines.
	Dump a single record. The first parameter is the descriptor,
	the second parameter is the info, the third parameter is
	optional and specifies the previous record's flags, used for
	properly formatting continued lines.
end

define dmesg
@@ -311,12 +303,13 @@ define dmesg

	while (1)
		set var $desc = &prb->desc_ring.descs[$id % $desc_count]
		set var $info = &prb->desc_ring.infos[$id % $desc_count]

		# skip non-committed record
		set var $state = 3 & ($desc->state_var.counter >> $desc_flags_shift)
		if ($state == $desc_committed || $state == $desc_finalized)
			dump_record $desc $prev_flags
			set var $prev_flags = $desc->info.flags
			dump_record $desc $info $prev_flags
			set var $prev_flags = $info->flags
		end

		set var $id = ($id + 1) & $id_mask
+16 −30
Original line number Diff line number Diff line
@@ -3815,22 +3815,21 @@ void device_shutdown(void)
 */

#ifdef CONFIG_PRINTK
static int
create_syslog_header(const struct device *dev, char *hdr, size_t hdrlen)
static void
set_dev_info(const struct device *dev, struct dev_printk_info *dev_info)
{
	const char *subsys;
	size_t pos = 0;

	memset(dev_info, 0, sizeof(*dev_info));

	if (dev->class)
		subsys = dev->class->name;
	else if (dev->bus)
		subsys = dev->bus->name;
	else
		return 0;
		return;

	pos += snprintf(hdr + pos, hdrlen - pos, "SUBSYSTEM=%s", subsys);
	if (pos >= hdrlen)
		goto overflow;
	strscpy(dev_info->subsystem, subsys, sizeof(dev_info->subsystem));

	/*
	 * Add device identifier DEVICE=:
@@ -3846,41 +3845,28 @@ create_syslog_header(const struct device *dev, char *hdr, size_t hdrlen)
			c = 'b';
		else
			c = 'c';
		pos++;
		pos += snprintf(hdr + pos, hdrlen - pos,
				"DEVICE=%c%u:%u",
				c, MAJOR(dev->devt), MINOR(dev->devt));

		snprintf(dev_info->device, sizeof(dev_info->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);

		pos++;
		pos += snprintf(hdr + pos, hdrlen - pos,
				"DEVICE=n%u", net->ifindex);
		snprintf(dev_info->device, sizeof(dev_info->device),
			 "n%u", net->ifindex);
	} else {
		pos++;
		pos += snprintf(hdr + pos, hdrlen - pos,
				"DEVICE=+%s:%s", subsys, dev_name(dev));
		snprintf(dev_info->device, sizeof(dev_info->device),
			 "+%s:%s", subsys, dev_name(dev));
	}

	if (pos >= hdrlen)
		goto overflow;

	return pos;

overflow:
	dev_WARN(dev, "device/subsystem name too long");
	return 0;
}

int dev_vprintk_emit(int level, const struct device *dev,
		     const char *fmt, va_list args)
{
	char hdr[128];
	size_t hdrlen;
	struct dev_printk_info dev_info;

	hdrlen = create_syslog_header(dev, hdr, sizeof(hdr));
	set_dev_info(dev, &dev_info);

	return vprintk_emit(0, level, hdrlen ? hdr : NULL, hdrlen, fmt, args);
	return vprintk_emit(0, level, &dev_info, fmt, args);
}
EXPORT_SYMBOL(dev_vprintk_emit);

+8 −0
Original line number Diff line number Diff line
@@ -21,6 +21,14 @@

struct device;

#define PRINTK_INFO_SUBSYSTEM_LEN	16
#define PRINTK_INFO_DEVICE_LEN		48

struct dev_printk_info {
	char subsystem[PRINTK_INFO_SUBSYSTEM_LEN];
	char device[PRINTK_INFO_DEVICE_LEN];
};

#ifdef CONFIG_PRINTK

__printf(3, 0) __cold
+4 −2
Original line number Diff line number Diff line
@@ -158,10 +158,12 @@ static inline void printk_nmi_direct_enter(void) { }
static inline void printk_nmi_direct_exit(void) { }
#endif /* PRINTK_NMI */

struct dev_printk_info;

#ifdef CONFIG_PRINTK
asmlinkage __printf(5, 0)
asmlinkage __printf(4, 0)
int vprintk_emit(int facility, int level,
		 const char *dict, size_t dictlen,
		 const struct dev_printk_info *dev_info,
		 const char *fmt, va_list args);

asmlinkage __printf(1, 0)
+2 −2
Original line number Diff line number Diff line
@@ -14,9 +14,9 @@

extern raw_spinlock_t logbuf_lock;

__printf(5, 0)
__printf(4, 0)
int vprintk_store(int facility, int level,
		  const char *dict, size_t dictlen,
		  const struct dev_printk_info *dev_info,
		  const char *fmt, va_list args);

__printf(1, 0) int vprintk_default(const char *fmt, va_list args);
Loading