From patchwork Mon Nov 14 16:28:55 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Ogness X-Patchwork-Id: 13042550 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C588EC41535 for ; Mon, 14 Nov 2022 16:29:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237540AbiKNQ3l (ORCPT ); Mon, 14 Nov 2022 11:29:41 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35524 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237434AbiKNQ3i (ORCPT ); Mon, 14 Nov 2022 11:29:38 -0500 Received: from galois.linutronix.de (Galois.linutronix.de [IPv6:2a0a:51c0:0:12e:550::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 18EA22C0; Mon, 14 Nov 2022 08:29:37 -0800 (PST) From: John Ogness DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1668443375; 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=tqcgl/PatKp2kr+pgaPtk6Kzu4HMlErNR4mnxas6jwk=; b=qKx+VJuDzpUJJXwJ3b9vs6bAjLubt6siELBgT+/DCZsajhHKOkdodlJbHKyBYzUTQl9X2K MBo7U6ZcGj/13xDDi241cAo2sBP1kHgw8JjW9cIo3Wq4busIZ59bCWXABMvosfia/0yscU UUoRRVYZlbr4W0xDK8zhGB8APbk/l/+d6Ygg6eTGAb0yUvts31imaUOK4k9PF1fXEKJStH 7wQ99bLM1thUiGw4T61ByBN/kU0XHseXl8btVFmAjlowH07dM9l2eIYKQfZxdV5o0zBSAP 0gvFqlVNrJUCa7jbvfQsuIFWBnTJL2U4zTU1YwRxfC4xgo3PmXa0uQpelb2b5Q== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1668443375; 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=tqcgl/PatKp2kr+pgaPtk6Kzu4HMlErNR4mnxas6jwk=; b=BkeXAU/i0KB66XosuQwcWeAbn0K+op/NilejsszupovN74oMW1gMhqCMwMggNOh7oZTz28 jKfU4QduTJTFMcAg== To: Petr Mladek Cc: Sergey Senozhatsky , Steven Rostedt , Thomas Gleixner , linux-kernel@vger.kernel.org, Greg Kroah-Hartman , linux-fsdevel@vger.kernel.org Subject: [PATCH printk v4 02/39] printk: Convert console_drivers list to hlist Date: Mon, 14 Nov 2022 17:34:55 +0106 Message-Id: <20221114162932.141883-3-john.ogness@linutronix.de> In-Reply-To: <20221114162932.141883-1-john.ogness@linutronix.de> References: <20221114162932.141883-1-john.ogness@linutronix.de> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org From: Thomas Gleixner Replace the open coded single linked list with a hlist so a conversion to SRCU protected list walks can reuse the existing primitives. Co-developed-by: John Ogness Signed-off-by: John Ogness Signed-off-by: Thomas Gleixner Reviewed-by: Greg Kroah-Hartman Reviewed-by: Sergey Senozhatsky Reviewed-by: Petr Mladek --- fs/proc/consoles.c | 3 +- include/linux/console.h | 8 ++-- kernel/printk/printk.c | 101 ++++++++++++++++++++++------------------ 3 files changed, 62 insertions(+), 50 deletions(-) diff --git a/fs/proc/consoles.c b/fs/proc/consoles.c index dfe6ce3505ce..cf2e0788f9c7 100644 --- a/fs/proc/consoles.c +++ b/fs/proc/consoles.c @@ -74,8 +74,9 @@ static void *c_start(struct seq_file *m, loff_t *pos) static void *c_next(struct seq_file *m, void *v, loff_t *pos) { struct console *con = v; + ++*pos; - return con->next; + return hlist_entry_safe(con->node.next, struct console, node); } static void c_stop(struct seq_file *m, void *v) diff --git a/include/linux/console.h b/include/linux/console.h index 8c1686e2c233..7b5f21f9e469 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -15,6 +15,7 @@ #define _LINUX_CONSOLE_H_ 1 #include +#include #include struct vc_data; @@ -154,14 +155,16 @@ struct console { u64 seq; unsigned long dropped; void *data; - struct console *next; + struct hlist_node node; }; +extern struct hlist_head console_list; + /* * for_each_console() allows you to iterate on each console */ #define for_each_console(con) \ - for (con = console_drivers; con != NULL; con = con->next) + hlist_for_each_entry(con, &console_list, node) extern int console_set_on_cmdline; extern struct console *early_console; @@ -174,7 +177,6 @@ enum con_flush_mode { extern int add_preferred_console(char *name, int idx, char *options); extern void register_console(struct console *); extern int unregister_console(struct console *); -extern struct console *console_drivers; extern void console_lock(void); extern int console_trylock(void); extern void console_unlock(void); diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index e4f1e7478b52..e6f0832e71f0 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -79,13 +79,12 @@ int oops_in_progress; EXPORT_SYMBOL(oops_in_progress); /* - * console_sem protects the console_drivers list, and also - * provides serialisation for access to the entire console - * driver system. + * console_sem protects console_list and console->flags updates, and also + * provides serialization for access to the entire console driver system. */ static DEFINE_SEMAPHORE(console_sem); -struct console *console_drivers; -EXPORT_SYMBOL_GPL(console_drivers); +HLIST_HEAD(console_list); +EXPORT_SYMBOL_GPL(console_list); /* * System may need to suppress printk message under certain @@ -2556,7 +2555,7 @@ static int console_cpu_notify(unsigned int cpu) * console_lock - lock the console system for exclusive use. * * Acquires a lock which guarantees that the caller has - * exclusive access to the console system and the console_drivers list. + * exclusive access to the console system and console_list. * * Can sleep, returns nothing. */ @@ -2576,7 +2575,7 @@ EXPORT_SYMBOL(console_lock); * console_trylock - try to lock the console system for exclusive use. * * Try to acquire a lock which guarantees that the caller has exclusive - * access to the console system and the console_drivers list. + * access to the console system and console_list. * * returns 1 on success, and 0 on failure to acquire the lock. */ @@ -2940,11 +2939,20 @@ void console_flush_on_panic(enum con_flush_mode mode) console_may_schedule = 0; if (mode == CONSOLE_REPLAY_ALL) { + struct hlist_node *tmp; struct console *c; u64 seq; seq = prb_first_valid_seq(prb); - for_each_console(c) + /* + * This cannot use for_each_console() because it's not established + * that the current context has console locked and neither there is + * a guarantee that there is no concurrency in that case. + * + * Open code it for documentation purposes and pretend that + * it works. + */ + hlist_for_each_entry_safe(c, tmp, &console_list, node) c->seq = seq; } console_unlock(); @@ -3081,6 +3089,9 @@ static void try_enable_default_console(struct console *newcon) (con->flags & CON_BOOT) ? "boot" : "", \ con->name, con->index, ##__VA_ARGS__) +#define console_first() \ + hlist_entry(console_list.first, struct console, node) + /* * The console driver calls this routine during kernel initialization * to register the console printing procedure with printk() and to @@ -3140,8 +3151,8 @@ void register_console(struct console *newcon) * flag set and will be first in the list. */ if (preferred_console < 0) { - if (!console_drivers || !console_drivers->device || - console_drivers->flags & CON_BOOT) { + if (hlist_empty(&console_list) || !console_first()->device || + console_first()->flags & CON_BOOT) { try_enable_default_console(newcon); } } @@ -3169,20 +3180,22 @@ void register_console(struct console *newcon) } /* - * Put this console in the list - keep the - * preferred driver at the head of the list. + * Put this console in the list - keep the + * preferred driver at the head of the list. */ console_lock(); - if ((newcon->flags & CON_CONSDEV) || console_drivers == NULL) { - newcon->next = console_drivers; - console_drivers = newcon; - if (newcon->next) - newcon->next->flags &= ~CON_CONSDEV; - /* Ensure this flag is always set for the head of the list */ + if (hlist_empty(&console_list)) { + /* Ensure CON_CONSDEV is always set for the head. */ newcon->flags |= CON_CONSDEV; + hlist_add_head(&newcon->node, &console_list); + + } else if (newcon->flags & CON_CONSDEV) { + /* Only the new head can have CON_CONSDEV set. */ + console_first()->flags &= ~CON_CONSDEV; + hlist_add_head(&newcon->node, &console_list); + } else { - newcon->next = console_drivers->next; - console_drivers->next = newcon; + hlist_add_behind(&newcon->node, console_list.first); } newcon->dropped = 0; @@ -3209,16 +3222,18 @@ void register_console(struct console *newcon) if (bootcon_enabled && ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV) && !keep_bootcon) { - for_each_console(con) + struct hlist_node *tmp; + + hlist_for_each_entry_safe(con, tmp, &console_list, node) { if (con->flags & CON_BOOT) unregister_console(con); + } } } EXPORT_SYMBOL(register_console); int unregister_console(struct console *console) { - struct console *con; int res; con_printk(KERN_INFO, console, "disabled\n"); @@ -3229,32 +3244,30 @@ int unregister_console(struct console *console) if (res > 0) return 0; - res = -ENODEV; console_lock(); - if (console_drivers == console) { - console_drivers=console->next; - res = 0; - } else { - for_each_console(con) { - if (con->next == console) { - con->next = console->next; - res = 0; - break; - } - } + + /* Disable it unconditionally */ + console->flags &= ~CON_ENABLED; + + if (hlist_unhashed(&console->node)) { + console_unlock(); + return -ENODEV; } - if (res) - goto out_disable_unlock; + hlist_del_init(&console->node); /* + * * If this isn't the last console and it has CON_CONSDEV set, we * need to set it on the next preferred console. + * + * + * The above makes no sense as there is no guarantee that the next + * console has any device attached. Oh well.... */ - if (console_drivers != NULL && console->flags & CON_CONSDEV) - console_drivers->flags |= CON_CONSDEV; + if (!hlist_empty(&console_list) && console->flags & CON_CONSDEV) + console_first()->flags |= CON_CONSDEV; - console->flags &= ~CON_ENABLED; console_unlock(); console_sysfs_notify(); @@ -3262,12 +3275,6 @@ int unregister_console(struct console *console) res = console->exit(console); return res; - -out_disable_unlock: - console->flags &= ~CON_ENABLED; - console_unlock(); - - return res; } EXPORT_SYMBOL(unregister_console); @@ -3317,10 +3324,11 @@ void __init console_init(void) */ static int __init printk_late_init(void) { + struct hlist_node *tmp; struct console *con; int ret; - for_each_console(con) { + hlist_for_each_entry_safe(con, tmp, &console_list, node) { if (!(con->flags & CON_BOOT)) continue; @@ -3340,6 +3348,7 @@ static int __init printk_late_init(void) unregister_console(con); } } + ret = cpuhp_setup_state_nocalls(CPUHP_PRINTK_DEAD, "printk:dead", NULL, console_cpu_notify); WARN_ON(ret < 0); From patchwork Mon Nov 14 16:29:02 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Ogness X-Patchwork-Id: 13042551 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4C4D6C433FE for ; Mon, 14 Nov 2022 16:29:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237549AbiKNQ3m (ORCPT ); Mon, 14 Nov 2022 11:29:42 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35558 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237539AbiKNQ3l (ORCPT ); Mon, 14 Nov 2022 11:29:41 -0500 Received: from galois.linutronix.de (Galois.linutronix.de [IPv6:2a0a:51c0:0:12e:550::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1C99426B; Mon, 14 Nov 2022 08:29:40 -0800 (PST) From: John Ogness DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1668443378; 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=WyGtVM99u5kVDH70iZExE1J1KzxzFf6H5/dTCHJGWmg=; b=FqAoNjaBB2Rlp2mNiLSbghpPzLzwe/mxSu1PahgKtAnhy0JYz8REmdtNz9jHFQFaj113nY ywZ/YEc1WnqLUt/lbm8feA+MyPzbJIRZv3VyR+hVIHoOTru/KIzygWDs2cWOkXnelZvsoo 32AkyhpdUEvPRj7CPilKpeib4j1jznLqH+nKWXz7/7IBnl7Xk86MCDk0tWzXGSqSVG/RUv QRAw1Gqdw/S2PhYt+lV+WuN3kZ8zlf7KMaF8BftoCfYw9WENgLe5lBCaUXBOUsalZFaZAb 9ZPCStORGaRXJVDKwcBdwVGTJacSupeBxD5165H9Ma8QabshUKzxXOyMSguQiA== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1668443378; 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=WyGtVM99u5kVDH70iZExE1J1KzxzFf6H5/dTCHJGWmg=; b=TSOchCPgjdlhJPka+GKTvoyPM/0XtrZC5Yjg7o2tlsAmZW/yw3oP7dxd3MB5cXFma4zBBg 1gDZE59V6J1GTfDQ== To: Petr Mladek Cc: Sergey Senozhatsky , Steven Rostedt , Thomas Gleixner , linux-kernel@vger.kernel.org, Greg Kroah-Hartman , linux-fsdevel@vger.kernel.org Subject: [PATCH printk v4 09/39] proc: consoles: document console_lock usage Date: Mon, 14 Nov 2022 17:35:02 +0106 Message-Id: <20221114162932.141883-10-john.ogness@linutronix.de> In-Reply-To: <20221114162932.141883-1-john.ogness@linutronix.de> References: <20221114162932.141883-1-john.ogness@linutronix.de> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org The console_lock is held throughout the start/show/stop procedure to print out device/driver information about all registered consoles. Since the console_lock is being used for multiple reasons, explicitly document these reasons. This will be useful when the console_lock is split into fine-grained locking. Signed-off-by: John Ogness Reviewed-by: Petr Mladek --- fs/proc/consoles.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fs/proc/consoles.c b/fs/proc/consoles.c index cf2e0788f9c7..46b305fa04ed 100644 --- a/fs/proc/consoles.c +++ b/fs/proc/consoles.c @@ -63,6 +63,15 @@ static void *c_start(struct seq_file *m, loff_t *pos) struct console *con; loff_t off = 0; + /* + * Take console_lock to serialize device() callback with + * other console operations. For example, fg_console is + * modified under console_lock when switching vt. + * + * Hold the console_lock to guarantee safe traversal of the + * console list. SRCU cannot be used because there is no + * place to store the SRCU cookie. + */ console_lock(); for_each_console(con) if (off++ == *pos) From patchwork Mon Nov 14 16:29:26 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Ogness X-Patchwork-Id: 13042552 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B8E9BC43217 for ; Mon, 14 Nov 2022 16:31:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237767AbiKNQbC (ORCPT ); Mon, 14 Nov 2022 11:31:02 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35772 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237694AbiKNQau (ORCPT ); Mon, 14 Nov 2022 11:30:50 -0500 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2A80E2F01D; Mon, 14 Nov 2022 08:29:50 -0800 (PST) From: John Ogness DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1668443388; 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=gLhbxNRRzLzgVuMAENy9jlZuW5IHKymo+X5t98vmt7E=; b=mfXS5Cw3dKtbQJm9mn+jcg8yDvbnLClYULmacns+jvjhLW6rZek5GuH88Ux2VGAzSEiGM+ 22pWQ8qF/fPePKGvvi1k6uu4aDqJWXFK1WWBjtv0tmYOVBDYEAs/ROS4JLOyUa1YgTJSBS FFFAIJonz5AKb777jVgTUWJqIPr38s89l4QvRMZ07iCVdI/jvx0YXISW0ty7Kco/C2TABd qo4nWg+wlTKPATLOpOb3qPPDigJsPiZzdmOHVzXM+cn7TZM8nhVmW2F9ayfwK/EOgNftaP j5HxMDyy54fs41BQhQzBQDCOEqhxBVcysteCb/v9FgrJKxSVFyAApdCPeSkvZw== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1668443388; 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=gLhbxNRRzLzgVuMAENy9jlZuW5IHKymo+X5t98vmt7E=; b=YF4kcTgIBdDPE43HzqRI7H6KMWjfmgcTt3tzko7kkdkywT7MIrIQCbxb+24VrZ/T8f2Pt3 dfouT9kVORt4Q/Dg== To: Petr Mladek Cc: Sergey Senozhatsky , Steven Rostedt , Thomas Gleixner , linux-kernel@vger.kernel.org, Greg Kroah-Hartman , linux-fsdevel@vger.kernel.org Subject: [PATCH printk v4 33/39] proc: consoles: use console_list_lock for list iteration Date: Mon, 14 Nov 2022 17:35:26 +0106 Message-Id: <20221114162932.141883-34-john.ogness@linutronix.de> In-Reply-To: <20221114162932.141883-1-john.ogness@linutronix.de> References: <20221114162932.141883-1-john.ogness@linutronix.de> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org The console_lock is used in part to guarantee safe list iteration. The console_list_lock should be used because list synchronization responsibility will be removed from the console_lock in a later change. Note, the console_lock is still needed to serialize the device() callback with other console operations. Signed-off-by: John Ogness Reviewed-by: Petr Mladek --- fs/proc/consoles.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/fs/proc/consoles.c b/fs/proc/consoles.c index 46b305fa04ed..e0758fe7936d 100644 --- a/fs/proc/consoles.c +++ b/fs/proc/consoles.c @@ -33,7 +33,16 @@ static int show_console_dev(struct seq_file *m, void *v) if (con->device) { const struct tty_driver *driver; int index; + + /* + * Take console_lock to serialize device() callback with + * other console operations. For example, fg_console is + * modified under console_lock when switching vt. + */ + console_lock(); driver = con->device(con, &index); + console_unlock(); + if (driver) { dev = MKDEV(driver->major, driver->minor_start); dev += index; @@ -64,15 +73,11 @@ static void *c_start(struct seq_file *m, loff_t *pos) loff_t off = 0; /* - * Take console_lock to serialize device() callback with - * other console operations. For example, fg_console is - * modified under console_lock when switching vt. - * - * Hold the console_lock to guarantee safe traversal of the + * Hold the console_list_lock to guarantee safe traversal of the * console list. SRCU cannot be used because there is no * place to store the SRCU cookie. */ - console_lock(); + console_list_lock(); for_each_console(con) if (off++ == *pos) break; @@ -90,7 +95,7 @@ static void *c_next(struct seq_file *m, void *v, loff_t *pos) static void c_stop(struct seq_file *m, void *v) { - console_unlock(); + console_list_unlock(); } static const struct seq_operations consoles_op = {