diff options
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/dev.c | 71 | ||||
-rw-r--r-- | net/core/dv.c | 5 | ||||
-rw-r--r-- | net/core/flow.c | 8 | ||||
-rw-r--r-- | net/core/gen_estimator.c | 3 | ||||
-rw-r--r-- | net/core/neighbour.c | 16 | ||||
-rw-r--r-- | net/core/net-sysfs.c | 2 | ||||
-rw-r--r-- | net/core/request_sock.c | 4 | ||||
-rw-r--r-- | net/core/sock.c | 109 | ||||
-rw-r--r-- | net/core/utils.c | 4 |
9 files changed, 189 insertions, 33 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index a3ab11f34153..83231a27ae02 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1080,6 +1080,70 @@ void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) rcu_read_unlock(); } + +void __netif_schedule(struct net_device *dev) +{ + if (!test_and_set_bit(__LINK_STATE_SCHED, &dev->state)) { + unsigned long flags; + struct softnet_data *sd; + + local_irq_save(flags); + sd = &__get_cpu_var(softnet_data); + dev->next_sched = sd->output_queue; + sd->output_queue = dev; + raise_softirq_irqoff(NET_TX_SOFTIRQ); + local_irq_restore(flags); + } +} +EXPORT_SYMBOL(__netif_schedule); + +void __netif_rx_schedule(struct net_device *dev) +{ + unsigned long flags; + + local_irq_save(flags); + dev_hold(dev); + list_add_tail(&dev->poll_list, &__get_cpu_var(softnet_data).poll_list); + if (dev->quota < 0) + dev->quota += dev->weight; + else + dev->quota = dev->weight; + __raise_softirq_irqoff(NET_RX_SOFTIRQ); + local_irq_restore(flags); +} +EXPORT_SYMBOL(__netif_rx_schedule); + +void dev_kfree_skb_any(struct sk_buff *skb) +{ + if (in_irq() || irqs_disabled()) + dev_kfree_skb_irq(skb); + else + dev_kfree_skb(skb); +} +EXPORT_SYMBOL(dev_kfree_skb_any); + + +/* Hot-plugging. */ +void netif_device_detach(struct net_device *dev) +{ + if (test_and_clear_bit(__LINK_STATE_PRESENT, &dev->state) && + netif_running(dev)) { + netif_stop_queue(dev); + } +} +EXPORT_SYMBOL(netif_device_detach); + +void netif_device_attach(struct net_device *dev) +{ + if (!test_and_set_bit(__LINK_STATE_PRESENT, &dev->state) && + netif_running(dev)) { + netif_wake_queue(dev); + __netdev_watchdog_up(dev); + } +} +EXPORT_SYMBOL(netif_device_attach); + + /* * Invalidate hardware checksum when packet is to be mangled, and * complete checksum manually on outgoing path. @@ -2978,11 +3042,11 @@ void netdev_run_todo(void) switch(dev->reg_state) { case NETREG_REGISTERING: + dev->reg_state = NETREG_REGISTERED; err = netdev_register_sysfs(dev); if (err) printk(KERN_ERR "%s: failed sysfs registration (%d)\n", dev->name, err); - dev->reg_state = NETREG_REGISTERED; break; case NETREG_UNREGISTERING: @@ -3036,12 +3100,11 @@ struct net_device *alloc_netdev(int sizeof_priv, const char *name, alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST; alloc_size += sizeof_priv + NETDEV_ALIGN_CONST; - p = kmalloc(alloc_size, GFP_KERNEL); + p = kzalloc(alloc_size, GFP_KERNEL); if (!p) { printk(KERN_ERR "alloc_dev: Unable to allocate device.\n"); return NULL; } - memset(p, 0, alloc_size); dev = (struct net_device *) (((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); @@ -3283,7 +3346,7 @@ static int __init net_dev_init(void) * Initialise the packet receive queues. */ - for_each_cpu(i) { + for_each_possible_cpu(i) { struct softnet_data *queue; queue = &per_cpu(softnet_data, i); diff --git a/net/core/dv.c b/net/core/dv.c index cf581407538c..29ee77f15932 100644 --- a/net/core/dv.c +++ b/net/core/dv.c @@ -55,15 +55,12 @@ int alloc_divert_blk(struct net_device *dev) dev->divert = NULL; if (dev->type == ARPHRD_ETHER) { - dev->divert = (struct divert_blk *) - kmalloc(alloc_size, GFP_KERNEL); + dev->divert = kzalloc(alloc_size, GFP_KERNEL); if (dev->divert == NULL) { printk(KERN_INFO "divert: unable to allocate divert_blk for %s\n", dev->name); return -ENOMEM; } - - memset(dev->divert, 0, sizeof(struct divert_blk)); dev_hold(dev); } diff --git a/net/core/flow.c b/net/core/flow.c index 55789f832eda..2191af5f26ac 100644 --- a/net/core/flow.c +++ b/net/core/flow.c @@ -79,7 +79,7 @@ static void flow_cache_new_hashrnd(unsigned long arg) { int i; - for_each_cpu(i) + for_each_possible_cpu(i) flow_hash_rnd_recalc(i) = 1; flow_hash_rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD; @@ -318,12 +318,10 @@ static void __devinit flow_cache_cpu_prepare(int cpu) /* NOTHING */; flow_table(cpu) = (struct flow_cache_entry **) - __get_free_pages(GFP_KERNEL, order); + __get_free_pages(GFP_KERNEL|__GFP_ZERO, order); if (!flow_table(cpu)) panic("NET: failed to allocate flow cache order %lu\n", order); - memset(flow_table(cpu), 0, PAGE_SIZE << order); - flow_hash_rnd_recalc(cpu) = 1; flow_count(cpu) = 0; @@ -363,7 +361,7 @@ static int __init flow_cache_init(void) flow_hash_rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD; add_timer(&flow_hash_rnd_timer); - for_each_cpu(i) + for_each_possible_cpu(i) flow_cache_cpu_prepare(i); hotcpu_notifier(flow_cache_cpu, 0); diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c index b07c029e8219..3cad026764f0 100644 --- a/net/core/gen_estimator.c +++ b/net/core/gen_estimator.c @@ -159,11 +159,10 @@ int gen_new_estimator(struct gnet_stats_basic *bstats, if (parm->interval < -2 || parm->interval > 3) return -EINVAL; - est = kmalloc(sizeof(*est), GFP_KERNEL); + est = kzalloc(sizeof(*est), GFP_KERNEL); if (est == NULL) return -ENOBUFS; - memset(est, 0, sizeof(*est)); est->interval = parm->interval + 2; est->bstats = bstats; est->rate_est = rate_est; diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 0c8666872d10..4cf878efdb49 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -284,14 +284,11 @@ static struct neighbour **neigh_hash_alloc(unsigned int entries) struct neighbour **ret; if (size <= PAGE_SIZE) { - ret = kmalloc(size, GFP_ATOMIC); + ret = kzalloc(size, GFP_ATOMIC); } else { ret = (struct neighbour **) - __get_free_pages(GFP_ATOMIC, get_order(size)); + __get_free_pages(GFP_ATOMIC|__GFP_ZERO, get_order(size)); } - if (ret) - memset(ret, 0, size); - return ret; } @@ -1089,8 +1086,7 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst, if (hh->hh_type == protocol) break; - if (!hh && (hh = kmalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) { - memset(hh, 0, sizeof(struct hh_cache)); + if (!hh && (hh = kzalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) { rwlock_init(&hh->hh_lock); hh->hh_type = protocol; atomic_set(&hh->hh_refcnt, 0); @@ -1366,13 +1362,11 @@ void neigh_table_init(struct neigh_table *tbl) tbl->hash_buckets = neigh_hash_alloc(tbl->hash_mask + 1); phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *); - tbl->phash_buckets = kmalloc(phsize, GFP_KERNEL); + tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL); if (!tbl->hash_buckets || !tbl->phash_buckets) panic("cannot allocate neighbour cache hashes"); - memset(tbl->phash_buckets, 0, phsize); - get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd)); rwlock_init(&tbl->lock); @@ -1633,7 +1627,7 @@ static int neightbl_fill_info(struct neigh_table *tbl, struct sk_buff *skb, memset(&ndst, 0, sizeof(ndst)); - for_each_cpu(cpu) { + for_each_possible_cpu(cpu) { struct neigh_statistics *st; st = per_cpu_ptr(tbl->stats, cpu); diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 21b68464cabb..c12990c9c603 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -165,7 +165,7 @@ static ssize_t show_operstate(struct class_device *dev, char *buf) operstate = IF_OPER_DOWN; read_unlock(&dev_base_lock); - if (operstate >= sizeof(operstates)) + if (operstate >= ARRAY_SIZE(operstates)) return -EINVAL; /* should not happen */ return sprintf(buf, "%s\n", operstates[operstate]); diff --git a/net/core/request_sock.c b/net/core/request_sock.c index 1e44eda1fda9..79ebd75fbe4d 100644 --- a/net/core/request_sock.c +++ b/net/core/request_sock.c @@ -38,13 +38,11 @@ int reqsk_queue_alloc(struct request_sock_queue *queue, { const int lopt_size = sizeof(struct listen_sock) + nr_table_entries * sizeof(struct request_sock *); - struct listen_sock *lopt = kmalloc(lopt_size, GFP_KERNEL); + struct listen_sock *lopt = kzalloc(lopt_size, GFP_KERNEL); if (lopt == NULL) return -ENOMEM; - memset(lopt, 0, lopt_size); - for (lopt->max_qlen_log = 6; (1 << lopt->max_qlen_log) < sysctl_max_syn_backlog; lopt->max_qlen_log++); diff --git a/net/core/sock.c b/net/core/sock.c index e110b9004147..ed2afdb9ea2d 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -187,6 +187,99 @@ static void sock_disable_timestamp(struct sock *sk) } +int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) +{ + int err = 0; + int skb_len; + + /* Cast skb->rcvbuf to unsigned... It's pointless, but reduces + number of warnings when compiling with -W --ANK + */ + if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= + (unsigned)sk->sk_rcvbuf) { + err = -ENOMEM; + goto out; + } + + /* It would be deadlock, if sock_queue_rcv_skb is used + with socket lock! We assume that users of this + function are lock free. + */ + err = sk_filter(sk, skb, 1); + if (err) + goto out; + + skb->dev = NULL; + skb_set_owner_r(skb, sk); + + /* Cache the SKB length before we tack it onto the receive + * queue. Once it is added it no longer belongs to us and + * may be freed by other threads of control pulling packets + * from the queue. + */ + skb_len = skb->len; + + skb_queue_tail(&sk->sk_receive_queue, skb); + + if (!sock_flag(sk, SOCK_DEAD)) + sk->sk_data_ready(sk, skb_len); +out: + return err; +} +EXPORT_SYMBOL(sock_queue_rcv_skb); + +int sk_receive_skb(struct sock *sk, struct sk_buff *skb) +{ + int rc = NET_RX_SUCCESS; + + if (sk_filter(sk, skb, 0)) + goto discard_and_relse; + + skb->dev = NULL; + + bh_lock_sock(sk); + if (!sock_owned_by_user(sk)) + rc = sk->sk_backlog_rcv(sk, skb); + else + sk_add_backlog(sk, skb); + bh_unlock_sock(sk); +out: + sock_put(sk); + return rc; +discard_and_relse: + kfree_skb(skb); + goto out; +} +EXPORT_SYMBOL(sk_receive_skb); + +struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie) +{ + struct dst_entry *dst = sk->sk_dst_cache; + + if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) { + sk->sk_dst_cache = NULL; + dst_release(dst); + return NULL; + } + + return dst; +} +EXPORT_SYMBOL(__sk_dst_check); + +struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie) +{ + struct dst_entry *dst = sk_dst_get(sk); + + if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) { + sk_dst_reset(sk); + dst_release(dst); + return NULL; + } + + return dst; +} +EXPORT_SYMBOL(sk_dst_check); + /* * This is meant for all protocols to use and covers goings on * at the socket level. Everything here is generic. @@ -292,7 +385,21 @@ set_sndbuf: val = sysctl_rmem_max; set_rcvbuf: sk->sk_userlocks |= SOCK_RCVBUF_LOCK; - /* FIXME: is this lower bound the right one? */ + /* + * We double it on the way in to account for + * "struct sk_buff" etc. overhead. Applications + * assume that the SO_RCVBUF setting they make will + * allow that much actual data to be received on that + * socket. + * + * Applications are unaware that "struct sk_buff" and + * other overheads allocate from the receive buffer + * during socket buffer allocation. + * + * And after considering the possible alternatives, + * returning the value we actually used in getsockopt + * is the most desirable behavior. + */ if ((val * 2) < SOCK_MIN_RCVBUF) sk->sk_rcvbuf = SOCK_MIN_RCVBUF; else diff --git a/net/core/utils.c b/net/core/utils.c index fdc4f38bc46c..4f96f389243d 100644 --- a/net/core/utils.c +++ b/net/core/utils.c @@ -121,7 +121,7 @@ void __init net_random_init(void) { int i; - for_each_cpu(i) { + for_each_possible_cpu(i) { struct nrnd_state *state = &per_cpu(net_rand_state,i); __net_srandom(state, i+jiffies); } @@ -133,7 +133,7 @@ static int net_random_reseed(void) unsigned long seed[NR_CPUS]; get_random_bytes(seed, sizeof(seed)); - for_each_cpu(i) { + for_each_possible_cpu(i) { struct nrnd_state *state = &per_cpu(net_rand_state,i); __net_srandom(state, seed[i]); } |