vprintk_store: was: [PATCH next v2 3/3] printk: remove logbuf_lock, add syslog_lock

From: Petr Mladek
Date: Fri Dec 04 2020 - 11:17:15 EST


On Tue 2020-12-01 21:59:41, John Ogness wrote:
> Since the ringbuffer is lockless, there is no need for it to be
> protected by @logbuf_lock. Remove @logbuf_lock.
>
> --- a/kernel/printk/printk.c
> +++ b/kernel/printk/printk.c
> @@ -1867,40 +1890,75 @@ static inline u32 printk_caller_id(void)
> 0x80000000 + raw_smp_processor_id();
> }
>
> -/* Must be called under logbuf_lock. */
> +static u16 printk_sprint(char *text, u16 size, int facility, enum log_flags *lflags,
> + const char *fmt, va_list args)
> +{
> + char *orig_text = text;
> + u16 text_len;
> +
> + text_len = vscnprintf(text, size, fmt, args);
> +
> + /* Mark and strip a trailing newline. */
> + if (text_len && text[text_len - 1] == '\n') {
> + text_len--;
> + *lflags |= LOG_NEWLINE;
> + }

We reserve the space for '\n' anyway. It would make sense to just
store it and remove all these LOG_NEWLINE-specific hacks.

Well, let's leave it as is now. It is still possible that people
will not love this approach and we will need to format the message
into some temporary buffer first.


> + /* Strip kernel syslog prefix. */

Syslog actually uses: <level> format. We are skipping log level
and control flags here.


> + if (facility == 0) {
> + while (text_len >= 2 && printk_get_level(text)) {
> + text_len -= 2;
> + text += 2;
> + }

We should avoid two completely different approaches
that handle printk_level prefix.

One solution is to implement something like:

static char *parse_prefix(text, &level, &flags)

That would return pointer to the text after the prefix.
And fill level and flags only when non-NULL pointers are passed.

Another solution would be to pass this information from
vprintk_store(). The prefix has already been parsed
after all.

> +
> + if (text != orig_text)
> + memmove(orig_text, text, text_len);
> + }

We should clear the freed space to make the ring buffer as
human readable as possible when someone just dumps the memory.

Sigh, I have to admit that I missed the problem with prefix and
trailing '\n' when I suggested to avoid the temporary buffers.
This memmove() and the space wasting is pity.

Well, it is typically 3 bytes per message. And the copying would
be necessary even with the temporary buffer. So, I am less convinced
but I would still try to avoid the temporary buffers for now.

> +
> + return text_len;
> +}
> +
> +__printf(4, 0)

Best Regards,
Petr