From: Tejun Heo <tj@kernel.org>
To: akpm@linux-foundation.org, davem@davemloft.net
Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org,
Tejun Heo <tj@kernel.org>
Subject: [PATCH 09/16] netconsole: replace target_list_lock with console_lock
Date: Thu, 16 Apr 2015 19:03:46 -0400 [thread overview]
Message-ID: <1429225433-11946-10-git-send-email-tj@kernel.org> (raw)
In-Reply-To: <1429225433-11946-1-git-send-email-tj@kernel.org>
netconsole has been using a spinlock - target_list_lock - to protect
the list of configured netconsole targets and their enable/disable
states. With the disabling from netdevice_notifier moved off to a
workqueue by the previous patch and thus outside of rtnl_lock,
target_list_lock can be replaced with console_lock, which allows us to
avoid grabbing an extra lock in the log write path and can simplify
locking when involving other subsystems as console_lock is only
trylocked from printk path.
This patch replaces target_list_lock with console_lock. The
conversion is one-to-one except for write_msg(). The function is
called with console_lock() already held so no further locking is
necessary; however, as netpoll_send_udp() expects irq to be disabled,
explicit irq save/restore pair is added around it.
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: David Miller <davem@davemloft.net>
---
drivers/net/netconsole.c | 50 ++++++++++++++++++------------------------------
1 file changed, 19 insertions(+), 31 deletions(-)
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index d355776..57c02ab 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -73,12 +73,12 @@ static int __init option_setup(char *opt)
__setup("netconsole=", option_setup);
#endif /* MODULE */
-/* Linked list of all configured targets */
+/*
+ * Linked list of all configured targets. The list and each target's
+ * enable/disable state are protected by console_lock.
+ */
static LIST_HEAD(target_list);
-/* This needs to be a spinlock because write_msg() cannot sleep */
-static DEFINE_SPINLOCK(target_list_lock);
-
/**
* struct netconsole_target - Represents a configured netconsole target.
* @list: Links this target into the target_list.
@@ -325,7 +325,6 @@ static ssize_t store_enabled(struct netconsole_target *nt,
const char *buf,
size_t count)
{
- unsigned long flags;
int enabled;
int err;
@@ -357,9 +356,9 @@ static ssize_t store_enabled(struct netconsole_target *nt,
* otherwise we might end up in write_msg() with
* nt->np.dev == NULL and nt->enabled == true
*/
- spin_lock_irqsave(&target_list_lock, flags);
+ console_lock();
nt->enabled = false;
- spin_unlock_irqrestore(&target_list_lock, flags);
+ console_unlock();
netpoll_cleanup(&nt->np);
}
@@ -601,7 +600,6 @@ static struct config_item_type netconsole_target_type = {
static struct config_item *make_netconsole_target(struct config_group *group,
const char *name)
{
- unsigned long flags;
struct netconsole_target *nt;
nt = alloc_netconsole_target();
@@ -612,9 +610,9 @@ static struct config_item *make_netconsole_target(struct config_group *group,
config_item_init_type_name(&nt->item, name, &netconsole_target_type);
/* Adding, but it is disabled */
- spin_lock_irqsave(&target_list_lock, flags);
+ console_lock();
list_add(&nt->list, &target_list);
- spin_unlock_irqrestore(&target_list_lock, flags);
+ console_unlock();
return &nt->item;
}
@@ -622,12 +620,11 @@ static struct config_item *make_netconsole_target(struct config_group *group,
static void drop_netconsole_target(struct config_group *group,
struct config_item *item)
{
- unsigned long flags;
struct netconsole_target *nt = to_target(item);
- spin_lock_irqsave(&target_list_lock, flags);
+ console_lock();
list_del(&nt->list);
- spin_unlock_irqrestore(&target_list_lock, flags);
+ console_unlock();
/*
* The target may have never been enabled, or was manually disabled
@@ -664,11 +661,10 @@ static struct configfs_subsystem netconsole_subsys = {
static void netconsole_deferred_disable_work_fn(struct work_struct *work)
{
struct netconsole_target *nt, *to_disable;
- unsigned long flags;
repeat:
to_disable = NULL;
- spin_lock_irqsave(&target_list_lock, flags);
+ console_lock();
list_for_each_entry(nt, &target_list, list) {
if (!nt->disable_scheduled)
continue;
@@ -682,7 +678,7 @@ repeat:
to_disable = nt;
break;
}
- spin_unlock_irqrestore(&target_list_lock, flags);
+ console_unlock();
if (to_disable) {
netpoll_cleanup(&to_disable->np);
@@ -698,7 +694,6 @@ static DECLARE_WORK(netconsole_deferred_disable_work,
static int netconsole_netdev_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
- unsigned long flags;
struct netconsole_target *nt;
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
bool stopped = false;
@@ -707,7 +702,7 @@ static int netconsole_netdev_event(struct notifier_block *this,
event == NETDEV_RELEASE || event == NETDEV_JOIN))
goto done;
- spin_lock_irqsave(&target_list_lock, flags);
+ console_lock();
list_for_each_entry(nt, &target_list, list) {
if (nt->np.dev == dev) {
switch (event) {
@@ -726,7 +721,7 @@ static int netconsole_netdev_event(struct notifier_block *this,
}
}
}
- spin_unlock_irqrestore(&target_list_lock, flags);
+ console_unlock();
if (stopped) {
const char *msg = "had an event";
switch (event) {
@@ -755,7 +750,6 @@ static struct notifier_block netconsole_netdev_notifier = {
static void write_msg(struct console *con, const char *msg, unsigned int len)
{
int frag, left;
- unsigned long flags;
struct netconsole_target *nt;
const char *tmp;
@@ -765,9 +759,7 @@ static void write_msg(struct console *con, const char *msg, unsigned int len)
if (list_empty(&target_list))
return;
- spin_lock_irqsave(&target_list_lock, flags);
list_for_each_entry(nt, &target_list, list) {
- netconsole_target_get(nt);
if (nt->enabled && netif_running(nt->np.dev)) {
/*
* We nest this inside the for-each-target loop above
@@ -783,9 +775,7 @@ static void write_msg(struct console *con, const char *msg, unsigned int len)
left -= frag;
}
}
- netconsole_target_put(nt);
}
- spin_unlock_irqrestore(&target_list_lock, flags);
}
static struct console netconsole = {
@@ -798,7 +788,6 @@ static int __init init_netconsole(void)
{
int err;
struct netconsole_target *nt, *tmp;
- unsigned long flags;
char *target_config;
char *input = config;
@@ -812,9 +801,9 @@ static int __init init_netconsole(void)
/* Dump existing printks when we register */
netconsole.flags |= CON_PRINTBUFFER;
- spin_lock_irqsave(&target_list_lock, flags);
+ console_lock();
list_add(&nt->list, &target_list);
- spin_unlock_irqrestore(&target_list_lock, flags);
+ console_unlock();
}
}
@@ -839,8 +828,8 @@ fail:
/*
* Remove all targets and destroy them (only targets created
- * from the boot/module option exist here). Skipping the list
- * lock is safe here, and netpoll_cleanup() will sleep.
+ * from the boot/module option exist here). Skipping the console
+ * lock is safe here.
*/
list_for_each_entry_safe(nt, tmp, &target_list, list) {
list_del(&nt->list);
@@ -864,8 +853,7 @@ static void __exit cleanup_netconsole(void)
* and would first be rmdir(2)'ed from userspace. We reach
* here only when they are already destroyed, and only those
* created from the boot/module option are left, so remove and
- * destroy them. Skipping the list lock is safe here, and
- * netpoll_cleanup() will sleep.
+ * destroy them. Skipping the console lock is safe here.
*/
list_for_each_entry_safe(nt, tmp, &target_list, list) {
list_del(&nt->list);
--
2.1.0
next prev parent reply other threads:[~2015-04-16 23:07 UTC|newest]
Thread overview: 47+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-04-16 23:03 [PATCHSET] printk, netconsole: implement reliable netconsole Tejun Heo
2015-04-16 23:03 ` [PATCH 01/16] printk: guard the amount written per line by devkmsg_read() Tejun Heo
2015-04-20 12:11 ` Petr Mladek
2015-04-20 12:33 ` Petr Mladek
2015-04-16 23:03 ` [PATCH 02/16] printk: factor out message formatting from devkmsg_read() Tejun Heo
2015-04-20 12:30 ` Petr Mladek
2015-04-16 23:03 ` [PATCH 03/16] printk: move LOG_NOCONS skipping into call_console_drivers() Tejun Heo
2015-04-20 12:50 ` Petr Mladek
2015-04-16 23:03 ` [PATCH 04/16] printk: implement support for extended console drivers Tejun Heo
2015-04-20 15:43 ` Petr Mladek
2015-04-21 10:03 ` Petr Mladek
2015-04-27 21:09 ` Tejun Heo
2015-04-28 9:42 ` Petr Mladek
2015-04-28 14:10 ` Tejun Heo
2015-04-28 14:24 ` Petr Mladek
2015-04-16 23:03 ` [PATCH 05/16] printk: implement log_seq_range() and ext_log_from_seq() Tejun Heo
2015-04-16 23:03 ` [PATCH 06/16] netconsole: make netconsole_target->enabled a bool Tejun Heo
2015-04-16 23:03 ` [PATCH 07/16] netconsole: factor out alloc_netconsole_target() Tejun Heo
2015-04-16 23:03 ` [PATCH 08/16] netconsole: punt disabling to workqueue from netdevice_notifier Tejun Heo
2015-04-16 23:03 ` Tejun Heo [this message]
2015-04-16 23:03 ` [PATCH 10/16] netconsole: introduce netconsole_mutex Tejun Heo
2015-04-16 23:03 ` [PATCH 11/16] netconsole: consolidate enable/disable and create/destroy paths Tejun Heo
2015-04-16 23:03 ` [PATCH 12/16] netconsole: implement extended console support Tejun Heo
2015-04-16 23:03 ` [PATCH 13/16] netconsole: implement retransmission support for extended consoles Tejun Heo
2015-04-16 23:03 ` [PATCH 14/16] netconsole: implement ack handling and emergency transmission Tejun Heo
2015-04-16 23:03 ` [PATCH 15/16] netconsole: implement netconsole receiver library Tejun Heo
2015-04-16 23:03 ` [PATCH 16/16] netconsole: update documentation for extended netconsole Tejun Heo
2015-04-17 15:35 ` [PATCHSET] printk, netconsole: implement reliable netconsole Tetsuo Handa
2015-04-17 16:28 ` Tejun Heo
2015-04-17 17:17 ` David Miller
2015-04-17 17:37 ` Tejun Heo
2015-04-17 17:43 ` Tetsuo Handa
2015-04-17 17:45 ` Tejun Heo
2015-04-17 18:03 ` Tetsuo Handa
2015-04-17 18:07 ` Tejun Heo
2015-04-17 18:20 ` Tetsuo Handa
2015-04-17 18:26 ` Tejun Heo
2015-04-18 13:09 ` Tetsuo Handa
2015-04-17 18:04 ` Tejun Heo
2015-04-17 18:55 ` David Miller
2015-04-17 19:52 ` Tejun Heo
2015-04-17 20:06 ` David Miller
2015-04-21 21:51 ` Stephen Hemminger
2015-04-19 7:25 ` Rob Landley
2015-04-20 12:00 ` David Laight
2015-04-20 12:00 ` David Laight
2015-04-20 14:33 ` Tejun Heo
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=1429225433-11946-10-git-send-email-tj@kernel.org \
--to=tj@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=davem@davemloft.net \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
/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.