aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
Diffstat (limited to 'net/core')
-rw-r--r--net/core/dev.c99
-rw-r--r--net/core/dev_mcast.c5
-rw-r--r--net/core/rtnetlink.c7
3 files changed, 58 insertions, 53 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index eb999003bb..f27d4ab181 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,26 +566,38 @@ 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);
578 578
579struct net_device *__dev_getfirstbyhwtype(unsigned short type)
580{
581 struct net_device *dev;
582
583 ASSERT_RTNL();
584 for_each_netdev(dev)
585 if (dev->type == type)
586 return dev;
587
588 return NULL;
589}
590
591EXPORT_SYMBOL(__dev_getfirstbyhwtype);
592
579struct net_device *dev_getfirstbyhwtype(unsigned short type) 593struct net_device *dev_getfirstbyhwtype(unsigned short type)
580{ 594{
581 struct net_device *dev; 595 struct net_device *dev;
582 596
583 rtnl_lock(); 597 rtnl_lock();
584 for (dev = dev_base; dev; dev = dev->next) { 598 dev = __dev_getfirstbyhwtype(type);
585 if (dev->type == type) { 599 if (dev)
586 dev_hold(dev); 600 dev_hold(dev);
587 break;
588 }
589 }
590 rtnl_unlock(); 601 rtnl_unlock();
591 return dev; 602 return dev;
592} 603}
@@ -606,17 +617,19 @@ EXPORT_SYMBOL(dev_getfirstbyhwtype);
606 617
607struct 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)
608{ 619{
609 struct net_device *dev; 620 struct net_device *dev, *ret;
610 621
622 ret = NULL;
611 read_lock(&dev_base_lock); 623 read_lock(&dev_base_lock);
612 for (dev = dev_base; dev != NULL; dev = dev->next) { 624 for_each_netdev(dev) {
613 if (((dev->flags ^ if_flags) & mask) == 0) { 625 if (((dev->flags ^ if_flags) & mask) == 0) {
614 dev_hold(dev); 626 dev_hold(dev);
627 ret = dev;
615 break; 628 break;
616 } 629 }
617 } 630 }
618 read_unlock(&dev_base_lock); 631 read_unlock(&dev_base_lock);
619 return dev; 632 return ret;
620} 633}
621 634
622/** 635/**
@@ -682,7 +695,7 @@ int dev_alloc_name(struct net_device *dev, const char *name)
682 if (!inuse) 695 if (!inuse)
683 return -ENOMEM; 696 return -ENOMEM;
684 697
685 for (d = dev_base; d; d = d->next) { 698 for_each_netdev(d) {
686 if (!sscanf(d->name, name, &i)) 699 if (!sscanf(d->name, name, &i))
687 continue; 700 continue;
688 if (i < 0 || i >= max_netdevices) 701 if (i < 0 || i >= max_netdevices)
@@ -964,7 +977,7 @@ int register_netdevice_notifier(struct notifier_block *nb)
964 rtnl_lock(); 977 rtnl_lock();
965 err = raw_notifier_chain_register(&netdev_chain, nb); 978 err = raw_notifier_chain_register(&netdev_chain, nb);
966 if (!err) { 979 if (!err) {
967 for (dev = dev_base; dev; dev = dev->next) { 980 for_each_netdev(dev) {
968 nb->notifier_call(nb, NETDEV_REGISTER, dev); 981 nb->notifier_call(nb, NETDEV_REGISTER, dev);
969 982
970 if (dev->flags & IFF_UP) 983 if (dev->flags & IFF_UP)
@@ -2038,7 +2051,7 @@ static int dev_ifconf(char __user *arg)
2038 */ 2051 */
2039 2052
2040 total = 0; 2053 total = 0;
2041 for (dev = dev_base; dev; dev = dev->next) { 2054 for_each_netdev(dev) {
2042 for (i = 0; i < NPROTO; i++) { 2055 for (i = 0; i < NPROTO; i++) {
2043 if (gifconf_list[i]) { 2056 if (gifconf_list[i]) {
2044 int done; 2057 int done;
@@ -2070,26 +2083,28 @@ static int dev_ifconf(char __user *arg)
2070 * 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
2071 * in detail. 2084 * in detail.
2072 */ 2085 */
2073static struct net_device *dev_get_idx(loff_t pos) 2086void *dev_seq_start(struct seq_file *seq, loff_t *pos)
2074{ 2087{
2088 loff_t off;
2075 struct net_device *dev; 2089 struct net_device *dev;
2076 loff_t i;
2077 2090
2078 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;
2079 2094
2080 return i == pos ? dev : NULL; 2095 off = 1;
2081} 2096 for_each_netdev(dev)
2097 if (off++ == *pos)
2098 return dev;
2082 2099
2083void *dev_seq_start(struct seq_file *seq, loff_t *pos) 2100 return NULL;
2084{
2085 read_lock(&dev_base_lock);
2086 return *pos ? dev_get_idx(*pos - 1) : SEQ_START_TOKEN;
2087} 2101}
2088 2102
2089void *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)
2090{ 2104{
2091 ++*pos; 2105 ++*pos;
2092 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);
2093} 2108}
2094 2109
2095void dev_seq_stop(struct seq_file *seq, void *v) 2110void dev_seq_stop(struct seq_file *seq, void *v)
@@ -3071,11 +3086,9 @@ int register_netdevice(struct net_device *dev)
3071 3086
3072 set_bit(__LINK_STATE_PRESENT, &dev->state); 3087 set_bit(__LINK_STATE_PRESENT, &dev->state);
3073 3088
3074 dev->next = NULL;
3075 dev_init_scheduler(dev); 3089 dev_init_scheduler(dev);
3076 write_lock_bh(&dev_base_lock); 3090 write_lock_bh(&dev_base_lock);
3077 *dev_tail = dev; 3091 list_add_tail(&dev->dev_list, &dev_base_head);
3078 dev_tail = &dev->next;
3079 hlist_add_head(&dev->name_hlist, head); 3092 hlist_add_head(&dev->name_hlist, head);
3080 hlist_add_head(&dev->index_hlist, dev_index_hash(dev->ifindex)); 3093 hlist_add_head(&dev->index_hlist, dev_index_hash(dev->ifindex));
3081 dev_hold(dev); 3094 dev_hold(dev);
@@ -3349,8 +3362,6 @@ void synchronize_net(void)
3349 3362
3350void unregister_netdevice(struct net_device *dev) 3363void unregister_netdevice(struct net_device *dev)
3351{ 3364{
3352 struct net_device *d, **dp;
3353
3354 BUG_ON(dev_boot_phase); 3365 BUG_ON(dev_boot_phase);
3355 ASSERT_RTNL(); 3366 ASSERT_RTNL();
3356 3367
@@ -3370,19 +3381,11 @@ void unregister_netdevice(struct net_device *dev)
3370 dev_close(dev); 3381 dev_close(dev);
3371 3382
3372 /* And unlink it from device chain. */ 3383 /* And unlink it from device chain. */
3373 for (dp = &dev_base; (d = *dp) != NULL; dp = &d->next) { 3384 write_lock_bh(&dev_base_lock);
3374 if (d == dev) { 3385 list_del(&dev->dev_list);
3375 write_lock_bh(&dev_base_lock); 3386 hlist_del(&dev->name_hlist);
3376 hlist_del(&dev->name_hlist); 3387 hlist_del(&dev->index_hlist);
3377 hlist_del(&dev->index_hlist); 3388 write_unlock_bh(&dev_base_lock);
3378 if (dev_tail == &dev->next)
3379 dev_tail = dp;
3380 *dp = d->next;
3381 write_unlock_bh(&dev_base_lock);
3382 break;
3383 }
3384 }
3385 BUG_ON(!d);
3386 3389
3387 dev->reg_state = NETREG_UNREGISTERING; 3390 dev->reg_state = NETREG_UNREGISTERING;
3388 3391
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c
index 7d57bf77f3..5a54053386 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 cec1111091..8c971a2efe 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