Commit 113dc07d authored by Andrew Morton's avatar Andrew Morton Committed by David S. Miller

[NET]: Loopback, allocate per-cpu stats statically and fix cpu refcounting.

Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarDavid S. Miller <davem@redhat.com>
parent 6d6b21c5
...@@ -55,8 +55,9 @@ ...@@ -55,8 +55,9 @@
#include <linux/if_arp.h> /* For ARPHRD_ETHER */ #include <linux/if_arp.h> /* For ARPHRD_ETHER */
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/tcp.h> #include <linux/tcp.h>
#include <linux/percpu.h>
static struct net_device_stats *loopback_stats; static DEFINE_PER_CPU(struct net_device_stats, loopback_stats);
#define LOOPBACK_OVERHEAD (128 + MAX_HEADER + 16 + 16) #define LOOPBACK_OVERHEAD (128 + MAX_HEADER + 16 + 16)
...@@ -124,6 +125,7 @@ static void emulate_large_send_offload(struct sk_buff *skb) ...@@ -124,6 +125,7 @@ static void emulate_large_send_offload(struct sk_buff *skb)
*/ */
static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
{ {
struct net_device_stats *lb_stats;
skb_orphan(skb); skb_orphan(skb);
...@@ -142,13 +144,13 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -142,13 +144,13 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
} }
dev->last_rx = jiffies; dev->last_rx = jiffies;
if (likely(loopback_stats)) {
get_cpu_ptr(loopback_stats)->rx_bytes += skb->len; lb_stats = &per_cpu(loopback_stats, get_cpu());
get_cpu_ptr(loopback_stats)->tx_bytes += skb->len; lb_stats->rx_bytes += skb->len;
get_cpu_ptr(loopback_stats)->rx_packets++; lb_stats->tx_bytes += skb->len;
get_cpu_ptr(loopback_stats)->tx_packets++; lb_stats->rx_packets++;
put_cpu_ptr(loopback_stats); lb_stats->tx_packets++;
} put_cpu();
netif_rx(skb); netif_rx(skb);
...@@ -165,17 +167,18 @@ static struct net_device_stats *get_stats(struct net_device *dev) ...@@ -165,17 +167,18 @@ static struct net_device_stats *get_stats(struct net_device *dev)
} }
memset(stats, 0, sizeof(struct net_device_stats)); memset(stats, 0, sizeof(struct net_device_stats));
if (!loopback_stats) {
return stats;
}
for (i=0; i < NR_CPUS; i++) { for (i=0; i < NR_CPUS; i++) {
struct net_device_stats *lb_stats;
if (!cpu_possible(i)) if (!cpu_possible(i))
continue; continue;
stats->rx_bytes += per_cpu_ptr(loopback_stats, i)->rx_bytes; lb_stats = &per_cpu(loopback_stats, get_cpu());
stats->tx_bytes += per_cpu_ptr(loopback_stats, i)->tx_bytes; stats->rx_bytes += lb_stats->rx_bytes;
stats->rx_packets += per_cpu_ptr(loopback_stats, i)->rx_packets; stats->tx_bytes += lb_stats->tx_bytes;
stats->tx_packets += per_cpu_ptr(loopback_stats, i)->tx_packets; stats->rx_packets += lb_stats->rx_packets;
stats->tx_packets += lb_stats->tx_packets;
put_cpu();
} }
return stats; return stats;
...@@ -211,8 +214,6 @@ int __init loopback_init(void) ...@@ -211,8 +214,6 @@ int __init loopback_init(void)
loopback_dev.priv = stats; loopback_dev.priv = stats;
loopback_dev.get_stats = &get_stats; loopback_dev.get_stats = &get_stats;
} }
loopback_stats = alloc_percpu(struct net_device_stats);
return register_netdev(&loopback_dev); return register_netdev(&loopback_dev);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment