cpumask: use percpu allocations instead of arrays in IPv4

Instead of allocating an nr_cpu_ids array, most places should be using
percpu_alloc().  This doesn't waste space if cpu numbers aren't
contiguous.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
---
 include/net/netns/ipv4.h |    2 +-
 net/ipv4/icmp.c          |   19 +++++++++----------
 2 files changed, 10 insertions(+), 11 deletions(-)

diff -r e4e56fba0e40 include/net/netns/ipv4.h
--- a/include/net/netns/ipv4.h	Tue Nov 18 23:50:59 2008 +1030
+++ b/include/net/netns/ipv4.h	Wed Nov 19 00:06:51 2008 +1030
@@ -28,7 +28,7 @@
 	struct hlist_head	*fib_table_hash;
 	struct sock		*fibnl;
 
-	struct sock		**icmp_sk;
+	struct sock		**icmp_sk_pcpu;
 	struct sock		*tcp_sock;
 
 	struct netns_frags	frags;
diff -r e4e56fba0e40 net/ipv4/icmp.c
--- a/net/ipv4/icmp.c	Tue Nov 18 23:50:59 2008 +1030
+++ b/net/ipv4/icmp.c	Wed Nov 19 00:06:51 2008 +1030
@@ -201,7 +201,7 @@
  */
 static struct sock *icmp_sk(struct net *net)
 {
-	return net->ipv4.icmp_sk[smp_processor_id()];
+	return *per_cpu_ptr(net->ipv4.icmp_sk_pcpu, smp_processor_id());
 }
 
 static inline struct sock *icmp_xmit_lock(struct net *net)
@@ -1136,18 +1136,17 @@
 	int i;
 
 	for_each_possible_cpu(i)
-		inet_ctl_sock_destroy(net->ipv4.icmp_sk[i]);
-	kfree(net->ipv4.icmp_sk);
-	net->ipv4.icmp_sk = NULL;
+		inet_ctl_sock_destroy(*per_cpu_ptr(net->ipv4.icmp_sk_pcpu, i));
+	free_percpu(net->ipv4.icmp_sk_pcpu);
+	net->ipv4.icmp_sk_pcpu = NULL;
 }
 
 static int __net_init icmp_sk_init(struct net *net)
 {
 	int i, err;
 
-	net->ipv4.icmp_sk =
-		kzalloc(nr_cpu_ids * sizeof(struct sock *), GFP_KERNEL);
-	if (net->ipv4.icmp_sk == NULL)
+	net->ipv4.icmp_sk_pcpu = alloc_percpu(struct sock *);
+	if (net->ipv4.icmp_sk_pcpu == NULL)
 		return -ENOMEM;
 
 	for_each_possible_cpu(i) {
@@ -1158,7 +1157,7 @@
 		if (err < 0)
 			goto fail;
 
-		net->ipv4.icmp_sk[i] = sk;
+		*per_cpu_ptr(net->ipv4.icmp_sk_pcpu, i) = sk;
 
 		/* Enough space for 2 64K ICMP packets, including
 		 * sk_buff struct overhead.
@@ -1196,8 +1195,8 @@
 
 fail:
 	for_each_possible_cpu(i)
-		inet_ctl_sock_destroy(net->ipv4.icmp_sk[i]);
-	kfree(net->ipv4.icmp_sk);
+		inet_ctl_sock_destroy(*per_cpu_ptr(net->ipv4.icmp_sk_pcpu, i));
+	free_percpu(net->ipv4.icmp_sk_pcpu);
 	return err;
 }
 
