diff options
author | Pavel Emelianov <xemul@openvz.org> | 2007-05-03 18:13:45 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2007-05-03 18:13:45 -0400 |
commit | 7562f876cd93800f2f8c89445f2a563590b24e09 (patch) | |
tree | 78a34c011af275efa0d55ba59c3bd49b771dd533 /net/core | |
parent | 03fba0479600114f32d29eee74ca3eaa364606bf (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.c | 84 | ||||
-rw-r--r-- | net/core/dev_mcast.c | 5 | ||||
-rw-r--r-- | net/core/rtnetlink.c | 7 |
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 | */ |
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,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 | ||
577 | EXPORT_SYMBOL(dev_getbyhwaddr); | 577 | EXPORT_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 | ||
591 | EXPORT_SYMBOL(__dev_getfirstbyhwtype); | 591 | EXPORT_SYMBOL(__dev_getfirstbyhwtype); |
@@ -617,17 +617,19 @@ EXPORT_SYMBOL(dev_getfirstbyhwtype); | |||
617 | 617 | ||
618 | 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) |
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 | */ |
2084 | static struct net_device *dev_get_idx(loff_t pos) | 2086 | void *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 | ||
2094 | void *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 | ||
2100 | 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) |
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 | ||
2106 | void dev_seq_stop(struct seq_file *seq, void *v) | 2110 | void 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 | ||
3361 | void unregister_netdevice(struct net_device *dev) | 3363 | void 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 | ||
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 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; |
550 | cont: | ||
551 | idx++; | ||
549 | } | 552 | } |
550 | cb->args[0] = idx; | 553 | cb->args[0] = idx; |
551 | 554 | ||