aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorPavel Emelianov <xemul@openvz.org>2007-05-03 18:13:45 -0400
committerDavid S. Miller <davem@davemloft.net>2007-05-03 18:13:45 -0400
commit7562f876cd93800f2f8c89445f2a563590b24e09 (patch)
tree78a34c011af275efa0d55ba59c3bd49b771dd533 /net/core
parent03fba0479600114f32d29eee74ca3eaa364606bf (diff)
[NET]: Rework dev_base via list_head (v3)
Cleanup of dev_base list use, with the aim to simplify making device list per-namespace. In almost every occasion, use of dev_base variable and dev->next pointer could be easily replaced by for_each_netdev loop. A few most complicated places were converted to using first_netdev()/next_netdev(). Signed-off-by: Pavel Emelianov <xemul@openvz.org> Acked-by: Kirill Korotaev <dev@openvz.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/dev.c84
-rw-r--r--net/core/dev_mcast.c5
-rw-r--r--net/core/rtnetlink.c7
3 files changed, 45 insertions, 51 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index c305819b7266..f27d4ab181e6 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -156,13 +156,13 @@ static spinlock_t net_dma_event_lock;
156#endif 156#endif
157 157
158/* 158/*
159 * The @dev_base list is protected by @dev_base_lock and the rtnl 159 * The @dev_base_head list is protected by @dev_base_lock and the rtnl
160 * semaphore. 160 * semaphore.
161 * 161 *
162 * Pure readers hold dev_base_lock for reading. 162 * Pure readers hold dev_base_lock for reading.
163 * 163 *
164 * Writers must hold the rtnl semaphore while they loop through the 164 * Writers must hold the rtnl semaphore while they loop through the
165 * dev_base list, and hold dev_base_lock for writing when they do the 165 * dev_base_head list, and hold dev_base_lock for writing when they do the
166 * actual updates. This allows pure readers to access the list even 166 * actual updates. This allows pure readers to access the list even
167 * while a writer is preparing to update it. 167 * while a writer is preparing to update it.
168 * 168 *
@@ -174,11 +174,10 @@ static spinlock_t net_dma_event_lock;
174 * unregister_netdevice(), which must be called with the rtnl 174 * unregister_netdevice(), which must be called with the rtnl
175 * semaphore held. 175 * semaphore held.
176 */ 176 */
177struct net_device *dev_base; 177LIST_HEAD(dev_base_head);
178static struct net_device **dev_tail = &dev_base;
179DEFINE_RWLOCK(dev_base_lock); 178DEFINE_RWLOCK(dev_base_lock);
180 179
181EXPORT_SYMBOL(dev_base); 180EXPORT_SYMBOL(dev_base_head);
182EXPORT_SYMBOL(dev_base_lock); 181EXPORT_SYMBOL(dev_base_lock);
183 182
184#define NETDEV_HASHBITS 8 183#define NETDEV_HASHBITS 8
@@ -567,11 +566,12 @@ struct net_device *dev_getbyhwaddr(unsigned short type, char *ha)
567 566
568 ASSERT_RTNL(); 567 ASSERT_RTNL();
569 568
570 for (dev = dev_base; dev; dev = dev->next) 569 for_each_netdev(dev)
571 if (dev->type == type && 570 if (dev->type == type &&
572 !memcmp(dev->dev_addr, ha, dev->addr_len)) 571 !memcmp(dev->dev_addr, ha, dev->addr_len))
573 break; 572 return dev;
574 return dev; 573
574 return NULL;
575} 575}
576 576
577EXPORT_SYMBOL(dev_getbyhwaddr); 577EXPORT_SYMBOL(dev_getbyhwaddr);
@@ -581,11 +581,11 @@ struct net_device *__dev_getfirstbyhwtype(unsigned short type)
581 struct net_device *dev; 581 struct net_device *dev;
582 582
583 ASSERT_RTNL(); 583 ASSERT_RTNL();
584 for (dev = dev_base; dev; dev = dev->next) { 584 for_each_netdev(dev)
585 if (dev->type == type) 585 if (dev->type == type)
586 break; 586 return dev;
587 } 587
588 return dev; 588 return NULL;
589} 589}
590 590
591EXPORT_SYMBOL(__dev_getfirstbyhwtype); 591EXPORT_SYMBOL(__dev_getfirstbyhwtype);
@@ -617,17 +617,19 @@ EXPORT_SYMBOL(dev_getfirstbyhwtype);
617 617
618struct net_device * dev_get_by_flags(unsigned short if_flags, unsigned short mask) 618struct net_device * dev_get_by_flags(unsigned short if_flags, unsigned short mask)
619{ 619{
620 struct net_device *dev; 620 struct net_device *dev, *ret;
621 621
622 ret = NULL;
622 read_lock(&dev_base_lock); 623 read_lock(&dev_base_lock);
623 for (dev = dev_base; dev != NULL; dev = dev->next) { 624 for_each_netdev(dev) {
624 if (((dev->flags ^ if_flags) & mask) == 0) { 625 if (((dev->flags ^ if_flags) & mask) == 0) {
625 dev_hold(dev); 626 dev_hold(dev);
627 ret = dev;
626 break; 628 break;
627 } 629 }
628 } 630 }
629 read_unlock(&dev_base_lock); 631 read_unlock(&dev_base_lock);
630 return dev; 632 return ret;
631} 633}
632 634
633/** 635/**
@@ -693,7 +695,7 @@ int dev_alloc_name(struct net_device *dev, const char *name)
693 if (!inuse) 695 if (!inuse)
694 return -ENOMEM; 696 return -ENOMEM;
695 697
696 for (d = dev_base; d; d = d->next) { 698 for_each_netdev(d) {
697 if (!sscanf(d->name, name, &i)) 699 if (!sscanf(d->name, name, &i))
698 continue; 700 continue;
699 if (i < 0 || i >= max_netdevices) 701 if (i < 0 || i >= max_netdevices)
@@ -975,7 +977,7 @@ int register_netdevice_notifier(struct notifier_block *nb)
975 rtnl_lock(); 977 rtnl_lock();
976 err = raw_notifier_chain_register(&netdev_chain, nb); 978 err = raw_notifier_chain_register(&netdev_chain, nb);
977 if (!err) { 979 if (!err) {
978 for (dev = dev_base; dev; dev = dev->next) { 980 for_each_netdev(dev) {
979 nb->notifier_call(nb, NETDEV_REGISTER, dev); 981 nb->notifier_call(nb, NETDEV_REGISTER, dev);
980 982
981 if (dev->flags & IFF_UP) 983 if (dev->flags & IFF_UP)
@@ -2049,7 +2051,7 @@ static int dev_ifconf(char __user *arg)
2049 */ 2051 */
2050 2052
2051 total = 0; 2053 total = 0;
2052 for (dev = dev_base; dev; dev = dev->next) { 2054 for_each_netdev(dev) {
2053 for (i = 0; i < NPROTO; i++) { 2055 for (i = 0; i < NPROTO; i++) {
2054 if (gifconf_list[i]) { 2056 if (gifconf_list[i]) {
2055 int done; 2057 int done;
@@ -2081,26 +2083,28 @@ static int dev_ifconf(char __user *arg)
2081 * This is invoked by the /proc filesystem handler to display a device 2083 * This is invoked by the /proc filesystem handler to display a device
2082 * in detail. 2084 * in detail.
2083 */ 2085 */
2084static struct net_device *dev_get_idx(loff_t pos) 2086void *dev_seq_start(struct seq_file *seq, loff_t *pos)
2085{ 2087{
2088 loff_t off;
2086 struct net_device *dev; 2089 struct net_device *dev;
2087 loff_t i;
2088 2090
2089 for (i = 0, dev = dev_base; dev && i < pos; ++i, dev = dev->next); 2091 read_lock(&dev_base_lock);
2092 if (!*pos)
2093 return SEQ_START_TOKEN;
2090 2094
2091 return i == pos ? dev : NULL; 2095 off = 1;
2092} 2096 for_each_netdev(dev)
2097 if (off++ == *pos)
2098 return dev;
2093 2099
2094void *dev_seq_start(struct seq_file *seq, loff_t *pos) 2100 return NULL;
2095{
2096 read_lock(&dev_base_lock);
2097 return *pos ? dev_get_idx(*pos - 1) : SEQ_START_TOKEN;
2098} 2101}
2099 2102
2100void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) 2103void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2101{ 2104{
2102 ++*pos; 2105 ++*pos;
2103 return v == SEQ_START_TOKEN ? dev_base : ((struct net_device *)v)->next; 2106 return v == SEQ_START_TOKEN ?
2107 first_net_device() : next_net_device((struct net_device *)v);
2104} 2108}
2105 2109
2106void dev_seq_stop(struct seq_file *seq, void *v) 2110void dev_seq_stop(struct seq_file *seq, void *v)
@@ -3082,11 +3086,9 @@ int register_netdevice(struct net_device *dev)
3082 3086
3083 set_bit(__LINK_STATE_PRESENT, &dev->state); 3087 set_bit(__LINK_STATE_PRESENT, &dev->state);
3084 3088
3085 dev->next = NULL;
3086 dev_init_scheduler(dev); 3089 dev_init_scheduler(dev);
3087 write_lock_bh(&dev_base_lock); 3090 write_lock_bh(&dev_base_lock);
3088 *dev_tail = dev; 3091 list_add_tail(&dev->dev_list, &dev_base_head);
3089 dev_tail = &dev->next;
3090 hlist_add_head(&dev->name_hlist, head); 3092 hlist_add_head(&dev->name_hlist, head);
3091 hlist_add_head(&dev->index_hlist, dev_index_hash(dev->ifindex)); 3093 hlist_add_head(&dev->index_hlist, dev_index_hash(dev->ifindex));
3092 dev_hold(dev); 3094 dev_hold(dev);
@@ -3360,8 +3362,6 @@ void synchronize_net(void)
3360 3362
3361void unregister_netdevice(struct net_device *dev) 3363void unregister_netdevice(struct net_device *dev)
3362{ 3364{
3363 struct net_device *d, **dp;
3364
3365 BUG_ON(dev_boot_phase); 3365 BUG_ON(dev_boot_phase);
3366 ASSERT_RTNL(); 3366 ASSERT_RTNL();
3367 3367
@@ -3381,19 +3381,11 @@ void unregister_netdevice(struct net_device *dev)
3381 dev_close(dev); 3381 dev_close(dev);
3382 3382
3383 /* And unlink it from device chain. */ 3383 /* And unlink it from device chain. */
3384 for (dp = &dev_base; (d = *dp) != NULL; dp = &d->next) { 3384 write_lock_bh(&dev_base_lock);
3385 if (d == dev) { 3385 list_del(&dev->dev_list);
3386 write_lock_bh(&dev_base_lock); 3386 hlist_del(&dev->name_hlist);
3387 hlist_del(&dev->name_hlist); 3387 hlist_del(&dev->index_hlist);
3388 hlist_del(&dev->index_hlist); 3388 write_unlock_bh(&dev_base_lock);
3389 if (dev_tail == &dev->next)
3390 dev_tail = dp;
3391 *dp = d->next;
3392 write_unlock_bh(&dev_base_lock);
3393 break;
3394 }
3395 }
3396 BUG_ON(!d);
3397 3389
3398 dev->reg_state = NETREG_UNREGISTERING; 3390 dev->reg_state = NETREG_UNREGISTERING;
3399 3391
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c
index 7d57bf77f3a3..5a54053386c8 100644
--- a/net/core/dev_mcast.c
+++ b/net/core/dev_mcast.c
@@ -223,7 +223,7 @@ static void *dev_mc_seq_start(struct seq_file *seq, loff_t *pos)
223 loff_t off = 0; 223 loff_t off = 0;
224 224
225 read_lock(&dev_base_lock); 225 read_lock(&dev_base_lock);
226 for (dev = dev_base; dev; dev = dev->next) { 226 for_each_netdev(dev) {
227 if (off++ == *pos) 227 if (off++ == *pos)
228 return dev; 228 return dev;
229 } 229 }
@@ -232,9 +232,8 @@ static void *dev_mc_seq_start(struct seq_file *seq, loff_t *pos)
232 232
233static void *dev_mc_seq_next(struct seq_file *seq, void *v, loff_t *pos) 233static void *dev_mc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
234{ 234{
235 struct net_device *dev = v;
236 ++*pos; 235 ++*pos;
237 return dev->next; 236 return next_net_device((struct net_device *)v);
238} 237}
239 238
240static void dev_mc_seq_stop(struct seq_file *seq, void *v) 239static void dev_mc_seq_stop(struct seq_file *seq, void *v)
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index cec111109155..8c971a2efe2a 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -539,13 +539,16 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
539 int s_idx = cb->args[0]; 539 int s_idx = cb->args[0];
540 struct net_device *dev; 540 struct net_device *dev;
541 541
542 for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) { 542 idx = 0;
543 for_each_netdev(dev) {
543 if (idx < s_idx) 544 if (idx < s_idx)
544 continue; 545 goto cont;
545 if (rtnl_fill_ifinfo(skb, dev, NULL, 0, RTM_NEWLINK, 546 if (rtnl_fill_ifinfo(skb, dev, NULL, 0, RTM_NEWLINK,
546 NETLINK_CB(cb->skb).pid, 547 NETLINK_CB(cb->skb).pid,
547 cb->nlh->nlmsg_seq, 0, NLM_F_MULTI) <= 0) 548 cb->nlh->nlmsg_seq, 0, NLM_F_MULTI) <= 0)
548 break; 549 break;
550cont:
551 idx++;
549 } 552 }
550 cb->args[0] = idx; 553 cb->args[0] = idx;
551 554