Re: [PATCH next v2 2/3] printk: change @clear_seq to atomic64_t

From: Petr Mladek
Date: Fri Dec 04 2020 - 04:13:05 EST


On Tue 2020-12-01 21:59:40, John Ogness wrote:
> Currently @clear_seq access is protected by @logbuf_lock. Once
> @logbuf_lock is removed some other form of synchronization will be
> required. Change the type of @clear_seq to atomic64_t to provide the
> synchronization.
>
> diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
> index fc5e3a7d6d89..e9018c4e1b66 100644
> --- a/kernel/printk/printk.c
> +++ b/kernel/printk/printk.c
> @@ -3412,7 +3418,7 @@ EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer);
> */
> void kmsg_dump_rewind_nolock(struct kmsg_dumper *dumper)
> {
> - dumper->cur_seq = clear_seq;
> + dumper->cur_seq = atomic64_read(&clear_seq);

Sigh, atomic64_read() uses a spin lock in the generic implementation
that is used on some architectures.

Hmm, this seems to be the only location where the lock must not be
used. At the same time, a best effort might be acceptable here.

I am not super-happy with the following hack but it might work:

/*
* Use the best effort to avoid locks. In the worst case,
* the bottom and upper halves will be inconsistent. Then
* the value will be far too big or far too low. Fallback
* to the first available sequence number when it is
* too big.
*/
if (IS_ENABLED(CONFIG_GENERIC_ATOMIC64)) {
u64 first_seq = prb_first_seq(prb);

dumper->cur_seq = READ_ONCE(&clear_seq->counter);
if (dumper->cur_seq > first_seq)
dumper->cur_seq = first_seq;
} else {
dumper->cur_seq = atomic64_read(&clear_seq);
}

Alternative solution would to always fallback to the first_seq
on these architectures. Few people would complain when they see
more messages. We could always improve it when it causes problems.

Adding Peter Zijstra for his opinion [*].

> dumper->next_seq = prb_next_seq(prb);

[*] I am going to hide under a stone for the above hack.

Best Regards,
Petr