* [patch 1/7] net_device list cleanup: core
@ 2006-07-03 8:18 Andrey Savochkin
2006-07-03 8:18 ` [patch 2/7] net_device list cleanup: proc seq_file output Andrey Savochkin
` (7 more replies)
0 siblings, 8 replies; 18+ messages in thread
From: Andrey Savochkin @ 2006-07-03 8:18 UTC (permalink / raw)
To: netdev; +Cc: Kirill Korotaev, Eric W. Biederman, Alexey Kuznetsov
Cleanup of net_device list use in net_dev core and IP.
The cleanup consists of
- converting the to list_head, to make the list double-linked (thus making
remove operation O(1)), and list walks more readable;
- introducing of for_each_netdev wrapper over list_for_each.
Signed-off-by: Andrey Savochkin <saw@swsoft.com>
Signed-off-by: Kirill Korotaev <dev@openvz.org>
---
include/linux/netdevice.h | 29 ++++++++++++++++++++++++++-
net/core/dev.c | 48 +++++++++++++++++++++++++---------------------
net/ipv4/devinet.c | 6 ++---
net/ipv6/addrconf.c | 8 +++----
net/ipv6/anycast.c | 10 +++++----
5 files changed, 68 insertions(+), 33 deletions(-)
--- ./include/linux/netdevice.h.vedevbase-core Mon Jul 3 15:14:15 2006
+++ ./include/linux/netdevice.h Mon Jul 3 16:09:11 2006
@@ -290,7 +290,8 @@ struct net_device
unsigned long state;
struct net_device *next;
-
+ struct list_head dev_list;
+
/* The device initialization function. Called only once. */
int (*init)(struct net_device *dev);
@@ -558,8 +559,34 @@ struct packet_type {
extern struct net_device loopback_dev; /* The loopback */
extern struct net_device *dev_base; /* All devices */
+extern struct list_head dev_base_head; /* All devices */
extern rwlock_t dev_base_lock; /* Device list lock */
+#define for_each_netdev(p) list_for_each_entry(p, &dev_base_head, dev_list)
+
+/*
+ * When possible, it is preferrable to use for_each_netdev() loop
+ * defined above, rather than first_netdev()/next_netdev() macros.
+ * for_each_netdev() loop makes the intentions clearer, and gives more
+ * flexibility in device list implementation.
+ * While next_netdev() is unavoidable in seq_proc functions,
+ * first_netdev() should be needed quite rarely.
+ */
+#define first_netdev() ({ \
+ list_empty(&dev_base_head) ? NULL : \
+ list_entry(dev_base_head.next, \
+ struct net_device, \
+ dev_list); \
+ })
+#define next_netdev(dev) ({ \
+ struct list_head *__next; \
+ __next = (dev)->dev_list.next; \
+ __next == &dev_base_head ? NULL : \
+ list_entry(__next, \
+ struct net_device, \
+ dev_list); \
+ })
+
extern int netdev_boot_setup_check(struct net_device *dev);
extern unsigned long netdev_boot_base(const char *prefix, int unit);
extern struct net_device *dev_getbyhwaddr(unsigned short type, char *hwaddr);
--- ./net/core/dev.c.vedevbase-core Mon Jul 3 15:14:19 2006
+++ ./net/core/dev.c Mon Jul 3 16:09:11 2006
@@ -181,6 +181,9 @@ DEFINE_RWLOCK(dev_base_lock);
EXPORT_SYMBOL(dev_base);
EXPORT_SYMBOL(dev_base_lock);
+LIST_HEAD(dev_base_head);
+EXPORT_SYMBOL(dev_base_head);
+
#define NETDEV_HASHBITS 8
static struct hlist_head dev_name_head[1<<NETDEV_HASHBITS];
static struct hlist_head dev_index_head[1<<NETDEV_HASHBITS];
@@ -575,11 +578,11 @@ struct net_device *dev_getbyhwaddr(unsig
ASSERT_RTNL();
- for (dev = dev_base; dev; dev = dev->next)
+ for_each_netdev(dev)
if (dev->type == type &&
!memcmp(dev->dev_addr, ha, dev->addr_len))
- break;
- return dev;
+ return dev;
+ return NULL;
}
EXPORT_SYMBOL(dev_getbyhwaddr);
@@ -589,14 +592,15 @@ struct net_device *dev_getfirstbyhwtype(
struct net_device *dev;
rtnl_lock();
- for (dev = dev_base; dev; dev = dev->next) {
+ for_each_netdev(dev) {
if (dev->type == type) {
dev_hold(dev);
- break;
+ rtnl_unlock();
+ return dev;
}
}
rtnl_unlock();
- return dev;
+ return NULL;
}
EXPORT_SYMBOL(dev_getfirstbyhwtype);
@@ -617,14 +621,15 @@ struct net_device * dev_get_by_flags(uns
struct net_device *dev;
read_lock(&dev_base_lock);
- for (dev = dev_base; dev != NULL; dev = dev->next) {
+ for_each_netdev(dev) {
if (((dev->flags ^ if_flags) & mask) == 0) {
dev_hold(dev);
- break;
+ read_unlock(&dev_base_lock);
+ return dev;
}
}
read_unlock(&dev_base_lock);
- return dev;
+ return NULL;
}
/**
@@ -680,7 +685,7 @@ int dev_alloc_name(struct net_device *de
if (!inuse)
return -ENOMEM;
- for (d = dev_base; d; d = d->next) {
+ for_each_netdev(d) {
if (!sscanf(d->name, name, &i))
continue;
if (i < 0 || i >= max_netdevices)
@@ -966,7 +971,7 @@ int register_netdevice_notifier(struct n
rtnl_lock();
err = raw_notifier_chain_register(&netdev_chain, nb);
if (!err) {
- for (dev = dev_base; dev; dev = dev->next) {
+ for_each_netdev(dev) {
nb->notifier_call(nb, NETDEV_REGISTER, dev);
if (dev->flags & IFF_UP)
@@ -2035,7 +2040,7 @@ static int dev_ifconf(char __user *arg)
*/
total = 0;
- for (dev = dev_base; dev; dev = dev->next) {
+ for_each_netdev(dev) {
for (i = 0; i < NPROTO; i++) {
if (gifconf_list[i]) {
int done;
@@ -2974,6 +2979,7 @@ int register_netdevice(struct net_device
write_lock_bh(&dev_base_lock);
*dev_tail = dev;
dev_tail = &dev->next;
+ list_add_tail(&dev->dev_list, &dev_base_head);
hlist_add_head(&dev->name_hlist, head);
hlist_add_head(&dev->index_hlist, dev_index_hash(dev->ifindex));
dev_hold(dev);
@@ -3271,22 +3277,22 @@ int unregister_netdevice(struct net_devi
/* And unlink it from device chain. */
for (dp = &dev_base; (d = *dp) != NULL; dp = &d->next) {
- if (d == dev) {
- write_lock_bh(&dev_base_lock);
- hlist_del(&dev->name_hlist);
- hlist_del(&dev->index_hlist);
- if (dev_tail == &dev->next)
- dev_tail = dp;
- *dp = d->next;
- write_unlock_bh(&dev_base_lock);
+ if (d == dev)
break;
- }
}
if (!d) {
printk(KERN_ERR "unregister net_device: '%s' not found\n",
dev->name);
return -ENODEV;
}
+ write_lock_bh(&dev_base_lock);
+ list_del(&dev->dev_list);
+ hlist_del(&dev->name_hlist);
+ hlist_del(&dev->index_hlist);
+ if (dev_tail == &dev->next)
+ dev_tail = dp;
+ *dp = d->next;
+ write_unlock_bh(&dev_base_lock);
dev->reg_state = NETREG_UNREGISTERING;
--- ./net/ipv4/devinet.c.vedevbase-core Mon Jul 3 15:14:20 2006
+++ ./net/ipv4/devinet.c Mon Jul 3 16:09:11 2006
@@ -841,7 +841,7 @@ no_in_dev:
*/
read_lock(&dev_base_lock);
rcu_read_lock();
- for (dev = dev_base; dev; dev = dev->next) {
+ for_each_netdev(dev) {
if ((in_dev = __in_dev_get_rcu(dev)) == NULL)
continue;
@@ -920,7 +920,7 @@ u32 inet_confirm_addr(const struct net_d
read_lock(&dev_base_lock);
rcu_read_lock();
- for (dev = dev_base; dev; dev = dev->next) {
+ for_each_netdev(dev) {
if ((in_dev = __in_dev_get_rcu(dev))) {
addr = confirm_addr_indev(in_dev, dst, local, scope);
if (addr)
@@ -1170,7 +1170,7 @@ void inet_forward_change(void)
ipv4_devconf_dflt.forwarding = on;
read_lock(&dev_base_lock);
- for (dev = dev_base; dev; dev = dev->next) {
+ for_each_netdev(dev) {
struct in_device *in_dev;
rcu_read_lock();
in_dev = __in_dev_get_rcu(dev);
--- ./net/ipv6/addrconf.c.vedevbase-core Mon Jul 3 15:14:22 2006
+++ ./net/ipv6/addrconf.c Mon Jul 3 16:09:11 2006
@@ -469,7 +469,7 @@ static void addrconf_forward_change(void
struct inet6_dev *idev;
read_lock(&dev_base_lock);
- for (dev=dev_base; dev; dev=dev->next) {
+ for_each_netdev(dev) {
read_lock(&addrconf_lock);
idev = __in6_dev_get(dev);
if (idev) {
@@ -894,7 +894,7 @@ int ipv6_dev_get_saddr(struct net_device
read_lock(&dev_base_lock);
read_lock(&addrconf_lock);
- for (dev = dev_base; dev; dev=dev->next) {
+ for_each_netdev(dev) {
struct inet6_dev *idev;
struct inet6_ifaddr *ifa;
@@ -1979,7 +1979,7 @@ static void sit_add_v4_addrs(struct inet
return;
}
- for (dev = dev_base; dev != NULL; dev = dev->next) {
+ for_each_netdev(dev) {
struct in_device * in_dev = __in_dev_get_rtnl(dev);
if (in_dev && (dev->flags & IFF_UP)) {
struct in_ifaddr * ifa;
@@ -2128,7 +2128,7 @@ static void ip6_tnl_add_linklocal(struct
return;
}
/* then try to inherit it from any device */
- for (link_dev = dev_base; link_dev; link_dev = link_dev->next) {
+ for_each_netdev(link_dev) {
if (!ipv6_inherit_linklocal(idev, link_dev))
return;
}
--- ./net/ipv6/anycast.c.vedevbase-core Mon Jul 3 15:14:22 2006
+++ ./net/ipv6/anycast.c Mon Jul 3 16:09:11 2006
@@ -427,11 +427,13 @@ int ipv6_chk_acast_addr(struct net_devic
if (dev)
return ipv6_chk_acast_dev(dev, addr);
read_lock(&dev_base_lock);
- for (dev=dev_base; dev; dev=dev->next)
- if (ipv6_chk_acast_dev(dev, addr))
- break;
+ for_each_netdev(dev)
+ if (ipv6_chk_acast_dev(dev, addr)) {
+ read_unlock(&dev_base_lock);
+ return 1;
+ }
read_unlock(&dev_base_lock);
- return dev != 0;
+ return 0;
}
^ permalink raw reply [flat|nested] 18+ messages in thread
* [patch 2/7] net_device list cleanup: proc seq_file output
2006-07-03 8:18 [patch 1/7] net_device list cleanup: core Andrey Savochkin
@ 2006-07-03 8:18 ` Andrey Savochkin
2006-07-03 8:18 ` [patch 3/7] net_device list cleanup: netlink_dump Andrey Savochkin
` (6 subsequent siblings)
7 siblings, 0 replies; 18+ messages in thread
From: Andrey Savochkin @ 2006-07-03 8:18 UTC (permalink / raw)
To: netdev; +Cc: Kirill Korotaev, Eric W. Biederman, Alexey Kuznetsov
Cleanup of net_device list use in seq_file output routines in core networking
files. Implementation of /proc/net/dev was copied from dev_mcast, since the
latter did the same in a more compact and cleaner way.
The cleanup consists of
- converting the to list_head, to make the list double-linked (thus making
remove operation O(1)), and list walks more readable;
- introducing of for_each_netdev wrapper over list_for_each.
Signed-off-by: Andrey Savochkin <saw@swsoft.com>
---
Note: functions covered by this patch are good candidates for further
restructuring by introduction of "library" routines for seq_file's showing some
information for each device.
core/dev.c | 23 +++++++++++------------
core/dev_mcast.c | 4 ++--
ipv4/igmp.c | 25 +++++++++++++++----------
ipv6/anycast.c | 12 +++++++-----
ipv6/mcast.c | 25 +++++++++++++++----------
5 files changed, 50 insertions(+), 39 deletions(-)
--- ./net/core/dev.c.vedevbase-proc Mon Jul 3 16:09:54 2006
+++ ./net/core/dev.c Mon Jul 3 16:09:54 2006
@@ -2072,26 +2072,25 @@ static int dev_ifconf(char __user *arg)
* This is invoked by the /proc filesystem handler to display a device
* in detail.
*/
-static __inline__ struct net_device *dev_get_idx(loff_t pos)
-{
- struct net_device *dev;
- loff_t i;
-
- for (i = 0, dev = dev_base; dev && i < pos; ++i, dev = dev->next);
-
- return i == pos ? dev : NULL;
-}
-
void *dev_seq_start(struct seq_file *seq, loff_t *pos)
{
+ struct net_device *dev;
+ loff_t off = 1;
read_lock(&dev_base_lock);
- return *pos ? dev_get_idx(*pos - 1) : SEQ_START_TOKEN;
+ if (!*pos)
+ return SEQ_START_TOKEN;
+ for_each_netdev(dev) {
+ if (off++ == *pos)
+ return dev;
+ }
+ return NULL;
}
void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
+ struct net_device *dev = v;
++*pos;
- return v == SEQ_START_TOKEN ? dev_base : ((struct net_device *)v)->next;
+ return v == SEQ_START_TOKEN ? first_netdev() : next_netdev(dev);
}
void dev_seq_stop(struct seq_file *seq, void *v)
--- ./net/core/dev_mcast.c.vedevbase-proc Mon Jul 3 15:14:19 2006
+++ ./net/core/dev_mcast.c Mon Jul 3 16:09:54 2006
@@ -225,7 +225,7 @@ static void *dev_mc_seq_start(struct seq
loff_t off = 0;
read_lock(&dev_base_lock);
- for (dev = dev_base; dev; dev = dev->next) {
+ for_each_netdev(dev) {
if (off++ == *pos)
return dev;
}
@@ -236,7 +236,7 @@ static void *dev_mc_seq_next(struct seq_
{
struct net_device *dev = v;
++*pos;
- return dev->next;
+ return next_netdev(dev);
}
static void dev_mc_seq_stop(struct seq_file *seq, void *v)
--- ./net/ipv4/igmp.c.vedevbase-proc Mon Jul 3 15:14:20 2006
+++ ./net/ipv4/igmp.c Mon Jul 3 16:09:54 2006
@@ -2254,19 +2254,21 @@ struct igmp_mc_iter_state {
static inline struct ip_mc_list *igmp_mc_get_first(struct seq_file *seq)
{
+ struct net_device *dev;
struct ip_mc_list *im = NULL;
struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq);
- for (state->dev = dev_base, state->in_dev = NULL;
- state->dev;
- state->dev = state->dev->next) {
+ state->dev = NULL;
+ state->in_dev = NULL;
+ for_each_netdev(dev) {
struct in_device *in_dev;
- in_dev = in_dev_get(state->dev);
+ in_dev = in_dev_get(dev);
if (!in_dev)
continue;
read_lock(&in_dev->mc_list_lock);
im = in_dev->mc_list;
if (im) {
+ state->dev = dev;
state->in_dev = in_dev;
break;
}
@@ -2285,7 +2287,7 @@ static struct ip_mc_list *igmp_mc_get_ne
read_unlock(&state->in_dev->mc_list_lock);
in_dev_put(state->in_dev);
}
- state->dev = state->dev->next;
+ state->dev = next_netdev(state->dev);
if (!state->dev) {
state->in_dev = NULL;
break;
@@ -2416,15 +2418,17 @@ struct igmp_mcf_iter_state {
static inline struct ip_sf_list *igmp_mcf_get_first(struct seq_file *seq)
{
+ struct net_device *dev;
struct ip_sf_list *psf = NULL;
struct ip_mc_list *im = NULL;
struct igmp_mcf_iter_state *state = igmp_mcf_seq_private(seq);
- for (state->dev = dev_base, state->idev = NULL, state->im = NULL;
- state->dev;
- state->dev = state->dev->next) {
+ state->dev = NULL;
+ state->im = NULL;
+ state->idev = NULL;
+ for_each_netdev(dev) {
struct in_device *idev;
- idev = in_dev_get(state->dev);
+ idev = in_dev_get(dev);
if (unlikely(idev == NULL))
continue;
read_lock(&idev->mc_list_lock);
@@ -2433,6 +2437,7 @@ static inline struct ip_sf_list *igmp_mc
spin_lock_bh(&im->lock);
psf = im->sources;
if (likely(psf != NULL)) {
+ state->dev = dev;
state->im = im;
state->idev = idev;
break;
@@ -2458,7 +2463,7 @@ static struct ip_sf_list *igmp_mcf_get_n
read_unlock(&state->idev->mc_list_lock);
in_dev_put(state->idev);
}
- state->dev = state->dev->next;
+ state->dev = next_netdev(state->dev);
if (!state->dev) {
state->idev = NULL;
goto out;
--- ./net/ipv6/anycast.c.vedevbase-proc Mon Jul 3 16:09:54 2006
+++ ./net/ipv6/anycast.c Mon Jul 3 16:09:54 2006
@@ -447,19 +447,21 @@ struct ac6_iter_state {
static inline struct ifacaddr6 *ac6_get_first(struct seq_file *seq)
{
+ struct net_device *dev;
struct ifacaddr6 *im = NULL;
struct ac6_iter_state *state = ac6_seq_private(seq);
- for (state->dev = dev_base, state->idev = NULL;
- state->dev;
- state->dev = state->dev->next) {
+ state->dev = NULL;
+ state->idev = NULL;
+ for_each_netdev(dev) {
struct inet6_dev *idev;
- idev = in6_dev_get(state->dev);
+ idev = in6_dev_get(dev);
if (!idev)
continue;
read_lock_bh(&idev->lock);
im = idev->ac_list;
if (im) {
+ state->dev = dev;
state->idev = idev;
break;
}
@@ -478,7 +480,7 @@ static struct ifacaddr6 *ac6_get_next(st
read_unlock_bh(&state->idev->lock);
in6_dev_put(state->idev);
}
- state->dev = state->dev->next;
+ state->dev = next_netdev(state->dev);
if (!state->dev) {
state->idev = NULL;
break;
--- ./net/ipv6/mcast.c.vedevbase-proc Mon Jul 3 15:14:22 2006
+++ ./net/ipv6/mcast.c Mon Jul 3 16:09:54 2006
@@ -2322,19 +2322,21 @@ struct igmp6_mc_iter_state {
static inline struct ifmcaddr6 *igmp6_mc_get_first(struct seq_file *seq)
{
+ struct net_device *dev;
struct ifmcaddr6 *im = NULL;
struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
- for (state->dev = dev_base, state->idev = NULL;
- state->dev;
- state->dev = state->dev->next) {
+ state->dev = NULL;
+ state->idev = NULL;
+ for_each_netdev(dev) {
struct inet6_dev *idev;
- idev = in6_dev_get(state->dev);
+ idev = in6_dev_get(dev);
if (!idev)
continue;
read_lock_bh(&idev->lock);
im = idev->mc_list;
if (im) {
+ state->dev = dev;
state->idev = idev;
break;
}
@@ -2354,7 +2356,7 @@ static struct ifmcaddr6 *igmp6_mc_get_ne
read_unlock_bh(&state->idev->lock);
in6_dev_put(state->idev);
}
- state->dev = state->dev->next;
+ state->dev = next_netdev(state->dev);
if (!state->dev) {
state->idev = NULL;
break;
@@ -2465,15 +2467,17 @@ struct igmp6_mcf_iter_state {
static inline struct ip6_sf_list *igmp6_mcf_get_first(struct seq_file *seq)
{
+ struct net_device *dev;
struct ip6_sf_list *psf = NULL;
struct ifmcaddr6 *im = NULL;
struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq);
- for (state->dev = dev_base, state->idev = NULL, state->im = NULL;
- state->dev;
- state->dev = state->dev->next) {
+ state->dev = NULL;
+ state->im = NULL;
+ state->idev = NULL;
+ for_each_netdev(dev) {
struct inet6_dev *idev;
- idev = in6_dev_get(state->dev);
+ idev = in6_dev_get(dev);
if (unlikely(idev == NULL))
continue;
read_lock_bh(&idev->lock);
@@ -2482,6 +2486,7 @@ static inline struct ip6_sf_list *igmp6_
spin_lock_bh(&im->mca_lock);
psf = im->mca_sources;
if (likely(psf != NULL)) {
+ state->dev = dev;
state->im = im;
state->idev = idev;
break;
@@ -2507,7 +2512,7 @@ static struct ip6_sf_list *igmp6_mcf_get
read_unlock_bh(&state->idev->lock);
in6_dev_put(state->idev);
}
- state->dev = state->dev->next;
+ state->dev = next_netdev(state->dev);
if (!state->dev) {
state->idev = NULL;
goto out;
^ permalink raw reply [flat|nested] 18+ messages in thread
* [patch 3/7] net_device list cleanup: netlink_dump
2006-07-03 8:18 [patch 1/7] net_device list cleanup: core Andrey Savochkin
2006-07-03 8:18 ` [patch 2/7] net_device list cleanup: proc seq_file output Andrey Savochkin
@ 2006-07-03 8:18 ` Andrey Savochkin
2006-07-03 8:18 ` [patch 4/7] net_device list cleanup: drivers and non-IP protocols Andrey Savochkin
` (5 subsequent siblings)
7 siblings, 0 replies; 18+ messages in thread
From: Andrey Savochkin @ 2006-07-03 8:18 UTC (permalink / raw)
To: netdev; +Cc: Kirill Korotaev, Eric W. Biederman, Alexey Kuznetsov
Cleanup of net_device list use in netlink_dump routines in core networking
files.
The cleanup consists of
- converting the to list_head, to make the list double-linked (thus making
remove operation O(1)), and list walks more readable;
- introducing of for_each_netdev wrapper over list_for_each.
Signed-off-by: Andrey Savochkin <saw@swsoft.com>
---
core/rtnetlink.c | 18 ++++++++++--------
ipv4/devinet.c | 14 ++++++++------
ipv6/addrconf.c | 20 +++++++++++++-------
sched/sch_api.c | 8 ++++++--
4 files changed, 37 insertions(+), 23 deletions(-)
--- ./net/core/rtnetlink.c.vedevbase-dump Mon Jul 3 15:14:19 2006
+++ ./net/core/rtnetlink.c Mon Jul 3 16:10:12 2006
@@ -319,14 +319,16 @@ static int rtnetlink_dump_ifinfo(struct
struct net_device *dev;
read_lock(&dev_base_lock);
- for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
- if (idx < s_idx)
- continue;
- if (rtnetlink_fill_ifinfo(skb, dev, RTM_NEWLINK,
- NETLINK_CB(cb->skb).pid,
- cb->nlh->nlmsg_seq, 0,
- NLM_F_MULTI) <= 0)
- break;
+ idx = 0;
+ for_each_netdev(dev) {
+ if (idx >= s_idx) {
+ if (rtnetlink_fill_ifinfo(skb, dev, RTM_NEWLINK,
+ NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq, 0,
+ NLM_F_MULTI) <= 0)
+ break;
+ }
+ idx++;
}
read_unlock(&dev_base_lock);
cb->args[0] = idx;
--- ./net/ipv4/devinet.c.vedevbase-dump Mon Jul 3 16:10:12 2006
+++ ./net/ipv4/devinet.c Mon Jul 3 16:10:12 2006
@@ -1094,18 +1094,17 @@ static int inet_dump_ifaddr(struct sk_bu
struct in_ifaddr *ifa;
int s_ip_idx, s_idx = cb->args[0];
+ idx = 0;
s_ip_idx = ip_idx = cb->args[1];
read_lock(&dev_base_lock);
- for (dev = dev_base, idx = 0; dev; dev = dev->next, idx++) {
+ for_each_netdev(dev) {
if (idx < s_idx)
- continue;
+ goto cont;
if (idx > s_idx)
s_ip_idx = 0;
rcu_read_lock();
- if ((in_dev = __in_dev_get_rcu(dev)) == NULL) {
- rcu_read_unlock();
- continue;
- }
+ if ((in_dev = __in_dev_get_rcu(dev)) == NULL)
+ goto cont_unlock;
for (ifa = in_dev->ifa_list, ip_idx = 0; ifa;
ifa = ifa->ifa_next, ip_idx++) {
@@ -1118,7 +1117,10 @@ static int inet_dump_ifaddr(struct sk_bu
goto done;
}
}
+cont_unlock:
rcu_read_unlock();
+cont:
+ idx++;
}
done:
--- ./net/ipv6/addrconf.c.vedevbase-dump Mon Jul 3 16:10:12 2006
+++ ./net/ipv6/addrconf.c Mon Jul 3 16:10:12 2006
@@ -3013,18 +3013,19 @@ static int inet6_dump_addr(struct sk_buf
struct ifmcaddr6 *ifmca;
struct ifacaddr6 *ifaca;
+ idx = 0;
s_idx = cb->args[0];
s_ip_idx = ip_idx = cb->args[1];
read_lock(&dev_base_lock);
- for (dev = dev_base, idx = 0; dev; dev = dev->next, idx++) {
+ for_each_netdev(dev) {
if (idx < s_idx)
- continue;
+ goto cont;
if (idx > s_idx)
s_ip_idx = 0;
ip_idx = 0;
if ((idev = in6_dev_get(dev)) == NULL)
- continue;
+ goto cont;
read_lock_bh(&idev->lock);
switch (type) {
case UNICAST_ADDR:
@@ -3071,6 +3072,8 @@ static int inet6_dump_addr(struct sk_buf
}
read_unlock_bh(&idev->lock);
in6_dev_put(idev);
+cont:
+ idx++;
}
done:
if (err <= 0) {
@@ -3238,17 +3241,20 @@ static int inet6_dump_ifinfo(struct sk_b
struct net_device *dev;
struct inet6_dev *idev;
+ idx = 0;
read_lock(&dev_base_lock);
- for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
+ for_each_netdev(dev) {
if (idx < s_idx)
- continue;
+ goto cont;
if ((idev = in6_dev_get(dev)) == NULL)
- continue;
+ goto cont;
err = inet6_fill_ifinfo(skb, idev, NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq, RTM_NEWLINK, NLM_F_MULTI);
in6_dev_put(idev);
if (err <= 0)
break;
+cont:
+ idx++;
}
read_unlock(&dev_base_lock);
cb->args[0] = idx;
@@ -3872,7 +3878,7 @@ void __exit addrconf_cleanup(void)
* clean dev list.
*/
- for (dev=dev_base; dev; dev=dev->next) {
+ for_each_netdev(dev) {
if ((idev = __in6_dev_get(dev)) == NULL)
continue;
addrconf_ifdown(dev, 1);
--- ./net/sched/sch_api.c.vedevbase-dump Mon Jul 3 15:14:22 2006
+++ ./net/sched/sch_api.c Mon Jul 3 16:10:12 2006
@@ -829,12 +829,15 @@ static int tc_dump_qdisc(struct sk_buff
struct net_device *dev;
struct Qdisc *q;
+ idx = 0;
s_idx = cb->args[0];
s_q_idx = q_idx = cb->args[1];
read_lock(&dev_base_lock);
- for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
- if (idx < s_idx)
+ for_each_netdev(dev) {
+ if (idx < s_idx) {
+ idx++;
continue;
+ }
if (idx > s_idx)
s_q_idx = 0;
read_lock_bh(&qdisc_tree_lock);
@@ -852,6 +855,7 @@ static int tc_dump_qdisc(struct sk_buff
q_idx++;
}
read_unlock_bh(&qdisc_tree_lock);
+ idx++;
}
done:
^ permalink raw reply [flat|nested] 18+ messages in thread
* [patch 4/7] net_device list cleanup: drivers and non-IP protocols
2006-07-03 8:18 [patch 1/7] net_device list cleanup: core Andrey Savochkin
2006-07-03 8:18 ` [patch 2/7] net_device list cleanup: proc seq_file output Andrey Savochkin
2006-07-03 8:18 ` [patch 3/7] net_device list cleanup: netlink_dump Andrey Savochkin
@ 2006-07-03 8:18 ` Andrey Savochkin
2006-07-07 19:18 ` Stephen Hemminger
2006-07-03 8:18 ` [patch 5/7] net_device list cleanup: arch-dependent code and block devices Andrey Savochkin
` (4 subsequent siblings)
7 siblings, 1 reply; 18+ messages in thread
From: Andrey Savochkin @ 2006-07-03 8:18 UTC (permalink / raw)
To: netdev
Cc: Kirill Korotaev, Eric W. Biederman, Alexey Kuznetsov,
Stuart Cheshire, Ben Greear, Stephen Hemminger, patrick, acme,
ralf, sri, per.liden
Cleanup of net_device list use in network device drivers and protocols
other than IP.
The cleanup consists of
- converting the to list_head, to make the list double-linked (thus making
remove operation O(1)), and list walks more readable;
- introducing of for_each_netdev wrapper over list_for_each.
Signed-off-by: Andrey Savochkin <saw@swsoft.com>
---
Requires "bridge: br_dump_ifinfo index fix"
drivers/net/wireless/strip.c | 4 +---
net/8021q/vlan.c | 4 ++--
net/8021q/vlanproc.c | 10 +++++-----
net/bridge/br_if.c | 4 ++--
net/bridge/br_ioctl.c | 4 +++-
net/bridge/br_netlink.c | 3 ++-
net/decnet/af_decnet.c | 11 +++++++----
net/decnet/dn_dev.c | 17 ++++++++++-------
net/decnet/dn_fib.c | 2 +-
net/decnet/dn_route.c | 13 +++++++------
net/llc/llc_core.c | 7 +++++--
net/netrom/nr_route.c | 5 +++--
net/rose/rose_route.c | 8 +++++---
net/sctp/protocol.c | 2 +-
net/tipc/eth_media.c | 11 +++++++----
15 files changed, 61 insertions(+), 44 deletions(-)
--- ./drivers/net/wireless/strip.c.vedevbase-onet Mon Jul 3 15:13:46 2006
+++ ./drivers/net/wireless/strip.c Mon Jul 3 16:12:11 2006
@@ -1969,8 +1969,7 @@ static struct net_device *get_strip_dev(
sizeof(zero_address))) {
struct net_device *dev;
read_lock_bh(&dev_base_lock);
- dev = dev_base;
- while (dev) {
+ for_each_netdev(dev) {
if (dev->type == strip_info->dev->type &&
!memcmp(dev->dev_addr,
&strip_info->true_dev_addr,
@@ -1981,7 +1980,6 @@ static struct net_device *get_strip_dev(
read_unlock_bh(&dev_base_lock);
return (dev);
}
- dev = dev->next;
}
read_unlock_bh(&dev_base_lock);
}
--- ./net/8021q/vlan.c.vedevbase-onet Mon Jul 3 15:14:17 2006
+++ ./net/8021q/vlan.c Mon Jul 3 16:12:11 2006
@@ -121,8 +121,8 @@ static void __exit vlan_cleanup_devices(
struct net_device *dev, *nxt;
rtnl_lock();
- for (dev = dev_base; dev; dev = nxt) {
- nxt = dev->next;
+ for (dev = first_netdev(); dev; dev = nxt) {
+ nxt = next_netdev(dev);
if (dev->priv_flags & IFF_802_1Q_VLAN) {
unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev,
VLAN_DEV_INFO(dev)->vlan_id);
--- ./net/8021q/vlanproc.c.vedevbase-onet Mon Jul 3 15:14:17 2006
+++ ./net/8021q/vlanproc.c Mon Jul 3 16:12:11 2006
@@ -241,7 +241,7 @@ int vlan_proc_rem_dev(struct net_device
static struct net_device *vlan_skip(struct net_device *dev)
{
while (dev && !(dev->priv_flags & IFF_802_1Q_VLAN))
- dev = dev->next;
+ dev = next_netdev(dev);
return dev;
}
@@ -257,8 +257,8 @@ static void *vlan_seq_start(struct seq_f
if (*pos == 0)
return SEQ_START_TOKEN;
- for (dev = vlan_skip(dev_base); dev && i < *pos;
- dev = vlan_skip(dev->next), ++i);
+ for (dev = vlan_skip(first_netdev()); dev && i < *pos;
+ dev = vlan_skip(next_netdev(dev)), ++i);
return (i == *pos) ? dev : NULL;
}
@@ -268,8 +268,8 @@ static void *vlan_seq_next(struct seq_fi
++*pos;
return vlan_skip((v == SEQ_START_TOKEN)
- ? dev_base
- : ((struct net_device *)v)->next);
+ ? first_netdev()
+ : next_netdev((struct net_device *)v));
}
static void vlan_seq_stop(struct seq_file *seq, void *v)
--- ./net/bridge/br_if.c.vedevbase-onet Mon Jul 3 15:14:19 2006
+++ ./net/bridge/br_if.c Mon Jul 3 16:12:11 2006
@@ -474,8 +474,8 @@ void __exit br_cleanup_bridges(void)
struct net_device *dev, *nxt;
rtnl_lock();
- for (dev = dev_base; dev; dev = nxt) {
- nxt = dev->next;
+ for (dev = first_netdev(); dev; dev = nxt) {
+ nxt = next_netdev(dev);
if (dev->priv_flags & IFF_EBRIDGE)
del_br(dev->priv);
}
--- ./net/bridge/br_ioctl.c.vedevbase-onet Mon Mar 20 08:53:29 2006
+++ ./net/bridge/br_ioctl.c Mon Jul 3 16:12:11 2006
@@ -27,7 +27,9 @@ static int get_bridge_ifindices(int *ind
struct net_device *dev;
int i = 0;
- for (dev = dev_base; dev && i < num; dev = dev->next) {
+ for_each_netdev(dev) {
+ if (i >= num)
+ break;
if (dev->priv_flags & IFF_EBRIDGE)
indices[i++] = dev->ifindex;
}
--- ./net/bridge/br_netlink.c.vedevbase-onet Mon Jul 3 16:12:11 2006
+++ ./net/bridge/br_netlink.c Mon Jul 3 16:12:11 2006
@@ -109,7 +109,8 @@ static int br_dump_ifinfo(struct sk_buff
int err = 0;
read_lock(&dev_base_lock);
- for (dev = dev_base, idx = 0; dev; dev = dev->next) {
+ idx = 0;
+ for_each_netdev(dev) {
struct net_bridge_port *p = dev->br_port;
/* not a bridge port */
--- ./net/decnet/af_decnet.c.vedevbase-onet Mon Jul 3 15:14:19 2006
+++ ./net/decnet/af_decnet.c Mon Jul 3 16:12:11 2006
@@ -720,7 +720,7 @@ static int dn_bind(struct socket *sock,
struct sock *sk = sock->sk;
struct dn_scp *scp = DN_SK(sk);
struct sockaddr_dn *saddr = (struct sockaddr_dn *)uaddr;
- struct net_device *dev;
+ struct net_device *pdev, *dev;
int rv;
if (addr_len != sizeof(struct sockaddr_dn))
@@ -744,12 +744,15 @@ static int dn_bind(struct socket *sock,
if (!(saddr->sdn_flags & SDF_WILD)) {
if (dn_ntohs(saddr->sdn_nodeaddrl)) {
+ dev = NULL;
read_lock(&dev_base_lock);
- for(dev = dev_base; dev; dev = dev->next) {
- if (!dev->dn_ptr)
+ for_each_netdev(pdev) {
+ if (!pdev->dn_ptr)
continue;
- if (dn_dev_islocal(dev, dn_saddr2dn(saddr)))
+ if (dn_dev_islocal(pdev, dn_saddr2dn(saddr))) {
+ dev = pdev;
break;
+ }
}
read_unlock(&dev_base_lock);
if (dev == NULL)
--- ./net/decnet/dn_dev.c.vedevbase-onet Mon Jul 3 15:14:19 2006
+++ ./net/decnet/dn_dev.c Mon Jul 3 16:12:11 2006
@@ -775,13 +775,14 @@ static int dn_dev_dump_ifaddr(struct sk_
s_idx = cb->args[0];
s_dn_idx = dn_idx = cb->args[1];
read_lock(&dev_base_lock);
- for(dev = dev_base, idx = 0; dev; dev = dev->next, idx++) {
+ idx = 0;
+ for_each_netdev(dev) {
if (idx < s_idx)
- continue;
+ goto cont;
if (idx > s_idx)
s_dn_idx = 0;
if ((dn_db = dev->dn_ptr) == NULL)
- continue;
+ goto cont;
for(ifa = dn_db->ifa_list, dn_idx = 0; ifa; ifa = ifa->ifa_next, dn_idx++) {
if (dn_idx < s_dn_idx)
@@ -794,6 +795,8 @@ static int dn_dev_dump_ifaddr(struct sk_
NLM_F_MULTI) <= 0)
goto done;
}
+cont:
+ idx++;
}
done:
read_unlock(&dev_base_lock);
@@ -1264,7 +1267,7 @@ void dn_dev_devices_off(void)
struct net_device *dev;
rtnl_lock();
- for(dev = dev_base; dev; dev = dev->next)
+ for_each_netdev(dev)
dn_dev_down(dev);
rtnl_unlock();
@@ -1275,7 +1278,7 @@ void dn_dev_devices_on(void)
struct net_device *dev;
rtnl_lock();
- for(dev = dev_base; dev; dev = dev->next) {
+ for_each_netdev(dev) {
if (dev->flags & IFF_UP)
dn_dev_up(dev);
}
@@ -1296,7 +1299,7 @@ int unregister_dnaddr_notifier(struct no
static inline struct net_device *dn_dev_get_next(struct seq_file *seq, struct net_device *dev)
{
do {
- dev = dev->next;
+ dev = next_netdev(dev);
} while(dev && !dev->dn_ptr);
return dev;
@@ -1306,7 +1309,7 @@ static struct net_device *dn_dev_get_idx
{
struct net_device *dev;
- dev = dev_base;
+ dev = first_netdev();
if (dev && !dev->dn_ptr)
dev = dn_dev_get_next(seq, dev);
if (pos) {
--- ./net/decnet/dn_fib.c.vedevbase-onet Mon Jul 3 15:14:19 2006
+++ ./net/decnet/dn_fib.c Mon Jul 3 16:12:11 2006
@@ -630,7 +630,7 @@ static void dn_fib_del_ifaddr(struct dn_
/* Scan device list */
read_lock(&dev_base_lock);
- for(dev = dev_base; dev; dev = dev->next) {
+ for_each_netdev(dev) {
dn_db = dev->dn_ptr;
if (dn_db == NULL)
continue;
--- ./net/decnet/dn_route.c.vedevbase-onet Mon Jul 3 15:14:19 2006
+++ ./net/decnet/dn_route.c Mon Jul 3 16:12:47 2006
@@ -922,16 +922,17 @@ static int dn_route_output_slow(struct d
goto out;
}
read_lock(&dev_base_lock);
- for(dev_out = dev_base; dev_out; dev_out = dev_out->next) {
+ for_each_netdev(dev_out) {
if (!dev_out->dn_ptr)
continue;
- if (dn_dev_islocal(dev_out, oldflp->fld_src))
- break;
+ if (dn_dev_islocal(dev_out, oldflp->fld_src)) {
+ dev_hold(dev_out);
+ read_unlock(&dev_base_lock);
+ goto source_ok;
+ }
}
read_unlock(&dev_base_lock);
- if (dev_out == NULL)
- goto out;
- dev_hold(dev_out);
+ goto out;
source_ok:
;
}
--- ./net/llc/llc_core.c.vedevbase-onet Mon Jul 3 15:10:43 2006
+++ ./net/llc/llc_core.c Mon Jul 3 16:12:11 2006
@@ -161,8 +161,11 @@ static struct packet_type llc_tr_packet_
static int __init llc_init(void)
{
- if (dev_base->next)
- memcpy(llc_station_mac_sa, dev_base->next->dev_addr, ETH_ALEN);
+ struct net_device *dev;
+
+ dev = next_netdev(first_netdev());
+ if (dev)
+ memcpy(llc_station_mac_sa, dev->dev_addr, ETH_ALEN);
else
memset(llc_station_mac_sa, 0, ETH_ALEN);
dev_add_pack(&llc_packet_type);
--- ./net/netrom/nr_route.c.vedevbase-onet Mon Jul 3 15:14:22 2006
+++ ./net/netrom/nr_route.c Mon Jul 3 16:12:11 2006
@@ -595,7 +595,7 @@ struct net_device *nr_dev_first(void)
struct net_device *dev, *first = NULL;
read_lock(&dev_base_lock);
- for (dev = dev_base; dev != NULL; dev = dev->next) {
+ for_each_netdev(dev) {
if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM)
if (first == NULL || strncmp(dev->name, first->name, 3) < 0)
first = dev;
@@ -615,12 +615,13 @@ struct net_device *nr_dev_get(ax25_addre
struct net_device *dev;
read_lock(&dev_base_lock);
- for (dev = dev_base; dev != NULL; dev = dev->next) {
+ for_each_netdev(dev) {
if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM && ax25cmp(addr, (ax25_address *)dev->dev_addr) == 0) {
dev_hold(dev);
goto out;
}
}
+ dev = NULL;
out:
read_unlock(&dev_base_lock);
return dev;
--- ./net/rose/rose_route.c.vedevbase-onet Mon Jul 3 15:10:43 2006
+++ ./net/rose/rose_route.c Mon Jul 3 16:12:11 2006
@@ -600,7 +600,7 @@ struct net_device *rose_dev_first(void)
struct net_device *dev, *first = NULL;
read_lock(&dev_base_lock);
- for (dev = dev_base; dev != NULL; dev = dev->next) {
+ for_each_netdev(dev) {
if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE)
if (first == NULL || strncmp(dev->name, first->name, 3) < 0)
first = dev;
@@ -618,12 +618,13 @@ struct net_device *rose_dev_get(rose_add
struct net_device *dev;
read_lock(&dev_base_lock);
- for (dev = dev_base; dev != NULL; dev = dev->next) {
+ for_each_netdev(dev) {
if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE && rosecmp(addr, (rose_address *)dev->dev_addr) == 0) {
dev_hold(dev);
goto out;
}
}
+ dev = NULL;
out:
read_unlock(&dev_base_lock);
return dev;
@@ -634,10 +635,11 @@ static int rose_dev_exists(rose_address
struct net_device *dev;
read_lock(&dev_base_lock);
- for (dev = dev_base; dev != NULL; dev = dev->next) {
+ for_each_netdev(dev) {
if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE && rosecmp(addr, (rose_address *)dev->dev_addr) == 0)
goto out;
}
+ dev = NULL;
out:
read_unlock(&dev_base_lock);
return dev != NULL;
--- ./net/sctp/protocol.c.vedevbase-onet Mon Jul 3 15:14:22 2006
+++ ./net/sctp/protocol.c Mon Jul 3 16:12:11 2006
@@ -177,7 +177,7 @@ static void __sctp_get_local_addr_list(v
struct sctp_af *af;
read_lock(&dev_base_lock);
- for (dev = dev_base; dev; dev = dev->next) {
+ for_each_netdev(dev) {
__list_for_each(pos, &sctp_address_families) {
af = list_entry(pos, struct sctp_af, list);
af->copy_addrlist(&sctp_local_addr_list, dev);
--- ./net/tipc/eth_media.c.vedevbase-onet Mon Jul 3 15:14:23 2006
+++ ./net/tipc/eth_media.c Mon Jul 3 16:14:31 2006
@@ -120,16 +120,19 @@ static int recv_msg(struct sk_buff *buf,
static int enable_bearer(struct tipc_bearer *tb_ptr)
{
- struct net_device *dev = dev_base;
+ struct net_device *pdev, *dev;
struct eth_bearer *eb_ptr = ð_bearers[0];
struct eth_bearer *stop = ð_bearers[MAX_ETH_BEARERS];
char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1;
/* Find device with specified name */
- while (dev && dev->name && strncmp(dev->name, driver_name, IFNAMSIZ)) {
- dev = dev->next;
- }
+ dev = NULL;
+ for_each_netdev(pdev)
+ if (pdev->name && !strncmp(pdev->name, driver_name, IFNAMSIZ)) {
+ dev = pdev;
+ break;
+ }
if (!dev)
return -ENODEV;
^ permalink raw reply [flat|nested] 18+ messages in thread
* [patch 5/7] net_device list cleanup: arch-dependent code and block devices
2006-07-03 8:18 [patch 1/7] net_device list cleanup: core Andrey Savochkin
` (2 preceding siblings ...)
2006-07-03 8:18 ` [patch 4/7] net_device list cleanup: drivers and non-IP protocols Andrey Savochkin
@ 2006-07-03 8:18 ` Andrey Savochkin
2006-07-03 8:18 ` [patch 6/7] net_device list cleanup: dev_base removal Andrey Savochkin
` (3 subsequent siblings)
7 siblings, 0 replies; 18+ messages in thread
From: Andrey Savochkin @ 2006-07-03 8:18 UTC (permalink / raw)
To: netdev
Cc: Kirill Korotaev, Eric W. Biederman, Alexey Kuznetsov,
Gerald Schaefer, schwidefsky, davem, ecashin, matthew
Cleanup of net_device list use in arch-dependent code and block devices.
The cleanup consists of
- converting the to list_head, to make the list double-linked (thus making
remove operation O(1)), and list walks more readable;
- introducing of for_each_netdev wrapper over list_for_each.
Signed-off-by: Andrey Savochkin <saw@swsoft.com>
---
arch/s390/appldata/appldata_net_sum.c | 2 +-
arch/sparc64/solaris/ioctl.c | 2 +-
drivers/block/aoe/aoecmd.c | 8 ++++++--
drivers/parisc/led.c | 2 +-
4 files changed, 9 insertions(+), 5 deletions(-)
--- ./arch/s390/appldata/appldata_net_sum.c.vedevbase-misc Mon Jul 3 15:13:15 2006
+++ ./arch/s390/appldata/appldata_net_sum.c Mon Jul 3 16:16:05 2006
@@ -107,7 +107,7 @@ static void appldata_get_net_sum_data(vo
tx_dropped = 0;
collisions = 0;
read_lock(&dev_base_lock);
- for (dev = dev_base; dev != NULL; dev = dev->next) {
+ for_each_netdev(dev) {
if (dev->get_stats == NULL) {
continue;
}
--- ./arch/sparc64/solaris/ioctl.c.vedevbase-misc Mon Mar 20 08:53:29 2006
+++ ./arch/sparc64/solaris/ioctl.c Mon Jul 3 16:16:05 2006
@@ -686,7 +686,7 @@ static inline int solaris_i(unsigned int
int i = 0;
read_lock_bh(&dev_base_lock);
- for (d = dev_base; d; d = d->next) i++;
+ for_each_netdev(d) i++;
read_unlock_bh(&dev_base_lock);
if (put_user (i, (int __user *)A(arg)))
--- ./drivers/block/aoe/aoecmd.c.vedevbase-misc Mon Jul 3 15:09:57 2006
+++ ./drivers/block/aoe/aoecmd.c Mon Jul 3 16:16:05 2006
@@ -204,14 +204,17 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigne
sl = sl_tail = NULL;
read_lock(&dev_base_lock);
- for (ifp = dev_base; ifp; dev_put(ifp), ifp = ifp->next) {
+ for_each_netdev(ifp) {
dev_hold(ifp);
- if (!is_aoe_netif(ifp))
+ if (!is_aoe_netif(ifp)) {
+ dev_put(ifp);
continue;
+ }
skb = new_skb(ifp, sizeof *h + sizeof *ch);
if (skb == NULL) {
printk(KERN_INFO "aoe: aoecmd_cfg: skb alloc failure\n");
+ dev_put(ifp);
continue;
}
if (sl_tail == NULL)
@@ -229,6 +232,7 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigne
skb->next = sl;
sl = skb;
+ dev_put(ifp);
}
read_unlock(&dev_base_lock);
--- ./drivers/parisc/led.c.vedevbase-misc Mon Jul 3 15:13:46 2006
+++ ./drivers/parisc/led.c Mon Jul 3 16:16:05 2006
@@ -367,7 +367,7 @@ static __inline__ int led_get_net_activi
* for reading should be OK */
read_lock(&dev_base_lock);
rcu_read_lock();
- for (dev = dev_base; dev; dev = dev->next) {
+ for_each_netdev(dev) {
struct net_device_stats *stats;
struct in_device *in_dev = __in_dev_get_rcu(dev);
if (!in_dev || !in_dev->ifa_list)
^ permalink raw reply [flat|nested] 18+ messages in thread
* [patch 6/7] net_device list cleanup: dev_base removal
2006-07-03 8:18 [patch 1/7] net_device list cleanup: core Andrey Savochkin
` (3 preceding siblings ...)
2006-07-03 8:18 ` [patch 5/7] net_device list cleanup: arch-dependent code and block devices Andrey Savochkin
@ 2006-07-03 8:18 ` Andrey Savochkin
2006-07-03 8:18 ` [patch 7/7] net_device list cleanup: debugging Andrey Savochkin
` (2 subsequent siblings)
7 siblings, 0 replies; 18+ messages in thread
From: Andrey Savochkin @ 2006-07-03 8:18 UTC (permalink / raw)
To: netdev; +Cc: Kirill Korotaev, Eric W. Biederman, Alexey Kuznetsov
Removal of dev_base and dev_tail variables as a part of net_device list
cleanup.
The cleanup consists of
- converting the to list_head, to make the list double-linked (thus making
remove operation O(1)), and list walks more readable;
- introducing of for_each_netdev wrapper over list_for_each.
Signed-off-by: Andrey Savochkin <saw@swsoft.com>
---
include/linux/netdevice.h | 2 --
net/core/dev.c | 21 ---------------------
2 files changed, 23 deletions(-)
--- ./include/linux/netdevice.h.vedevbase-fin Mon Jul 3 16:16:28 2006
+++ ./include/linux/netdevice.h Mon Jul 3 16:16:28 2006
@@ -289,7 +289,6 @@ struct net_device
unsigned long state;
- struct net_device *next;
struct list_head dev_list;
/* The device initialization function. Called only once. */
@@ -558,7 +557,6 @@ struct packet_type {
#include <linux/notifier.h>
extern struct net_device loopback_dev; /* The loopback */
-extern struct net_device *dev_base; /* All devices */
extern struct list_head dev_base_head; /* All devices */
extern rwlock_t dev_base_lock; /* Device list lock */
--- ./net/core/dev.c.vedevbase-fin Mon Jul 3 16:16:28 2006
+++ ./net/core/dev.c Mon Jul 3 16:16:28 2006
@@ -174,11 +174,7 @@ static spinlock_t net_dma_event_lock;
* unregister_netdevice(), which must be called with the rtnl
* semaphore held.
*/
-struct net_device *dev_base;
-static struct net_device **dev_tail = &dev_base;
DEFINE_RWLOCK(dev_base_lock);
-
-EXPORT_SYMBOL(dev_base);
EXPORT_SYMBOL(dev_base_lock);
LIST_HEAD(dev_base_head);
@@ -2973,11 +2969,8 @@ int register_netdevice(struct net_device
set_bit(__LINK_STATE_PRESENT, &dev->state);
- dev->next = NULL;
dev_init_scheduler(dev);
write_lock_bh(&dev_base_lock);
- *dev_tail = dev;
- dev_tail = &dev->next;
list_add_tail(&dev->dev_list, &dev_base_head);
hlist_add_head(&dev->name_hlist, head);
hlist_add_head(&dev->index_hlist, dev_index_hash(dev->ifindex));
@@ -3256,8 +3249,6 @@ void synchronize_net(void)
int unregister_netdevice(struct net_device *dev)
{
- struct net_device *d, **dp;
-
BUG_ON(dev_boot_phase);
ASSERT_RTNL();
@@ -3275,22 +3266,10 @@ int unregister_netdevice(struct net_devi
dev_close(dev);
/* And unlink it from device chain. */
- for (dp = &dev_base; (d = *dp) != NULL; dp = &d->next) {
- if (d == dev)
- break;
- }
- if (!d) {
- printk(KERN_ERR "unregister net_device: '%s' not found\n",
- dev->name);
- return -ENODEV;
- }
write_lock_bh(&dev_base_lock);
list_del(&dev->dev_list);
hlist_del(&dev->name_hlist);
hlist_del(&dev->index_hlist);
- if (dev_tail == &dev->next)
- dev_tail = dp;
- *dp = d->next;
write_unlock_bh(&dev_base_lock);
dev->reg_state = NETREG_UNREGISTERING;
^ permalink raw reply [flat|nested] 18+ messages in thread
* [patch 7/7] net_device list cleanup: debugging
2006-07-03 8:18 [patch 1/7] net_device list cleanup: core Andrey Savochkin
` (4 preceding siblings ...)
2006-07-03 8:18 ` [patch 6/7] net_device list cleanup: dev_base removal Andrey Savochkin
@ 2006-07-03 8:18 ` Andrey Savochkin
2006-07-03 17:46 ` [patch 1/7] net_device list cleanup: core Christoph Hellwig
2006-07-07 4:34 ` YOSHIFUJI Hideaki / 吉藤英明
7 siblings, 0 replies; 18+ messages in thread
From: Andrey Savochkin @ 2006-07-03 8:18 UTC (permalink / raw)
To: netdev; +Cc: Kirill Korotaev, Eric W. Biederman, Alexey Kuznetsov
Optional code to catch cases when loop cursor is used after for_each_netdev
loop: often it's a sign of a bug, since it isn't guaranteed to point to a
device.
Signed-off-by: Andrey Savochkin <saw@swsoft.com>
---
If anyone wants to keep this under some debug config option,
let me know which one.
netdevice.h | 8 +++++++-
1 files changed, 7 insertions(+), 1 deletion(-)
--- ./include/linux/netdevice.h.vedevbase-dbg Mon Jul 3 16:16:51 2006
+++ ./include/linux/netdevice.h Mon Jul 3 16:16:51 2006
@@ -560,7 +560,13 @@ extern struct net_device loopback_dev;
extern struct list_head dev_base_head; /* All devices */
extern rwlock_t dev_base_lock; /* Device list lock */
-#define for_each_netdev(p) list_for_each_entry(p, &dev_base_head, dev_list)
+#define for_each_netdev(pos) \
+for (pos = list_entry(dev_base_head.next, typeof(*pos), dev_list); \
+ prefetch(pos->dev_list.next), \
+ &pos->dev_list != &dev_base_head ? : \
+ ({ void *__check_dev_use_after_for_each_netdev; \
+ pos = __check_dev_use_after_for_each_netdev; 0; }); \
+ pos = list_entry(pos->dev_list.next, typeof(*pos), dev_list))
/*
* When possible, it is preferrable to use for_each_netdev() loop
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [patch 1/7] net_device list cleanup: core
2006-07-03 8:18 [patch 1/7] net_device list cleanup: core Andrey Savochkin
` (5 preceding siblings ...)
2006-07-03 8:18 ` [patch 7/7] net_device list cleanup: debugging Andrey Savochkin
@ 2006-07-03 17:46 ` Christoph Hellwig
2006-07-04 7:24 ` Andrey Savochkin
2006-07-07 4:34 ` YOSHIFUJI Hideaki / 吉藤英明
7 siblings, 1 reply; 18+ messages in thread
From: Christoph Hellwig @ 2006-07-03 17:46 UTC (permalink / raw)
To: Andrey Savochkin
Cc: netdev, Kirill Korotaev, Eric W. Biederman, Alexey Kuznetsov
On Mon, Jul 03, 2006 at 12:18:51PM +0400, Andrey Savochkin wrote:
> Cleanup of net_device list use in net_dev core and IP.
> The cleanup consists of
> - converting the to list_head, to make the list double-linked (thus making
> remove operation O(1)), and list walks more readable;
> - introducing of for_each_netdev wrapper over list_for_each.
When you change all this please make sure dev_base_head is never directly
accessed anymore, not even through macros and dev_base_head is not exported
anymore. That's the only way to keep drivers messing with it.
Yes, it's a little more work as you need to audit all drivers to see what
they are doing and find suitable abstractions but it's a must have that
should have been done a lot earlier.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [patch 1/7] net_device list cleanup: core
2006-07-03 17:46 ` [patch 1/7] net_device list cleanup: core Christoph Hellwig
@ 2006-07-04 7:24 ` Andrey Savochkin
2006-07-04 9:10 ` Christoph Hellwig
0 siblings, 1 reply; 18+ messages in thread
From: Andrey Savochkin @ 2006-07-04 7:24 UTC (permalink / raw)
To: Christoph Hellwig
Cc: netdev, Kirill Korotaev, Eric W. Biederman, Alexey Kuznetsov
Christoph,
On Mon, Jul 03, 2006 at 06:46:50PM +0100, Christoph Hellwig wrote:
> On Mon, Jul 03, 2006 at 12:18:51PM +0400, Andrey Savochkin wrote:
> > Cleanup of net_device list use in net_dev core and IP.
> > The cleanup consists of
> > - converting the to list_head, to make the list double-linked (thus making
> > remove operation O(1)), and list walks more readable;
> > - introducing of for_each_netdev wrapper over list_for_each.
>
> When you change all this please make sure dev_base_head is never directly
> accessed anymore, not even through macros and dev_base_head is not exported
> anymore. That's the only way to keep drivers messing with it.
>
> Yes, it's a little more work as you need to audit all drivers to see what
> they are doing and find suitable abstractions but it's a must have that
> should have been done a lot earlier.
Hiding dev_base_head can be done by converting first_netdev/next_netdev into
functions and implementing for_each_netdev loop through them.
Or are you talking about abstractions like functions
for_each_netdev/find_netdev with callbacks?
Do you think that hiding the list internals is worth the additional
complexity and substantial increase of the patch size?
Andrey
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [patch 1/7] net_device list cleanup: core
2006-07-04 7:24 ` Andrey Savochkin
@ 2006-07-04 9:10 ` Christoph Hellwig
2006-07-04 14:50 ` Andrey Savochkin
0 siblings, 1 reply; 18+ messages in thread
From: Christoph Hellwig @ 2006-07-04 9:10 UTC (permalink / raw)
To: Andrey Savochkin
Cc: Christoph Hellwig, netdev, Kirill Korotaev, Eric W. Biederman,
Alexey Kuznetsov
On Tue, Jul 04, 2006 at 11:24:05AM +0400, Andrey Savochkin wrote:
> > Yes, it's a little more work as you need to audit all drivers to see what
> > they are doing and find suitable abstractions but it's a must have that
> > should have been done a lot earlier.
>
> Hiding dev_base_head can be done by converting first_netdev/next_netdev into
> functions and implementing for_each_netdev loop through them.
>
> Or are you talking about abstractions like functions
> for_each_netdev/find_netdev with callbacks?
an for_each_netdev with a callback makes sense and gives a cleaner
abstraction, yes. I don't think you should need a callback for the lookup
structure.
> Do you think that hiding the list internals is worth the additional
> complexity and substantial increase of the patch size?
Yes, absolutely. We've converted scsi hosts and devices from a model
where drivers could directly access the list to strict iterators in the
2.5 series. It's quite a lot of work as you have to understand what
the drivers actually do (and to at least 50% they were doing something
really stupid) and convert them to the right abstractions.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [patch 1/7] net_device list cleanup: core
2006-07-04 9:10 ` Christoph Hellwig
@ 2006-07-04 14:50 ` Andrey Savochkin
2006-07-04 16:35 ` Alexey Kuznetsov
0 siblings, 1 reply; 18+ messages in thread
From: Andrey Savochkin @ 2006-07-04 14:50 UTC (permalink / raw)
To: Christoph Hellwig
Cc: netdev, Kirill Korotaev, Eric W. Biederman, Alexey Kuznetsov
On Tue, Jul 04, 2006 at 10:10:03AM +0100, Christoph Hellwig wrote:
> On Tue, Jul 04, 2006 at 11:24:05AM +0400, Andrey Savochkin wrote:
> > > Yes, it's a little more work as you need to audit all drivers to see what
> > > they are doing and find suitable abstractions but it's a must have that
> > > should have been done a lot earlier.
> >
> > Hiding dev_base_head can be done by converting first_netdev/next_netdev into
> > functions and implementing for_each_netdev loop through them.
> >
> > Or are you talking about abstractions like functions
> > for_each_netdev/find_netdev with callbacks?
>
> an for_each_netdev with a callback makes sense and gives a cleaner
> abstraction, yes. I don't think you should need a callback for the lookup
> structure.
Different modules want different kinds of lookup.
So, I'm thinking about something like ilookup5.
>
> > Do you think that hiding the list internals is worth the additional
> > complexity and substantial increase of the patch size?
>
> Yes, absolutely. We've converted scsi hosts and devices from a model
> where drivers could directly access the list to strict iterators in the
> 2.5 series. It's quite a lot of work as you have to understand what
> the drivers actually do (and to at least 50% they were doing something
> really stupid) and convert them to the right abstractions.
The next question: would people agree to review a patch doing this for
net_devices? :)
Andrey
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [patch 1/7] net_device list cleanup: core
2006-07-04 14:50 ` Andrey Savochkin
@ 2006-07-04 16:35 ` Alexey Kuznetsov
2006-07-05 8:26 ` Andrey Savochkin
0 siblings, 1 reply; 18+ messages in thread
From: Alexey Kuznetsov @ 2006-07-04 16:35 UTC (permalink / raw)
To: Andrey Savochkin
Cc: Christoph Hellwig, netdev, Kirill Korotaev, Eric W. Biederman
Hello!
> Different modules want different kinds of lookup.
> So, I'm thinking about something like ilookup5.
....
> The next question: would people agree to review a patch doing this for
> net_devices? :)
One not original suggestion, which did not sound nevertheless:
to implement netdev_iterate_list() or whatever, update only core
and a few of devices and deprecate dev_base_head
with __deprecated_for_modules adding it to
Documentation/feature-removal-schedule.txt
Alexey
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [patch 1/7] net_device list cleanup: core
2006-07-04 16:35 ` Alexey Kuznetsov
@ 2006-07-05 8:26 ` Andrey Savochkin
0 siblings, 0 replies; 18+ messages in thread
From: Andrey Savochkin @ 2006-07-05 8:26 UTC (permalink / raw)
To: Alexey Kuznetsov
Cc: Christoph Hellwig, netdev, Kirill Korotaev, Eric W. Biederman
On Tue, Jul 04, 2006 at 08:35:37PM +0400, A.N.Kuznetsov wrote:
>
> > Different modules want different kinds of lookup.
> > So, I'm thinking about something like ilookup5.
> ....
> > The next question: would people agree to review a patch doing this for
> > net_devices? :)
>
> One not original suggestion, which did not sound nevertheless:
> to implement netdev_iterate_list() or whatever, update only core
> and a few of devices and deprecate dev_base_head
> with __deprecated_for_modules adding it to
> Documentation/feature-removal-schedule.txt
I like this idea
Andrey
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [patch 1/7] net_device list cleanup: core
2006-07-03 8:18 [patch 1/7] net_device list cleanup: core Andrey Savochkin
` (6 preceding siblings ...)
2006-07-03 17:46 ` [patch 1/7] net_device list cleanup: core Christoph Hellwig
@ 2006-07-07 4:34 ` YOSHIFUJI Hideaki / 吉藤英明
2006-07-07 7:54 ` Andrey Savochkin
7 siblings, 1 reply; 18+ messages in thread
From: YOSHIFUJI Hideaki / 吉藤英明 @ 2006-07-07 4:34 UTC (permalink / raw)
To: saw; +Cc: netdev, dev, ebiederm, kuznet, yoshfuji
In article <20060630150823.A22285@castle.nmd.msu.ru> (at Mon, 3 Jul 2006 12:18:51 +0400), Andrey Savochkin <saw@swsoft.com> says:
> @@ -3271,22 +3277,22 @@ int unregister_netdevice(struct net_devi
>
> /* And unlink it from device chain. */
> for (dp = &dev_base; (d = *dp) != NULL; dp = &d->next) {
Why not for_each_netdev?
--yoshfuji
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [patch 1/7] net_device list cleanup: core
2006-07-07 4:34 ` YOSHIFUJI Hideaki / 吉藤英明
@ 2006-07-07 7:54 ` Andrey Savochkin
2006-07-07 16:48 ` YOSHIFUJI Hideaki / 吉藤英明
0 siblings, 1 reply; 18+ messages in thread
From: Andrey Savochkin @ 2006-07-07 7:54 UTC (permalink / raw)
To: YOSHIFUJI Hideaki / ?$B5HF#1QL@?(B; +Cc: netdev, dev, ebiederm, kuznet
On Fri, Jul 07, 2006 at 01:34:34PM +0900, YOSHIFUJI Hideaki / ?$B5HF#1QL@?(B wrote:
> In article <20060630150823.A22285@castle.nmd.msu.ru> (at Mon, 3 Jul 2006 12:18:51 +0400), Andrey Savochkin <saw@swsoft.com> says:
>
> > @@ -3271,22 +3277,22 @@ int unregister_netdevice(struct net_devi
> >
> > /* And unlink it from device chain. */
> > for (dp = &dev_base; (d = *dp) != NULL; dp = &d->next) {
>
> Why not for_each_netdev?
it's a different list
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [patch 1/7] net_device list cleanup: core
2006-07-07 7:54 ` Andrey Savochkin
@ 2006-07-07 16:48 ` YOSHIFUJI Hideaki / 吉藤英明
2006-07-10 6:53 ` Andrey Savochkin
0 siblings, 1 reply; 18+ messages in thread
From: YOSHIFUJI Hideaki / 吉藤英明 @ 2006-07-07 16:48 UTC (permalink / raw)
To: saw; +Cc: netdev, dev, ebiederm, kuznet, yoshfuji
In article <20060707115425.A28991@castle.nmd.msu.ru> (at Fri, 7 Jul 2006 11:54:25 +0400), Andrey Savochkin <saw@swsoft.com> says:
> On Fri, Jul 07, 2006 at 01:34:34PM +0900, YOSHIFUJI Hideaki / ?$B5HF#1QL@?(B wrote:
> > In article <20060630150823.A22285@castle.nmd.msu.ru> (at Mon, 3 Jul 2006 12:18:51 +0400), Andrey Savochkin <saw@swsoft.com> says:
> >
> > > @@ -3271,22 +3277,22 @@ int unregister_netdevice(struct net_devi
> > >
> > > /* And unlink it from device chain. */
> > > for (dp = &dev_base; (d = *dp) != NULL; dp = &d->next) {
> >
> > Why not for_each_netdev?
>
> it's a different list
Sorry, I still do not understand.
In other words, why will we still have dev->next?
After introducing net_device->dev_list, we do not need
dev->next anymore, do we?
--yoshfuji
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [patch 4/7] net_device list cleanup: drivers and non-IP protocols
2006-07-03 8:18 ` [patch 4/7] net_device list cleanup: drivers and non-IP protocols Andrey Savochkin
@ 2006-07-07 19:18 ` Stephen Hemminger
0 siblings, 0 replies; 18+ messages in thread
From: Stephen Hemminger @ 2006-07-07 19:18 UTC (permalink / raw)
To: Andrey Savochkin; +Cc: netdev
On Mon, 3 Jul 2006 12:18:54 +0400
Andrey Savochkin <saw@swsoft.com> wrote:
> Cleanup of net_device list use in network device drivers and protocols
> other than IP.
>
> The cleanup consists of
> - converting the to list_head, to make the list double-linked (thus making
> remove operation O(1)), and list walks more readable;
Maybe this should be RCU'd to get rid of the read_lock.
> - introducing of for_each_netdev wrapper over list_for_each.
>
> Signed-off-by: Andrey Savochkin <saw@swsoft.com>
Looks good thanks.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [patch 1/7] net_device list cleanup: core
2006-07-07 16:48 ` YOSHIFUJI Hideaki / 吉藤英明
@ 2006-07-10 6:53 ` Andrey Savochkin
0 siblings, 0 replies; 18+ messages in thread
From: Andrey Savochkin @ 2006-07-10 6:53 UTC (permalink / raw)
To: YOSHIFUJI Hideaki / ?$B5HF#1QL@?(B; +Cc: netdev, dev, ebiederm, kuznet
On Sat, Jul 08, 2006 at 01:48:13AM +0900, YOSHIFUJI Hideaki / ?$B5HF#1QL@?(B wrote:
> In article <20060707115425.A28991@castle.nmd.msu.ru> (at Fri, 7 Jul 2006 11:54:25 +0400), Andrey Savochkin <saw@swsoft.com> says:
>
> > On Fri, Jul 07, 2006 at 01:34:34PM +0900, YOSHIFUJI Hideaki / ?$B5HF#1QL@?(B wrote:
> > > In article <20060630150823.A22285@castle.nmd.msu.ru> (at Mon, 3 Jul 2006 12:18:51 +0400), Andrey Savochkin <saw@swsoft.com> says:
> > >
> > > > @@ -3271,22 +3277,22 @@ int unregister_netdevice(struct net_devi
> > > >
> > > > /* And unlink it from device chain. */
> > > > for (dp = &dev_base; (d = *dp) != NULL; dp = &d->next) {
> > >
> > > Why not for_each_netdev?
> >
> > it's a different list
>
> Sorry, I still do not understand.
> In other words, why will we still have dev->next?
> After introducing net_device->dev_list, we do not need
> dev->next anymore, do we?
dev->next is removed in the last patch, to make possible the bisection
of patch list.
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2006-07-10 6:53 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-07-03 8:18 [patch 1/7] net_device list cleanup: core Andrey Savochkin
2006-07-03 8:18 ` [patch 2/7] net_device list cleanup: proc seq_file output Andrey Savochkin
2006-07-03 8:18 ` [patch 3/7] net_device list cleanup: netlink_dump Andrey Savochkin
2006-07-03 8:18 ` [patch 4/7] net_device list cleanup: drivers and non-IP protocols Andrey Savochkin
2006-07-07 19:18 ` Stephen Hemminger
2006-07-03 8:18 ` [patch 5/7] net_device list cleanup: arch-dependent code and block devices Andrey Savochkin
2006-07-03 8:18 ` [patch 6/7] net_device list cleanup: dev_base removal Andrey Savochkin
2006-07-03 8:18 ` [patch 7/7] net_device list cleanup: debugging Andrey Savochkin
2006-07-03 17:46 ` [patch 1/7] net_device list cleanup: core Christoph Hellwig
2006-07-04 7:24 ` Andrey Savochkin
2006-07-04 9:10 ` Christoph Hellwig
2006-07-04 14:50 ` Andrey Savochkin
2006-07-04 16:35 ` Alexey Kuznetsov
2006-07-05 8:26 ` Andrey Savochkin
2006-07-07 4:34 ` YOSHIFUJI Hideaki / 吉藤英明
2006-07-07 7:54 ` Andrey Savochkin
2006-07-07 16:48 ` YOSHIFUJI Hideaki / 吉藤英明
2006-07-10 6:53 ` Andrey Savochkin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).