Message ID | 20240218185726.1994771-7-john.ogness@linutronix.de |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel+bounces-70499-ouuuleilei=gmail.com@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:693c:2685:b0:108:e6aa:91d0 with SMTP id mn5csp911314dyc; Sun, 18 Feb 2024 10:58:42 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCUOhCH7hQ+9eR/H+1VWD1tUcIIRdbNNQfkKuJ+8M9iwdlG0OmXZR3eAwB/aKfGl8ULSjYBwCuGn9+/J8KzfKVWWrXjEJA== X-Google-Smtp-Source: AGHT+IFnjA5J4uwOroMcaXPT1Wf5pSQhVNkjLSP8Z1pXyEhWNAaAk5gFT/zmV4ihHMfFk2MG4GjE X-Received: by 2002:a05:6a00:2da0:b0:6dd:da40:948d with SMTP id fb32-20020a056a002da000b006ddda40948dmr10837933pfb.25.1708282722060; Sun, 18 Feb 2024 10:58:42 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1708282722; cv=pass; d=google.com; s=arc-20160816; b=EP3Gl9hENYH6XQfuN/MqfeAKQVkIFnRy3Jtk3toW9Bydd8/mYe6qI8tCr3Mwne6th9 dlp2mGdbnOUm3z/jfXl98kVfTjydfp3duzREPDrAf+ccPsLRo3lB4U7CuWpDvI5a5Jq6 ZNvO2lA3lLQnNAb0KC2vVmU/jOGDYN5QmLwFXPvPK5Uwe8yB6HhWEFO/DH+qqb1uAfx1 tAXQAxolmp6Q/Ji7hSEiRXSfDKe6w7UCAlO7UWzCFJrI58JRJNBd5bJwlIHlJQitG7sb pjsIWMdFj+df5EDtteYJJfZJvTXg+jyM5kbCAtFhI1++Dhz1o1aSPbtYigVDn1edObEH ZJtA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:dkim-signature:dkim-signature:from; bh=Kjns8XLkW3UOjxVLP1Xg+LLtdkqweLRjHg511yq2AQM=; fh=pKnPKUsir0uEGSsor+4Zc2vgbu+g+ayvUgsdzkuXaoA=; b=sbH61/zIuqyadHniBHJwOvnosLfYgTcCv5bNNcDldi/ooUHB0Vfqbow+4Spogrypt7 Zjt+qIefc33dZnpVPez3F5x3YwrsKRd7NKB4ie+G2Ox/zmfRWHmlgGHqzZugtOvjXKdx DUX1Fu3k52FeNLfgdHjbzDtS+7oGQ2BRUFHZ5Es8w5ukQi3TOEyIWiduGpSgdvTvQcws kC4w7yThcvkcZ+zERJsIjRvwmoV+FHmQRlaeFxyzfV+qmVZFY0ty18z4Pv7JCq9YcKOt Ji27YqqofDipQxMB5KfFZ45+zkXdaOrkGn9VfEVWMh2tEmpJNdCQrE4g+f3k0FJmN2Bx sKSQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b=snqAalWA; dkim=neutral (no key) header.i=@linutronix.de header.s=2020e; arc=pass (i=1 spf=pass spfdomain=linutronix.de dkim=pass dkdomain=linutronix.de dmarc=pass fromdomain=linutronix.de); spf=pass (google.com: domain of linux-kernel+bounces-70499-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-70499-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=linutronix.de Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [139.178.88.99]) by mx.google.com with ESMTPS id by8-20020a056a00400800b006e302dd06aasi2599925pfb.66.2024.02.18.10.58.41 for <ouuuleilei@gmail.com> (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 18 Feb 2024 10:58:42 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-70499-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) client-ip=139.178.88.99; Authentication-Results: mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b=snqAalWA; dkim=neutral (no key) header.i=@linutronix.de header.s=2020e; arc=pass (i=1 spf=pass spfdomain=linutronix.de dkim=pass dkdomain=linutronix.de dmarc=pass fromdomain=linutronix.de); spf=pass (google.com: domain of linux-kernel+bounces-70499-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-70499-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=linutronix.de Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id DD70E281819 for <ouuuleilei@gmail.com>; Sun, 18 Feb 2024 18:58:41 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id BBDB971B55; Sun, 18 Feb 2024 18:57:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="snqAalWA"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="ZmyFWTbF" Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 376F76F094 for <linux-kernel@vger.kernel.org>; Sun, 18 Feb 2024 18:57:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708282673; cv=none; b=Uv8s91tBnvaOp/R2oG0A0MJpYp7Jehn0wwBJfSmSDngELDRkCJ0KIgwiF2pZH77QEin566yf7pMj3zsLBFnzIK1YW+3VN4gO0pG/HeuPmDqVj0VwDL4cQxarPHjZXiumWSFnffxeDeXqfkEvBR+CULeSbwvSHLKjw5M4oU/wlH0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708282673; c=relaxed/simple; bh=xRjhM41YiCV0XIFxys+lC68vQSHxZf7wjECrZPYdxII=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Mj0bkQ6pLnjysOZ3uzyjxPZAFa03D9aicEziRr9PWz4W7jTD6dFAWCa/49QmzwDRMHLr5+9JcCcsgNIh4IvrkZ19rN0ANhC/wD9v18xmyEvFQ4inHmvCwgJrm1k34E2y3KKIPC4BTSWVYpMJifewp3iyR6qtk/1zvs3PdHVtC6A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=snqAalWA; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=ZmyFWTbF; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de From: John Ogness <john.ogness@linutronix.de> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1708282670; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Kjns8XLkW3UOjxVLP1Xg+LLtdkqweLRjHg511yq2AQM=; b=snqAalWATXYn0aUg65LZvGca4wwwf8i8uVStRHQLraQha7BTOjAHnpHAmXikabBL39RLiE MRmXDgvvG2+RBg0rtq5N4Y099iHJtZtZRA2IM7CyqsvJkv1hL2xszoPrUIuRQu2i7iPNm5 4Ct4gXVxeZ//4jnJt56fzxkAOIuycjU+ZRQseZzN1btEl27/9yjG37VTWInD4oLeSwQB14 42u4kchPISfE4m5ic24bedmSDw3pVg7g13BwY2g5C762aTwkRl/Awgk1+pErAzruPbDe6c eU+3HuZVI71hY0OhWp23G8N/FtzzDJANTPF4+myOwLmf1PAuNXlNo146FHyCKg== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1708282670; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Kjns8XLkW3UOjxVLP1Xg+LLtdkqweLRjHg511yq2AQM=; b=ZmyFWTbFlEMBKl9FVuqkxwy1anMpcoUdWmv8BI2orJRjCsQxNuo7BoQOG21L6KMv1rWiVC 1NYdc0VXdvcu3ICg== To: Petr Mladek <pmladek@suse.com> Cc: Sergey Senozhatsky <senozhatsky@chromium.org>, Steven Rostedt <rostedt@goodmis.org>, Thomas Gleixner <tglx@linutronix.de>, linux-kernel@vger.kernel.org Subject: [PATCH printk v2 06/26] printk: nbcon: Ensure ownership release on failed emit Date: Sun, 18 Feb 2024 20:03:06 +0106 Message-Id: <20240218185726.1994771-7-john.ogness@linutronix.de> In-Reply-To: <20240218185726.1994771-1-john.ogness@linutronix.de> References: <20240218185726.1994771-1-john.ogness@linutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: <linux-kernel.vger.kernel.org> List-Subscribe: <mailto:linux-kernel+subscribe@vger.kernel.org> List-Unsubscribe: <mailto:linux-kernel+unsubscribe@vger.kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1791264263728502817 X-GMAIL-MSGID: 1791264263728502817 |
Series |
wire up write_atomic() printing
|
|
Commit Message
John Ogness
Feb. 18, 2024, 6:57 p.m. UTC
Until now it was assumed that ownership has been lost when the
write_atomic() callback fails. And nbcon_emit_next_record()
directly returned false. However, if nbcon_emit_next_record()
returns false, the context must no longer have ownership.
The semantics for the callbacks could be specified such that
if they return false, they must have released ownership. But
in practice those semantics seem odd since the ownership was
acquired outside of the callback.
Ensure ownership has been released before reporting failure by
explicitly attempting a release. If the current context is not
the owner, the release has no effect.
Signed-off-by: John Ogness <john.ogness@linutronix.de>
---
kernel/printk/nbcon.c | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
Comments
On Sun 2024-02-18 20:03:06, John Ogness wrote: > Until now it was assumed that ownership has been lost when the > write_atomic() callback fails. And nbcon_emit_next_record() > directly returned false. However, if nbcon_emit_next_record() > returns false, the context must no longer have ownership. > > The semantics for the callbacks could be specified such that > if they return false, they must have released ownership. But > in practice those semantics seem odd since the ownership was > acquired outside of the callback. > > Ensure ownership has been released before reporting failure by > explicitly attempting a release. If the current context is not > the owner, the release has no effect. Hmm, the new semantic is not ideal either. And I think that it is even worse. The function still releases the owership even though it has been acquired by the caller. In addition, it causes a double unlock in a valid case. I know that the 2nd nbcon_context_release() is a NOP but... I would personally solve this by adding a comment into the code and moving the check, see below. > --- a/kernel/printk/nbcon.c > +++ b/kernel/printk/nbcon.c > @@ -891,17 +891,18 @@ static bool nbcon_emit_next_record(struct nbcon_write_context *wctxt) > nbcon_state_read(con, &cur); > wctxt->unsafe_takeover = cur.unsafe_takeover; > > - if (con->write_atomic) { > + if (con->write_atomic) > done = con->write_atomic(con, wctxt); > - } else { This code path does not create a bad semantic. The semantic is as it is because the context might lose the ownership in "any" nested function. Well, it might deserve a comment, something like: /* * nbcon_emit_next_record() should never be called for legacy * consoles. Handle it as if write_atomic() have lost * the ownership and try to continue. */ > - nbcon_context_release(ctxt); > - WARN_ON_ONCE(1); > - done = false; > - } > > - /* If not done, the emit was aborted. */ > - if (!done) > + if (!done) { > + /* > + * The emit was aborted, probably due to a loss of ownership. > + * Ensure ownership was lost or released before reporting the > + * loss. > + */ Is there a valid reason when con->write_atomic() would return false and still own the context? If not, then this would hide bugs and cause double unlock in the valid case. > + nbcon_context_release(ctxt); > return false; Even better solution might be to do the check at the beginning of the function. It might look like: if (WARN_ON_ONCE(!con->write_atomic)) { /* * This function should never be called for legacy consoles. * Handle it as if write_atomic() have lost the ownership * and try to continue. */ nbcon_context_release(ctxt); return false; } Best Regards, Petr
On 2024-02-20, Petr Mladek <pmladek@suse.com> wrote: >> Until now it was assumed that ownership has been lost when the >> write_atomic() callback fails. And nbcon_emit_next_record() >> directly returned false. However, if nbcon_emit_next_record() >> returns false, the context must no longer have ownership. >> >> The semantics for the callbacks could be specified such that >> if they return false, they must have released ownership. But >> in practice those semantics seem odd since the ownership was >> acquired outside of the callback. >> >> Ensure ownership has been released before reporting failure by >> explicitly attempting a release. If the current context is not >> the owner, the release has no effect. > > Hmm, the new semantic is not ideal either. And I think that it is > even worse. The function still releases the owership even though > it has been acquired by the caller. In addition, it causes > a double unlock in a valid case. I know that the 2nd > nbcon_context_release() is a NOP but... > > I would personally solve this by adding a comment into the code > and moving the check, see below. > >> --- a/kernel/printk/nbcon.c >> +++ b/kernel/printk/nbcon.c >> @@ -891,17 +891,18 @@ static bool nbcon_emit_next_record(struct nbcon_write_context *wctxt) >> nbcon_state_read(con, &cur); >> wctxt->unsafe_takeover = cur.unsafe_takeover; >> >> - if (con->write_atomic) { >> + if (con->write_atomic) >> done = con->write_atomic(con, wctxt); >> - } else { > > This code path does not create a bad semantic. The semantic is > as it is because the context might lose the ownership in "any" > nested function. > > Well, it might deserve a comment, something like: > > /* > * nbcon_emit_next_record() should never be called for legacy > * consoles. Handle it as if write_atomic() have lost > * the ownership and try to continue. > */ >> - nbcon_context_release(ctxt); >> - WARN_ON_ONCE(1); >> - done = false; >> - } >> >> - /* If not done, the emit was aborted. */ >> - if (!done) >> + if (!done) { >> + /* >> + * The emit was aborted, probably due to a loss of ownership. >> + * Ensure ownership was lost or released before reporting the >> + * loss. >> + */ > > Is there a valid reason when con->write_atomic() would return false > and still own the context? This is driver code, so you must use your imagination. But I thought maybe there might be some reason why the driver cannot print the message (due to other driver-internal reasons). In this case, it would return false even though it never lost ownership. > If not, then this would hide bugs and cause double unlock in > the valid case. Even if true is returned, that does not mean that there is still ownership (because it can be lost at any time). And even if we hit the WARN because there is no callback, ownership may have been lost. My point is that there is _always_ a chance that nbcon_context_release() will be called when ownership was already lost. nbcon_context_release() was purposely implemented with the idea that it may be called by a context that has lost ownership. So why not leverage this here? It is _critical_ that if _this_ function returns false, the context no longer has ownership. We could add a nbcon_can_proceed() in front of the release, but nbcon_context_release() already does that internally. >> + nbcon_context_release(ctxt); >> return false; > > Even better solution might be to do the check at the beginning of > the function. It might look like: > > if (WARN_ON_ONCE(!con->write_atomic)) { > /* > * This function should never be called for legacy consoles. > * Handle it as if write_atomic() have lost the ownership > * and try to continue. > */ > nbcon_context_release(ctxt); > return false; > } In the future, con->write_thread() is added. So the missing callback check will end up in a final else branch anyway. John
On 2024-02-20, John Ogness <john.ogness@linutronix.de> wrote: >> Is there a valid reason when con->write_atomic() would return false >> and still own the context? > > This is driver code, so you must use your imagination. But I thought > maybe there might be some reason why the driver cannot print the > message (due to other driver-internal reasons). In this case, it would > return false even though it never lost ownership. I have been thinking about this. I think there is nothing useful that write_atomic() can return. I suggest making it a void return. Then the driver must print the message if ownership was not lost. This is already how write() works and I think it is fine. This simplifies nbcon_emit_next_record() because it can assume write_atomic() was successful and try to enter the unsafe section for the @seq update. If ownership was lost, it will be detected here. If not, the message will be considered handled and @seq is updated. >> if (WARN_ON_ONCE(!con->write_atomic)) { >> /* >> * This function should never be called for legacy consoles. >> * Handle it as if write_atomic() have lost the ownership >> * and try to continue. >> */ >> nbcon_context_release(ctxt); >> return false; >> } I will keep the WARN with a comment similar to your suggestion. John
diff --git a/kernel/printk/nbcon.c b/kernel/printk/nbcon.c index c8093bcc01fe..8ecd76aa22e6 100644 --- a/kernel/printk/nbcon.c +++ b/kernel/printk/nbcon.c @@ -852,7 +852,7 @@ static bool nbcon_emit_next_record(struct nbcon_write_context *wctxt) unsigned long con_dropped; struct nbcon_state cur; unsigned long dropped; - bool done; + bool done = false; /* * The printk buffers are filled within an unsafe section. This @@ -891,17 +891,18 @@ static bool nbcon_emit_next_record(struct nbcon_write_context *wctxt) nbcon_state_read(con, &cur); wctxt->unsafe_takeover = cur.unsafe_takeover; - if (con->write_atomic) { + if (con->write_atomic) done = con->write_atomic(con, wctxt); - } else { - nbcon_context_release(ctxt); - WARN_ON_ONCE(1); - done = false; - } - /* If not done, the emit was aborted. */ - if (!done) + if (!done) { + /* + * The emit was aborted, probably due to a loss of ownership. + * Ensure ownership was lost or released before reporting the + * loss. + */ + nbcon_context_release(ctxt); return false; + } /* * Since any dropped message was successfully output, reset the