summaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
Diffstat (limited to 'net/core')
-rw-r--r--net/core/dev.c71
-rw-r--r--net/core/dv.c5
-rw-r--r--net/core/flow.c8
-rw-r--r--net/core/gen_estimator.c3
-rw-r--r--net/core/neighbour.c16
-rw-r--r--net/core/net-sysfs.c2
-rw-r--r--net/core/request_sock.c4
-rw-r--r--net/core/sock.c109
-rw-r--r--net/core/utils.c4
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]);
}