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

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
...@@ -172,13 +172,13 @@ end ...@@ -172,13 +172,13 @@ end
define dump_record define dump_record
set var $desc = $arg0 set var $desc = $arg0
if ($argc > 1) set var $info = $arg1
set var $prev_flags = $arg1 if ($argc > 2)
set var $prev_flags = $arg2
else else
set var $prev_flags = 0 set var $prev_flags = 0
end end
set var $info = &$desc->info
set var $prefix = 1 set var $prefix = 1
set var $newline = 1 set var $newline = 1
...@@ -237,44 +237,36 @@ define dump_record ...@@ -237,44 +237,36 @@ define dump_record
# handle dictionary data # handle dictionary data
set var $begin = $desc->dict_blk_lpos.begin % (1U << prb->dict_data_ring.size_bits) set var $dict = &$info->dev_info.subsystem[0]
set var $next = $desc->dict_blk_lpos.next % (1U << prb->dict_data_ring.size_bits) set var $dict_len = sizeof($info->dev_info.subsystem)
if ($dict[0] != '\0')
# handle data-less record printf " SUBSYSTEM="
if ($begin & 1) set var $idx = 0
set var $dict_len = 0 while ($idx < $dict_len)
set var $dict = "" set var $c = $dict[$idx]
else if ($c == '\0')
# handle wrapping data block loop_break
if ($begin > $next) else
set var $begin = 0 if ($c < ' ' || $c >= 127 || $c == '\\')
end printf "\\x%02x", $c
else
# skip over descriptor id printf "%c", $c
set var $begin = $begin + sizeof(long) end
end
# handle truncated message set var $idx = $idx + 1
if ($next - $begin < $info->dict_len)
set var $dict_len = $next - $begin
else
set var $dict_len = $info->dict_len
end end
printf "\n"
set var $dict = &prb->dict_data_ring.data[$begin]
end 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 $idx = 0
set var $line = 1
while ($idx < $dict_len) while ($idx < $dict_len)
if ($line)
printf " "
set var $line = 0
end
set var $c = $dict[$idx] set var $c = $dict[$idx]
if ($c == '\0') if ($c == '\0')
printf "\n" loop_break
set var $line = 1
else else
if ($c < ' ' || $c >= 127 || $c == '\\') if ($c < ' ' || $c >= 127 || $c == '\\')
printf "\\x%02x", $c printf "\\x%02x", $c
...@@ -288,10 +280,10 @@ define dump_record ...@@ -288,10 +280,10 @@ define dump_record
end end
end end
document dump_record document dump_record
Dump a single record. The first parameter is the descriptor Dump a single record. The first parameter is the descriptor,
sequence number, the second is optional and specifies the the second parameter is the info, the third parameter is
previous record's flags, used for properly formatting optional and specifies the previous record's flags, used for
continued lines. properly formatting continued lines.
end end
define dmesg define dmesg
...@@ -311,12 +303,13 @@ define dmesg ...@@ -311,12 +303,13 @@ define dmesg
while (1) while (1)
set var $desc = &prb->desc_ring.descs[$id % $desc_count] set var $desc = &prb->desc_ring.descs[$id % $desc_count]
set var $info = &prb->desc_ring.infos[$id % $desc_count]
# skip non-committed record # skip non-committed record
set var $state = 3 & ($desc->state_var.counter >> $desc_flags_shift) set var $state = 3 & ($desc->state_var.counter >> $desc_flags_shift)
if ($state == $desc_committed || $state == $desc_finalized) if ($state == $desc_committed || $state == $desc_finalized)
dump_record $desc $prev_flags dump_record $desc $info $prev_flags
set var $prev_flags = $desc->info.flags set var $prev_flags = $info->flags
end end
set var $id = ($id + 1) & $id_mask set var $id = ($id + 1) & $id_mask
......
...@@ -3815,22 +3815,21 @@ void device_shutdown(void) ...@@ -3815,22 +3815,21 @@ void device_shutdown(void)
*/ */
#ifdef CONFIG_PRINTK #ifdef CONFIG_PRINTK
static int static void
create_syslog_header(const struct device *dev, char *hdr, size_t hdrlen) set_dev_info(const struct device *dev, struct dev_printk_info *dev_info)
{ {
const char *subsys; const char *subsys;
size_t pos = 0;
memset(dev_info, 0, sizeof(*dev_info));
if (dev->class) if (dev->class)
subsys = dev->class->name; subsys = dev->class->name;
else if (dev->bus) else if (dev->bus)
subsys = dev->bus->name; subsys = dev->bus->name;
else else
return 0; return;
pos += snprintf(hdr + pos, hdrlen - pos, "SUBSYSTEM=%s", subsys); strscpy(dev_info->subsystem, subsys, sizeof(dev_info->subsystem));
if (pos >= hdrlen)
goto overflow;
/* /*
* Add device identifier DEVICE=: * Add device identifier DEVICE=:
...@@ -3846,41 +3845,28 @@ create_syslog_header(const struct device *dev, char *hdr, size_t hdrlen) ...@@ -3846,41 +3845,28 @@ create_syslog_header(const struct device *dev, char *hdr, size_t hdrlen)
c = 'b'; c = 'b';
else else
c = 'c'; c = 'c';
pos++;
pos += snprintf(hdr + pos, hdrlen - pos, snprintf(dev_info->device, sizeof(dev_info->device),
"DEVICE=%c%u:%u", "%c%u:%u", c, MAJOR(dev->devt), MINOR(dev->devt));
c, MAJOR(dev->devt), MINOR(dev->devt));
} else if (strcmp(subsys, "net") == 0) { } else if (strcmp(subsys, "net") == 0) {
struct net_device *net = to_net_dev(dev); struct net_device *net = to_net_dev(dev);
pos++; snprintf(dev_info->device, sizeof(dev_info->device),
pos += snprintf(hdr + pos, hdrlen - pos, "n%u", net->ifindex);
"DEVICE=n%u", net->ifindex);
} else { } else {
pos++; snprintf(dev_info->device, sizeof(dev_info->device),
pos += snprintf(hdr + pos, hdrlen - pos, "+%s:%s", subsys, dev_name(dev));
"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, int dev_vprintk_emit(int level, const struct device *dev,
const char *fmt, va_list args) const char *fmt, va_list args)
{ {
char hdr[128]; struct dev_printk_info dev_info;
size_t hdrlen;
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); EXPORT_SYMBOL(dev_vprintk_emit);
......
...@@ -21,6 +21,14 @@ ...@@ -21,6 +21,14 @@
struct device; 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 #ifdef CONFIG_PRINTK
__printf(3, 0) __cold __printf(3, 0) __cold
......
...@@ -158,10 +158,12 @@ static inline void printk_nmi_direct_enter(void) { } ...@@ -158,10 +158,12 @@ static inline void printk_nmi_direct_enter(void) { }
static inline void printk_nmi_direct_exit(void) { } static inline void printk_nmi_direct_exit(void) { }
#endif /* PRINTK_NMI */ #endif /* PRINTK_NMI */
struct dev_printk_info;
#ifdef CONFIG_PRINTK #ifdef CONFIG_PRINTK
asmlinkage __printf(5, 0) asmlinkage __printf(4, 0)
int vprintk_emit(int facility, int level, 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); const char *fmt, va_list args);
asmlinkage __printf(1, 0) asmlinkage __printf(1, 0)
......
...@@ -14,9 +14,9 @@ ...@@ -14,9 +14,9 @@
extern raw_spinlock_t logbuf_lock; extern raw_spinlock_t logbuf_lock;
__printf(5, 0) __printf(4, 0)
int vprintk_store(int facility, int level, 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); const char *fmt, va_list args);
__printf(1, 0) int vprintk_default(const char *fmt, va_list args); __printf(1, 0) int vprintk_default(const char *fmt, va_list args);
......
This diff is collapsed.
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#define _KERNEL_PRINTK_RINGBUFFER_H #define _KERNEL_PRINTK_RINGBUFFER_H
#include <linux/atomic.h> #include <linux/atomic.h>
#include <linux/dev_printk.h>
/* /*
* Meta information about each stored message. * Meta information about each stored message.
...@@ -21,6 +22,8 @@ struct printk_info { ...@@ -21,6 +22,8 @@ struct printk_info {
u8 flags:5; /* internal record flags */ u8 flags:5; /* internal record flags */
u8 level:3; /* syslog level */ u8 level:3; /* syslog level */
u32 caller_id; /* thread id or processor id */ u32 caller_id; /* thread id or processor id */
struct dev_printk_info dev_info;
}; };
/* /*
......
...@@ -375,7 +375,7 @@ __printf(1, 0) int vprintk_func(const char *fmt, va_list args) ...@@ -375,7 +375,7 @@ __printf(1, 0) int vprintk_func(const char *fmt, va_list args)
raw_spin_trylock(&logbuf_lock)) { raw_spin_trylock(&logbuf_lock)) {
int len; int len;
len = vprintk_store(0, LOGLEVEL_DEFAULT, NULL, 0, fmt, args); len = vprintk_store(0, LOGLEVEL_DEFAULT, NULL, fmt, args);
raw_spin_unlock(&logbuf_lock); raw_spin_unlock(&logbuf_lock);
defer_console_output(); defer_console_output();
return len; return len;
......
...@@ -52,6 +52,12 @@ class LxDmesg(gdb.Command): ...@@ -52,6 +52,12 @@ class LxDmesg(gdb.Command):
addr = utils.read_ulong(desc_ring, off) addr = utils.read_ulong(desc_ring, off)
descs = utils.read_memoryview(inf, addr, desc_sz * desc_ring_count).tobytes() descs = utils.read_memoryview(inf, addr, desc_sz * desc_ring_count).tobytes()
# read in info array
info_sz = printk_info_type.get_type().sizeof
off = prb_desc_ring_type.get_type()['infos'].bitpos // 8
addr = utils.read_ulong(desc_ring, off)
infos = utils.read_memoryview(inf, addr, info_sz * desc_ring_count).tobytes()
# read in text data ring structure # read in text data ring structure
off = printk_ringbuffer_type.get_type()['text_data_ring'].bitpos // 8 off = printk_ringbuffer_type.get_type()['text_data_ring'].bitpos // 8
addr = prb_addr + off addr = prb_addr + off
...@@ -73,9 +79,8 @@ class LxDmesg(gdb.Command): ...@@ -73,9 +79,8 @@ class LxDmesg(gdb.Command):
begin_off = off + (prb_data_blk_lpos_type.get_type()['begin'].bitpos // 8) begin_off = off + (prb_data_blk_lpos_type.get_type()['begin'].bitpos // 8)
next_off = off + (prb_data_blk_lpos_type.get_type()['next'].bitpos // 8) next_off = off + (prb_data_blk_lpos_type.get_type()['next'].bitpos // 8)
off = prb_desc_type.get_type()['info'].bitpos // 8 ts_off = printk_info_type.get_type()['ts_nsec'].bitpos // 8
ts_off = off + printk_info_type.get_type()['ts_nsec'].bitpos // 8 len_off = printk_info_type.get_type()['text_len'].bitpos // 8
len_off = off + printk_info_type.get_type()['text_len'].bitpos // 8
# definitions from kernel/printk/printk_ringbuffer.h # definitions from kernel/printk/printk_ringbuffer.h
desc_committed = 1 desc_committed = 1
...@@ -95,6 +100,7 @@ class LxDmesg(gdb.Command): ...@@ -95,6 +100,7 @@ class LxDmesg(gdb.Command):
while True: while True:
ind = did % desc_ring_count ind = did % desc_ring_count
desc_off = desc_sz * ind desc_off = desc_sz * ind
info_off = info_sz * ind
# skip non-committed record # skip non-committed record
state = 3 & (utils.read_u64(descs, desc_off + sv_off + state = 3 & (utils.read_u64(descs, desc_off + sv_off +
...@@ -119,7 +125,7 @@ class LxDmesg(gdb.Command): ...@@ -119,7 +125,7 @@ class LxDmesg(gdb.Command):
# skip over descriptor id # skip over descriptor id
text_start = begin + utils.get_long_type().sizeof text_start = begin + utils.get_long_type().sizeof
text_len = utils.read_u16(descs, desc_off + len_off) text_len = utils.read_u16(infos, info_off + len_off)
# handle truncated message # handle truncated message
if end - text_start < text_len: if end - text_start < text_len:
...@@ -128,7 +134,7 @@ class LxDmesg(gdb.Command): ...@@ -128,7 +134,7 @@ class LxDmesg(gdb.Command):
text = text_data[text_start:text_start + text_len].decode( text = text_data[text_start:text_start + text_len].decode(
encoding='utf8', errors='replace') encoding='utf8', errors='replace')
time_stamp = utils.read_u64(descs, desc_off + ts_off) time_stamp = utils.read_u64(infos, info_off + ts_off)
for line in text.splitlines(): for line in text.splitlines():
msg = u"[{time:12.6f}] {line}\n".format( msg = u"[{time:12.6f}] {line}\n".format(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment