diff options
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/dev.c | 99 | ||||
-rw-r--r-- | net/core/dev_mcast.c | 5 | ||||
-rw-r--r-- | net/core/rtnetlink.c | 7 |
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 | */ |
177 | struct net_device *dev_base; | 177 | LIST_HEAD(dev_base_head); |
178 | static struct net_device **dev_tail = &dev_base; | ||
179 | DEFINE_RWLOCK(dev_base_lock); | 178 | DEFINE_RWLOCK(dev_base_lock); |
180 | 179 | ||
181 | EXPORT_SYMBOL(dev_base); | 180 | EXPORT_SYMBOL(dev_base_head); |
182 | EXPORT_SYMBOL(dev_base_lock); | 181 | EXPORT_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 | ||
577 | EXPORT_SYMBOL(dev_getbyhwaddr); | 577 | EXPORT_SYMBOL(dev_getbyhwaddr); |
578 | 578 | ||
579 | struct 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 | |||
591 | EXPORT_SYMBOL(__dev_getfirstbyhwtype); | ||
592 | |||
579 | struct net_device *dev_getfirstbyhwtype(unsigned short type) | 593 | struct 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 | ||
607 | struct net_device * dev_get_by_flags(unsigned short if_flags, unsigned short mask) | 618 | struct 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 | */ |
2073 | static struct net_device *dev_get_idx(loff_t pos) | 2086 | void *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 | ||
2083 | void *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 | ||
2089 | void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 2103 | void *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 | ||
2095 | void dev_seq_stop(struct seq_file *seq, void *v) | 2110 | void 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 | ||
3350 | void unregister_netdevice(struct net_device *dev) | 3363 | void 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 | ||
233 | static void *dev_mc_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 233 | static 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 | ||
240 | static void dev_mc_seq_stop(struct seq_file *seq, void *v) | 239 | static 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; |
550 | cont: | ||
551 | idx++; | ||
549 | } | 552 | } |
550 | cb->args[0] = idx; | 553 | cb->args[0] = idx; |
551 | 554 | ||