From: Flavio Leitner <fleitner@redhat.com>
To: netdev@vger.kernel.org
Cc: bridge@lists.linux-foundation.org, Cong Wang <amwang@redhat.com>,
Neil Horman <nhorman@tuxdriver.com>,
Andy Gospodarek <gospo@redhat.com>,
Jay Vosburgh <fubar@us.ibm.com>,
lkml <linux-kernel@vger.kernel.org>,
bonding-devel@lists.sourceforge.net,
Flavio Leitner <fbl@sysclose.org>, Jeff Moyer <jmoyer@redhat.com>,
Flavio Leitner <fleitner@redhat.com>,
Matt Mackall <mpm@selenic.com>,
David Miller <davem@davemloft.net>
Subject: [Bridge] [PATCH] netconsole: queue console messages to send later
Date: Mon, 7 Jun 2010 16:24:52 -0300 [thread overview]
Message-ID: <1275938692-26997-1-git-send-email-fleitner@redhat.com> (raw)
In-Reply-To: <24059.1275417767@death.nxdomain.ibm.com>
There are some networking drivers that hold a lock in the
transmit path. Therefore, if a console message is printed
after that, netconsole will push it through the transmit path,
resulting in a deadlock.
This patch fixes the re-injection problem by queuing the console
messages in a preallocated circular buffer and then scheduling a
workqueue to send them later with another context.
Signed-off-by: Flavio Leitner <fleitner@redhat.com>
---
drivers/net/netconsole.c | 156 +++++++++++++++++++++++++++++++++++++++-------
1 files changed, 133 insertions(+), 23 deletions(-)
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index ca142c4..874376d 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -44,6 +44,8 @@
#include <linux/netpoll.h>
#include <linux/inet.h>
#include <linux/configfs.h>
+#include <linux/workqueue.h>
+#include <linux/circ_buf.h>
MODULE_AUTHOR("Maintainer: Matt Mackall <mpm@selenic.com>");
MODULE_DESCRIPTION("Console driver for network interfaces");
@@ -56,6 +58,10 @@ static char config[MAX_PARAM_LENGTH];
module_param_string(netconsole, config, MAX_PARAM_LENGTH, 0);
MODULE_PARM_DESC(netconsole, " netconsole=[src-port]@[src-ip]/[dev],[tgt-port]@<tgt-ip>/[tgt-macaddr]");
+static int logsize = PAGE_SIZE;
+module_param(logsize, int, 0444);
+MODULE_PARM_DESC(logsize, "netconsole buffer size");
+
#ifndef MODULE
static int __init option_setup(char *opt)
{
@@ -100,6 +106,75 @@ struct netconsole_target {
struct netpoll np;
};
+struct netconsole_msg_ctl {
+ struct circ_buf messages;
+ unsigned long ring_size;
+ struct page *buffer_page;
+ struct work_struct tx_work;
+};
+static struct netconsole_msg_ctl *netconsole_ctl;
+
+#define RING_INC_POS(pos, inc, size) ((pos + inc) & (size - 1))
+
+static void netconsole_target_get(struct netconsole_target *nt);
+static void netconsole_target_put(struct netconsole_target *nt);
+
+static void netconsole_start_xmit(const char *msg, unsigned int length)
+{
+ int frag, left;
+ unsigned long flags;
+ struct netconsole_target *nt;
+ const char *tmp;
+
+ /* Avoid taking lock and disabling interrupts unnecessarily */
+ 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
+ * so that we're able to get as much logging out to
+ * at least one target if we die inside here, instead
+ * of unnecessarily keeping all targets in lock-step.
+ */
+ tmp = msg;
+ for (left = length; left;) {
+ frag = min(left, MAX_PRINT_CHUNK);
+ netpoll_send_udp(&nt->np, tmp, frag);
+ tmp += frag;
+ left -= frag;
+ }
+ }
+ netconsole_target_put(nt);
+ }
+ spin_unlock_irqrestore(&target_list_lock, flags);
+}
+
+static void netconsole_process_queue(struct work_struct *work)
+{
+ struct circ_buf *messages = &netconsole_ctl->messages;
+ unsigned long ring_size = netconsole_ctl->ring_size;
+ unsigned long head = ACCESS_ONCE(messages->head);
+ unsigned long len;
+
+ while (CIRC_CNT(head, messages->tail, ring_size) >= 1) {
+ /* read index before reading contents at that index */
+ smp_read_barrier_depends();
+
+ /* pick up a length that don't wrap in the middle */
+ len = CIRC_CNT_TO_END(head, messages->tail, ring_size);
+ netconsole_start_xmit(&messages->buf[messages->tail], len);
+
+ /* finish reading descriptor before incrementing tail */
+ smp_mb();
+ messages->tail = RING_INC_POS(messages->tail, len, ring_size);
+ head = ACCESS_ONCE(messages->head);
+ }
+}
+
#ifdef CONFIG_NETCONSOLE_DYNAMIC
static struct configfs_subsystem netconsole_subsys;
@@ -702,38 +777,43 @@ static struct notifier_block netconsole_netdev_notifier = {
.notifier_call = netconsole_netdev_event,
};
+/* called with console sem, interrupts disabled */
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;
+ struct circ_buf *messages = &netconsole_ctl->messages;
+ unsigned long ring_size = netconsole_ctl->ring_size;
+ unsigned long tail = ACCESS_ONCE(messages->tail);
+ unsigned long left;
+ unsigned long end;
+ unsigned long pos;
/* Avoid taking lock and disabling interrupts unnecessarily */
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
- * so that we're able to get as much logging out to
- * at least one target if we die inside here, instead
- * of unnecessarily keeping all targets in lock-step.
- */
- tmp = msg;
- for (left = len; left;) {
- frag = min(left, MAX_PRINT_CHUNK);
- netpoll_send_udp(&nt->np, tmp, frag);
- tmp += frag;
- left -= frag;
- }
+ pos = 0;
+ left = len;
+ while (left && CIRC_SPACE(messages->head, tail, ring_size) >= 1) {
+ end = CIRC_SPACE_TO_END(messages->head, tail, ring_size);
+ /* fast path, no wrapping is needed */
+ if (end >= left) {
+ memcpy(&messages->buf[messages->head], &msg[pos], left);
+ smp_wmb();
+ messages->head = RING_INC_POS(messages->head, left, ring_size);
+ left = 0;
}
- netconsole_target_put(nt);
+ else {
+ /* copy up to the end */
+ memcpy(&messages->buf[messages->head], &msg[pos], end);
+ smp_wmb();
+ messages->head = RING_INC_POS(messages->head, end, ring_size);
+ left -= end;
+ pos += end;
+ }
+
}
- spin_unlock_irqrestore(&target_list_lock, flags);
+
+ schedule_work(&netconsole_ctl->tx_work);
}
static struct console netconsole = {
@@ -746,9 +826,25 @@ static int __init init_netconsole(void)
{
int err;
struct netconsole_target *nt, *tmp;
+ struct circ_buf *messages;
unsigned long flags;
char *target_config;
char *input = config;
+ int order = get_order(logsize);
+
+ err = -ENOMEM;
+ netconsole_ctl = kzalloc(sizeof(*netconsole_ctl), GFP_KERNEL);
+ if (netconsole_ctl == NULL)
+ goto nomem;
+
+ netconsole_ctl->buffer_page = alloc_pages(GFP_KERNEL, order);
+ if (netconsole_ctl->buffer_page == NULL)
+ goto nopage;
+
+ netconsole_ctl->ring_size = (PAGE_SIZE << order);
+ messages = &netconsole_ctl->messages;
+ messages->buf = page_address(netconsole_ctl->buffer_page);
+ INIT_WORK(&netconsole_ctl->tx_work, netconsole_process_queue);
if (strnlen(input, MAX_PARAM_LENGTH)) {
while ((target_config = strsep(&input, ";"))) {
@@ -795,6 +891,11 @@ fail:
free_param_target(nt);
}
+ __free_pages(netconsole_ctl->buffer_page, order);
+nopage:
+ kfree(netconsole_ctl);
+
+nomem:
return err;
}
@@ -806,6 +907,10 @@ static void __exit cleanup_netconsole(void)
dynamic_netconsole_exit();
unregister_netdevice_notifier(&netconsole_netdev_notifier);
+ flush_work(&netconsole_ctl->tx_work);
+ cancel_work_sync(&netconsole_ctl->tx_work);
+ netconsole_process_queue(NULL);
+
/*
* Targets created via configfs pin references on our module
* and would first be rmdir(2)'ed from userspace. We reach
@@ -818,6 +923,11 @@ static void __exit cleanup_netconsole(void)
list_del(&nt->list);
free_param_target(nt);
}
+
+ __free_pages(netconsole_ctl->buffer_page,
+ get_order(netconsole_ctl->ring_size));
+
+ kfree(netconsole_ctl);
}
module_init(init_netconsole);
--
1.7.0.1
WARNING: multiple messages have this Message-ID (diff)
From: Flavio Leitner <fleitner@redhat.com>
To: netdev@vger.kernel.org
Cc: David Miller <davem@davemloft.net>, Cong Wang <amwang@redhat.com>,
Jay Vosburgh <fubar@us.ibm.com>,
Flavio Leitner <fbl@sysclose.org>, Matt Mackall <mpm@selenic.com>,
Andy Gospodarek <gospo@redhat.com>,
Neil Horman <nhorman@tuxdriver.com>,
Jeff Moyer <jmoyer@redhat.com>,
Stephen Hemminger <shemminger@linux-foundation.org>,
lkml <linux-kernel@vger.kernel.org>,
<bridge@lists.linux-foundation.org>,
<bonding-devel@lists.sourceforge.net>,
Flavio Leitner <fleitner@redhat.com>
Subject: [PATCH] netconsole: queue console messages to send later
Date: Mon, 7 Jun 2010 16:24:52 -0300 [thread overview]
Message-ID: <1275938692-26997-1-git-send-email-fleitner@redhat.com> (raw)
In-Reply-To: <24059.1275417767@death.nxdomain.ibm.com>
There are some networking drivers that hold a lock in the
transmit path. Therefore, if a console message is printed
after that, netconsole will push it through the transmit path,
resulting in a deadlock.
This patch fixes the re-injection problem by queuing the console
messages in a preallocated circular buffer and then scheduling a
workqueue to send them later with another context.
Signed-off-by: Flavio Leitner <fleitner@redhat.com>
---
drivers/net/netconsole.c | 156 +++++++++++++++++++++++++++++++++++++++-------
1 files changed, 133 insertions(+), 23 deletions(-)
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index ca142c4..874376d 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -44,6 +44,8 @@
#include <linux/netpoll.h>
#include <linux/inet.h>
#include <linux/configfs.h>
+#include <linux/workqueue.h>
+#include <linux/circ_buf.h>
MODULE_AUTHOR("Maintainer: Matt Mackall <mpm@selenic.com>");
MODULE_DESCRIPTION("Console driver for network interfaces");
@@ -56,6 +58,10 @@ static char config[MAX_PARAM_LENGTH];
module_param_string(netconsole, config, MAX_PARAM_LENGTH, 0);
MODULE_PARM_DESC(netconsole, " netconsole=[src-port]@[src-ip]/[dev],[tgt-port]@<tgt-ip>/[tgt-macaddr]");
+static int logsize = PAGE_SIZE;
+module_param(logsize, int, 0444);
+MODULE_PARM_DESC(logsize, "netconsole buffer size");
+
#ifndef MODULE
static int __init option_setup(char *opt)
{
@@ -100,6 +106,75 @@ struct netconsole_target {
struct netpoll np;
};
+struct netconsole_msg_ctl {
+ struct circ_buf messages;
+ unsigned long ring_size;
+ struct page *buffer_page;
+ struct work_struct tx_work;
+};
+static struct netconsole_msg_ctl *netconsole_ctl;
+
+#define RING_INC_POS(pos, inc, size) ((pos + inc) & (size - 1))
+
+static void netconsole_target_get(struct netconsole_target *nt);
+static void netconsole_target_put(struct netconsole_target *nt);
+
+static void netconsole_start_xmit(const char *msg, unsigned int length)
+{
+ int frag, left;
+ unsigned long flags;
+ struct netconsole_target *nt;
+ const char *tmp;
+
+ /* Avoid taking lock and disabling interrupts unnecessarily */
+ 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
+ * so that we're able to get as much logging out to
+ * at least one target if we die inside here, instead
+ * of unnecessarily keeping all targets in lock-step.
+ */
+ tmp = msg;
+ for (left = length; left;) {
+ frag = min(left, MAX_PRINT_CHUNK);
+ netpoll_send_udp(&nt->np, tmp, frag);
+ tmp += frag;
+ left -= frag;
+ }
+ }
+ netconsole_target_put(nt);
+ }
+ spin_unlock_irqrestore(&target_list_lock, flags);
+}
+
+static void netconsole_process_queue(struct work_struct *work)
+{
+ struct circ_buf *messages = &netconsole_ctl->messages;
+ unsigned long ring_size = netconsole_ctl->ring_size;
+ unsigned long head = ACCESS_ONCE(messages->head);
+ unsigned long len;
+
+ while (CIRC_CNT(head, messages->tail, ring_size) >= 1) {
+ /* read index before reading contents at that index */
+ smp_read_barrier_depends();
+
+ /* pick up a length that don't wrap in the middle */
+ len = CIRC_CNT_TO_END(head, messages->tail, ring_size);
+ netconsole_start_xmit(&messages->buf[messages->tail], len);
+
+ /* finish reading descriptor before incrementing tail */
+ smp_mb();
+ messages->tail = RING_INC_POS(messages->tail, len, ring_size);
+ head = ACCESS_ONCE(messages->head);
+ }
+}
+
#ifdef CONFIG_NETCONSOLE_DYNAMIC
static struct configfs_subsystem netconsole_subsys;
@@ -702,38 +777,43 @@ static struct notifier_block netconsole_netdev_notifier = {
.notifier_call = netconsole_netdev_event,
};
+/* called with console sem, interrupts disabled */
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;
+ struct circ_buf *messages = &netconsole_ctl->messages;
+ unsigned long ring_size = netconsole_ctl->ring_size;
+ unsigned long tail = ACCESS_ONCE(messages->tail);
+ unsigned long left;
+ unsigned long end;
+ unsigned long pos;
/* Avoid taking lock and disabling interrupts unnecessarily */
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
- * so that we're able to get as much logging out to
- * at least one target if we die inside here, instead
- * of unnecessarily keeping all targets in lock-step.
- */
- tmp = msg;
- for (left = len; left;) {
- frag = min(left, MAX_PRINT_CHUNK);
- netpoll_send_udp(&nt->np, tmp, frag);
- tmp += frag;
- left -= frag;
- }
+ pos = 0;
+ left = len;
+ while (left && CIRC_SPACE(messages->head, tail, ring_size) >= 1) {
+ end = CIRC_SPACE_TO_END(messages->head, tail, ring_size);
+ /* fast path, no wrapping is needed */
+ if (end >= left) {
+ memcpy(&messages->buf[messages->head], &msg[pos], left);
+ smp_wmb();
+ messages->head = RING_INC_POS(messages->head, left, ring_size);
+ left = 0;
}
- netconsole_target_put(nt);
+ else {
+ /* copy up to the end */
+ memcpy(&messages->buf[messages->head], &msg[pos], end);
+ smp_wmb();
+ messages->head = RING_INC_POS(messages->head, end, ring_size);
+ left -= end;
+ pos += end;
+ }
+
}
- spin_unlock_irqrestore(&target_list_lock, flags);
+
+ schedule_work(&netconsole_ctl->tx_work);
}
static struct console netconsole = {
@@ -746,9 +826,25 @@ static int __init init_netconsole(void)
{
int err;
struct netconsole_target *nt, *tmp;
+ struct circ_buf *messages;
unsigned long flags;
char *target_config;
char *input = config;
+ int order = get_order(logsize);
+
+ err = -ENOMEM;
+ netconsole_ctl = kzalloc(sizeof(*netconsole_ctl), GFP_KERNEL);
+ if (netconsole_ctl == NULL)
+ goto nomem;
+
+ netconsole_ctl->buffer_page = alloc_pages(GFP_KERNEL, order);
+ if (netconsole_ctl->buffer_page == NULL)
+ goto nopage;
+
+ netconsole_ctl->ring_size = (PAGE_SIZE << order);
+ messages = &netconsole_ctl->messages;
+ messages->buf = page_address(netconsole_ctl->buffer_page);
+ INIT_WORK(&netconsole_ctl->tx_work, netconsole_process_queue);
if (strnlen(input, MAX_PARAM_LENGTH)) {
while ((target_config = strsep(&input, ";"))) {
@@ -795,6 +891,11 @@ fail:
free_param_target(nt);
}
+ __free_pages(netconsole_ctl->buffer_page, order);
+nopage:
+ kfree(netconsole_ctl);
+
+nomem:
return err;
}
@@ -806,6 +907,10 @@ static void __exit cleanup_netconsole(void)
dynamic_netconsole_exit();
unregister_netdevice_notifier(&netconsole_netdev_notifier);
+ flush_work(&netconsole_ctl->tx_work);
+ cancel_work_sync(&netconsole_ctl->tx_work);
+ netconsole_process_queue(NULL);
+
/*
* Targets created via configfs pin references on our module
* and would first be rmdir(2)'ed from userspace. We reach
@@ -818,6 +923,11 @@ static void __exit cleanup_netconsole(void)
list_del(&nt->list);
free_param_target(nt);
}
+
+ __free_pages(netconsole_ctl->buffer_page,
+ get_order(netconsole_ctl->ring_size));
+
+ kfree(netconsole_ctl);
}
module_init(init_netconsole);
--
1.7.0.1
next prev parent reply other threads:[~2010-06-07 19:24 UTC|newest]
Thread overview: 73+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-05-05 8:11 [Bridge] [v5 Patch 1/3] netpoll: add generic support for bridge and bonding devices Amerigo Wang
2010-05-05 8:11 ` Amerigo Wang
2010-05-05 8:11 ` Amerigo Wang
2010-05-05 8:11 ` [Bridge] [v5 Patch 2/3] bridge: make bridge support netpoll Amerigo Wang
2010-05-05 8:11 ` Amerigo Wang
2010-05-05 8:11 ` Amerigo Wang
2010-05-05 8:11 ` [Bridge] [v5 Patch 3/3] bonding: make bonding " Amerigo Wang
2010-05-05 8:11 ` Amerigo Wang
2010-05-05 8:11 ` Amerigo Wang
2010-05-06 2:05 ` [Bridge] [v5 Patch 1/3] netpoll: add generic support for bridge and bonding devices Matt Mackall
2010-05-06 2:05 ` Matt Mackall
2010-05-06 7:44 ` [Bridge] " David Miller
2010-05-06 7:44 ` David Miller
2010-05-07 3:24 ` [Bridge] " Cong Wang
2010-05-07 3:24 ` Cong Wang
2010-05-27 18:05 ` [Bridge] " Flavio Leitner
2010-05-27 18:05 ` Flavio Leitner
2010-05-27 20:35 ` [Bridge] " David Miller
2010-05-27 20:35 ` David Miller
2010-05-27 21:25 ` [Bridge] " Flavio Leitner
2010-05-27 21:25 ` Flavio Leitner
2010-05-28 2:47 ` [Bridge] " Cong Wang
2010-05-28 2:47 ` Cong Wang
2010-05-28 19:40 ` [Bridge] " Flavio Leitner
2010-05-28 19:40 ` Flavio Leitner
2010-05-31 5:56 ` [Bridge] " Cong Wang
2010-05-31 5:56 ` Cong Wang
2010-05-31 19:08 ` [Bridge] " Flavio Leitner
2010-05-31 19:08 ` Flavio Leitner
2010-06-01 9:57 ` [Bridge] " Cong Wang
2010-06-01 9:57 ` Cong Wang
2010-06-01 18:42 ` [Bridge] " Jay Vosburgh
2010-06-01 18:42 ` Jay Vosburgh
2010-06-02 10:04 ` [Bridge] " Cong Wang
2010-06-02 10:04 ` Cong Wang
2010-06-04 19:18 ` [Bridge] " Andy Gospodarek
2010-06-04 19:18 ` Andy Gospodarek
2010-06-07 9:57 ` [Bridge] " Cong Wang
2010-06-07 9:57 ` Cong Wang
2010-06-07 10:01 ` [Bridge] " David Miller
2010-06-07 10:01 ` David Miller
2010-06-08 8:36 ` [Bridge] " Cong Wang
2010-06-08 8:36 ` Cong Wang
2010-06-07 13:03 ` [Bridge] " Andy Gospodarek
2010-06-07 13:03 ` Andy Gospodarek
2010-06-08 8:38 ` [Bridge] " Cong Wang
2010-06-08 8:38 ` Cong Wang
2010-06-07 19:24 ` Flavio Leitner [this message]
2010-06-07 19:24 ` [PATCH] netconsole: queue console messages to send later Flavio Leitner
2010-06-07 19:50 ` [Bridge] " Matt Mackall
2010-06-07 19:50 ` Matt Mackall
2010-06-07 20:00 ` [Bridge] " Stephen Hemminger
2010-06-07 20:00 ` Stephen Hemminger
2010-06-07 20:21 ` [Bridge] " Matt Mackall
2010-06-07 20:21 ` Matt Mackall
2010-06-07 23:52 ` [Bridge] " David Miller
2010-06-07 23:52 ` David Miller
2010-06-07 23:50 ` [Bridge] " David Miller
2010-06-07 23:50 ` David Miller
2010-06-08 0:37 ` [Bridge] " Flavio Leitner
2010-06-08 0:37 ` Flavio Leitner
2010-06-08 8:59 ` [Bridge] " Cong Wang
2010-06-08 8:59 ` Cong Wang
2010-05-28 8:16 ` [Bridge] [v5 Patch 1/3] netpoll: add generic support for bridge and bonding devices Cong Wang
2010-05-28 8:16 ` Cong Wang
2010-05-28 20:42 ` [Bridge] " Flavio Leitner
2010-05-28 20:42 ` Flavio Leitner
2010-05-28 21:03 ` [Bridge] " Jay Vosburgh
2010-05-28 21:03 ` Jay Vosburgh
2010-05-31 5:29 ` [Bridge] " Cong Wang
2010-05-31 5:29 ` Cong Wang
2010-05-31 5:37 ` [Bridge] " Cong Wang
2010-05-31 5:37 ` Cong Wang
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=1275938692-26997-1-git-send-email-fleitner@redhat.com \
--to=fleitner@redhat.com \
--cc=amwang@redhat.com \
--cc=bonding-devel@lists.sourceforge.net \
--cc=bridge@lists.linux-foundation.org \
--cc=davem@davemloft.net \
--cc=fbl@sysclose.org \
--cc=fubar@us.ibm.com \
--cc=gospo@redhat.com \
--cc=jmoyer@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mpm@selenic.com \
--cc=netdev@vger.kernel.org \
--cc=nhorman@tuxdriver.com \
/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.