diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2001-01-10 05:27:25 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2001-01-10 05:27:25 +0000 |
commit | c9c06167e7933d93a6e396174c68abf242294abb (patch) | |
tree | d9a8bb30663e9a3405a1ef37ffb62bc14b9f019f /net/core | |
parent | f79e8cc3c34e4192a3e5ef4cc9c6542fdef703c0 (diff) |
Merge with Linux 2.4.0-test12.
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/dev.c | 111 | ||||
-rw-r--r-- | net/core/dst.c | 3 | ||||
-rw-r--r-- | net/core/dv.c | 2 | ||||
-rw-r--r-- | net/core/neighbour.c | 39 | ||||
-rw-r--r-- | net/core/skbuff.c | 14 |
5 files changed, 84 insertions, 85 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 1e5b59c3d..cf4dcf8cd 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -154,6 +154,12 @@ static void sample_queue(unsigned long dummy); static struct timer_list samp_timer = { function: sample_queue }; #endif +#ifdef CONFIG_HOTPLUG +static int net_run_sbin_hotplug(struct net_device *dev, char *action); +#else +#define net_run_sbin_hotplug(dev, action) ({ 0; }) +#endif + /* * Our notifier list */ @@ -617,7 +623,7 @@ void netdev_state_change(struct net_device *dev) void dev_load(const char *name) { - if (!__dev_get_by_name(name) && capable(CAP_SYS_MODULE)) + if (!dev_get(name) && capable(CAP_SYS_MODULE)) request_module(name); } @@ -875,8 +881,6 @@ void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) skb2->h.raw = skb2->nh.raw; skb2->pkt_type = PACKET_OUTGOING; - skb2->rx_dev = skb->dev; - dev_hold(skb2->rx_dev); ptype->func(skb2, skb->dev, ptype); } } @@ -1129,10 +1133,7 @@ int netif_rx(struct sk_buff *skb) goto drop; enqueue: - if (skb->rx_dev) - dev_put(skb->rx_dev); - skb->rx_dev = skb->dev; - dev_hold(skb->rx_dev); + dev_hold(skb->dev); __skb_queue_tail(&queue->input_pkt_queue,skb); __cpu_raise_softirq(this_cpu, NET_RX_SOFTIRQ); local_irq_restore(flags); @@ -1206,11 +1207,11 @@ static int deliver_to_old_ones(struct packet_type *pt, struct sk_buff *skb, int */ static __inline__ void skb_bond(struct sk_buff *skb) { - struct net_device *dev = skb->rx_dev; + struct net_device *dev = skb->dev; if (dev->master) { dev_hold(dev->master); - skb->dev = skb->rx_dev = dev->master; + skb->dev = dev->master; dev_put(dev); } } @@ -1320,6 +1321,7 @@ static void net_rx_action(struct softirq_action *h) for (;;) { struct sk_buff *skb; + struct net_device *rx_dev; local_irq_disable(); skb = __skb_dequeue(&queue->input_pkt_queue); @@ -1330,10 +1332,13 @@ static void net_rx_action(struct softirq_action *h) skb_bond(skb); + rx_dev = skb->dev; + #ifdef CONFIG_NET_FASTROUTE if (skb->pkt_type == PACKET_FASTROUTE) { netdev_rx_stat[this_cpu].fastroute_deferred_out++; dev_queue_xmit(skb); + dev_put(rx_dev); continue; } #endif @@ -1369,6 +1374,7 @@ static void net_rx_action(struct softirq_action *h) if (skb->dev->br_port != NULL && br_handle_frame_hook != NULL) { handle_bridge(skb, pt_prev); + dev_put(rx_dev); continue; } #endif @@ -1399,6 +1405,8 @@ static void net_rx_action(struct softirq_action *h) kfree_skb(skb); } + dev_put(rx_dev); + if (bugdet-- < 0 || jiffies - start_time > 1) goto softnet_break; @@ -2196,9 +2204,11 @@ int dev_ioctl(unsigned int cmd, void *arg) if (!capable(CAP_NET_ADMIN)) return -EPERM; dev_load(ifr.ifr_name); + dev_probe_lock(); rtnl_lock(); ret = dev_ifsioc(&ifr, cmd); rtnl_unlock(); + dev_probe_unlock(); return ret; case SIOCGIFMEM: @@ -2217,9 +2227,11 @@ int dev_ioctl(unsigned int cmd, void *arg) if (cmd >= SIOCDEVPRIVATE && cmd <= SIOCDEVPRIVATE + 15) { dev_load(ifr.ifr_name); + dev_probe_lock(); rtnl_lock(); ret = dev_ifsioc(&ifr, cmd); rtnl_unlock(); + dev_probe_unlock(); if (!ret && copy_to_user(arg, &ifr, sizeof(struct ifreq))) return -EFAULT; return ret; @@ -2303,6 +2315,12 @@ int register_netdevice(struct net_device *dev) #endif if (dev_boot_phase) { +#ifdef CONFIG_NET_DIVERT + ret = alloc_divert_blk(dev); + if (ret) + return ret; +#endif /* CONFIG_NET_DIVERT */ + /* This is NOT bug, but I am not sure, that all the devices, initialized before netdev module is started are sane. @@ -2328,12 +2346,6 @@ int register_netdevice(struct net_device *dev) dev_hold(dev); write_unlock_bh(&dev_base_lock); -#ifdef CONFIG_NET_DIVERT - ret = alloc_divert_blk(dev); - if (ret) - return ret; -#endif /* CONFIG_NET_DIVERT */ - /* * Default initial state at registry is that the * device is present. @@ -2344,6 +2356,12 @@ int register_netdevice(struct net_device *dev) return 0; } +#ifdef CONFIG_NET_DIVERT + ret = alloc_divert_blk(dev); + if (ret) + return ret; +#endif /* CONFIG_NET_DIVERT */ + dev->iflink = -1; /* Init, if this function is available */ @@ -2383,15 +2401,11 @@ int register_netdevice(struct net_device *dev) dev->deadbeaf = 0; write_unlock_bh(&dev_base_lock); -#ifdef CONFIG_NET_DIVERT - ret = alloc_divert_blk(dev); - if (ret) - return ret; -#endif /* CONFIG_NET_DIVERT */ - /* Notify protocols, that a new device appeared. */ notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev); + net_run_sbin_hotplug(dev, "register"); + return 0; } @@ -2414,11 +2428,12 @@ int netdev_finish_unregister(struct net_device *dev) return 0; } #ifdef NET_REFCNT_DEBUG - printk(KERN_DEBUG "netdev_finish_unregister: %s%s.\n", dev->name, dev->new_style?"":", old style"); + printk(KERN_DEBUG "netdev_finish_unregister: %s%s.\n", dev->name, + (dev->features & NETIF_F_DYNALLOC)?"":", old style"); #endif if (dev->destructor) dev->destructor(dev); - if (dev->new_style) + if (dev->features & NETIF_F_DYNALLOC) kfree(dev); return 0; } @@ -2462,6 +2477,10 @@ int unregister_netdevice(struct net_device *dev) return -ENODEV; } + /* Synchronize to net_rx_action. */ + br_write_lock_bh(BR_NETPROTO_LOCK); + br_write_unlock_bh(BR_NETPROTO_LOCK); + if (dev_boot_phase == 0) { #ifdef CONFIG_NET_FASTROUTE dev_clear_fastroute(dev); @@ -2470,6 +2489,8 @@ int unregister_netdevice(struct net_device *dev) /* Shutdown queueing discipline. */ dev_shutdown(dev); + net_run_sbin_hotplug(dev, "unregister"); + /* Notify protocols, that we are about to destroy this device. They should clean all the things. */ @@ -2491,7 +2512,7 @@ int unregister_netdevice(struct net_device *dev) free_divert_blk(dev); #endif - if (dev->new_style) { + if (dev->features & NETIF_F_DYNALLOC) { #ifdef NET_REFCNT_DEBUG if (atomic_read(&dev->refcnt) != 1) printk(KERN_DEBUG "unregister_netdevice: holding %s refcnt=%d\n", dev->name, atomic_read(&dev->refcnt)-1); @@ -2709,29 +2730,15 @@ int __init net_dev_init(void) /* Notify userspace when a netdevice event occurs, * by running '/sbin/hotplug net' with certain * environment variables set. - * - * Currently reported events are listed in netdev_event_names[]. */ -/* /sbin/hotplug ONLY executes for events named here */ -static char *netdev_event_names[] = { - [NETDEV_REGISTER] = "register", - [NETDEV_UNREGISTER] = "unregister", -}; - -static int run_sbin_hotplug(struct notifier_block *this, - unsigned long event, void *ptr) +static int net_run_sbin_hotplug(struct net_device *dev, char *action) { - struct net_device *dev = (struct net_device *) ptr; - char *argv[3], *envp[5], ifname[12 + IFNAMSIZ], action[32]; + char *argv[3], *envp[5], ifname[12 + IFNAMSIZ], action_str[32]; int i; - if ((event >= ARRAY_SIZE(netdev_event_names)) || - !netdev_event_names[event]) - return NOTIFY_DONE; - sprintf(ifname, "INTERFACE=%s", dev->name); - sprintf(action, "ACTION=%s", netdev_event_names[event]); + sprintf(action_str, "ACTION=%s", action); i = 0; argv[i++] = hotplug_path; @@ -2743,27 +2750,9 @@ static int run_sbin_hotplug(struct notifier_block *this, envp [i++] = "HOME=/"; envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; envp [i++] = ifname; - envp [i++] = action; + envp [i++] = action_str; envp [i] = 0; - call_usermodehelper (argv [0], argv, envp); - - return NOTIFY_DONE; -} - -static struct notifier_block sbin_hotplug = { - notifier_call: run_sbin_hotplug, -}; - -/* - * called from init/main.c, -after- all the initcalls are complete. - * Registers a hook that calls /sbin/hotplug on every netdev - * addition and removal. - */ -void __init net_notifier_init (void) -{ - if (register_netdevice_notifier(&sbin_hotplug)) - printk (KERN_WARNING "unable to register netdev notifier\n" - KERN_WARNING "/sbin/hotplug will not be run.\n"); + return call_usermodehelper(argv [0], argv, envp); } #endif diff --git a/net/core/dst.c b/net/core/dst.c index 2b17d3782..0771c634b 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -179,7 +179,8 @@ static int dst_dev_event(struct notifier_block *this, unsigned long event, void now. _It_ _is_ _explicit_ _deliberate_ _race_ _condition_. */ - if (event!=NETDEV_DOWN && !dev->new_style && + if (event!=NETDEV_DOWN && + !(dev->features & NETIF_F_DYNALLOC) && dst->output == dst_blackhole) { dst->dev = &loopback_dev; dev_put(dev); diff --git a/net/core/dv.c b/net/core/dv.c index 4df7747b8..0e5b3e671 100644 --- a/net/core/dv.c +++ b/net/core/dv.c @@ -62,7 +62,7 @@ int alloc_divert_blk(struct net_device *dev) if (dev->divert == NULL) { printk(KERN_DEBUG "divert: unable to allocate divert_blk for %s\n", dev->name); - return -EFAULT; + return -ENOMEM; } else { memset(dev->divert, 0, sizeof(struct divert_blk)); } diff --git a/net/core/neighbour.c b/net/core/neighbour.c index ecbea0425..2cb555071 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -165,6 +165,16 @@ static int neigh_del_timer(struct neighbour *n) return 0; } +static void pneigh_queue_purge(struct sk_buff_head *list) +{ + struct sk_buff *skb; + + while ((skb = skb_dequeue(list)) != NULL) { + dev_put(skb->dev); + kfree_skb(skb); + } +} + int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev) { int i; @@ -209,11 +219,11 @@ int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev) } } - skb_queue_purge(&tbl->proxy_queue); pneigh_ifdown(tbl, dev); write_unlock_bh(&tbl->lock); del_timer_sync(&tbl->proxy_timer); + pneigh_queue_purge(&tbl->proxy_queue); return 0; } @@ -999,7 +1009,11 @@ static void neigh_proxy_process(unsigned long arg) struct neigh_table *tbl = (struct neigh_table *)arg; long sched_next = 0; unsigned long now = jiffies; - struct sk_buff *skb = tbl->proxy_queue.next; + struct sk_buff *skb; + + spin_lock(&tbl->proxy_queue.lock); + + skb = tbl->proxy_queue.next; while (skb != (struct sk_buff*)&tbl->proxy_queue) { struct sk_buff *back = skb; @@ -1007,19 +1021,21 @@ static void neigh_proxy_process(unsigned long arg) skb = skb->next; if (tdif <= 0) { + struct net_device *dev = back->dev; __skb_unlink(back, &tbl->proxy_queue); - if (tbl->proxy_redo) + if (tbl->proxy_redo && netif_running(dev)) tbl->proxy_redo(back); else kfree_skb(back); + + dev_put(dev); } else if (!sched_next || tdif < sched_next) sched_next = tdif; } del_timer(&tbl->proxy_timer); - if (sched_next) { - tbl->proxy_timer.expires = jiffies + sched_next; - add_timer(&tbl->proxy_timer); - } + if (sched_next) + mod_timer(&tbl->proxy_timer, jiffies + sched_next); + spin_unlock(&tbl->proxy_queue.lock); } void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p, @@ -1034,16 +1050,19 @@ void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p, } skb->stamp.tv_sec = 0; skb->stamp.tv_usec = now + sched_next; + + spin_lock(&tbl->proxy_queue.lock); if (del_timer(&tbl->proxy_timer)) { long tval = tbl->proxy_timer.expires - now; if (tval < sched_next) sched_next = tval; } - tbl->proxy_timer.expires = now + sched_next; dst_release(skb->dst); skb->dst = NULL; + dev_hold(skb->dev); __skb_queue_tail(&tbl->proxy_queue, skb); - add_timer(&tbl->proxy_timer); + mod_timer(&tbl->proxy_timer, now + sched_next); + spin_unlock(&tbl->proxy_queue.lock); } @@ -1135,7 +1154,7 @@ int neigh_table_clear(struct neigh_table *tbl) del_timer_sync(&tbl->gc_timer); tasklet_kill(&tbl->gc_task); del_timer_sync(&tbl->proxy_timer); - skb_queue_purge(&tbl->proxy_queue); + pneigh_queue_purge(&tbl->proxy_queue); neigh_ifdown(tbl, NULL); if (tbl->entries) printk(KERN_CRIT "neighbour leakage\n"); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 173506c3d..c5dcecfb3 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -4,7 +4,7 @@ * Authors: Alan Cox <iiitac@pyr.swan.ac.uk> * Florian La Roche <rzsfl@rz.uni-sb.de> * - * Version: $Id: skbuff.c,v 1.73 2000/05/22 07:29:44 davem Exp $ + * Version: $Id: skbuff.c,v 1.75 2000/12/08 17:15:53 davem Exp $ * * Fixes: * Alan Cox : Fixed the worst of the load balancer bugs. @@ -202,7 +202,6 @@ struct sk_buff *alloc_skb(unsigned int size,int gfp_mask) /* Set up other state */ skb->len = 0; - skb->is_clone = 0; skb->cloned = 0; atomic_set(&skb->users, 1); @@ -233,7 +232,6 @@ static inline void skb_headerinit(void *p, kmem_cache_t *cache, skb->ip_summed = 0; skb->security = 0; /* By default packets are insecure */ skb->dst = NULL; - skb->rx_dev = NULL; #ifdef CONFIG_NETFILTER skb->nfmark = skb->nfcache = 0; skb->nfct = NULL; @@ -287,10 +285,6 @@ void __kfree_skb(struct sk_buff *skb) #ifdef CONFIG_NETFILTER nf_conntrack_put(skb->nfct); #endif -#ifdef CONFIG_NET - if(skb->rx_dev) - dev_put(skb->rx_dev); -#endif skb_headerinit(skb, NULL, 0); /* clean state */ kfree_skbmem(skb); } @@ -325,12 +319,10 @@ struct sk_buff *skb_clone(struct sk_buff *skb, int gfp_mask) skb->cloned = 1; dst_clone(n->dst); - n->rx_dev = NULL; n->cloned = 1; n->next = n->prev = NULL; n->list = NULL; n->sk = NULL; - n->is_clone = 1; atomic_set(&n->users, 1); n->destructor = NULL; #ifdef CONFIG_NETFILTER @@ -349,7 +341,6 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) new->list=NULL; new->sk=NULL; new->dev=old->dev; - new->rx_dev=NULL; new->priority=old->priority; new->protocol=old->protocol; new->dst=dst_clone(old->dst); @@ -358,7 +349,6 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) new->mac.raw=old->mac.raw+offset; memcpy(new->cb, old->cb, sizeof(old->cb)); new->used=old->used; - new->is_clone=0; atomic_set(&new->users, 1); new->pkt_type=old->pkt_type; new->stamp=old->stamp; @@ -417,7 +407,7 @@ struct sk_buff *skb_copy(const struct sk_buff *skb, int gfp_mask) } /** - * skb_copy - copy and expand sk_buff + * skb_copy_expand - copy and expand sk_buff * @skb: buffer to copy * @newheadroom: new free bytes at head * @newtailroom: new free bytes at tail |