cpumask: use percpu allocations instead of arrays in IPv6

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/ipv6.h |    2 +-
 net/ipv6/icmp.c          |   17 ++++++++---------
 2 files changed, 9 insertions(+), 10 deletions(-)

diff -r d0e8d4cd0588 include/net/netns/ipv6.h
--- a/include/net/netns/ipv6.h	Tue Nov 18 23:57:24 2008 +1030
+++ b/include/net/netns/ipv6.h	Wed Nov 19 00:06:27 2008 +1030
@@ -51,7 +51,7 @@
 	struct fib6_table       *fib6_local_tbl;
 	struct fib_rules_ops    *fib6_rules_ops;
 #endif
-	struct sock		**icmp_sk;
+	struct sock		**icmp_sk_pcpu;
 	struct sock             *ndisc_sk;
 	struct sock             *tcp_sk;
 	struct sock             *igmp_sk;
diff -r d0e8d4cd0588 net/ipv6/icmp.c
--- a/net/ipv6/icmp.c	Tue Nov 18 23:57:24 2008 +1030
+++ b/net/ipv6/icmp.c	Wed Nov 19 00:06:27 2008 +1030
@@ -81,7 +81,7 @@
  */
 static inline struct sock *icmpv6_sk(struct net *net)
 {
-	return net->ipv6.icmp_sk[smp_processor_id()];
+	return *per_cpu_ptr(net->ipv6.icmp_sk_pcpu, smp_processor_id());
 }
 
 static int icmpv6_rcv(struct sk_buff *skb);
@@ -804,9 +804,8 @@
 	struct sock *sk;
 	int err, i, j;
 
-	net->ipv6.icmp_sk =
-		kzalloc(nr_cpu_ids * sizeof(struct sock *), GFP_KERNEL);
-	if (net->ipv6.icmp_sk == NULL)
+	net->ipv6.icmp_sk_pcpu = alloc_percpu(struct sock *);
+	if (net->ipv6.icmp_sk_pcpu == NULL)
 		return -ENOMEM;
 
 	for_each_possible_cpu(i) {
@@ -820,7 +819,7 @@
 			goto fail;
 		}
 
-		net->ipv6.icmp_sk[i] = sk;
+		*per_cpu_ptr(net->ipv6.icmp_sk_pcpu, i) = sk;
 
 		/*
 		 * Split off their lock-class, because sk->sk_dst_lock
@@ -841,8 +840,8 @@
 
  fail:
 	for (j = 0; j < i; j++)
-		inet_ctl_sock_destroy(net->ipv6.icmp_sk[j]);
-	kfree(net->ipv6.icmp_sk);
+		inet_ctl_sock_destroy(*per_cpu_ptr(net->ipv6.icmp_sk_pcpu, i));
+	free_percpu(net->ipv6.icmp_sk_pcpu);
 	return err;
 }
 
@@ -851,9 +850,9 @@
 	int i;
 
 	for_each_possible_cpu(i) {
-		inet_ctl_sock_destroy(net->ipv6.icmp_sk[i]);
+		inet_ctl_sock_destroy(*per_cpu_ptr(net->ipv6.icmp_sk_pcpu, i));
 	}
-	kfree(net->ipv6.icmp_sk);
+	free_percpu(net->ipv6.icmp_sk_pcpu);
 }
 
 static struct pernet_operations icmpv6_sk_ops = {
