* [PATCH v3 13/22] netpoll: Introduce netpoll_target configs
From: Mike Waychison @ 2010-12-14 21:30 UTC (permalink / raw)
To: simon.kagstrom, davem, nhorman, Matt Mackall
Cc: adurbin, linux-kernel, chavey, Greg KH, netdev, Américo Wang,
akpm, linux-api
In-Reply-To: <20101214212846.17022.64836.stgit@mike.mtv.corp.google.com>
As preparation for moving netpoll_targets out of netconsole and making
them available to other clients, introduce new Kconfig options.
CONFIG_NETPOLL_TARGETS
Access to targets APIs. Only supports parameter based parsing of
targets (via the kernel command line or module paramters).
CONFIG_NETPOLL_TARGETS_DYNAMIC
Extends the support that netpoll_targets provides by allowing for the
dynamic creation of targets in configfs on a per client basis. This is
boolean flag used to enable dynamic support. Specifying it without
also selecting NETPOLL_TARGETS is meaningless.
Signed-off-by: Mike Waychison <mikew@google.com>
Acked-by: Matt Mackall <mpm@selenic.com>
---
Changelog:
- v3
- Fixed to support building netpoll_targets as a module. It depends
on netpoll, but netpoll itself doesn't depend on it.
netpoll_targets will be built as a module if it is needed by either
NETCONSOLE or NETOOPS are enabled as modules (and neither are built
in). CONFIGFS_FS is also only selected to be a module if that is
possible.
---
drivers/net/Kconfig | 15 ++++++++++++---
drivers/net/netconsole.c | 10 +++++-----
2 files changed, 17 insertions(+), 8 deletions(-)
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 4f1755b..2ae9818 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -3379,14 +3379,15 @@ config NET_FC
config NETCONSOLE
tristate "Network console logging support"
+ select NETPOLL_TARGETS
---help---
If you want to log kernel messages over the network, enable this.
See <file:Documentation/networking/netconsole.txt> for details.
config NETCONSOLE_DYNAMIC
bool "Dynamic reconfiguration of logging targets"
- depends on NETCONSOLE && SYSFS
- select CONFIGFS_FS
+ depends on NETCONSOLE
+ select NETPOLL_TARGETS_DYNAMIC
help
This option enables the ability to dynamically reconfigure target
parameters (interface, IP addresses, port numbers, MAC addresses)
@@ -3394,7 +3395,15 @@ config NETCONSOLE_DYNAMIC
See <file:Documentation/networking/netconsole.txt> for details.
config NETPOLL
- def_bool NETCONSOLE
+ def_bool false
+
+config NETPOLL_TARGETS
+ tristate
+ select NETPOLL
+ select CONFIGFS_FS if NETPOLL_TARGETS_DYNAMIC
+
+config NETPOLL_TARGETS_DYNAMIC
+ bool
config NETPOLL_TRAP
bool "Netpoll traffic trapping"
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index fbef723..1970be3 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -69,7 +69,7 @@ struct netpoll_targets {
struct list_head list;
spinlock_t lock;
u16 default_local_port, default_remote_port;
-#ifdef CONFIG_NETCONSOLE_DYNAMIC
+#ifdef CONFIG_NETPOLL_TARGETS_DYNAMIC
struct configfs_subsystem configfs_subsys;
#endif
struct notifier_block netdev_notifier;
@@ -111,7 +111,7 @@ static DEFINE_NETPOLL_TARGETS(targets);
struct netpoll_target {
struct netpoll_targets *nts;
struct list_head list;
-#ifdef CONFIG_NETCONSOLE_DYNAMIC
+#ifdef CONFIG_NETPOLL_TARGETS_DYNAMIC
struct config_item item;
#endif
int np_state;
@@ -194,7 +194,7 @@ static void free_param_target(struct netpoll_target *nt)
kfree(nt);
}
-#ifdef CONFIG_NETCONSOLE_DYNAMIC
+#ifdef CONFIG_NETPOLL_TARGETS_DYNAMIC
/*
* Our subsystem hierarchy is:
@@ -724,7 +724,7 @@ static void netpoll_target_put(struct netpoll_target *nt)
config_item_put(&nt->item);
}
-#else /* !CONFIG_NETCONSOLE_DYNAMIC */
+#else /* !CONFIG_NETPOLL_TARGETS_DYNAMIC */
static int __init dynamic_netpoll_targets_init(const char *subsys_name,
struct netpoll_targets *nts)
@@ -748,7 +748,7 @@ static void netpoll_target_put(struct netpoll_target *nt)
{
}
-#endif /* CONFIG_NETCONSOLE_DYNAMIC */
+#endif /* CONFIG_NETPOLL_TARGETS_DYNAMIC */
/*
* Call netpoll_cleanup on this target asynchronously.
^ permalink raw reply related
* [PATCH v3 12/22] netconsole: Move setting of default ports.
From: Mike Waychison @ 2010-12-14 21:29 UTC (permalink / raw)
To: simon.kagstrom, davem, nhorman, Matt Mackall
Cc: adurbin, linux-kernel, chavey, Greg KH, netdev, Américo Wang,
akpm, linux-api
In-Reply-To: <20101214212846.17022.64836.stgit@mike.mtv.corp.google.com>
Clients of netpoll_targets need to be able to specify the default port
numbers. Do this by specifying the default port numbers in struct
netpoll_targets directly.
Signed-off-by: Mike Waychison <mikew@google.com>
Acked-by: Matt Mackall <mpm@selenic.com>
---
drivers/net/netconsole.c | 13 +++++++++----
1 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 5c8701f..fbef723 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -68,6 +68,7 @@ __setup("netconsole=", option_setup);
struct netpoll_targets {
struct list_head list;
spinlock_t lock;
+ u16 default_local_port, default_remote_port;
#ifdef CONFIG_NETCONSOLE_DYNAMIC
struct configfs_subsystem configfs_subsys;
#endif
@@ -161,8 +162,8 @@ static struct netpoll_target *alloc_param_target(struct netpoll_targets *nts,
nt->nts = nts;
nt->np.name = nts->subsys_name;
strlcpy(nt->np.dev_name, "eth0", IFNAMSIZ);
- nt->np.local_port = 6665;
- nt->np.remote_port = 6666;
+ nt->np.local_port = nts->default_local_port;
+ nt->np.remote_port = nts->default_remote_port;
memset(nt->np.remote_mac, 0xff, ETH_ALEN);
INIT_WORK(&nt->cleanup_work, deferred_netpoll_cleanup);
@@ -635,8 +636,8 @@ static struct config_item *make_netpoll_target(struct config_group *group,
nt->nts = nts;
nt->np.name = nts->subsys_name;
strlcpy(nt->np.dev_name, "eth0", IFNAMSIZ);
- nt->np.local_port = 6665;
- nt->np.remote_port = 6666;
+ nt->np.local_port = nts->default_local_port;
+ nt->np.remote_port = nts->default_remote_port;
memset(nt->np.remote_mac, 0xff, ETH_ALEN);
INIT_WORK(&nt->cleanup_work, deferred_netpoll_cleanup);
@@ -926,6 +927,10 @@ static void __exit unregister_netpoll_targets(struct netpoll_targets *nts)
static int __init init_netconsole(void)
{
int err;
+
+ targets.default_local_port = 6665;
+ targets.default_remote_port = 6666;
+
err = register_netpoll_targets("netconsole", &targets, config);
if (err)
return err;
^ permalink raw reply related
* [PATCH v3 11/22] netconsole: Abstract away the subsystem name
From: Mike Waychison @ 2010-12-14 21:29 UTC (permalink / raw)
To: simon.kagstrom, davem, nhorman, Matt Mackall
Cc: adurbin, linux-kernel, chavey, Greg KH, netdev, Américo Wang,
akpm, linux-api
In-Reply-To: <20101214212846.17022.64836.stgit@mike.mtv.corp.google.com>
Remove any hardcoded instances of "netconsole" and keep a new copy in
netpoll_targets. We could perhaps use the copy that is stored in the
configfs group's name, but that isn't always available depending on
build config options,and maintaining the extra string is just easier.
Signed-off-by: Mike Waychison <mikew@google.com>
Acked-by: Matt Mackall <mpm@selenic.com>
---
drivers/net/netconsole.c | 50 +++++++++++++++++++++++++++++-----------------
1 files changed, 32 insertions(+), 18 deletions(-)
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 2f6282d..5c8701f 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -72,6 +72,7 @@ struct netpoll_targets {
struct configfs_subsystem configfs_subsys;
#endif
struct notifier_block netdev_notifier;
+ char *subsys_name;
};
#define DEFINE_NETPOLL_TARGETS(x) struct netpoll_targets x = \
{ .list = LIST_HEAD_INIT(x.list), \
@@ -152,12 +153,13 @@ static struct netpoll_target *alloc_param_target(struct netpoll_targets *nts,
*/
nt = kzalloc(sizeof(*nt), GFP_KERNEL);
if (!nt) {
- printk(KERN_ERR "netconsole: failed to allocate memory\n");
+ printk(KERN_ERR "%s: failed to allocate memory\n",
+ nts->subsys_name);
goto fail;
}
nt->nts = nts;
- nt->np.name = "netconsole";
+ nt->np.name = nts->subsys_name;
strlcpy(nt->np.dev_name, "eth0", IFNAMSIZ);
nt->np.local_port = 6665;
nt->np.remote_port = 6666;
@@ -196,7 +198,7 @@ static void free_param_target(struct netpoll_target *nt)
/*
* Our subsystem hierarchy is:
*
- * /sys/kernel/config/netconsole/
+ * /sys/kernel/config/<subsys_name>/
* |
* <target>/
* | enabled
@@ -232,7 +234,8 @@ static struct netpoll_target *to_target(struct config_item *item)
* We return (signed) long only because we may want to return errors.
* Do not use this to convert numbers that are allowed to be negative.
*/
-static long strtol10_check_range(const char *cp, long min, long max)
+static long strtol10_check_range(struct netpoll_targets *nts,
+ const char *cp, long min, long max)
{
long ret;
char *p = (char *) cp;
@@ -243,12 +246,12 @@ static long strtol10_check_range(const char *cp, long min, long max)
ret = simple_strtol(p, &p, 10);
if (*p && (*p != '\n')) {
- printk(KERN_ERR "netconsole: invalid input\n");
+ printk(KERN_ERR "%s: invalid input\n", nts->subsys_name);
return -EINVAL;
}
if ((ret < min) || (ret > max)) {
- printk(KERN_ERR "netconsole: input %ld must be between "
- "%ld and %ld\n", ret, min, max);
+ printk(KERN_ERR "%s: input %ld must be between %ld and %ld\n",
+ nts->subsys_name, ret, min, max);
return -EINVAL;
}
@@ -319,7 +322,7 @@ static ssize_t store_enabled(struct netpoll_target *nt,
int err;
long enabled;
- enabled = strtol10_check_range(buf, 0, 1);
+ enabled = strtol10_check_range(nts, buf, 0, 1);
if (enabled < 0)
return enabled;
@@ -355,7 +358,8 @@ static ssize_t store_enabled(struct netpoll_target *nt,
if (err)
return err;
- printk(KERN_INFO "netconsole: network logging started\n");
+ printk(KERN_INFO "%s: network logging started\n",
+ nts->subsys_name);
} else { /* 0 */
spin_lock_irqsave(&nts->lock, flags);
if (nt->np_state == NETPOLL_ENABLED)
@@ -400,7 +404,7 @@ static ssize_t store_local_port(struct netpoll_target *nt,
long local_port;
#define __U16_MAX ((__u16) ~0U)
- local_port = strtol10_check_range(buf, 0, __U16_MAX);
+ local_port = strtol10_check_range(nt->nts, buf, 0, __U16_MAX);
if (local_port < 0)
return local_port;
@@ -416,7 +420,7 @@ static ssize_t store_remote_port(struct netpoll_target *nt,
long remote_port;
#define __U16_MAX ((__u16) ~0U)
- remote_port = strtol10_check_range(buf, 0, __U16_MAX);
+ remote_port = strtol10_check_range(nt->nts, buf, 0, __U16_MAX);
if (remote_port < 0)
return remote_port;
@@ -466,7 +470,7 @@ static ssize_t store_remote_mac(struct netpoll_target *nt,
return strnlen(buf, count);
invalid:
- printk(KERN_ERR "netconsole: invalid input\n");
+ printk(KERN_ERR "%s: invalid input\n", nt->nts->subsys_name);
return -EINVAL;
}
@@ -493,8 +497,9 @@ static ssize_t store_locked_##_name(struct netpoll_target *nt, \
ssize_t ret; \
spin_lock_irqsave(&nts->lock, flags); \
if (nt->np_state != NETPOLL_DISABLED) { \
- printk(KERN_ERR "netconsole: target (%s) is enabled, " \
+ printk(KERN_ERR "%s: target (%s) is enabled, " \
"disable to update parameters\n", \
+ nts->subsys_name, \
config_item_name(&nt->item)); \
spin_unlock_irqrestore(&nts->lock, flags); \
return -EBUSY; \
@@ -622,12 +627,13 @@ static struct config_item *make_netpoll_target(struct config_group *group,
*/
nt = kzalloc(sizeof(*nt), GFP_KERNEL);
if (!nt) {
- printk(KERN_ERR "netconsole: failed to allocate memory\n");
+ printk(KERN_ERR "%s: failed to allocate memory\n",
+ nts->subsys_name);
return ERR_PTR(-ENOMEM);
}
nt->nts = nts;
- nt->np.name = "netconsole";
+ nt->np.name = nts->subsys_name;
strlcpy(nt->np.dev_name, "eth0", IFNAMSIZ);
nt->np.local_port = 6665;
nt->np.remote_port = 6666;
@@ -790,8 +796,8 @@ static int netpoll_targets_netdev_event(struct notifier_block *this,
}
spin_unlock_irqrestore(&nts->lock, flags);
if (event == NETDEV_UNREGISTER || event == NETDEV_BONDING_DESLAVE)
- printk(KERN_INFO "netconsole: network logging stopped, "
- "interface %s %s\n", dev->name,
+ printk(KERN_INFO "%s: network logging stopped, "
+ "interface %s %s\n", nts->subsys_name, dev->name,
event == NETDEV_UNREGISTER ? "unregistered" : "released slaves");
done:
@@ -866,12 +872,19 @@ static int __init register_netpoll_targets(const char *subsys_name,
if (err)
goto fail;
+ nts->subsys_name = kstrdup(subsys_name, GFP_KERNEL);
+ err = -ENOMEM;
+ if (!nts->subsys_name)
+ goto undonotifier;
+
err = dynamic_netpoll_targets_init(subsys_name, nts);
if (err)
- goto undonotifier;
+ goto free_subsys_name;
return 0;
+free_subsys_name:
+ kfree(nts->subsys_name);
undonotifier:
unregister_netdevice_notifier(&nts->netdev_notifier);
fail:
@@ -907,6 +920,7 @@ static void __exit unregister_netpoll_targets(struct netpoll_targets *nts)
list_del(&nt->list);
free_param_target(nt);
}
+ kfree(nts->subsys_name);
}
static int __init init_netconsole(void)
^ permalink raw reply related
* [PATCH v3 09/22] netconsole: Add pointer to netpoll_targets
From: Mike Waychison @ 2010-12-14 21:29 UTC (permalink / raw)
To: simon.kagstrom, davem, nhorman, Matt Mackall
Cc: adurbin, linux-kernel, chavey, Greg KH, netdev, Américo Wang,
akpm, linux-api
In-Reply-To: <20101214212846.17022.64836.stgit@mike.mtv.corp.google.com>
For each netconsole_target, we'd like to get back at the parenting
netpoll_targets structure so that we can access the locking and list
fields. Add a pointer that points to the netpoll_targets structure. We
don't have to maintain reference counting because a netpoll_targets will
always out-live their children netconsole_target structures.
Signed-off-by: Mike Waychison <mikew@google.com>
Acked-by: Matt Mackall <mpm@selenic.com>
---
drivers/net/netconsole.c | 71 +++++++++++++++++++++++++++++-----------------
1 files changed, 45 insertions(+), 26 deletions(-)
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 57451a7..6ab41f8 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -107,6 +107,7 @@ static DEFINE_NETPOLL_TARGETS(targets);
* remote_mac (read-write)
*/
struct netconsole_target {
+ struct netpoll_targets *nts;
struct list_head list;
#ifdef CONFIG_NETCONSOLE_DYNAMIC
struct config_item item;
@@ -122,21 +123,25 @@ static void netconsole_target_put(struct netconsole_target *nt);
static void deferred_netpoll_cleanup(struct work_struct *work)
{
struct netconsole_target *nt;
+ struct netpoll_targets *nts;
unsigned long flags;
nt = container_of(work, struct netconsole_target, cleanup_work);
+ nts = nt->nts;
+
netpoll_cleanup(&nt->np);
- spin_lock_irqsave(&targets.lock, flags);
+ spin_lock_irqsave(&nts->lock, flags);
BUG_ON(nt->np_state != NETPOLL_CLEANING);
nt->np_state = NETPOLL_DISABLED;
- spin_unlock_irqrestore(&targets.lock, flags);
+ spin_unlock_irqrestore(&nts->lock, flags);
netconsole_target_put(nt);
}
/* Allocate new target (from boot/module param) and setup netpoll for it */
-static struct netconsole_target *alloc_param_target(char *target_config)
+static struct netconsole_target *alloc_param_target(struct netpoll_targets *nts,
+ char *target_config)
{
int err = -ENOMEM;
struct netconsole_target *nt;
@@ -151,6 +156,7 @@ static struct netconsole_target *alloc_param_target(char *target_config)
goto fail;
}
+ nt->nts = nts;
nt->np.name = "netconsole";
strlcpy(nt->np.dev_name, "eth0", IFNAMSIZ);
nt->np.local_port = 6665;
@@ -308,6 +314,7 @@ static ssize_t store_enabled(struct netconsole_target *nt,
const char *buf,
size_t count)
{
+ struct netpoll_targets *nts = nt->nts;
unsigned long flags;
int err;
long enabled;
@@ -317,7 +324,7 @@ static ssize_t store_enabled(struct netconsole_target *nt,
return enabled;
if (enabled) { /* 1 */
- spin_lock_irqsave(&targets.lock, flags);
+ spin_lock_irqsave(&nts->lock, flags);
if (nt->np_state != NETPOLL_DISABLED)
goto busy;
else {
@@ -329,7 +336,7 @@ static ssize_t store_enabled(struct netconsole_target *nt,
* because there is a reference implicitly held by the
* caller of the store operation.
*/
- spin_unlock_irqrestore(&targets.lock, flags);
+ spin_unlock_irqrestore(&nts->lock, flags);
}
/*
@@ -339,34 +346,34 @@ static ssize_t store_enabled(struct netconsole_target *nt,
netpoll_print_options(&nt->np);
err = netpoll_setup(&nt->np);
- spin_lock_irqsave(&targets.lock, flags);
+ spin_lock_irqsave(&nts->lock, flags);
if (err)
nt->np_state = NETPOLL_DISABLED;
else
nt->np_state = NETPOLL_ENABLED;
- spin_unlock_irqrestore(&targets.lock, flags);
+ spin_unlock_irqrestore(&nts->lock, flags);
if (err)
return err;
printk(KERN_INFO "netconsole: network logging started\n");
} else { /* 0 */
- spin_lock_irqsave(&targets.lock, flags);
+ spin_lock_irqsave(&nts->lock, flags);
if (nt->np_state == NETPOLL_ENABLED)
nt->np_state = NETPOLL_CLEANING;
else if (nt->np_state != NETPOLL_DISABLED)
goto busy;
- spin_unlock_irqrestore(&targets.lock, flags);
+ spin_unlock_irqrestore(&nts->lock, flags);
netpoll_cleanup(&nt->np);
- spin_lock_irqsave(&targets.lock, flags);
+ spin_lock_irqsave(&nts->lock, flags);
nt->np_state = NETPOLL_DISABLED;
- spin_unlock_irqrestore(&targets.lock, flags);
+ spin_unlock_irqrestore(&nts->lock, flags);
}
return strnlen(buf, count);
busy:
- spin_unlock_irqrestore(&targets.lock, flags);
+ spin_unlock_irqrestore(&nts->lock, flags);
return -EBUSY;
}
@@ -481,29 +488,31 @@ static ssize_t store_locked_##_name(struct netconsole_target *nt, \
const char *buf, \
size_t count) \
{ \
+ struct netpoll_targets *nts = nt->nts; \
unsigned long flags; \
ssize_t ret; \
- spin_lock_irqsave(&targets.lock, flags); \
+ spin_lock_irqsave(&nts->lock, flags); \
if (nt->np_state != NETPOLL_DISABLED) { \
printk(KERN_ERR "netconsole: target (%s) is enabled, " \
"disable to update parameters\n", \
config_item_name(&nt->item)); \
- spin_unlock_irqrestore(&targets.lock, flags); \
+ spin_unlock_irqrestore(&nts->lock, flags); \
return -EBUSY; \
} \
ret = store_##_name(nt, buf, count); \
- spin_unlock_irqrestore(&targets.lock, flags); \
+ spin_unlock_irqrestore(&nts->lock, flags); \
return ret; \
}
#define NETCONSOLE_WRAP_ATTR_SHOW(_name) \
static ssize_t show_locked_##_name(struct netconsole_target *nt, char *buf) \
{ \
+ struct netpoll_targets *nts = nt->nts; \
unsigned long flags; \
ssize_t ret; \
- spin_lock_irqsave(&targets.lock, flags); \
+ spin_lock_irqsave(&nts->lock, flags); \
ret = show_##_name(nt, buf); \
- spin_unlock_irqrestore(&targets.lock, flags); \
+ spin_unlock_irqrestore(&nts->lock, flags); \
return ret; \
}
@@ -589,6 +598,13 @@ static struct config_item_type netconsole_target_type = {
.ct_owner = THIS_MODULE,
};
+static struct netpoll_targets *group_to_targets(struct config_group *group)
+{
+ struct configfs_subsystem *subsys;
+ subsys = container_of(group, struct configfs_subsystem, su_group);
+ return container_of(subsys, struct netpoll_targets, configfs_subsys);
+}
+
/*
* Group operations and type for netconsole_subsys.
*/
@@ -596,8 +612,9 @@ 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 netpoll_targets *nts = group_to_targets(group);
struct netconsole_target *nt;
+ unsigned long flags;
/*
* Allocate and initialize with defaults.
@@ -609,6 +626,7 @@ static struct config_item *make_netconsole_target(struct config_group *group,
return ERR_PTR(-ENOMEM);
}
+ nt->nts = nts;
nt->np.name = "netconsole";
strlcpy(nt->np.dev_name, "eth0", IFNAMSIZ);
nt->np.local_port = 6665;
@@ -620,9 +638,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(&targets.lock, flags);
- list_add(&nt->list, &targets.list);
- spin_unlock_irqrestore(&targets.lock, flags);
+ spin_lock_irqsave(&nts->lock, flags);
+ list_add(&nt->list, &nts->list);
+ spin_unlock_irqrestore(&nts->lock, flags);
return &nt->item;
}
@@ -630,12 +648,13 @@ 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 netpoll_targets *nts = group_to_targets(group);
struct netconsole_target *nt = to_target(item);
+ unsigned long flags;
- spin_lock_irqsave(&targets.lock, flags);
+ spin_lock_irqsave(&nts->lock, flags);
list_del(&nt->list);
- spin_unlock_irqrestore(&targets.lock, flags);
+ spin_unlock_irqrestore(&nts->lock, flags);
/*
* The target may have never been disabled, or was disabled due
@@ -726,7 +745,7 @@ static void netconsole_target_put(struct netconsole_target *nt)
/*
* Call netpoll_cleanup on this target asynchronously.
- * targets.lock is required.
+ * nts->lock is required.
*/
static void defer_netpoll_cleanup(struct netconsole_target *nt)
{
@@ -830,7 +849,7 @@ static int __init register_netpoll_targets(const char *subsys_name,
if (strnlen(input, MAX_PARAM_LENGTH)) {
while ((target_config = strsep(&input, ";"))) {
- nt = alloc_param_target(target_config);
+ nt = alloc_param_target(nts, target_config);
if (IS_ERR(nt)) {
err = PTR_ERR(nt);
goto fail;
^ permalink raw reply related
* [PATCH v3 08/22] netconsole: Split out netpoll_targets init/exit
From: Mike Waychison @ 2010-12-14 21:29 UTC (permalink / raw)
To: simon.kagstrom-vI6UBbBVNY+JA8cjQkG2/g,
davem-fT/PcQaiUtIeIZ0/mPfg9Q, nhorman-2XuSBdqkA4R54TAoqtyWWQ,
Matt Mackall
Cc: adurbin-hpIqsD4AKlfQT0dZR+AlfA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
chavey-hpIqsD4AKlfQT0dZR+AlfA, Greg KH,
netdev-u79uwXL29TY76Z2rM5mHXA, Américo Wang,
akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
linux-api-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20101214212846.17022.64836.stgit-tzAwxxnF6Tt6FDdRrpk8kO4/NqBCd+6Q@public.gmane.org>
As part of the factoring to move target handling out of netconsole,
abstract the construction and destruction of struct netpoll_targets
into their own functions.
Signed-off-by: Mike Waychison <mikew-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
Acked-by: Matt Mackall <mpm-VDJrAJ4Gl5ZBDgjK7y7TUQ@public.gmane.org>
---
drivers/net/netconsole.c | 69 ++++++++++++++++++++++++++++------------------
1 files changed, 42 insertions(+), 27 deletions(-)
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index fed427d..57451a7 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -663,13 +663,14 @@ static struct config_item_type netconsole_subsys_type = {
.ct_owner = THIS_MODULE,
};
-static int __init dynamic_netpoll_targets_init(struct netpoll_targets *nts)
+static int __init dynamic_netpoll_targets_init(const char *subsys_name,
+ struct netpoll_targets *nts)
{
struct configfs_subsystem *subsys = &nts->configfs_subsys;
config_group_init(&subsys->su_group);
mutex_init(&subsys->su_mutex);
- strncpy((char *)&subsys->su_group.cg_item.ci_namebuf, "netconsole",
+ strncpy((char *)&subsys->su_group.cg_item.ci_namebuf, subsys_name,
CONFIGFS_ITEM_NAME_LEN);
subsys->su_group.cg_item.ci_type = &netconsole_subsys_type;
return configfs_register_subsystem(subsys);
@@ -817,13 +818,15 @@ static struct console netconsole = {
.write = write_msg,
};
-static int __init init_netconsole(void)
+static int __init register_netpoll_targets(const char *subsys_name,
+ struct netpoll_targets *nts,
+ char *static_targets)
{
int err;
struct netconsole_target *nt, *tmp;
- unsigned long flags;
char *target_config;
- char *input = config;
+ char *input = static_targets;
+ unsigned long flags;
if (strnlen(input, MAX_PARAM_LENGTH)) {
while ((target_config = strsep(&input, ";"))) {
@@ -832,41 +835,33 @@ static int __init init_netconsole(void)
err = PTR_ERR(nt);
goto fail;
}
- /* Dump existing printks when we register */
- netconsole.flags |= CON_PRINTBUFFER;
- spin_lock_irqsave(&targets.lock, flags);
- list_add(&nt->list, &targets.list);
- spin_unlock_irqrestore(&targets.lock, flags);
+ spin_lock_irqsave(&nts->lock, flags);
+ list_add(&nt->list, &nts->list);
+ spin_unlock_irqrestore(&nts->lock, flags);
}
}
- targets.netdev_notifier.notifier_call = netconsole_netdev_event;
- err = register_netdevice_notifier(&targets.netdev_notifier);
+ nts->netdev_notifier.notifier_call = netconsole_netdev_event;
+ err = register_netdevice_notifier(&nts->netdev_notifier);
if (err)
goto fail;
- err = dynamic_netpoll_targets_init(&targets);
+ err = dynamic_netpoll_targets_init(subsys_name, nts);
if (err)
goto undonotifier;
- register_console(&netconsole);
- printk(KERN_INFO "netconsole: network logging started\n");
-
- return err;
+ return 0;
undonotifier:
- unregister_netdevice_notifier(&targets.netdev_notifier);
-
+ unregister_netdevice_notifier(&nts->netdev_notifier);
fail:
- printk(KERN_ERR "netconsole: cleaning up\n");
-
/*
* 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.
*/
- list_for_each_entry_safe(nt, tmp, &targets.list, list) {
+ list_for_each_entry_safe(nt, tmp, &nts->list, list) {
list_del(&nt->list);
free_param_target(nt);
}
@@ -874,13 +869,12 @@ fail:
return err;
}
-static void __exit cleanup_netconsole(void)
+static void __exit unregister_netpoll_targets(struct netpoll_targets *nts)
{
struct netconsole_target *nt, *tmp;
- unregister_console(&netconsole);
- dynamic_netpoll_targets_exit(&targets);
- unregister_netdevice_notifier(&targets.netdev_notifier);
+ dynamic_netpoll_targets_exit(nts);
+ unregister_netdevice_notifier(&nts->netdev_notifier);
/*
* Targets created via configfs pin references on our module
@@ -890,11 +884,32 @@ static void __exit cleanup_netconsole(void)
* destroy them. Skipping the list lock is safe here, and
* netpoll_cleanup() will sleep.
*/
- list_for_each_entry_safe(nt, tmp, &targets.list, list) {
+ list_for_each_entry_safe(nt, tmp, &nts->list, list) {
list_del(&nt->list);
free_param_target(nt);
}
}
+static int __init init_netconsole(void)
+{
+ int err;
+ err = register_netpoll_targets("netconsole", &targets, config);
+ if (err)
+ return err;
+ /* Dump existing printks if we registered any targets */
+ if (!list_empty(&targets.list))
+ netconsole.flags |= CON_PRINTBUFFER;
+ register_console(&netconsole);
+ printk(KERN_INFO "netconsole: network logging started\n");
+
+ return 0;
+}
+
+static void __exit cleanup_netconsole(void)
+{
+ unregister_console(&netconsole);
+ unregister_netpoll_targets(&targets);
+}
+
module_init(init_netconsole);
module_exit(cleanup_netconsole);
^ permalink raw reply related
* Re: [PATCH] e1000e: convert to stats64
From: Eric Dumazet @ 2010-12-14 21:29 UTC (permalink / raw)
To: Flavio Leitner; +Cc: netdev, e1000-devel
In-Reply-To: <1292358735-32089-1-git-send-email-fleitner@redhat.com>
Le mardi 14 décembre 2010 à 18:32 -0200, Flavio Leitner a écrit :
> Provides accurate stats at the time user reads them.
>
> Signed-off-by: Flavio Leitner <fleitner@redhat.com>
> ---
> drivers/net/e1000e/e1000.h | 5 ++-
> drivers/net/e1000e/ethtool.c | 27 +++++++++-------
> drivers/net/e1000e/netdev.c | 68 ++++++++++++++++++++++++-----------------
> 3 files changed, 59 insertions(+), 41 deletions(-)
>
> diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
> index fdc67fe..5a5e944 100644
> --- a/drivers/net/e1000e/e1000.h
> +++ b/drivers/net/e1000e/e1000.h
> @@ -363,6 +363,8 @@ struct e1000_adapter {
> /* structs defined in e1000_hw.h */
> struct e1000_hw hw;
>
> + spinlock_t stats64_lock;
> + struct rtnl_link_stats64 stats64;
I am not sure why you add this stats64 in e1000_adapter ?
Why isnt it provided by callers (automatic variable, or provided to
ndo_get_stats64()). I dont see accumulators, only a full rewrite of this
structure in e1000e_update_stats() ?
^ permalink raw reply
* Re: [PATCH] ixgb: Convert to new vlan model.
From: Jesse Gross @ 2010-12-14 21:29 UTC (permalink / raw)
To: Ben Hutchings
Cc: Tantilov, Emil S, David Miller, netdev@vger.kernel.org,
Kirsher, Jeffrey T, Duyck, Alexander H
In-Reply-To: <1292354121.20458.11.camel@bwh-desktop>
On Tue, Dec 14, 2010 at 11:15 AM, Ben Hutchings
<bhutchings@solarflare.com> wrote:
> On Tue, 2010-12-14 at 12:08 -0700, Tantilov, Emil S wrote:
>> Ben Hutchings wrote:
>> > On Tue, 2010-12-14 at 11:09 -0700, Tantilov, Emil S wrote:
>> >> Ben Hutchings wrote:
>> >>> On Mon, 2010-12-13 at 19:42 -0800, Jesse Gross wrote:
>> >>>> This switches the ixgb driver to use the new vlan interfaces.
>> >>>> In doing this, it completes the work begun in
>> >>>> ae54496f9e8d40c89e5668205c181dccfa9ecda1 allowing the use of
>> >>>> hardware vlan insertion without having a vlan group configured.
>> >>>> [...] diff --git a/drivers/net/ixgb/ixgb_ethtool.c
>> >>>> b/drivers/net/ixgb/ixgb_ethtool.c
>> >>>> index 43994c1..0e4c527 100644
>> >>>> --- a/drivers/net/ixgb/ixgb_ethtool.c
>> >>>> +++ b/drivers/net/ixgb/ixgb_ethtool.c
>> >>>> @@ -706,6 +706,45 @@ ixgb_get_strings(struct net_device *netdev,
>> >>>> u32 stringset, u8 *data) } }
>> >>>>
>> >>>> +static int ixgb_set_flags(struct net_device *netdev, u32 data) +{
>> >>>> + struct ixgb_adapter *adapter = netdev_priv(netdev); + bool
>> >>>> need_reset; + int rc; +
>> >>>> + /* The hardware requires that RX vlan stripping and TX vlan
>> >>>> insertion + * be configured together. Therefore, if one setting
>> >>>> changes adjust the + * other one to match. + */
>> >>>> + if (!!(data & ETH_FLAG_RXVLAN) != !!(data & ETH_FLAG_TXVLAN)) {
>> >>>> + if ((data & ETH_FLAG_RXVLAN) !=
>> >>>> + (netdev->features & NETIF_F_HW_VLAN_RX))
>> >>>> + data ^= ETH_FLAG_TXVLAN;
>> >>>> + else if ((data & ETH_FLAG_TXVLAN) !=
>> >>>> + (netdev->features & NETIF_F_HW_VLAN_TX))
>> >>>> + data ^= ETH_FLAG_RXVLAN;
>> >>>> + }
>> >>> [...]
>> >>>
>> >>> I think this should reject attempts to change just one flag with
>> >>> -EINVAL, rather than quietly 'fixing' the setting.
>> >>>
>> >>> Ben.
>> >>
>> >> I'm not sure this is a good idea. At least not without some sort of
>> >> explanation. Since there is no way for the user to know that he needs
>> >> to disable both.
>> >
>> > Document the limitation in Documentation/networking/ixgb.txt. You
>> > could also send a patch for the ethtool manual page stating that this
>> > restriction might exist.
>> >
>> > Ben.
>>
>> Just to make sure it's clear - there is no hard requirement for both
>> settings to be set at the same time. So setting:
>> ethtool -K eth0 rxvlan off
>>
>> Is a valid setting and will disable stripping on Rx, but because of
>> the design, stripping on Tx will also be disabled.
>
> Then it's *not* a valid setting for your hardware/driver.
Ben, I agree that limiting the settings to what is actually supported
is conceptually cleaner but in practice it's not very intuitive. If
you try to turn something off and the response is that it's invalid,
most people are going to assume that you just can't do it. This is
especially true since you actually can't turn these settings off in
most drivers.
There's a precedent for this type of thing: turn off TX checksum
offloading and watch scatter/gather and TSO be automatically disabled
as well. It makes sense - the user requested a change, we do what is
necessary to make that happen without requiring them to understand why
these features are interrelated.
Emil, I realized afterwards that, as you pointed out, TX vlan
offloading can be disabled without requiring RX offloading to be
disabled. Feel free to make the modification yourself or I can
resubmit, whichever is easier.
^ permalink raw reply
* [PATCH v3 07/22] netconsole: Move netdev_notifier into netpoll_targets
From: Mike Waychison @ 2010-12-14 21:29 UTC (permalink / raw)
To: simon.kagstrom, davem, nhorman, Matt Mackall
Cc: adurbin, linux-kernel, chavey, Greg KH, netdev, Américo Wang,
akpm, linux-api
In-Reply-To: <20101214212846.17022.64836.stgit@mike.mtv.corp.google.com>
Move the notifier chain node up into struct netpoll_targets, and use it
to get at the netpoll_targets struct whenever we get a NETDEV event.
Signed-off-by: Mike Waychison <mikew@google.com>
Acked-by: Matt Mackall <mpm@selenic.com>
---
drivers/net/netconsole.c | 20 ++++++++++----------
1 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index aa95b91..fed427d 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -71,6 +71,7 @@ struct netpoll_targets {
#ifdef CONFIG_NETCONSOLE_DYNAMIC
struct configfs_subsystem configfs_subsys;
#endif
+ struct notifier_block netdev_notifier;
};
#define DEFINE_NETPOLL_TARGETS(x) struct netpoll_targets x = \
{ .list = LIST_HEAD_INIT(x.list), \
@@ -740,6 +741,8 @@ static int netconsole_netdev_event(struct notifier_block *this,
unsigned long event,
void *ptr)
{
+ struct netpoll_targets *nts = container_of(this, struct netpoll_targets,
+ netdev_notifier);
unsigned long flags;
struct netconsole_target *nt;
struct net_device *dev = ptr;
@@ -748,8 +751,8 @@ static int netconsole_netdev_event(struct notifier_block *this,
event == NETDEV_BONDING_DESLAVE))
goto done;
- spin_lock_irqsave(&targets.lock, flags);
- list_for_each_entry(nt, &targets.list, list) {
+ spin_lock_irqsave(&nts->lock, flags);
+ list_for_each_entry(nt, &nts->list, list) {
if (nt->np_state == NETPOLL_ENABLED && nt->np.dev == dev) {
switch (event) {
case NETDEV_CHANGENAME:
@@ -765,7 +768,7 @@ static int netconsole_netdev_event(struct notifier_block *this,
}
}
}
- spin_unlock_irqrestore(&targets.lock, flags);
+ spin_unlock_irqrestore(&nts->lock, flags);
if (event == NETDEV_UNREGISTER || event == NETDEV_BONDING_DESLAVE)
printk(KERN_INFO "netconsole: network logging stopped, "
"interface %s %s\n", dev->name,
@@ -775,10 +778,6 @@ done:
return NOTIFY_DONE;
}
-static struct notifier_block netconsole_netdev_notifier = {
- .notifier_call = netconsole_netdev_event,
-};
-
static void write_msg(struct console *con, const char *msg, unsigned int len)
{
int frag, left;
@@ -842,7 +841,8 @@ static int __init init_netconsole(void)
}
}
- err = register_netdevice_notifier(&netconsole_netdev_notifier);
+ targets.netdev_notifier.notifier_call = netconsole_netdev_event;
+ err = register_netdevice_notifier(&targets.netdev_notifier);
if (err)
goto fail;
@@ -856,7 +856,7 @@ static int __init init_netconsole(void)
return err;
undonotifier:
- unregister_netdevice_notifier(&netconsole_netdev_notifier);
+ unregister_netdevice_notifier(&targets.netdev_notifier);
fail:
printk(KERN_ERR "netconsole: cleaning up\n");
@@ -880,7 +880,7 @@ static void __exit cleanup_netconsole(void)
unregister_console(&netconsole);
dynamic_netpoll_targets_exit(&targets);
- unregister_netdevice_notifier(&netconsole_netdev_notifier);
+ unregister_netdevice_notifier(&targets.netdev_notifier);
/*
* Targets created via configfs pin references on our module
^ permalink raw reply related
* [PATCH v3 06/22] netconsole: Push configfs_subsystem into netpoll_targets
From: Mike Waychison @ 2010-12-14 21:29 UTC (permalink / raw)
To: simon.kagstrom, davem, nhorman, Matt Mackall
Cc: adurbin, linux-kernel, chavey, Greg KH, netdev, Américo Wang,
akpm, linux-api
In-Reply-To: <20101214212846.17022.64836.stgit@mike.mtv.corp.google.com>
This patch is a step in the preparation of pushing the target handling
code out of netconsole and into netpoll proper where it can be used by
other clients.
Here, we move the configfs_subsystem bits out of global scope and
package it in the netpoll_targets structure that will maintain a set of
targets. There is a bit of code that is rearranged due to needing to
provide netconsole_subsys_type in scope much earlier in the file. This
has the added benefit of folding all of the dynamic target handling code
under a single #ifdef CONFIG_NETCONSOLE_DYNAMIC block.
Signed-off-by: Mike Waychison <mikew@google.com>
Acked-by: Matt Mackall <mpm@selenic.com>
---
drivers/net/netconsole.c | 132 ++++++++++++++++++++++------------------------
1 files changed, 64 insertions(+), 68 deletions(-)
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 3aa7151..aa95b91 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -68,6 +68,9 @@ __setup("netconsole=", option_setup);
struct netpoll_targets {
struct list_head list;
spinlock_t lock;
+#ifdef CONFIG_NETCONSOLE_DYNAMIC
+ struct configfs_subsystem configfs_subsys;
+#endif
};
#define DEFINE_NETPOLL_TARGETS(x) struct netpoll_targets x = \
{ .list = LIST_HEAD_INIT(x.list), \
@@ -112,63 +115,8 @@ struct netconsole_target {
struct work_struct cleanup_work;
};
-#ifdef CONFIG_NETCONSOLE_DYNAMIC
-
-static struct configfs_subsystem netconsole_subsys;
-
-static int __init dynamic_netconsole_init(void)
-{
- config_group_init(&netconsole_subsys.su_group);
- mutex_init(&netconsole_subsys.su_mutex);
- return configfs_register_subsystem(&netconsole_subsys);
-}
-
-static void __exit dynamic_netconsole_exit(void)
-{
- configfs_unregister_subsystem(&netconsole_subsys);
-}
-
-/*
- * Targets that were created by parsing the boot/module option string
- * do not exist in the configfs hierarchy (and have NULL names) and will
- * never go away, so make these a no-op for them.
- */
-static void netconsole_target_get(struct netconsole_target *nt)
-{
- if (config_item_name(&nt->item))
- config_item_get(&nt->item);
-}
-
-static void netconsole_target_put(struct netconsole_target *nt)
-{
- if (config_item_name(&nt->item))
- config_item_put(&nt->item);
-}
-
-#else /* !CONFIG_NETCONSOLE_DYNAMIC */
-
-static int __init dynamic_netconsole_init(void)
-{
- return 0;
-}
-
-static void __exit dynamic_netconsole_exit(void)
-{
-}
-
-/*
- * No danger of targets going away from under us when dynamic
- * reconfigurability is off.
- */
-static void netconsole_target_get(struct netconsole_target *nt)
-{
-}
-
-static void netconsole_target_put(struct netconsole_target *nt)
-{
-}
-
-#endif /* CONFIG_NETCONSOLE_DYNAMIC */
+static void netconsole_target_get(struct netconsole_target *nt);
+static void netconsole_target_put(struct netconsole_target *nt);
static void deferred_netpoll_cleanup(struct work_struct *work)
{
@@ -714,15 +662,63 @@ static struct config_item_type netconsole_subsys_type = {
.ct_owner = THIS_MODULE,
};
-/* The netconsole configfs subsystem */
-static struct configfs_subsystem netconsole_subsys = {
- .su_group = {
- .cg_item = {
- .ci_namebuf = "netconsole",
- .ci_type = &netconsole_subsys_type,
- },
- },
-};
+static int __init dynamic_netpoll_targets_init(struct netpoll_targets *nts)
+{
+ struct configfs_subsystem *subsys = &nts->configfs_subsys;
+
+ config_group_init(&subsys->su_group);
+ mutex_init(&subsys->su_mutex);
+ strncpy((char *)&subsys->su_group.cg_item.ci_namebuf, "netconsole",
+ CONFIGFS_ITEM_NAME_LEN);
+ subsys->su_group.cg_item.ci_type = &netconsole_subsys_type;
+ return configfs_register_subsystem(subsys);
+}
+
+static void __exit dynamic_netpoll_targets_exit(struct netpoll_targets *nts)
+{
+ configfs_unregister_subsystem(&nts->configfs_subsys);
+}
+
+/*
+ * Targets that were created by parsing the boot/module option string
+ * do not exist in the configfs hierarchy (and have NULL names) and will
+ * never go away, so make these a no-op for them.
+ */
+static void netconsole_target_get(struct netconsole_target *nt)
+{
+ if (config_item_name(&nt->item))
+ config_item_get(&nt->item);
+}
+
+static void netconsole_target_put(struct netconsole_target *nt)
+{
+ if (config_item_name(&nt->item))
+ config_item_put(&nt->item);
+}
+
+#else /* !CONFIG_NETCONSOLE_DYNAMIC */
+
+static int __init dynamic_netpoll_targets_init(const char *subsys_name,
+ struct netpoll_targets *nts)
+{
+ return 0;
+}
+
+static void __exit dynamic_netpoll_targets_exit(struct netpoll_targets *nts)
+{
+}
+
+/*
+ * No danger of targets going away from under us when dynamic
+ * reconfigurability is off.
+ */
+static void netconsole_target_get(struct netconsole_target *nt)
+{
+}
+
+static void netconsole_target_put(struct netconsole_target *nt)
+{
+}
#endif /* CONFIG_NETCONSOLE_DYNAMIC */
@@ -850,7 +846,7 @@ static int __init init_netconsole(void)
if (err)
goto fail;
- err = dynamic_netconsole_init();
+ err = dynamic_netpoll_targets_init(&targets);
if (err)
goto undonotifier;
@@ -883,7 +879,7 @@ static void __exit cleanup_netconsole(void)
struct netconsole_target *nt, *tmp;
unregister_console(&netconsole);
- dynamic_netconsole_exit();
+ dynamic_netpoll_targets_exit(&targets);
unregister_netdevice_notifier(&netconsole_netdev_notifier);
/*
^ permalink raw reply related
* [PATCH v3 05/22] netconsole: Wrap the list and locking in a structure
From: Mike Waychison @ 2010-12-14 21:29 UTC (permalink / raw)
To: simon.kagstrom, davem, nhorman, Matt Mackall
Cc: adurbin, linux-kernel, chavey, Greg KH, netdev, Américo Wang,
akpm, linux-api
In-Reply-To: <20101214212846.17022.64836.stgit@mike.mtv.corp.google.com>
In preparation for moving all the netpoll target handling code out of
netconsole proper and into netpoll, wrap the list and lock in a new
structure, netpoll_targets.
Signed-off-by: Mike Waychison <mikew@google.com>
Acked-by: Matt Mackall <mpm@selenic.com>
---
drivers/net/netconsole.c | 85 ++++++++++++++++++++++++----------------------
1 files changed, 44 insertions(+), 41 deletions(-)
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 68700c1..3aa7151 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -65,11 +65,14 @@ static int __init option_setup(char *opt)
__setup("netconsole=", option_setup);
#endif /* MODULE */
-/* Linked list of all configured targets */
-static LIST_HEAD(target_list);
-
-/* This needs to be a spinlock because write_msg() cannot sleep */
-static DEFINE_SPINLOCK(target_list_lock);
+struct netpoll_targets {
+ struct list_head list;
+ spinlock_t lock;
+};
+#define DEFINE_NETPOLL_TARGETS(x) struct netpoll_targets x = \
+ { .list = LIST_HEAD_INIT(x.list), \
+ .lock = __SPIN_LOCK_UNLOCKED(x.lock) }
+static DEFINE_NETPOLL_TARGETS(targets);
#define NETPOLL_DISABLED 0
#define NETPOLL_SETTINGUP 1
@@ -78,7 +81,7 @@ static DEFINE_SPINLOCK(target_list_lock);
/**
* struct netconsole_target - Represents a configured netconsole target.
- * @list: Links this target into the target_list.
+ * @list: Links this target into the netpoll_targets.list.
* @item: Links us into the configfs subsystem hierarchy.
* @np_state: Enabled / Disabled / SettingUp / Cleaning
* Visible from userspace (read-write) as "enabled".
@@ -175,10 +178,10 @@ static void deferred_netpoll_cleanup(struct work_struct *work)
nt = container_of(work, struct netconsole_target, cleanup_work);
netpoll_cleanup(&nt->np);
- spin_lock_irqsave(&target_list_lock, flags);
+ spin_lock_irqsave(&targets.lock, flags);
BUG_ON(nt->np_state != NETPOLL_CLEANING);
nt->np_state = NETPOLL_DISABLED;
- spin_unlock_irqrestore(&target_list_lock, flags);
+ spin_unlock_irqrestore(&targets.lock, flags);
netconsole_target_put(nt);
}
@@ -365,7 +368,7 @@ static ssize_t store_enabled(struct netconsole_target *nt,
return enabled;
if (enabled) { /* 1 */
- spin_lock_irqsave(&target_list_lock, flags);
+ spin_lock_irqsave(&targets.lock, flags);
if (nt->np_state != NETPOLL_DISABLED)
goto busy;
else {
@@ -377,7 +380,7 @@ static ssize_t store_enabled(struct netconsole_target *nt,
* because there is a reference implicitly held by the
* caller of the store operation.
*/
- spin_unlock_irqrestore(&target_list_lock, flags);
+ spin_unlock_irqrestore(&targets.lock, flags);
}
/*
@@ -387,34 +390,34 @@ static ssize_t store_enabled(struct netconsole_target *nt,
netpoll_print_options(&nt->np);
err = netpoll_setup(&nt->np);
- spin_lock_irqsave(&target_list_lock, flags);
+ spin_lock_irqsave(&targets.lock, flags);
if (err)
nt->np_state = NETPOLL_DISABLED;
else
nt->np_state = NETPOLL_ENABLED;
- spin_unlock_irqrestore(&target_list_lock, flags);
+ spin_unlock_irqrestore(&targets.lock, flags);
if (err)
return err;
printk(KERN_INFO "netconsole: network logging started\n");
} else { /* 0 */
- spin_lock_irqsave(&target_list_lock, flags);
+ spin_lock_irqsave(&targets.lock, flags);
if (nt->np_state == NETPOLL_ENABLED)
nt->np_state = NETPOLL_CLEANING;
else if (nt->np_state != NETPOLL_DISABLED)
goto busy;
- spin_unlock_irqrestore(&target_list_lock, flags);
+ spin_unlock_irqrestore(&targets.lock, flags);
netpoll_cleanup(&nt->np);
- spin_lock_irqsave(&target_list_lock, flags);
+ spin_lock_irqsave(&targets.lock, flags);
nt->np_state = NETPOLL_DISABLED;
- spin_unlock_irqrestore(&target_list_lock, flags);
+ spin_unlock_irqrestore(&targets.lock, flags);
}
return strnlen(buf, count);
busy:
- spin_unlock_irqrestore(&target_list_lock, flags);
+ spin_unlock_irqrestore(&targets.lock, flags);
return -EBUSY;
}
@@ -531,16 +534,16 @@ static ssize_t store_locked_##_name(struct netconsole_target *nt, \
{ \
unsigned long flags; \
ssize_t ret; \
- spin_lock_irqsave(&target_list_lock, flags); \
+ spin_lock_irqsave(&targets.lock, flags); \
if (nt->np_state != NETPOLL_DISABLED) { \
printk(KERN_ERR "netconsole: target (%s) is enabled, " \
"disable to update parameters\n", \
config_item_name(&nt->item)); \
- spin_unlock_irqrestore(&target_list_lock, flags); \
+ spin_unlock_irqrestore(&targets.lock, flags); \
return -EBUSY; \
} \
ret = store_##_name(nt, buf, count); \
- spin_unlock_irqrestore(&target_list_lock, flags); \
+ spin_unlock_irqrestore(&targets.lock, flags); \
return ret; \
}
@@ -549,9 +552,9 @@ static ssize_t show_locked_##_name(struct netconsole_target *nt, char *buf) \
{ \
unsigned long flags; \
ssize_t ret; \
- spin_lock_irqsave(&target_list_lock, flags); \
+ spin_lock_irqsave(&targets.lock, flags); \
ret = show_##_name(nt, buf); \
- spin_unlock_irqrestore(&target_list_lock, flags); \
+ spin_unlock_irqrestore(&targets.lock, flags); \
return ret; \
}
@@ -668,9 +671,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);
- list_add(&nt->list, &target_list);
- spin_unlock_irqrestore(&target_list_lock, flags);
+ spin_lock_irqsave(&targets.lock, flags);
+ list_add(&nt->list, &targets.list);
+ spin_unlock_irqrestore(&targets.lock, flags);
return &nt->item;
}
@@ -681,9 +684,9 @@ static void drop_netconsole_target(struct config_group *group,
unsigned long flags;
struct netconsole_target *nt = to_target(item);
- spin_lock_irqsave(&target_list_lock, flags);
+ spin_lock_irqsave(&targets.lock, flags);
list_del(&nt->list);
- spin_unlock_irqrestore(&target_list_lock, flags);
+ spin_unlock_irqrestore(&targets.lock, flags);
/*
* The target may have never been disabled, or was disabled due
@@ -698,7 +701,7 @@ static void drop_netconsole_target(struct config_group *group,
if (nt->np_state == NETPOLL_ENABLED || nt->np_state == NETPOLL_CLEANING)
netpoll_cleanup(&nt->np);
- config_item_put(&nt->item);
+ netconsole_target_put(nt);
}
static struct configfs_group_operations netconsole_subsys_group_ops = {
@@ -725,7 +728,7 @@ static struct configfs_subsystem netconsole_subsys = {
/*
* Call netpoll_cleanup on this target asynchronously.
- * target_list_lock is required.
+ * targets.lock is required.
*/
static void defer_netpoll_cleanup(struct netconsole_target *nt)
{
@@ -749,8 +752,8 @@ static int netconsole_netdev_event(struct notifier_block *this,
event == NETDEV_BONDING_DESLAVE))
goto done;
- spin_lock_irqsave(&target_list_lock, flags);
- list_for_each_entry(nt, &target_list, list) {
+ spin_lock_irqsave(&targets.lock, flags);
+ list_for_each_entry(nt, &targets.list, list) {
if (nt->np_state == NETPOLL_ENABLED && nt->np.dev == dev) {
switch (event) {
case NETDEV_CHANGENAME:
@@ -766,7 +769,7 @@ static int netconsole_netdev_event(struct notifier_block *this,
}
}
}
- spin_unlock_irqrestore(&target_list_lock, flags);
+ spin_unlock_irqrestore(&targets.lock, flags);
if (event == NETDEV_UNREGISTER || event == NETDEV_BONDING_DESLAVE)
printk(KERN_INFO "netconsole: network logging stopped, "
"interface %s %s\n", dev->name,
@@ -788,11 +791,11 @@ static void write_msg(struct console *con, const char *msg, unsigned int len)
const char *tmp;
/* Avoid taking lock and disabling interrupts unnecessarily */
- if (list_empty(&target_list))
+ if (list_empty(&targets.list))
return;
- spin_lock_irqsave(&target_list_lock, flags);
- list_for_each_entry(nt, &target_list, list) {
+ spin_lock_irqsave(&targets.lock, flags);
+ list_for_each_entry(nt, &targets.list, list) {
if (nt->np_state == NETPOLL_ENABLED
&& netif_running(nt->np.dev)) {
/*
@@ -810,7 +813,7 @@ static void write_msg(struct console *con, const char *msg, unsigned int len)
}
}
}
- spin_unlock_irqrestore(&target_list_lock, flags);
+ spin_unlock_irqrestore(&targets.lock, flags);
}
static struct console netconsole = {
@@ -837,9 +840,9 @@ static int __init init_netconsole(void)
/* Dump existing printks when we register */
netconsole.flags |= CON_PRINTBUFFER;
- spin_lock_irqsave(&target_list_lock, flags);
- list_add(&nt->list, &target_list);
- spin_unlock_irqrestore(&target_list_lock, flags);
+ spin_lock_irqsave(&targets.lock, flags);
+ list_add(&nt->list, &targets.list);
+ spin_unlock_irqrestore(&targets.lock, flags);
}
}
@@ -867,7 +870,7 @@ fail:
* from the boot/module option exist here). Skipping the list
* lock is safe here, and netpoll_cleanup() will sleep.
*/
- list_for_each_entry_safe(nt, tmp, &target_list, list) {
+ list_for_each_entry_safe(nt, tmp, &targets.list, list) {
list_del(&nt->list);
free_param_target(nt);
}
@@ -891,7 +894,7 @@ static void __exit cleanup_netconsole(void)
* destroy them. Skipping the list lock is safe here, and
* netpoll_cleanup() will sleep.
*/
- list_for_each_entry_safe(nt, tmp, &target_list, list) {
+ list_for_each_entry_safe(nt, tmp, &targets.list, list) {
list_del(&nt->list);
free_param_target(nt);
}
^ permalink raw reply related
* [PATCH v3 04/22] netconsole: Call netpoll_cleanup() in process context
From: Mike Waychison @ 2010-12-14 21:29 UTC (permalink / raw)
To: simon.kagstrom, davem, nhorman, Matt Mackall
Cc: adurbin, linux-kernel, chavey, Greg KH, netdev, Américo Wang,
akpm, linux-api
In-Reply-To: <20101214212846.17022.64836.stgit@mike.mtv.corp.google.com>
The netconsole driver currently deadlocks if a NETDEV_UNREGISTER event
is received while netconsole is in use, which in turn causes it to pin a
reference to the network device. The first deadlock was dealt with in
3b410a31 so that we wouldn't recursively grab RTNL, but even calling
__netpoll_cleanup isn't safe to do considering that we are in atomic
context. __netpoll_cleanup assumes it can sleep and has several
sleeping calls, such as synchronize_rcu_bh and
cancel_rearming_delayed_work.
Fix this by deferring netpoll_cleanup using scheduling work that
operates in process context. We have to grab a reference to the
config_item in this case as we need to pin the item in place until it is
operated on.
Signed-off-by: Mike Waychison <mikew@google.com>
Acked-by: Matt Mackall <mpm@selenic.com>
---
Changelog:
- v3
- Updated to also cancel any pending workers and clean the target up
if needed when removing being dropped from configfs. Issue
identified by Neil Horman.
---
drivers/net/netconsole.c | 64 +++++++++++++++++++++++++++++++++++++++-------
1 files changed, 54 insertions(+), 10 deletions(-)
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 288a025..68700c1 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -106,6 +106,7 @@ struct netconsole_target {
#endif
int np_state;
struct netpoll np;
+ struct work_struct cleanup_work;
};
#ifdef CONFIG_NETCONSOLE_DYNAMIC
@@ -166,6 +167,22 @@ static void netconsole_target_put(struct netconsole_target *nt)
#endif /* CONFIG_NETCONSOLE_DYNAMIC */
+static void deferred_netpoll_cleanup(struct work_struct *work)
+{
+ struct netconsole_target *nt;
+ unsigned long flags;
+
+ nt = container_of(work, struct netconsole_target, cleanup_work);
+ netpoll_cleanup(&nt->np);
+
+ spin_lock_irqsave(&target_list_lock, flags);
+ BUG_ON(nt->np_state != NETPOLL_CLEANING);
+ nt->np_state = NETPOLL_DISABLED;
+ spin_unlock_irqrestore(&target_list_lock, flags);
+
+ netconsole_target_put(nt);
+}
+
/* Allocate new target (from boot/module param) and setup netpoll for it */
static struct netconsole_target *alloc_param_target(char *target_config)
{
@@ -187,6 +204,7 @@ static struct netconsole_target *alloc_param_target(char *target_config)
nt->np.local_port = 6665;
nt->np.remote_port = 6666;
memset(nt->np.remote_mac, 0xff, ETH_ALEN);
+ INIT_WORK(&nt->cleanup_work, deferred_netpoll_cleanup);
/* Parse parameters and setup netpoll */
err = netpoll_parse_options(&nt->np, target_config);
@@ -209,7 +227,9 @@ fail:
/* Cleanup netpoll for given target (from boot/module param) and free it */
static void free_param_target(struct netconsole_target *nt)
{
- netpoll_cleanup(&nt->np);
+ cancel_work_sync(&nt->cleanup_work);
+ if (nt->np_state == NETPOLL_CLEANING || nt->np_state == NETPOLL_ENABLED)
+ netpoll_cleanup(&nt->np);
kfree(nt);
}
@@ -350,6 +370,13 @@ static ssize_t store_enabled(struct netconsole_target *nt,
goto busy;
else {
nt->np_state = NETPOLL_SETTINGUP;
+ /*
+ * Nominally, we would grab an extra reference on the
+ * config_item here for dynamic targets while we let go
+ * of the lock, but this isn't required in this case
+ * because there is a reference implicitly held by the
+ * caller of the store operation.
+ */
spin_unlock_irqrestore(&target_list_lock, flags);
}
@@ -635,6 +662,7 @@ static struct config_item *make_netconsole_target(struct config_group *group,
nt->np.local_port = 6665;
nt->np.remote_port = 6666;
memset(nt->np.remote_mac, 0xff, ETH_ALEN);
+ INIT_WORK(&nt->cleanup_work, deferred_netpoll_cleanup);
/* Initialize the config_item member */
config_item_init_type_name(&nt->item, name, &netconsole_target_type);
@@ -658,10 +686,16 @@ static void drop_netconsole_target(struct config_group *group,
spin_unlock_irqrestore(&target_list_lock, flags);
/*
- * The target may have never been enabled, or was manually disabled
- * before being removed so netpoll may have already been cleaned up.
+ * The target may have never been disabled, or was disabled due
+ * to a netdev event, but we haven't had the chance to clean
+ * things up yet.
+ *
+ * We can't wait for the target to be cleaned up by its
+ * scheduled work however, as that work doesn't pin this module
+ * in place.
*/
- if (nt->np_state == NETPOLL_ENABLED)
+ cancel_work_sync(&nt->cleanup_work);
+ if (nt->np_state == NETPOLL_ENABLED || nt->np_state == NETPOLL_CLEANING)
netpoll_cleanup(&nt->np);
config_item_put(&nt->item);
@@ -689,6 +723,19 @@ static struct configfs_subsystem netconsole_subsys = {
#endif /* CONFIG_NETCONSOLE_DYNAMIC */
+/*
+ * Call netpoll_cleanup on this target asynchronously.
+ * target_list_lock is required.
+ */
+static void defer_netpoll_cleanup(struct netconsole_target *nt)
+{
+ if (nt->np_state != NETPOLL_ENABLED)
+ return;
+ netconsole_target_get(nt);
+ nt->np_state = NETPOLL_CLEANING;
+ schedule_work(&nt->cleanup_work);
+}
+
/* Handle network interface device notifications */
static int netconsole_netdev_event(struct notifier_block *this,
unsigned long event,
@@ -712,13 +759,10 @@ static int netconsole_netdev_event(struct notifier_block *this,
case NETDEV_BONDING_DESLAVE:
case NETDEV_UNREGISTER:
/*
- * rtnl_lock already held
+ * We can't cleanup netpoll in atomic context.
+ * Kick it off as deferred work.
*/
- if (nt->np.dev) {
- __netpoll_cleanup(&nt->np);
- dev_put(nt->np.dev);
- nt->np.dev = NULL;
- }
+ defer_netpoll_cleanup(nt);
}
}
}
^ permalink raw reply related
* [PATCH v3 03/22] netconsole: Introduce 'enabled' state-machine
From: Mike Waychison @ 2010-12-14 21:29 UTC (permalink / raw)
To: simon.kagstrom, davem, nhorman, Matt Mackall
Cc: adurbin, linux-kernel, chavey, Greg KH, netdev, Américo Wang,
akpm, linux-api
In-Reply-To: <20101214212846.17022.64836.stgit@mike.mtv.corp.google.com>
Representing the internal state within netconsole isn't really a boolean
value, but rather a state machine with transitions.
This patch introduces 4 states that the netconsole multi-target can
handle. These states are:
- NETPOLL_DISABLED:
The netpoll structure hasn't been setup.
- NETPOLL_SETTINGUP:
The netpoll structure is being setup, and only whoever set this
state can transition out of it. Must come from the NETPOLL_DISABLED
state.
- NETPOLL_ENABLED:
The netpoll structure has been setup and we are good to emit
packets.
- NETPOLL_CLEANING:
Somebody is queued to call netpoll_clean. Whoever does so must
transition out of this state. Must come from the NETPOLL_CLEANING
state.
The SETTINGUP state specifically targets the window where
netpoll_setup() can take a while (for example, waiting on RTNL).
During this window, we want to exclude console messages from being
emitted to this netpoll target. We also want to exclude any subsequent
user thread that tries to simultaneously enable or disable the target.
The CLEANING state will be used in a subsequent patch to safely defer
netpoll_cleanup to scheduled work in process context (to fix the
deadlock that will occur whenever NETDEV_UNREGISTER is seen).
When introducing these new transition states, it no longer makes sense
to 'disable' the target if the interface is going down, only when it is
being removed completely (or deslaved). In fact, prior to this change,
we would leak a reference to the network device if an interface was
brought down, the target removed, and netconsole unloaded.
Signed-off-by: Mike Waychison <mikew@google.com>
Acked-by: Matt Mackall <mpm@selenic.com>
---
drivers/net/netconsole.c | 62 +++++++++++++++++++++++++++++-----------------
1 files changed, 39 insertions(+), 23 deletions(-)
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 6e16888..288a025 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -71,16 +71,24 @@ static LIST_HEAD(target_list);
/* This needs to be a spinlock because write_msg() cannot sleep */
static DEFINE_SPINLOCK(target_list_lock);
+#define NETPOLL_DISABLED 0
+#define NETPOLL_SETTINGUP 1
+#define NETPOLL_ENABLED 2
+#define NETPOLL_CLEANING 3
+
/**
* struct netconsole_target - Represents a configured netconsole target.
* @list: Links this target into the target_list.
* @item: Links us into the configfs subsystem hierarchy.
- * @enabled: On / off knob to enable / disable target.
- * Visible from userspace (read-write).
- * We maintain a strict 1:1 correspondence between this and
- * whether the corresponding netpoll is active or inactive.
+ * @np_state: Enabled / Disabled / SettingUp / Cleaning
+ * Visible from userspace (read-write) as "enabled".
+ * We maintain a state machine here of the valid states. Either a
+ * target is enabled or disabled, but it may also be in a
+ * transitional state whereby nobody is allowed to act on the
+ * target other than whoever owns the transition.
+ *
* Also, other parameters of a target may be modified at
- * runtime only when it is disabled (enabled == 0).
+ * runtime only when it is disabled (np_state == NETPOLL_ENABLED).
* @np: The netpoll structure for this target.
* Contains the other userspace visible parameters:
* dev_name (read-write)
@@ -96,7 +104,7 @@ struct netconsole_target {
#ifdef CONFIG_NETCONSOLE_DYNAMIC
struct config_item item;
#endif
- int enabled;
+ int np_state;
struct netpoll np;
};
@@ -189,7 +197,7 @@ static struct netconsole_target *alloc_param_target(char *target_config)
if (err)
goto fail;
- nt->enabled = 1;
+ nt->np_state = NETPOLL_ENABLED;
return nt;
@@ -275,7 +283,8 @@ static long strtol10_check_range(const char *cp, long min, long max)
static ssize_t show_enabled(struct netconsole_target *nt, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%d\n", nt->enabled);
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ nt->np_state == NETPOLL_ENABLED);
}
static ssize_t show_dev_name(struct netconsole_target *nt, char *buf)
@@ -337,9 +346,12 @@ static ssize_t store_enabled(struct netconsole_target *nt,
if (enabled) { /* 1 */
spin_lock_irqsave(&target_list_lock, flags);
- if (nt->enabled)
+ if (nt->np_state != NETPOLL_DISABLED)
goto busy;
- spin_unlock_irqrestore(&target_list_lock, flags);
+ else {
+ nt->np_state = NETPOLL_SETTINGUP;
+ spin_unlock_irqrestore(&target_list_lock, flags);
+ }
/*
* Skip netpoll_parse_options() -- all the attributes are
@@ -350,9 +362,9 @@ static ssize_t store_enabled(struct netconsole_target *nt,
err = netpoll_setup(&nt->np);
spin_lock_irqsave(&target_list_lock, flags);
if (err)
- nt->enabled = 0;
+ nt->np_state = NETPOLL_DISABLED;
else
- nt->enabled = 1;
+ nt->np_state = NETPOLL_ENABLED;
spin_unlock_irqrestore(&target_list_lock, flags);
if (err)
return err;
@@ -360,10 +372,17 @@ static ssize_t store_enabled(struct netconsole_target *nt,
printk(KERN_INFO "netconsole: network logging started\n");
} else { /* 0 */
spin_lock_irqsave(&target_list_lock, flags);
- nt->enabled = 0;
+ if (nt->np_state == NETPOLL_ENABLED)
+ nt->np_state = NETPOLL_CLEANING;
+ else if (nt->np_state != NETPOLL_DISABLED)
+ goto busy;
spin_unlock_irqrestore(&target_list_lock, flags);
netpoll_cleanup(&nt->np);
+
+ spin_lock_irqsave(&target_list_lock, flags);
+ nt->np_state = NETPOLL_DISABLED;
+ spin_unlock_irqrestore(&target_list_lock, flags);
}
return strnlen(buf, count);
@@ -486,7 +505,7 @@ static ssize_t store_locked_##_name(struct netconsole_target *nt, \
unsigned long flags; \
ssize_t ret; \
spin_lock_irqsave(&target_list_lock, flags); \
- if (nt->enabled) { \
+ if (nt->np_state != NETPOLL_DISABLED) { \
printk(KERN_ERR "netconsole: target (%s) is enabled, " \
"disable to update parameters\n", \
config_item_name(&nt->item)); \
@@ -642,7 +661,7 @@ static void drop_netconsole_target(struct config_group *group,
* The target may have never been enabled, or was manually disabled
* before being removed so netpoll may have already been cleaned up.
*/
- if (nt->enabled)
+ if (nt->np_state == NETPOLL_ENABLED)
netpoll_cleanup(&nt->np);
config_item_put(&nt->item);
@@ -680,16 +699,17 @@ static int netconsole_netdev_event(struct notifier_block *this,
struct net_device *dev = ptr;
if (!(event == NETDEV_CHANGENAME || event == NETDEV_UNREGISTER ||
- event == NETDEV_BONDING_DESLAVE || event == NETDEV_GOING_DOWN))
+ event == NETDEV_BONDING_DESLAVE))
goto done;
spin_lock_irqsave(&target_list_lock, flags);
list_for_each_entry(nt, &target_list, list) {
- if (nt->np.dev == dev) {
+ if (nt->np_state == NETPOLL_ENABLED && nt->np.dev == dev) {
switch (event) {
case NETDEV_CHANGENAME:
strlcpy(nt->np.dev_name, dev->name, IFNAMSIZ);
break;
+ case NETDEV_BONDING_DESLAVE:
case NETDEV_UNREGISTER:
/*
* rtnl_lock already held
@@ -699,11 +719,6 @@ static int netconsole_netdev_event(struct notifier_block *this,
dev_put(nt->np.dev);
nt->np.dev = NULL;
}
- /* Fall through */
- case NETDEV_GOING_DOWN:
- case NETDEV_BONDING_DESLAVE:
- nt->enabled = 0;
- break;
}
}
}
@@ -734,7 +749,8 @@ static void write_msg(struct console *con, const char *msg, unsigned int len)
spin_lock_irqsave(&target_list_lock, flags);
list_for_each_entry(nt, &target_list, list) {
- if (nt->enabled && netif_running(nt->np.dev)) {
+ if (nt->np_state == NETPOLL_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
^ permalink raw reply related
* [PATCH v3 02/22] netconsole: Introduce locking over the netpoll fields
From: Mike Waychison @ 2010-12-14 21:29 UTC (permalink / raw)
To: simon.kagstrom, davem, nhorman, Matt Mackall
Cc: adurbin, linux-kernel, chavey, Greg KH, netdev, Américo Wang,
akpm, linux-api
In-Reply-To: <20101214212846.17022.64836.stgit@mike.mtv.corp.google.com>
The netconsole driver currently doesn't do any locking over its
configuration fields. This can cause problems if we were to ever have
concurrent writing to fields while somebody is enabling the service.
For simplicity, this patch extends targets_list_lock to cover all
configuration fields within the targets. Macros are also added here to
wrap accessors so that we check whether the target has been enabled with
locking handled.
Signed-off-by: Mike Waychison <mikew@google.com>
Acked-by: Matt Mackall <mpm@selenic.com>
---
drivers/net/netconsole.c | 114 ++++++++++++++++++++++++++--------------------
1 files changed, 64 insertions(+), 50 deletions(-)
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index c87a49e..6e16888 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -327,6 +327,7 @@ static ssize_t store_enabled(struct netconsole_target *nt,
const char *buf,
size_t count)
{
+ unsigned long flags;
int err;
long enabled;
@@ -335,6 +336,10 @@ static ssize_t store_enabled(struct netconsole_target *nt,
return enabled;
if (enabled) { /* 1 */
+ spin_lock_irqsave(&target_list_lock, flags);
+ if (nt->enabled)
+ goto busy;
+ spin_unlock_irqrestore(&target_list_lock, flags);
/*
* Skip netpoll_parse_options() -- all the attributes are
@@ -343,18 +348,28 @@ static ssize_t store_enabled(struct netconsole_target *nt,
netpoll_print_options(&nt->np);
err = netpoll_setup(&nt->np);
+ spin_lock_irqsave(&target_list_lock, flags);
+ if (err)
+ nt->enabled = 0;
+ else
+ nt->enabled = 1;
+ spin_unlock_irqrestore(&target_list_lock, flags);
if (err)
return err;
printk(KERN_INFO "netconsole: network logging started\n");
-
} else { /* 0 */
+ spin_lock_irqsave(&target_list_lock, flags);
+ nt->enabled = 0;
+ spin_unlock_irqrestore(&target_list_lock, flags);
+
netpoll_cleanup(&nt->np);
}
- nt->enabled = enabled;
-
return strnlen(buf, count);
+busy:
+ spin_unlock_irqrestore(&target_list_lock, flags);
+ return -EBUSY;
}
static ssize_t store_dev_name(struct netconsole_target *nt,
@@ -363,13 +378,6 @@ static ssize_t store_dev_name(struct netconsole_target *nt,
{
size_t len;
- if (nt->enabled) {
- printk(KERN_ERR "netconsole: target (%s) is enabled, "
- "disable to update parameters\n",
- config_item_name(&nt->item));
- return -EINVAL;
- }
-
strlcpy(nt->np.dev_name, buf, IFNAMSIZ);
/* Get rid of possible trailing newline from echo(1) */
@@ -387,13 +395,6 @@ static ssize_t store_local_port(struct netconsole_target *nt,
long local_port;
#define __U16_MAX ((__u16) ~0U)
- if (nt->enabled) {
- printk(KERN_ERR "netconsole: target (%s) is enabled, "
- "disable to update parameters\n",
- config_item_name(&nt->item));
- return -EINVAL;
- }
-
local_port = strtol10_check_range(buf, 0, __U16_MAX);
if (local_port < 0)
return local_port;
@@ -410,13 +411,6 @@ static ssize_t store_remote_port(struct netconsole_target *nt,
long remote_port;
#define __U16_MAX ((__u16) ~0U)
- if (nt->enabled) {
- printk(KERN_ERR "netconsole: target (%s) is enabled, "
- "disable to update parameters\n",
- config_item_name(&nt->item));
- return -EINVAL;
- }
-
remote_port = strtol10_check_range(buf, 0, __U16_MAX);
if (remote_port < 0)
return remote_port;
@@ -430,13 +424,6 @@ static ssize_t store_local_ip(struct netconsole_target *nt,
const char *buf,
size_t count)
{
- if (nt->enabled) {
- printk(KERN_ERR "netconsole: target (%s) is enabled, "
- "disable to update parameters\n",
- config_item_name(&nt->item));
- return -EINVAL;
- }
-
nt->np.local_ip = in_aton(buf);
return strnlen(buf, count);
@@ -446,13 +433,6 @@ static ssize_t store_remote_ip(struct netconsole_target *nt,
const char *buf,
size_t count)
{
- if (nt->enabled) {
- printk(KERN_ERR "netconsole: target (%s) is enabled, "
- "disable to update parameters\n",
- config_item_name(&nt->item));
- return -EINVAL;
- }
-
nt->np.remote_ip = in_aton(buf);
return strnlen(buf, count);
@@ -466,13 +446,6 @@ static ssize_t store_remote_mac(struct netconsole_target *nt,
char *p = (char *) buf;
int i;
- if (nt->enabled) {
- printk(KERN_ERR "netconsole: target (%s) is enabled, "
- "disable to update parameters\n",
- config_item_name(&nt->item));
- return -EINVAL;
- }
-
for (i = 0; i < ETH_ALEN - 1; i++) {
remote_mac[i] = simple_strtoul(p, &p, 16);
if (*p != ':')
@@ -496,15 +469,56 @@ invalid:
* Attribute definitions for netconsole_target.
*/
-#define NETCONSOLE_TARGET_ATTR_RO(_name) \
+#define __NETCONSOLE_TARGET_ATTR_RO(_name, _prefix_...) \
static struct netconsole_target_attr netconsole_target_##_name = \
- __CONFIGFS_ATTR(_name, S_IRUGO, show_##_name, NULL)
+ __CONFIGFS_ATTR(_name, S_IRUGO, show_##_prefix_##_name, NULL)
-#define NETCONSOLE_TARGET_ATTR_RW(_name) \
+#define __NETCONSOLE_TARGET_ATTR_RW(_name, _prefix_...) \
static struct netconsole_target_attr netconsole_target_##_name = \
- __CONFIGFS_ATTR(_name, S_IRUGO | S_IWUSR, show_##_name, store_##_name)
+ __CONFIGFS_ATTR(_name, S_IRUGO | S_IWUSR, \
+ show_##_prefix_##_name, store_##_prefix_##_name)
+
+#define NETCONSOLE_WRAP_ATTR_STORE(_name) \
+static ssize_t store_locked_##_name(struct netconsole_target *nt, \
+ const char *buf, \
+ size_t count) \
+{ \
+ unsigned long flags; \
+ ssize_t ret; \
+ spin_lock_irqsave(&target_list_lock, flags); \
+ if (nt->enabled) { \
+ printk(KERN_ERR "netconsole: target (%s) is enabled, " \
+ "disable to update parameters\n", \
+ config_item_name(&nt->item)); \
+ spin_unlock_irqrestore(&target_list_lock, flags); \
+ return -EBUSY; \
+ } \
+ ret = store_##_name(nt, buf, count); \
+ spin_unlock_irqrestore(&target_list_lock, flags); \
+ return ret; \
+}
+
+#define NETCONSOLE_WRAP_ATTR_SHOW(_name) \
+static ssize_t show_locked_##_name(struct netconsole_target *nt, char *buf) \
+{ \
+ unsigned long flags; \
+ ssize_t ret; \
+ spin_lock_irqsave(&target_list_lock, flags); \
+ ret = show_##_name(nt, buf); \
+ spin_unlock_irqrestore(&target_list_lock, flags); \
+ return ret; \
+}
+
+#define NETCONSOLE_TARGET_ATTR_RW(_name) \
+ NETCONSOLE_WRAP_ATTR_STORE(_name) \
+ NETCONSOLE_WRAP_ATTR_SHOW(_name) \
+ __NETCONSOLE_TARGET_ATTR_RW(_name, locked_)
+
+#define NETCONSOLE_TARGET_ATTR_RO(_name) \
+ NETCONSOLE_WRAP_ATTR_SHOW(_name) \
+ __NETCONSOLE_TARGET_ATTR_RO(_name, locked_)
-NETCONSOLE_TARGET_ATTR_RW(enabled);
+__NETCONSOLE_TARGET_ATTR_RW(enabled);
NETCONSOLE_TARGET_ATTR_RW(dev_name);
NETCONSOLE_TARGET_ATTR_RW(local_port);
NETCONSOLE_TARGET_ATTR_RW(remote_port);
^ permalink raw reply related
* [PATCH v3 01/22] netconsole: Remove unneeded reference counting
From: Mike Waychison @ 2010-12-14 21:28 UTC (permalink / raw)
To: simon.kagstrom, davem, nhorman, Matt Mackall
Cc: adurbin, linux-kernel, chavey, Greg KH, netdev, Américo Wang,
akpm, linux-api
In-Reply-To: <20101214212846.17022.64836.stgit@mike.mtv.corp.google.com>
The loops that iterate through the list of targets for emitting console
messages in the netconsole driver operating with interrupts disabled and
the list-protecting lock held. There is no way for the elements of the
list to disappear, so we don't need to grab references to them.
This patch keeps the definitions however of netconsole_target_get() and
netconsole_target_put() as they are used in a subsequent patch.
Signed-off-by: Mike Waychison <mikew@google.com>
Acked-by: Matt Mackall <mpm@selenic.com>
---
drivers/net/netconsole.c | 4 ----
1 files changed, 0 insertions(+), 4 deletions(-)
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 94255f0..c87a49e 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -671,7 +671,6 @@ static int netconsole_netdev_event(struct notifier_block *this,
spin_lock_irqsave(&target_list_lock, flags);
list_for_each_entry(nt, &target_list, list) {
- netconsole_target_get(nt);
if (nt->np.dev == dev) {
switch (event) {
case NETDEV_CHANGENAME:
@@ -693,7 +692,6 @@ static int netconsole_netdev_event(struct notifier_block *this,
break;
}
}
- netconsole_target_put(nt);
}
spin_unlock_irqrestore(&target_list_lock, flags);
if (event == NETDEV_UNREGISTER || event == NETDEV_BONDING_DESLAVE)
@@ -722,7 +720,6 @@ static void write_msg(struct console *con, const char *msg, unsigned int len)
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
@@ -738,7 +735,6 @@ 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);
}
^ permalink raw reply related
* [PATCH v3 00/22] netoops support
From: Mike Waychison @ 2010-12-14 21:28 UTC (permalink / raw)
To: simon.kagstrom, davem, nhorman, Matt Mackall
Cc: adurbin, linux-kernel, chavey, Greg KH, netdev, Américo Wang,
akpm, linux-api
This patchset applies to v2.6.37-rc5. It also applies cleanly to net-next as
of this morning.
The following series implements support for 'netoops', a simple driver that
will deliver kmsg logs together with machine specifics over the network.
This driver is based on code used in Google's production server environment.
We internally call the driver 'netdump', but are planning on changing the name
to 'netoops' to follow the convention set by both the mtdoops and ramoops
drivers. We use these facilities to gather crash data from our entire fleet of
machines in a light-weight manner. We do things this way because it
simply isn't feasible to gather full crash data off of every machine in
the wild when they decide it is time to die.
Currently, this driver only supports UDP over ipv4.
In order to handle configuration, the target support in netconsole is
fixed, seperated out, and re-used by netoops.
I'm posting these patches in an effort to eventually get this sort of
functionality mainlined. Issues that I had personal concerns about have
been addressed, as well have several from others. These changes are
documented below.
There is some contention as to whether or not the transmission of
structured data is useful in a crash situation. I have documented why
we prefer to have structured date below in the comparison to netconsole.
Patchset summary
================
Patches 1 through 4 inclusive are fixes to the existing netconsole code,
adding locking consistency, fixing races and deadlocks. These are probably
ready to be merged as they fix real problems with the netconsole driver.
Patches 5 through 14 inclusive splits the target configuration portion
of netconsole out into a new component in net/core/netpoll_targets.c. These
are ready to merge as a cleanup series.
Patches 15 through 18 inclusive are core changes to support functionality in
the netoops driver. These are required for the netoops driver itself, but are
independent of all prior patches.
Patches 19 through 22 represent the netoops driver itself, with different
functional aspects broken out.
1 - netconsole: Remove unneeded reference counting
2 - netconsole: Introduce locking over the netpoll fields
3 - netconsole: Introduce 'enabled' state-machine
4 - netconsole: Call netpoll_cleanup() in process context
5 - netconsole: Wrap the list and locking in a structure
6 - netconsole: Push configfs_subsystem into netpoll_targets
7 - netconsole: Move netdev_notifier into netpoll_targets
8 - netconsole: Split out netpoll_targets init/exit
9 - netconsole: Add pointer to netpoll_targets
10 - netconsole: Rename netconsole_target -> netpoll_target
11 - netconsole: Abstract away the subsystem name
12 - netconsole: Move setting of default ports.
13 - netpoll: Introduce netpoll_target configs
14 - netpoll: Move target code into netpoll_targets.c
15 - Oops: Pass regs to oops_exit()
16 - kmsg_dumper: Pass pt_regs along to dumpers.
17 - kmsg_dumper: Introduce a new 'SOFT' dump reason
18 - sys-rq: Add option to soft dump
19 - netoops: add core functionality
20 - netoops: Add x86 specific bits to packet headers
21 - netoops: Add user-programmable boot_id
22 - netoops: Add a user programmable blob to the netoops packet.
Diffstat
========
Documentation/sysrq.txt | 4
arch/arm/kernel/traps.c | 2
arch/parisc/kernel/traps.c | 2
arch/powerpc/kernel/traps.c | 2
arch/s390/kernel/traps.c | 2
arch/sh/kernel/traps_32.c | 2
arch/x86/kernel/dumpstack.c | 2
drivers/char/ramoops.c | 4
drivers/mtd/mtdoops.c | 4
drivers/net/Kconfig | 26 +
drivers/net/Makefile | 1
drivers/net/netconsole.c | 735 +--------------------------------------
drivers/net/netoops.c | 346 ++++++++++++++++++
drivers/tty/sysrq.c | 14
include/linux/kernel.h | 2
include/linux/kmsg_dump.h | 9
include/linux/netpoll_targets.h | 76 ++++
kernel/kexec.c | 5
kernel/panic.c | 6
kernel/printk.c | 4
net/core/Makefile | 1
net/core/netpoll_targets.c | 749 ++++++++++++++++++++++++++++++++++++++++
22 files changed, 1260 insertions(+), 738 deletions(-)
Comparison to netconsole
========================
This driver differs from netconsole in a couple different ways.
* Network overheads:
With the number of machines we have, streaming large amounts of consoles
within the data center can really add up. This gets worse when you take
into account how reliant we are on kernel logging like OOM conditions
(which are very regular and very verbose). Events in the data center
(such as application growth) tend to be temporally correlated, which
causes large bursts of logging when we are OOM. We aren't so interested
in this kernel verbosity from a global collection standpoint though, and
haven't been keen on the amount of extra un-regulated UDP traffic it would
generate. We are however interested in kernel oopses which occur far less
often.
* Structured data:
In terms of the data received, we've really benefited by having structured
data in the payload. We've been collecting kernel oopses since sometime
in 2006 and have a _vast_ collection of crashes that we have indexed by
just about anything you could ever want (registers, full dmesg text,
backtraces, motherboards, CPU types, kernel versions, bios versions, etc).
This has allowed us to quickly find 'big bugs' vs 'rare bugs' (similar to
kerneloops.org) in a data center environment.
This structured data also allows for automated labeling of oopses/panics
using a variety of criteria. Netconsole only provides unstructured
streaming data, and the bits that we care about are either not present in
the dmesg logs or they are, but is extremely difficult to parse them out
(especially across kernel versions). Other bits of information, like
firmware version, are also difficult to associate with crashes with
post-processing due to gaps in global sampling and the churn that occurs
in the lab where versions can change quickly.
* Network reliability:
Another area where the two approaches have differed has been in handling
of network reliability. Historically (though less and less now), we found
that we had to transmit data several times. We also used to explicitly
space out packets with delays to handle switch chip buffer overruns. Both
of these functions I presume could be added to netconsole without too much
of a problem.
ChangeLog:
==========
- v3
- Dropped 'net_dump_now' interface as we already have CONFIG_LKDTM to
trigger crashes.
- Updated to also cancel any pending workers and clean the target up
if needed when removing being dropped from configfs. Issue
identified by Neil Horman.
- The user-programmable boot_id was been split out into its own patch.
- Other userland programmable entries have been removed and replaced
by a 'netoops_user_blob' field that is programmable to anything
less than or equal to 128 bytes in length.
- Support for 'one-shot' has been removed completely.
- Now that one-shot support and net_dump_now support are removed from
the patchset, we no longer have any interfaces in procfs.
- x86 vendor is now specified in the packet headers.
- 'netpoll_targets' can now be compiled as a module if neither
netconsole nor netoops require it to be built in. This property
also extends to CONFIGFS_FS.
- All fields for packets are now encoded in little-endian.
- v2
- Now uses the same mechanism that netconsole uses for configuring
targets, which is also now abstracted out to
net/core/netpoll_targets.c.
^ permalink raw reply
* Re: [RFC] Fix ip routing rules (partially revert b6c69d4b)
From: Ben Greear @ 2010-12-14 21:28 UTC (permalink / raw)
To: netdev
In-Reply-To: <1292025842-14959-1-git-send-email-greearb@candelatech.com>
On 12/10/2010 04:04 PM, greearb@candelatech.com wrote:
> From: Ben Greear<greearb@candelatech.com>
>
> Change 4465b469008bc03b98a1b8df4e9ae501b6c69d4b caused rules
> to stop matching the input device properly because the
> FLOWI_FLAG_MATCH_ANY_IIF is always defined in ip_dev_find().
Any comments on this? I think we should resolve this before .37, since
it appears to be a regression bug...
>
> This breaks rules such as:
>
> ip rule add pref 512 lookup local
> ip rule del pref 0 lookup local
> ip link set eth2 up
> ip -4 addr add 172.16.0.102/24 broadcast 172.16.0.255 dev eth2
> ip rule add to 172.16.0.102 iif eth2 lookup local pref 10
> ip rule add iif eth2 lookup 10001 pref 20
> ip route add 172.16.0.0/24 dev eth2 table 10001
> ip route add unreachable 0/0 table 10001
>
> If you had a second interface 'eth0' that was on a different
> subnet, pinging a system on that interface would fail:
>
> [root@ct503-60 ~]# ping 192.168.100.1
> connect: Invalid argument
>
> This patch partially reverts the problematic patch by
> NOT defining FLOWI_FLAG_MATCH_ANY_IIF. This probably breaks
> the feature that the original author intended to add, and
> it could easily be that the entire patch should be reverted,
> so this needs review before applying.
>
> Signed-off-by: Ben Greear<greearb@candelatech.com>
> ---
> :100644 100644 eb6f69a... 5f73819... M net/ipv4/fib_frontend.c
> net/ipv4/fib_frontend.c | 1 -
> 1 files changed, 0 insertions(+), 1 deletions(-)
>
> diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
> index eb6f69a..5f73819 100644
> --- a/net/ipv4/fib_frontend.c
> +++ b/net/ipv4/fib_frontend.c
> @@ -163,7 +163,6 @@ struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref)
> .daddr = addr
> }
> },
> - .flags = FLOWI_FLAG_MATCH_ANY_IIF
> };
> struct fib_result res = { 0 };
> struct net_device *dev = NULL;
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* Re: [PATCH 1/2] workqueue: convert cancel_rearming_delayed_work[queue]() users to cancel_delayed_work_sync()
From: Evgeniy Polyakov @ 2010-12-14 21:24 UTC (permalink / raw)
To: Tejun Heo
Cc: linux-kernel, jgarzik, benh, mchehab, davem, netdev, cbou, dwmw2,
gregkh, bfields, neilb, aelder, xfs-masters, cl, penberg, akpm,
netfilter-devel, Trond.Myklebust, linux-nfs
In-Reply-To: <4D078B6D.5060202@kernel.org>
Hi.
On Tue, Dec 14, 2010 at 04:21:17PM +0100, Tejun Heo (tj@kernel.org) wrote:
> cancel_rearming_delayed_work[queue]() has been superceded by
> cancel_delayed_work_sync() quite some time ago. Convert all the
> in-kernel users. The conversions are completely equivalent and
> trivial.
>
> Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Evgeniy Polyakov <zbr@ioremap.net>
--
Evgeniy Polyakov
^ permalink raw reply
* Re: [PATCH net-2.6 v2] net: fix nulls list corruptions in sk_prot_alloc
From: Eric Dumazet @ 2010-12-14 21:23 UTC (permalink / raw)
To: Octavian Purdila; +Cc: netdev, Leonard Crestez, stable
In-Reply-To: <1292347187-24154-1-git-send-email-opurdila@ixiacom.com>
Le mardi 14 décembre 2010 à 19:19 +0200, Octavian Purdila a écrit :
> Special care is taken inside sk_port_alloc to avoid overwriting
> skc_node/skc_nulls_node. We should also avoid overwriting
> skc_bind_node/skc_portaddr_node.
>
> The patch fixes the following crash:
>
> BUG: unable to handle kernel paging request at fffffffffffffff0
> IP: [<ffffffff812ec6dd>] udp4_lib_lookup2+0xad/0x370
> [<ffffffff812ecc22>] __udp4_lib_lookup+0x282/0x360
> [<ffffffff812ed63e>] __udp4_lib_rcv+0x31e/0x700
> [<ffffffff812bba45>] ? ip_local_deliver_finish+0x65/0x190
> [<ffffffff812bbbf8>] ? ip_local_deliver+0x88/0xa0
> [<ffffffff812eda35>] udp_rcv+0x15/0x20
> [<ffffffff812bba45>] ip_local_deliver_finish+0x65/0x190
> [<ffffffff812bbbf8>] ip_local_deliver+0x88/0xa0
> [<ffffffff812bb2cd>] ip_rcv_finish+0x32d/0x6f0
> [<ffffffff8128c14c>] ? netif_receive_skb+0x99c/0x11c0
> [<ffffffff812bb94b>] ip_rcv+0x2bb/0x350
> [<ffffffff8128c14c>] netif_receive_skb+0x99c/0x11c0
>
> Signed-off-by: Leonard Crestez <lcrestez@ixiacom.com>
> Signed-off-by: Octavian Purdila <opurdila@ixiacom.com>
> Cc: Eric Dumazet <eric.dumazet@gmail.com>
> Cc: stable@kernel.org
> ---
Thanks Octavian !
Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
^ permalink raw reply
* [PATCH] net: Abstract default MTU metric calculation behind an accessor.
From: David Miller @ 2010-12-14 21:20 UTC (permalink / raw)
To: netdev
Like RTAX_ADVMSS, make the default calculation go through a dst_ops
method rather than caching the computation in the routing cache
entries.
Now dst metrics are pretty much left as-is when new entries are
created, thus optimizing metric sharing becomes a real possibility.
Signed-off-by: David S. Miller <davem@davemloft.net>
---
include/net/dst.h | 15 ++++++++-------
include/net/dst_ops.h | 1 +
net/decnet/dn_route.c | 10 ++++++++--
net/ipv4/route.c | 29 ++++++++++++++++++++---------
net/ipv6/route.c | 37 ++++++++++++++++---------------------
net/xfrm/xfrm_policy.c | 7 +++++++
6 files changed, 60 insertions(+), 39 deletions(-)
diff --git a/include/net/dst.h b/include/net/dst.h
index 03a1c3d..93b0310 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -113,7 +113,8 @@ static inline u32
dst_metric(const struct dst_entry *dst, const int metric)
{
WARN_ON_ONCE(metric == RTAX_HOPLIMIT ||
- metric == RTAX_ADVMSS);
+ metric == RTAX_ADVMSS ||
+ metric == RTAX_MTU);
return dst_metric_raw(dst, metric);
}
@@ -156,11 +157,11 @@ dst_feature(const struct dst_entry *dst, u32 feature)
static inline u32 dst_mtu(const struct dst_entry *dst)
{
- u32 mtu = dst_metric(dst, RTAX_MTU);
- /*
- * Alexey put it here, so ask him about it :)
- */
- barrier();
+ u32 mtu = dst_metric_raw(dst, RTAX_MTU);
+
+ if (!mtu)
+ mtu = dst->ops->default_mtu(dst);
+
return mtu;
}
@@ -186,7 +187,7 @@ dst_allfrag(const struct dst_entry *dst)
}
static inline int
-dst_metric_locked(struct dst_entry *dst, int metric)
+dst_metric_locked(const struct dst_entry *dst, int metric)
{
return dst_metric(dst, RTAX_LOCK) & (1<<metric);
}
diff --git a/include/net/dst_ops.h b/include/net/dst_ops.h
index 15fb7af..21a320b 100644
--- a/include/net/dst_ops.h
+++ b/include/net/dst_ops.h
@@ -17,6 +17,7 @@ struct dst_ops {
int (*gc)(struct dst_ops *ops);
struct dst_entry * (*check)(struct dst_entry *, __u32 cookie);
unsigned int (*default_advmss)(const struct dst_entry *);
+ unsigned int (*default_mtu)(const struct dst_entry *);
void (*destroy)(struct dst_entry *);
void (*ifdown)(struct dst_entry *,
struct net_device *dev, int how);
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index b8a5c05..5e63636 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -111,6 +111,7 @@ static unsigned long dn_rt_deadline;
static int dn_dst_gc(struct dst_ops *ops);
static struct dst_entry *dn_dst_check(struct dst_entry *, __u32);
static unsigned int dn_dst_default_advmss(const struct dst_entry *dst);
+static unsigned int dn_dst_default_mtu(const struct dst_entry *dst);
static struct dst_entry *dn_dst_negative_advice(struct dst_entry *);
static void dn_dst_link_failure(struct sk_buff *);
static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu);
@@ -131,6 +132,7 @@ static struct dst_ops dn_dst_ops = {
.gc = dn_dst_gc,
.check = dn_dst_check,
.default_advmss = dn_dst_default_advmss,
+ .default_mtu = dn_dst_default_mtu,
.negative_advice = dn_dst_negative_advice,
.link_failure = dn_dst_link_failure,
.update_pmtu = dn_dst_update_pmtu,
@@ -803,6 +805,11 @@ static unsigned int dn_dst_default_advmss(const struct dst_entry *dst)
return dn_mss_from_pmtu(dst->dev, dst_mtu(dst));
}
+static unsigned int dn_dst_default_mtu(const struct dst_entry *dst)
+{
+ return dst->dev->mtu;
+}
+
static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res)
{
struct dn_fib_info *fi = res->fi;
@@ -825,8 +832,7 @@ static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res)
rt->dst.neighbour = n;
}
- if (dst_metric(&rt->dst, RTAX_MTU) == 0 ||
- dst_metric(&rt->dst, RTAX_MTU) > rt->dst.dev->mtu)
+ if (dst_metric(&rt->dst, RTAX_MTU) > rt->dst.dev->mtu)
dst_metric_set(&rt->dst, RTAX_MTU, rt->dst.dev->mtu);
metric = dst_metric_raw(&rt->dst, RTAX_ADVMSS);
if (metric) {
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 8099733..ae52096 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -140,6 +140,7 @@ static unsigned long expires_ljiffies;
static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie);
static unsigned int ipv4_default_advmss(const struct dst_entry *dst);
+static unsigned int ipv4_default_mtu(const struct dst_entry *dst);
static void ipv4_dst_destroy(struct dst_entry *dst);
static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst);
static void ipv4_link_failure(struct sk_buff *skb);
@@ -157,6 +158,7 @@ static struct dst_ops ipv4_dst_ops = {
.gc = rt_garbage_collect,
.check = ipv4_dst_check,
.default_advmss = ipv4_default_advmss,
+ .default_mtu = ipv4_default_mtu,
.destroy = ipv4_dst_destroy,
.ifdown = ipv4_dst_ifdown,
.negative_advice = ipv4_negative_advice,
@@ -1812,6 +1814,23 @@ static unsigned int ipv4_default_advmss(const struct dst_entry *dst)
return advmss;
}
+static unsigned int ipv4_default_mtu(const struct dst_entry *dst)
+{
+ unsigned int mtu = dst->dev->mtu;
+
+ if (unlikely(dst_metric_locked(dst, RTAX_MTU))) {
+ const struct rtable *rt = (const struct rtable *) dst;
+
+ if (rt->rt_gateway != rt->rt_dst && mtu > 576)
+ mtu = 576;
+ }
+
+ if (mtu > IP_MAX_MTU)
+ mtu = IP_MAX_MTU;
+
+ return mtu;
+}
+
static void rt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag)
{
struct dst_entry *dst = &rt->dst;
@@ -1822,18 +1841,10 @@ static void rt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag)
FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
rt->rt_gateway = FIB_RES_GW(*res);
dst_import_metrics(dst, fi->fib_metrics);
- if (fi->fib_mtu == 0) {
- dst_metric_set(dst, RTAX_MTU, dst->dev->mtu);
- if (dst_metric_locked(dst, RTAX_MTU) &&
- rt->rt_gateway != rt->rt_dst &&
- dst->dev->mtu > 576)
- dst_metric_set(dst, RTAX_MTU, 576);
- }
#ifdef CONFIG_NET_CLS_ROUTE
dst->tclassid = FIB_RES_NH(*res).nh_tclassid;
#endif
- } else
- dst_metric_set(dst, RTAX_MTU, dst->dev->mtu);
+ }
if (dst_mtu(dst) > IP_MAX_MTU)
dst_metric_set(dst, RTAX_MTU, IP_MAX_MTU);
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index d9cb832..e7efb26 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -77,6 +77,7 @@
static struct rt6_info * ip6_rt_copy(struct rt6_info *ort);
static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie);
static unsigned int ip6_default_advmss(const struct dst_entry *dst);
+static unsigned int ip6_default_mtu(const struct dst_entry *dst);
static struct dst_entry *ip6_negative_advice(struct dst_entry *);
static void ip6_dst_destroy(struct dst_entry *);
static void ip6_dst_ifdown(struct dst_entry *,
@@ -105,6 +106,7 @@ static struct dst_ops ip6_dst_ops_template = {
.gc_thresh = 1024,
.check = ip6_dst_check,
.default_advmss = ip6_default_advmss,
+ .default_mtu = ip6_default_mtu,
.destroy = ip6_dst_destroy,
.ifdown = ip6_dst_ifdown,
.negative_advice = ip6_negative_advice,
@@ -937,8 +939,6 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
}
}
-static int ipv6_get_mtu(struct net_device *dev);
-
static unsigned int ip6_default_advmss(const struct dst_entry *dst)
{
struct net_device *dev = dst->dev;
@@ -961,6 +961,20 @@ static unsigned int ip6_default_advmss(const struct dst_entry *dst)
return mtu;
}
+static unsigned int ip6_default_mtu(const struct dst_entry *dst)
+{
+ unsigned int mtu = IPV6_MIN_MTU;
+ struct inet6_dev *idev;
+
+ rcu_read_lock();
+ idev = __in6_dev_get(dst->dev);
+ if (idev)
+ mtu = idev->cnf.mtu6;
+ rcu_read_unlock();
+
+ return mtu;
+}
+
static struct dst_entry *icmp6_dst_gc_list;
static DEFINE_SPINLOCK(icmp6_dst_lock);
@@ -995,7 +1009,6 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
rt->rt6i_nexthop = neigh;
atomic_set(&rt->dst.__refcnt, 1);
dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255);
- dst_metric_set(&rt->dst, RTAX_MTU, ipv6_get_mtu(rt->rt6i_dev));
rt->dst.output = ip6_output;
#if 0 /* there's no chance to use these for ndisc */
@@ -1094,19 +1107,6 @@ out:
Remove it only when all the things will work!
*/
-static int ipv6_get_mtu(struct net_device *dev)
-{
- int mtu = IPV6_MIN_MTU;
- struct inet6_dev *idev;
-
- rcu_read_lock();
- idev = __in6_dev_get(dev);
- if (idev)
- mtu = idev->cnf.mtu6;
- rcu_read_unlock();
- return mtu;
-}
-
int ip6_dst_hoplimit(struct dst_entry *dst)
{
int hoplimit = dst_metric_raw(dst, RTAX_HOPLIMIT);
@@ -1315,8 +1315,6 @@ install_route:
}
}
- if (!dst_mtu(&rt->dst))
- dst_metric_set(&rt->dst, RTAX_MTU, ipv6_get_mtu(dev));
rt->dst.dev = dev;
rt->rt6i_idev = idev;
rt->rt6i_table = table;
@@ -1541,8 +1539,6 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src,
ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key);
nrt->rt6i_nexthop = neigh_clone(neigh);
- /* Reset pmtu, it may be better */
- dst_metric_set(&nrt->dst, RTAX_MTU, ipv6_get_mtu(neigh->dev));
if (ip6_ins_rt(nrt))
goto out;
@@ -1971,7 +1967,6 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
rt->dst.output = ip6_output;
rt->rt6i_dev = net->loopback_dev;
rt->rt6i_idev = idev;
- dst_metric_set(&rt->dst, RTAX_MTU, ipv6_get_mtu(rt->rt6i_dev));
dst_metric_set(&rt->dst, RTAX_HOPLIMIT, -1);
rt->dst.obsolete = -1;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 36936c8..8b3ef40 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -2366,6 +2366,11 @@ static unsigned int xfrm_default_advmss(const struct dst_entry *dst)
return dst_metric_advmss(dst->path);
}
+static unsigned int xfrm_default_mtu(const struct dst_entry *dst)
+{
+ return dst_mtu(dst->path);
+}
+
int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
{
struct net *net;
@@ -2385,6 +2390,8 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
dst_ops->check = xfrm_dst_check;
if (likely(dst_ops->default_advmss == NULL))
dst_ops->default_advmss = xfrm_default_advmss;
+ if (likely(dst_ops->default_mtu == NULL))
+ dst_ops->default_mtu = xfrm_default_mtu;
if (likely(dst_ops->negative_advice == NULL))
dst_ops->negative_advice = xfrm_negative_advice;
if (likely(dst_ops->link_failure == NULL))
--
1.7.3.2
^ permalink raw reply related
* Re: [PATCH] net/sunrpc/auth_gss/gss_krb5_crypto.c: Use normal negative error value return
From: J. Bruce Fields @ 2010-12-14 21:19 UTC (permalink / raw)
To: Joe Perches
Cc: Neil Brown, Trond Myklebust, David S. Miller,
linux-nfs-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1289786891.16461.102.camel@Joe-Laptop>
On Sun, Nov 14, 2010 at 06:08:11PM -0800, Joe Perches wrote:
> And remove unnecessary double semicolon too.
>
> No effect to code, as test is != 0.
Hm, the error return's actually ignored. But OK. Applying to my tree
for 2.6.38 assuming nobody else has picked it up.
--b.
>
> Signed-off-by: Joe Perches <joe-6d6DIl74uiNBDgjK7y7TUQ@public.gmane.org>
> ---
> net/sunrpc/auth_gss/gss_krb5_crypto.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
> index 75ee993..9576f35 100644
> --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
> +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
> @@ -137,7 +137,7 @@ arcfour_hmac_md5_usage_to_salt(unsigned int usage, u8 salt[4])
> ms_usage = 13;
> break;
> default:
> - return EINVAL;;
> + return -EINVAL;
> }
> salt[0] = (ms_usage >> 0) & 0xff;
> salt[1] = (ms_usage >> 8) & 0xff;
>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 12/12] cxgb4: NUMA-aware Tx queue allocations
From: Eric Dumazet @ 2010-12-14 21:17 UTC (permalink / raw)
To: Dimitris Michailidis; +Cc: netdev
In-Reply-To: <1292357896-14339-13-git-send-email-dm@chelsio.com>
Le mardi 14 décembre 2010 à 12:18 -0800, Dimitris Michailidis a écrit :
> Allocate Tx queue memory on the node indicated by the new
> netdev_queue_numa_node_read. If that fails we allocate on any node.
>
> Signed-off-by: Dimitris Michailidis <dm@chelsio.com>
> ---
> drivers/net/cxgb4/sge.c | 20 +++++++++++++-------
> 1 files changed, 13 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/net/cxgb4/sge.c b/drivers/net/cxgb4/sge.c
> index cc0b997..ed98b8a 100644
> --- a/drivers/net/cxgb4/sge.c
> +++ b/drivers/net/cxgb4/sge.c
> @@ -579,6 +579,7 @@ static inline void __refill_fl(struct adapter *adap, struct sge_fl *fl)
> * @phys: the physical address of the allocated ring
> * @metadata: address of the array holding the SW state for the ring
> * @stat_size: extra space in HW ring for status information
> + * @node: preferred node for memory allocations
> *
> * Allocates resources for an SGE descriptor ring, such as Tx queues,
> * free buffer lists, or response queues. Each SGE ring requires
> @@ -590,7 +591,7 @@ static inline void __refill_fl(struct adapter *adap, struct sge_fl *fl)
> */
> static void *alloc_ring(struct device *dev, size_t nelem, size_t elem_size,
> size_t sw_size, dma_addr_t *phys, void *metadata,
> - size_t stat_size)
> + size_t stat_size, int node)
> {
> size_t len = nelem * elem_size + stat_size;
> void *s = NULL;
> @@ -599,7 +600,10 @@ static void *alloc_ring(struct device *dev, size_t nelem, size_t elem_size,
> if (!p)
> return NULL;
> if (sw_size) {
> - s = kcalloc(nelem, sw_size, GFP_KERNEL);
> + if (node >= 0)
> + s = kzalloc_node(nelem * sw_size, GFP_KERNEL, node);
kzalloc_node() has a fallback, you dont need to retry with kcalloc()
> + if (!s)
> + s = kcalloc(nelem, sw_size, GFP_KERNEL);
>
> if (!s) {
> dma_free_coherent(dev, len, p, *phys);
Also, I am not sure it is going to work, since we can setup XPS only
after device being setup ?
By the time your driver allocates rings, we probably read
-1/NUMA_NO_NODE
^ permalink raw reply
* Re: [PATCH] ehea: Fixing LRO configuration
From: Jesse Gross @ 2010-12-14 20:55 UTC (permalink / raw)
To: Breno Leitao; +Cc: shemminger, davem, netdev
In-Reply-To: <4D076AAF.5040505@linux.vnet.ibm.com>
On Tue, Dec 14, 2010 at 5:01 AM, Breno Leitao <leitao@linux.vnet.ibm.com> wrote:
> Hi Jesse,
>
> On 12/12/2010 10:39 PM, Jesse Gross wrote:
>>
>> I don't think that this should enable those vlan offloading flags.
>
> I just inserted ETH_FLAG_TXVLAN and ETH_FLAG_RXVLAN there because when I
> call ethtool -K ethX lro on/off, it sends the ETH_FLAG_LRO plus the vlan
> flags if they are enabled (and they are by default).
>
> So, if it doesn't make sense to be toggled, I can mask these flags at
> ehea_set_flags(). so that it doesn't arrive at ethtool_op_set_flags().
I think the right solution is to check that they are set before the
call to ethtool_op_set_flags() and return -EINVAL if not. Masking
them out would result in turning the features off, which isn't a valid
state here.
Of course, the alternative is to actually add support for the settings
to be toggled. This would be ideal but it doesn't look the driver
ever does that currently, so maybe it's not supported by hardware.
Thanks.
^ permalink raw reply
* [GIT] Networking
From: David Miller @ 2010-12-14 20:39 UTC (permalink / raw)
To: torvalds; +Cc: akpm, netdev, linux-kernel
A lot of small stuff has queued up while you were away.
1) Revert a pppoe change that causes SKBs to be accessed after
being freed, from Andrej Ota.
2) SFC driver crash and list corruption fixes from Ben Hutchings.
3) EHEA driver needs to respect ethtool enable/disable LRO requests
otherwise bridging and routing won't work properly, from
Breno Leitao.
4) x25 device refcount leak fix from Apollon Oikonomopoulos.
5) Endian fixes in LSO code in bnx2x driver from Vladislav Zolotarov.
6) stmmac driver uses spinlock uninitialized, from Vlad Lungu.
7) enic driver passes wrong pointer to IRQ handler, from Vasanthy Kolluri.
8) TCP time-wait bucket message can spam logs, use event counter instead.
From Tom Herbert.
9) IPSEC code leaks in error path of xfrm_state_migrate(), fix from
Thomas Egerer.
10) Elide checksumming offload on GE0301 option HSO cards
From Thomas Bogendoerfer.
11) Runtime PM fix in r8169 from Rafael J. Wysocki.
12) Netlink group improperly choosen during ipv6 net link advertisement.
Fix frm Nicolas Dichtel.
13) Improper cleanup in econet's SIOCSIFADDR ioctl code.
14) benet driver loads mac addresses incorrectly due to improperly
coded memcpy() call, fix from Joe Jin.
15) Several fixes from Eric Dumazet:
a) sk_filter() hits RCU incorrectly
b) llc leaks netdevices
c) obscure sysctl settings can make tcp divide by zero
d) Use ACCESS_ONCE() when reading sysctl_tcp_cookie_size
multiple times
e) Fix crash when skb_defer_rx_timestamp() encounters a packet
lacking a link-level header.
16) ECONET aun_incoming() makes bogus unconditional deref of skb->dev,
it should use dst->dev when 'dst' is non-NULL instead.
17) Blocking mechanism for bonding netpoll support via a cpumask is
busted, use a counter instead. From Neil Horman.
18) SCTP_SET_PEER_PRIMARY_ADDR erroneously does not accept ipv4-mapped
ipv6 addresses, fix from Wei Yongjun.
19) ATM layer creates sysfs device links with bogus parent relationships,
fix from Dan Williams.
20) Fix deadlock in qlge, from Ron Mercer.
21) Several bluetooth fixes:
a) Fix error propagation from sco_connect_ind(), sco_connect_cfm(), and
sco_disconn_cfm().
b) fix btusb log spam during autosuspend
c) Add USB device ID for Atheros 3011
22) Fix bonding regression in MAC address assignment behavior, from
David Strand.
23) IPV6 over IPV4 tunnel fix from David McCullough. SIT driver was
consuming all the packets and sending ICMP port unreachables out.
24) Various ath9k, mac80211, orinoco, libertas et al. fixes via John
Linville and the wireless team.
25) Fix NULL deref during ixgbe shutdown, from Don Skidmore.
26) TCP receive window initialization boundary checks improperly
coded, fix from Nandita Dukkipati.
27) IFB transmit queue can deadlock, fix from Changli Gao.
28) Modalias fixes in l2tp and connector.
29) IPv6 tunnel uses incorrect MTU when encap limit is enabled, fix from
Anders Franzen.
30) VHOST dirty page logging traversal fix from Michael S. Tsirkin.
Please pull, thanks a lot!
The following changes since commit bcb38ceb225f5d5b2198a2755277cd441ed1e82b:
Revert "debug_locks: set oops_in_progress if we will log messages." (2010-11-29 15:18:28 -0800)
are available in the git repository at:
master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6.git master
Alexander V. Lukyanov (1):
tulip: fix hang in dmfe driver on sending of big packet
Anders Franzen (1):
Make the ip6_tunnel reflect the true mtu.
Andrej Ota (1):
pppoe.c: Fix kernel panic caused by __pppoe_xmit
Apollon Oikonomopoulos (1):
x25: decrement netdev reference counts on unload
Bala Shanmugam (1):
Bluetooth: Add new PID for Atheros 3011
Ben Hutchings (2):
sfc: Fix crash in legacy onterrupt handler during ring reallocation
sfc: Fix NAPI list corruption during ring reallocation
Breno Leitao (1):
ehea: Fixing LRO configuration
Casey Leedom (1):
cxgb4vf: Ingress Queue Entry Size needs to be 64 bytes
Changli Gao (1):
ifb: goto resched directly if error happens and dp->tq isn't empty
Christian Lamparter (2):
carl9170: fix carl9170_tx_prepare typo
mac80211: ignore non-bcast mcast deauth/disassoc franes
Dan Williams (1):
atm: correct sysfs 'device' link creation and parent relationships
Daniel Drake (1):
libertas: fix memory corruption in lbs_remove_card()
David Kilroy (4):
orinoco: abort scan on interface down
orinoco: initialise priv->hw before assigning the interrupt
orinoco: clear countermeasure setting on commit
orinoco: fix TKIP countermeasure behaviour
David McCullough (1):
net/ipv6/sit.c: return unhandled skb to tunnel4_rcv
David S. Miller (5):
Merge branch 'master' of git://git.kernel.org/.../linville/wireless-2.6
Merge branch 'sfc-2.6.37' of git://git.kernel.org/.../bwh/sfc-2.6
econet: Fix crash in aun_incoming().
Merge branch 'master' of git://git.kernel.org/.../linville/wireless-2.6
Merge branch 'vhost-net' of git://git.kernel.org/.../mst/vhost
David Strand (1):
bonding: check for assigned mac before adopting the slaves mac address
Dimitris Michailidis (1):
cxgb4: fix MAC address hash filter
Don Skidmore (1):
ixgbe: fix possible NULL pointer deference in shutdown path
Eric Dumazet (5):
filter: fix sk_filter rcu handling
llc: fix a device refcount imbalance
tcp: avoid a possible divide by zero
tcp: protect sysctl_tcp_cookie_size reads
net: fix skb_defer_rx_timestamp()
Felix Fietkau (3):
ath9k_hw: fix endian issues with CTLs on AR9003
ath9k_hw: fix more bitfield related endian issues
ath9k: fix a DMA related race condition on reset
Gabor Juhos (1):
ath9k: use per-device struct for pm_qos_* operations
Giuseppe CAVALLARO (1):
phy: add the IC+ IP1001 driver
Gustavo F. Padovan (1):
Bluetooth: Fix not returning proper error in SCO
Hauke Mehrtens (1):
b44: fix workarround for wap54g10
Helmut Schaa (1):
mac80211: Fix BUG in pskb_expand_head when transmitting shared skbs
Javier Cardona (3):
ath5k: Fix beaconing in mesh mode
ath5k: Prevent mesh interfaces from being counted as ad-hoc
ath5k: Put the right tsf value in mesh beacons
Joe Jin (1):
driver/net/benet: fix be_cmd_multicast_set() memcpy bug
Johannes Berg (1):
ath9k/carl9170: advertise P2P
John W. Linville (2):
Merge branch 'master' of git://git.kernel.org/.../padovan/bluetooth-2.6
Revert "ath9k: Fix STA disconnect issue due to received MIC failed bcast frames"
Jouni Malinen (1):
mac80211: Fix frame injection using non-AP vif
Kim Lilliestierna XX (1):
CAIF: Fix U5500 compile error for shared memory driver
Krzysztof Halasa (1):
WAN: Fix a TX IRQ causing BUG() in PC300 and PCI200SYN drivers.
Kyle McMartin (1):
MAINTAINERS: remove me from tulip
Martin Lucina (1):
net: Document the kernel_recvmsg() function
Matteo Croce (1):
ath9k: fix bug in tx power
Michael S. Tsirkin (1):
vhost: correctly set bits of dirty pages
Michal Marek (1):
l2tp: Fix modalias of l2tp_ip
Nandita Dukkipati (1):
tcp: Bug fix in initialization of receive window.
Neil Horman (1):
net: Convert netpoll blocking api in bonding driver to be a counter
Nelson Elhage (1):
econet: Do the correct cleanup after an unprivileged SIOCSIFADDR.
Nicolas Dichtel (1):
ipv6: fix nl group when advertising a new link
Rafael J. Wysocki (1):
r8169: Fix runtime power management
Rajkumar Manoharan (2):
ath9k: Disable SWBA interrupt on remove_interface
ath9k: fix beacon resource related race condition
Ron Mercer (1):
qlge: Fix deadlock when cancelling worker.
Senthil Balasubramanian (3):
mac80211: Fix STA disconnect due to MIC failure
ath9k: Fix STA disconnect issue due to received MIC failed bcast frames
ath9k: Fix STA disconnect issue due to received MIC failed bcast frames
Stefan Seyfried (1):
Bluetooth: Fix log spamming in btusb due to autosuspend
Stephen Hemminger (1):
connector: add module alias
Sujith Manoharan (1):
ath9k_htc: Fix suspend/resume
Sven Neumann (1):
libertas: fix invalid access
Thomas Bogendoerfer (1):
hso: IP checksuming doesn't work on GE0301 option cards
Thomas Egerer (1):
xfrm: Fix xfrm_state_migrate leak
Tom Herbert (1):
tcp: Replace time wait bucket msg by counter
Vasanthakumar Thiagarajan (1):
ath9k: Fix bug in reading input gpio state for ar9003
Vasanthy Kolluri (1):
enic: Bug Fix: Pass napi reference to the isr that services receive queue
Vlad Lungu (1):
stmmac: priv->lock can be used uninitialized
Vladislav Zolotarov (3):
bnx2x: LSO code was broken on BE platforms
bnx2x: Fixed a compilation warning
bnx2x: Advance a version number to 1.60.01-0
Wei Yongjun (1):
SCTP: Fix SCTP_SET_PEER_PRIMARY_ADDR to accpet v4mapped address
MAINTAINERS | 1 -
drivers/atm/adummy.c | 2 +-
drivers/atm/ambassador.c | 3 +-
drivers/atm/atmtcp.c | 2 +-
drivers/atm/eni.c | 2 +-
drivers/atm/firestream.c | 2 +-
drivers/atm/fore200e.c | 14 ++--
drivers/atm/he.c | 2 +-
drivers/atm/horizon.c | 3 +-
drivers/atm/idt77252.c | 3 +-
drivers/atm/iphase.c | 2 +-
drivers/atm/lanai.c | 2 +-
drivers/atm/nicstar.c | 3 +-
drivers/atm/solos-pci.c | 8 +-
drivers/atm/zatm.c | 2 +-
drivers/bluetooth/ath3k.c | 4 +
drivers/bluetooth/btusb.c | 12 +++-
drivers/connector/connector.c | 1 +
drivers/net/b44.c | 11 ++--
drivers/net/benet/be_cmds.c | 2 +-
drivers/net/bnx2x/bnx2x.h | 4 +-
drivers/net/bnx2x/bnx2x_cmn.c | 42 ++++++++-----
drivers/net/bnx2x/bnx2x_init_ops.h | 4 +-
drivers/net/bonding/bond_main.c | 19 ++----
drivers/net/bonding/bonding.h | 12 +---
drivers/net/caif/caif_shm_u5500.c | 2 +-
drivers/net/caif/caif_shmcore.c | 2 +-
drivers/net/cxgb4/t4_hw.c | 2 +-
drivers/net/cxgb4vf/cxgb4vf_main.c | 15 ++++-
drivers/net/ehea/ehea_ethtool.c | 9 +++
drivers/net/ehea/ehea_main.c | 7 ++-
drivers/net/enic/enic_main.c | 3 +-
drivers/net/ifb.c | 2 +
drivers/net/ixgbe/ixgbe_main.c | 3 +
drivers/net/phy/Kconfig | 2 +-
drivers/net/phy/icplus.c | 59 +++++++++++++++++--
drivers/net/pppoe.c | 2 +-
drivers/net/qlge/qlge.h | 1 +
drivers/net/qlge/qlge_main.c | 1 +
drivers/net/qlge/qlge_mpi.c | 12 +---
drivers/net/r8169.c | 26 +++++---
drivers/net/sfc/efx.c | 43 +++++++++-----
drivers/net/sfc/net_driver.h | 2 +
drivers/net/sfc/nic.c | 6 ++
drivers/net/stmmac/stmmac_main.c | 4 +-
drivers/net/tulip/dmfe.c | 6 +-
drivers/net/usb/hso.c | 4 -
drivers/net/wan/hd64572.c | 5 +-
drivers/net/wireless/ath/ath5k/base.c | 13 +++--
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 73 ++++++++++++-----------
drivers/net/wireless/ath/ath9k/ar9003_eeprom.h | 9 +--
drivers/net/wireless/ath/ath9k/ath9k.h | 6 +-
drivers/net/wireless/ath/ath9k/eeprom.c | 6 +-
drivers/net/wireless/ath/ath9k/eeprom.h | 27 +++++----
drivers/net/wireless/ath/ath9k/eeprom_def.c | 23 +++++---
drivers/net/wireless/ath/ath9k/hif_usb.c | 7 ++
drivers/net/wireless/ath/ath9k/htc.h | 3 +
drivers/net/wireless/ath/ath9k/htc_drv_init.c | 6 ++
drivers/net/wireless/ath/ath9k/htc_drv_main.c | 4 +-
drivers/net/wireless/ath/ath9k/hw.c | 3 +-
drivers/net/wireless/ath/ath9k/init.c | 9 +--
drivers/net/wireless/ath/ath9k/mac.c | 3 +-
drivers/net/wireless/ath/ath9k/main.c | 28 +++++----
drivers/net/wireless/ath/ath9k/recv.c | 9 +++-
drivers/net/wireless/ath/ath9k/reg.h | 6 +-
drivers/net/wireless/ath/ath9k/xmit.c | 22 ++-----
drivers/net/wireless/ath/carl9170/fw.c | 3 +-
drivers/net/wireless/ath/carl9170/main.c | 3 +-
drivers/net/wireless/ath/carl9170/tx.c | 2 +-
drivers/net/wireless/libertas/if_sdio.c | 1 -
drivers/net/wireless/libertas/if_spi.c | 1 -
drivers/net/wireless/libertas/main.c | 2 -
drivers/net/wireless/orinoco/main.c | 18 ++++--
drivers/net/wireless/orinoco/orinoco_cs.c | 14 ++--
drivers/net/wireless/orinoco/scan.c | 8 +++
drivers/net/wireless/orinoco/scan.h | 1 +
drivers/net/wireless/orinoco/spectrum_cs.c | 14 ++--
drivers/net/wireless/orinoco/wext.c | 4 +-
drivers/usb/atm/usbatm.c | 15 +----
drivers/vhost/vhost.c | 3 +-
include/linux/atmdev.h | 6 +-
include/linux/snmp.h | 1 +
include/net/sock.h | 4 +-
net/atm/atm_sysfs.c | 3 +-
net/atm/resources.c | 7 +-
net/atm/resources.h | 2 +-
net/bluetooth/sco.c | 6 +-
net/core/filter.c | 19 ++----
net/core/timestamping.c | 6 +-
net/econet/af_econet.c | 12 +++-
net/ipv4/proc.c | 1 +
net/ipv4/tcp_minisocks.c | 2 +-
net/ipv4/tcp_output.c | 42 ++++++++------
net/ipv6/addrconf.c | 4 +-
net/ipv6/ip6_tunnel.c | 7 ++
net/ipv6/sit.c | 3 +-
net/l2tp/l2tp_ip.c | 6 ++-
net/llc/af_llc.c | 5 +-
net/mac80211/rx.c | 6 ++
net/mac80211/tx.c | 28 ++++++++-
net/sctp/socket.c | 8 +++
net/socket.c | 15 +++++
net/x25/x25_link.c | 1 +
net/xfrm/xfrm_state.c | 2 +-
104 files changed, 569 insertions(+), 353 deletions(-)
^ permalink raw reply
* Re: After memory pressure: can't read from tape anymore
From: Vladislav Bolkhovitin @ 2010-12-14 20:35 UTC (permalink / raw)
To: James Bottomley
Cc: Lukas Kolbe, Kai Mäkisara, FUJITA Tomonori, linux-scsi,
Kashyap Desai, netdev
In-Reply-To: <1291399814.2881.66.camel@mulgrave.site>
James Bottomley, on 12/03/2010 09:10 PM wrote:
>>>> Thanks for noticing this bug. I hope this helps the users. The question
>>>> about number of s/g segments is still valid for the direct i/o case but
>>>> that is optimization and not whether one can read/write.
>>>
>>> Realistically, though, this will only increase the probability of making
>>> an allocation work, we can't get this to a certainty.
>>>
>>> Since we fixed up the infrastructure to allow arbitrary length sg lists,
>>> perhaps we should document what cards can actually take advantage of
>>> this (and how to do so, since it's not set automatically on boot). That
>>> way users wanting tapes at least know what the problems are likely to be
>>> and how to avoid them in their hardware purchasing decisions. The
>>> corollary is that we should likely have a list of not recommended cards:
>>> if they can't go over 128 SG elements, then they're pretty much
>>> unsuitable for modern tapes.
>>
>> Are you implying here that the LSI SAS1068E is unsuitable to drive two
>> LTO-4 tape drives? Or is it 'just' a problem with the driver?
>
> The information seems to be the former. There's no way the kernel can
> guarantee physical contiguity of memory as it operates. We try to
> defrag, but it's probabalistic, not certain, so if we have to try to
> find a physically contiguous buffer to copy into for an operation like
> this, at some point that allocation is going to fail.
What is interesting to me in this regard is how networking with 9K jumbo
frames manages to work acceptably reliable? Jumbo frames used
sufficiently often, including under high memory pressure.
I'm not a deep networking guru, but network drivers need to allocate
physically continual memory for skbs, which means 16K per 9K packet,
which means order 2 allocations per skb.
I guess, it works reliably, because for networking it is OK to drop an
incoming packet and retry allocation for the next one later.
If so, maybe similarly in this case it is worth to not return allocation
error immediately, but retry it several times after few seconds intervals?
Usually tape read/write operations have pretty big timeouts, like 60
seconds. In this time it is possible to retry 10 times in 5 seconds
between retries.
Vlad
> The only way to be certain you can get a 2MB block down to a tape device
> is to be able to transmit the whole thing as a SG list of fully
> discontiguous pages. On a system with 4k pages, that requires 512 SG
> entries. From what I've heard Kashyap say, that can't currently be done
> on the 1068 because of firmware limitations (I'm not entirely clear on
> this, but that's how it sounds to me ... if there is a way of making
> firmware accept more than 128 SG elements per SCSI command, then it is a
> fairly simple driver change). This isn't something we can work around
> in the driver because the transaction can't be split ... it has to go
> down as a single WRITE command with a single output data buffer.
>
> The LSI 1068 is an upgradeable firmware system, so it's always possible
> LSI can come up with a firmware update that increases the size (this
> would also require a corresponding driver change), but it doesn't sound
> to be something that can be done in the driver alone.
>
> James
^ permalink raw reply
* [PATCH] e1000e: convert to stats64
From: Flavio Leitner @ 2010-12-14 20:32 UTC (permalink / raw)
To: netdev; +Cc: e1000-devel, Flavio Leitner
Provides accurate stats at the time user reads them.
Signed-off-by: Flavio Leitner <fleitner@redhat.com>
---
drivers/net/e1000e/e1000.h | 5 ++-
drivers/net/e1000e/ethtool.c | 27 +++++++++-------
drivers/net/e1000e/netdev.c | 68 ++++++++++++++++++++++++-----------------
3 files changed, 59 insertions(+), 41 deletions(-)
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
index fdc67fe..5a5e944 100644
--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/e1000e/e1000.h
@@ -363,6 +363,8 @@ struct e1000_adapter {
/* structs defined in e1000_hw.h */
struct e1000_hw hw;
+ spinlock_t stats64_lock;
+ struct rtnl_link_stats64 stats64;
struct e1000_hw_stats stats;
struct e1000_phy_info phy_info;
struct e1000_phy_stats phy_stats;
@@ -492,7 +494,8 @@ extern int e1000e_setup_rx_resources(struct e1000_adapter *adapter);
extern int e1000e_setup_tx_resources(struct e1000_adapter *adapter);
extern void e1000e_free_rx_resources(struct e1000_adapter *adapter);
extern void e1000e_free_tx_resources(struct e1000_adapter *adapter);
-extern void e1000e_update_stats(struct e1000_adapter *adapter);
+extern void e1000e_update_stats(struct e1000_adapter *adapter,
+ struct rtnl_link_stats64 *net_stats);
extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter);
extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter);
extern void e1000e_disable_aspm(struct pci_dev *pdev, u16 state);
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
index 8984d16..07e4d7c 100644
--- a/drivers/net/e1000e/ethtool.c
+++ b/drivers/net/e1000e/ethtool.c
@@ -49,8 +49,8 @@ struct e1000_stats {
sizeof(((struct e1000_adapter *)0)->m), \
offsetof(struct e1000_adapter, m)
#define E1000_NETDEV_STAT(m) NETDEV_STATS, \
- sizeof(((struct net_device *)0)->m), \
- offsetof(struct net_device, m)
+ sizeof(((struct rtnl_link_stats64 *)0)->m), \
+ offsetof(struct rtnl_link_stats64, m)
static const struct e1000_stats e1000_gstrings_stats[] = {
{ "rx_packets", E1000_STAT(stats.gprc) },
@@ -61,21 +61,21 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
{ "tx_broadcast", E1000_STAT(stats.bptc) },
{ "rx_multicast", E1000_STAT(stats.mprc) },
{ "tx_multicast", E1000_STAT(stats.mptc) },
- { "rx_errors", E1000_NETDEV_STAT(stats.rx_errors) },
- { "tx_errors", E1000_NETDEV_STAT(stats.tx_errors) },
- { "tx_dropped", E1000_NETDEV_STAT(stats.tx_dropped) },
+ { "rx_errors", E1000_NETDEV_STAT(rx_errors) },
+ { "tx_errors", E1000_NETDEV_STAT(tx_errors) },
+ { "tx_dropped", E1000_NETDEV_STAT(tx_dropped) },
{ "multicast", E1000_STAT(stats.mprc) },
{ "collisions", E1000_STAT(stats.colc) },
- { "rx_length_errors", E1000_NETDEV_STAT(stats.rx_length_errors) },
- { "rx_over_errors", E1000_NETDEV_STAT(stats.rx_over_errors) },
+ { "rx_length_errors", E1000_NETDEV_STAT(rx_length_errors) },
+ { "rx_over_errors", E1000_NETDEV_STAT(rx_over_errors) },
{ "rx_crc_errors", E1000_STAT(stats.crcerrs) },
- { "rx_frame_errors", E1000_NETDEV_STAT(stats.rx_frame_errors) },
+ { "rx_frame_errors", E1000_NETDEV_STAT(rx_frame_errors) },
{ "rx_no_buffer_count", E1000_STAT(stats.rnbc) },
{ "rx_missed_errors", E1000_STAT(stats.mpc) },
{ "tx_aborted_errors", E1000_STAT(stats.ecol) },
{ "tx_carrier_errors", E1000_STAT(stats.tncrs) },
- { "tx_fifo_errors", E1000_NETDEV_STAT(stats.tx_fifo_errors) },
- { "tx_heartbeat_errors", E1000_NETDEV_STAT(stats.tx_heartbeat_errors) },
+ { "tx_fifo_errors", E1000_NETDEV_STAT(tx_fifo_errors) },
+ { "tx_heartbeat_errors", E1000_NETDEV_STAT(tx_heartbeat_errors) },
{ "tx_window_errors", E1000_STAT(stats.latecol) },
{ "tx_abort_late_coll", E1000_STAT(stats.latecol) },
{ "tx_deferred_ok", E1000_STAT(stats.dc) },
@@ -1972,14 +1972,16 @@ static void e1000_get_ethtool_stats(struct net_device *netdev,
u64 *data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct rtnl_link_stats64 *net_stats = &adapter->stats64;
int i;
char *p = NULL;
- e1000e_update_stats(adapter);
+ spin_lock(&adapter->stats64_lock);
+ e1000e_update_stats(adapter, net_stats);
for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
switch (e1000_gstrings_stats[i].type) {
case NETDEV_STATS:
- p = (char *) netdev +
+ p = (char *) net_stats +
e1000_gstrings_stats[i].stat_offset;
break;
case E1000_STATS:
@@ -1991,6 +1993,7 @@ static void e1000_get_ethtool_stats(struct net_device *netdev,
data[i] = (e1000_gstrings_stats[i].sizeof_stat ==
sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
}
+ spin_unlock(&adapter->stats64_lock);
}
static void e1000_get_strings(struct net_device *netdev, u32 stringset,
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index c4ca162..0b919ab 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -894,8 +894,6 @@ next_desc:
adapter->total_rx_bytes += total_rx_bytes;
adapter->total_rx_packets += total_rx_packets;
- netdev->stats.rx_bytes += total_rx_bytes;
- netdev->stats.rx_packets += total_rx_packets;
return cleaned;
}
@@ -1051,8 +1049,6 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
}
adapter->total_tx_bytes += total_tx_bytes;
adapter->total_tx_packets += total_tx_packets;
- netdev->stats.tx_bytes += total_tx_bytes;
- netdev->stats.tx_packets += total_tx_packets;
return count < tx_ring->count;
}
@@ -1240,8 +1236,6 @@ next_desc:
adapter->total_rx_bytes += total_rx_bytes;
adapter->total_rx_packets += total_rx_packets;
- netdev->stats.rx_bytes += total_rx_bytes;
- netdev->stats.rx_packets += total_rx_packets;
return cleaned;
}
@@ -1421,8 +1415,6 @@ next_desc:
adapter->total_rx_bytes += total_rx_bytes;
adapter->total_rx_packets += total_rx_packets;
- netdev->stats.rx_bytes += total_rx_bytes;
- netdev->stats.rx_packets += total_rx_packets;
return cleaned;
}
@@ -3367,6 +3359,11 @@ void e1000e_down(struct e1000_adapter *adapter)
del_timer_sync(&adapter->phy_info_timer);
netif_carrier_off(netdev);
+
+ spin_lock(&adapter->stats64_lock);
+ e1000e_update_stats(adapter, &adapter->stats64);
+ spin_unlock(&adapter->stats64_lock);
+
adapter->link_speed = 0;
adapter->link_duplex = 0;
@@ -3408,6 +3405,8 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
+ spin_lock_init(&adapter->stats64_lock);
+
e1000e_set_interrupt_capability(adapter);
if (e1000_alloc_queues(adapter))
@@ -3880,9 +3879,9 @@ release:
* e1000e_update_stats - Update the board statistics counters
* @adapter: board private structure
**/
-void e1000e_update_stats(struct e1000_adapter *adapter)
+void e1000e_update_stats(struct e1000_adapter *adapter,
+ struct rtnl_link_stats64 *net_stats)
{
- struct net_device *netdev = adapter->netdev;
struct e1000_hw *hw = &adapter->hw;
struct pci_dev *pdev = adapter->pdev;
@@ -3950,8 +3949,12 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
adapter->stats.tsctfc += er32(TSCTFC);
/* Fill out the OS statistics structure */
- netdev->stats.multicast = adapter->stats.mprc;
- netdev->stats.collisions = adapter->stats.colc;
+ net_stats->rx_bytes = adapter->stats.gorc;
+ net_stats->rx_packets = adapter->stats.gprc;
+ net_stats->tx_bytes = adapter->stats.gotc;
+ net_stats->tx_packets = adapter->stats.gptc;
+ net_stats->multicast = adapter->stats.mprc;
+ net_stats->collisions = adapter->stats.colc;
/* Rx Errors */
@@ -3959,22 +3962,22 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
* RLEC on some newer hardware can be incorrect so build
* our own version based on RUC and ROC
*/
- netdev->stats.rx_errors = adapter->stats.rxerrc +
+ net_stats->rx_errors = adapter->stats.rxerrc +
adapter->stats.crcerrs + adapter->stats.algnerrc +
adapter->stats.ruc + adapter->stats.roc +
adapter->stats.cexterr;
- netdev->stats.rx_length_errors = adapter->stats.ruc +
+ net_stats->rx_length_errors = adapter->stats.ruc +
adapter->stats.roc;
- netdev->stats.rx_crc_errors = adapter->stats.crcerrs;
- netdev->stats.rx_frame_errors = adapter->stats.algnerrc;
- netdev->stats.rx_missed_errors = adapter->stats.mpc;
+ net_stats->rx_crc_errors = adapter->stats.crcerrs;
+ net_stats->rx_frame_errors = adapter->stats.algnerrc;
+ net_stats->rx_missed_errors = adapter->stats.mpc;
/* Tx Errors */
- netdev->stats.tx_errors = adapter->stats.ecol +
+ net_stats->tx_errors = adapter->stats.ecol +
adapter->stats.latecol;
- netdev->stats.tx_aborted_errors = adapter->stats.ecol;
- netdev->stats.tx_window_errors = adapter->stats.latecol;
- netdev->stats.tx_carrier_errors = adapter->stats.tncrs;
+ net_stats->tx_aborted_errors = adapter->stats.ecol;
+ net_stats->tx_window_errors = adapter->stats.latecol;
+ net_stats->tx_carrier_errors = adapter->stats.tncrs;
/* Tx Dropped needs to be maintained elsewhere */
@@ -4279,7 +4282,9 @@ static void e1000_watchdog_task(struct work_struct *work)
}
link_up:
- e1000e_update_stats(adapter);
+ spin_lock(&adapter->stats64_lock);
+ e1000e_update_stats(adapter, &adapter->stats64);
+ spin_unlock(&adapter->stats64_lock);
mac->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old;
adapter->tpt_old = adapter->stats.tpt;
@@ -4891,16 +4896,23 @@ static void e1000_reset_task(struct work_struct *work)
}
/**
- * e1000_get_stats - Get System Network Statistics
+ * e1000_get_stats64 - Get System Network Statistics
* @netdev: network interface device structure
+ * @stats: rtnl_link_stats64 pointer
*
* Returns the address of the device statistics structure.
- * The statistics are actually updated from the timer callback.
**/
-static struct net_device_stats *e1000_get_stats(struct net_device *netdev)
+static struct rtnl_link_stats64 *e1000_get_stats64(struct net_device *netdev,
+ struct rtnl_link_stats64 *stats)
{
- /* only return the current stats */
- return &netdev->stats;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+
+ spin_lock(&adapter->stats64_lock);
+ e1000e_update_stats(adapter, &adapter->stats64);
+ memcpy(stats, &adapter->stats64, sizeof(*stats));
+ spin_unlock(&adapter->stats64_lock);
+
+ return stats;
}
/**
@@ -5624,7 +5636,7 @@ static const struct net_device_ops e1000e_netdev_ops = {
.ndo_open = e1000_open,
.ndo_stop = e1000_close,
.ndo_start_xmit = e1000_xmit_frame,
- .ndo_get_stats = e1000_get_stats,
+ .ndo_get_stats64 = e1000_get_stats64,
.ndo_set_multicast_list = e1000_set_multi,
.ndo_set_mac_address = e1000_set_mac,
.ndo_change_mtu = e1000_change_mtu,
--
1.7.3.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox