All of lore.kernel.org
 help / color / mirror / Atom feed
From: Petr Mladek <pmladek@suse.com>
To: John Ogness <john.ogness@linutronix.de>
Cc: Sergey Senozhatsky <senozhatsky@chromium.org>,
	Steven Rostedt <rostedt@goodmis.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	linux-kernel@vger.kernel.org,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Subject: misc details: was: Re: [PATCH printk v1 09/18] printk: nobkl: Add print state functions
Date: Wed, 29 Mar 2023 16:05:38 +0200	[thread overview]
Message-ID: <ZCRFsu2VSmqTSGkS@alley> (raw)
In-Reply-To: <20230302195618.156940-10-john.ogness@linutronix.de>

On Thu 2023-03-02 21:02:09, John Ogness wrote:
> From: Thomas Gleixner <tglx@linutronix.de>
> 
> Provide three functions which are related to the safe handover
> mechanism and allow console drivers to denote takeover unsafe
> sections:
> 
>  - console_can_proceed()
> 
>    Invoked by a console driver to check whether a handover request
>    is pending or whether the console was taken over in a hostile
>    fashion.
> 
>  - console_enter/exit_unsafe()
> 
>    Invoked by a console driver to denote that the driver output
>    function is about to enter or to leave an critical region where a
>    hostile take over is unsafe. These functions are also
>    cancellation points.
> 
>    The unsafe state is stored in the console state and allows a
>    takeover attempt to make informed decisions whether to take over
>    and/or output on such a console at all. The unsafe state is also
>    available to the driver in the write context for the
>    atomic_write() output function so the driver can make informed
>    decisions about the required actions or take a special emergency
>    path.
> 
> --- a/kernel/printk/printk_nobkl.c
> +++ b/kernel/printk/printk_nobkl.c
> @@ -947,6 +947,145 @@ static void cons_free_percpu_data(struct console *con)
>  	con->pcpu_data = NULL;
>  }
>  
> +/**
> + * console_can_proceed - Check whether printing can proceed
> + * @wctxt:	The write context that was handed to the write function
> + *
> + * Returns:	True if the state is correct. False if a handover
> + *		has been requested or if the console was taken
> + *		over.
> + *
> + * Must be invoked after the record was dumped into the assigned record
> + * buffer and at appropriate safe places in the driver.  For unsafe driver
> + * sections see console_enter_unsafe().
> + *
> + * When this function returns false then the calling context is not allowed
> + * to go forward and has to back out immediately and carefully. The buffer
> + * content is no longer trusted either and the console lock is no longer
> + * held.
> + */
> +bool console_can_proceed(struct cons_write_context *wctxt)
> +{
> +	struct cons_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt);
> +	struct console *con = ctxt->console;
> +	struct cons_state state;
> +
> +	cons_state_read(con, CON_STATE_CUR, &state);
> +	/* Store it for analysis or reuse */
> +	copy_full_state(ctxt->old_state, state);
> +
> +	/* Make sure this context is still the owner. */
> +	if (!cons_state_full_match(state, ctxt->state))
> +		return false;
> +
> +	/*
> +	 * Having a safe point for take over and eventually a few
> +	 * duplicated characters or a full line is way better than a
> +	 * hostile takeover. Post processing can take care of the garbage.
> +	 * Continue if the requested priority is not sufficient.
> +	 */
> +	if (state.req_prio <= state.cur_prio)
> +		return true;
> +
> +	/*
> +	 * A console printer within an unsafe region is allowed to continue.
> +	 * It can perform the handover when exiting the safe region. Otherwise
> +	 * a hostile takeover will be necessary.
> +	 */
> +	if (state.unsafe)
> +		return true;

It took me quite some time to scratch my head around the above two comments.
The code is clear but the comments are somehow cryptic ;-)

It is probably because the 1st comment starts talking about a safe point.
But .unsafe is checked after the 2nd comment. And the word "allowed"
confused me in the 2nd comment.

I would explain this in these details in the function description. The
code will be self-explanatory then. I would write something like:

	 * The console is allowed to continue when it still owns the lock
	 * and there is no request from a higher priority context.
	 *
	 * The context might have lost the lock during a hostile takeover.
	 *
	 * The function will handover the lock when there is a request
	 * with a higher priority and the console is in a safe context.
	 * The new owner would print the same line again. But a duplicated
	 * part of a line is better than risking a hostile takeover in
	 * an unsafe context.

> +
> +	/* Release and hand over */
> +	cons_release(ctxt);
> +	/*
> +	 * This does not check whether the handover succeeded.

This is a bit ambiguous. What exactly means that the handover succeeded?
I guess that it means that the context with the higher priority
successfully took over the lock.

A "failure" might be when the other context timeouted and given up.
In that case, nobody would continue printing.

We actually should wake up the kthread when the lock was not
successfully passed. Or even better, we should release the lock
only when the request was still pending. It should be possible
with the cmpxchg().


> +	 * outermost callsite has to make the final decision whether printing
> +	 * should continue

This is a bit misleading. The current owner could not continue after
loosing the lock. It would need to re-start the entire operation.

Is this about the kthread or cons_flush*() layers? Yes, they have to
decide what to do next. Well, we should make it clear that we are talking
about this layer. The con->atomic_write() layer can only carefully
back off.

Maybe, we do not need to describe it here. It should be enough to
mention in the function description that the driver has to
carefully back off and that the buffer content is not longer
trusted. It is already mentioned there.

> +	 * or not (via reacquire, possibly hostile). The
> +	 * console is unlocked already so go back all the way instead of
> +	 * trying to implement heuristics in tons of places.
> +	 */
> +	return false;
> +}
> +
> +static bool __console_update_unsafe(struct cons_write_context *wctxt, bool unsafe)
 > +{
> +	struct cons_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt);
> +	struct console *con = ctxt->console;
> +	struct cons_state new;
> +
> +	do  {
> +		if (!console_can_proceed(wctxt))
> +			return false;
> +		/*
> +		 * console_can_proceed() saved the real state in
> +		 * ctxt->old_state
> +		 */
> +		copy_full_state(new, ctxt->old_state);
> +		new.unsafe = unsafe;
> +
> +	} while (!cons_state_try_cmpxchg(con, CON_STATE_CUR, &ctxt->old_state, &new));

This updates only the bit in struct cons_state. But there is also
"bool unsafe" in struct cons_write_context. Should the boolean
be updated as well?

Or is the boolean needed at all? It seems that it is set in
cons_emit_record() and never read.

> +
> +	copy_full_state(ctxt->state, new);
> +	return true;
> +}

Best Regards,
Petr

  parent reply	other threads:[~2023-03-29 14:07 UTC|newest]

Thread overview: 92+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-02 19:56 [PATCH printk v1 00/18] threaded/atomic console support John Ogness
2023-03-02 19:56 ` [PATCH printk v1 01/18] kdb: do not assume write() callback available John Ogness
2023-03-07 14:57   ` Petr Mladek
2023-03-07 16:34   ` Doug Anderson
2023-03-09 10:52   ` Daniel Thompson
2023-03-09 11:26     ` Petr Mladek
2023-03-09 11:30       ` Daniel Thompson
2023-03-02 19:56 ` [PATCH printk v1 02/18] printk: Add NMI check to down_trylock_console_sem() John Ogness
2023-03-07 16:05   ` Petr Mladek
2023-03-17 11:37     ` John Ogness
2023-04-13 13:42       ` Petr Mladek
2023-03-02 19:56 ` [PATCH printk v1 03/18] printk: Consolidate console deferred printing John Ogness
2023-03-08 13:15   ` Petr Mladek
2023-03-17 13:05     ` John Ogness
2023-04-13 15:15       ` Petr Mladek
2023-03-02 19:56 ` [PATCH printk v1 04/18] printk: Add per-console suspended state John Ogness
2023-03-08 14:40   ` Petr Mladek
2023-03-17 13:22     ` John Ogness
2023-04-14  9:56       ` Petr Mladek
2023-03-02 19:56 ` [PATCH printk v1 05/18] printk: Add non-BKL console basic infrastructure John Ogness
2023-03-09 14:08   ` global states: was: " Petr Mladek
2023-03-17 13:29     ` John Ogness
2023-03-09 15:32   ` naming: " Petr Mladek
2023-03-17 13:39     ` John Ogness
2023-03-21 16:04   ` union: was: " Petr Mladek
2023-03-27 16:28     ` John Ogness
2023-03-28  8:20       ` Petr Mladek
2023-03-28  9:42         ` John Ogness
2023-03-28 12:52           ` Petr Mladek
2023-03-28 13:47           ` Steven Rostedt
2023-03-02 19:56 ` [PATCH printk v1 06/18] printk: nobkl: Add acquire/release logic John Ogness
2023-03-06  9:07   ` Dan Carpenter
2023-03-06  9:39     ` John Ogness
2023-03-13 16:07   ` Petr Mladek
2023-03-17 14:56     ` John Ogness
2023-03-20 16:10       ` Petr Mladek
2023-03-17 17:34   ` simplify: was: " Petr Mladek
2023-03-21 15:36     ` Petr Mladek
2023-04-02 18:39       ` John Ogness
2023-03-02 19:56 ` [PATCH printk v1 07/18] printk: nobkl: Add buffer management John Ogness
2023-03-21 16:38   ` Petr Mladek
2023-03-23 13:38     ` John Ogness
2023-03-23 15:25       ` Petr Mladek
2023-03-02 19:56 ` [PATCH printk v1 08/18] printk: nobkl: Add sequence handling John Ogness
2023-03-27 15:45   ` Petr Mladek
2023-03-02 19:56 ` [PATCH printk v1 09/18] printk: nobkl: Add print state functions John Ogness
2023-03-29 13:58   ` buffer write race: " Petr Mladek
2023-03-29 14:33     ` John Ogness
2023-03-30 11:54       ` Petr Mladek
2023-03-29 14:05   ` Petr Mladek [this message]
2023-03-02 19:56 ` [PATCH printk v1 10/18] printk: nobkl: Add emit function and callback functions for atomic printing John Ogness
2023-03-03  0:19   ` kernel test robot
2023-03-03 10:55     ` John Ogness
2023-03-31 10:29   ` dropped handling: was: " Petr Mladek
2023-03-31 10:36   ` semantic: " Petr Mladek
     [not found]     ` <87edp29kvq.fsf@jogness.linutronix.de>
     [not found]       ` <ZCraqrkqFtsfLWuP@alley>
     [not found]         ` <87ilecsrvl.fsf@jogness.linutronix.de>
2023-04-04 14:09           ` Petr Mladek
2023-03-02 19:56 ` [PATCH printk v1 11/18] printk: nobkl: Introduce printer threads John Ogness
2023-03-03  1:23   ` kernel test robot
2023-03-03 10:56     ` John Ogness
2023-04-05 10:48   ` boot console: was: " Petr Mladek
2023-04-06  8:09   ` wakeup synchronization: " Petr Mladek
2023-04-06  9:46   ` port lock: " Petr Mladek
2023-04-20  9:55     ` Petr Mladek
2023-04-20 10:33       ` John Ogness
2023-04-20 13:33         ` Petr Mladek
2023-04-21 16:15           ` Petr Mladek
2023-04-06 13:19   ` misc: " Petr Mladek
2023-04-13 13:28   ` (k)thread: " Petr Mladek
2023-03-02 19:56 ` [PATCH printk v1 12/18] printk: nobkl: Add printer thread wakeups John Ogness
2023-04-12  9:38   ` Petr Mladek
2023-03-02 19:56 ` [PATCH printk v1 13/18] printk: nobkl: Add write context storage for atomic writes John Ogness
2023-03-02 19:56 ` [PATCH printk v1 14/18] printk: nobkl: Provide functions for atomic write enforcement John Ogness
2023-04-12 14:53   ` Petr Mladek
2023-03-02 19:56 ` [PATCH printk v1 15/18] printk: nobkl: Stop threads on shutdown/reboot John Ogness
2023-04-13  9:03   ` Petr Mladek
2023-03-02 19:56 ` [PATCH printk v1 16/18] kernel/panic: Add atomic write enforcement to warn/panic John Ogness
2023-04-13 10:08   ` Petr Mladek
2023-04-13 12:13     ` John Ogness
2023-04-14 10:10       ` Petr Mladek
2023-03-02 19:56 ` [PATCH printk v1 17/18] rcu: Add atomic write enforcement for rcu stalls John Ogness
2023-04-13 12:10   ` Petr Mladek
2023-03-02 19:56 ` [PATCH printk v1 18/18] printk: Perform atomic flush in console_flush_on_panic() John Ogness
2023-04-13 12:20   ` Petr Mladek
2023-03-02 19:58 ` [PATCH printk v1 00/18] serial: 8250: implement non-BKL console John Ogness
2023-03-28 13:33   ` locking API: was: " Petr Mladek
2023-03-28 13:57     ` John Ogness
2023-03-28 15:10       ` Petr Mladek
2023-03-28 21:47         ` John Ogness
2023-03-29  8:03           ` Petr Mladek
2023-03-28 13:59   ` [PATCH printk v1 00/18] POC: serial: 8250: implement nbcon console John Ogness
2023-03-09 10:55 ` [PATCH printk v1 00/18] threaded/atomic console support Daniel Thompson
2023-03-09 11:14   ` John Ogness

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ZCRFsu2VSmqTSGkS@alley \
    --to=pmladek@suse.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=john.ogness@linutronix.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=rostedt@goodmis.org \
    --cc=senozhatsky@chromium.org \
    --cc=tglx@linutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.