patch-2.4.21 linux-2.4.21/net/ipv4/icmp.c

Next file: linux-2.4.21/net/ipv4/igmp.c
Previous file: linux-2.4.21/net/ipv4/fib_semantics.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.20/net/ipv4/icmp.c linux-2.4.21/net/ipv4/icmp.c
@@ -178,55 +178,27 @@
 static struct icmp_control icmp_pointers[NR_ICMP_TYPES+1];
 
 /*
- *	The ICMP socket. This is the most convenient way to flow control
+ *	The ICMP socket(s). This is the most convenient way to flow control
  *	our ICMP output as well as maintain a clean interface throughout
  *	all layers. All Socketless IP sends will soon be gone.
  */
 	
-struct inode icmp_inode;
-struct socket *icmp_socket = &icmp_inode.u.socket_i;
+static struct inode __icmp_inode[NR_CPUS];
+#define icmp_socket (&__icmp_inode[smp_processor_id()].u.socket_i)
+#define icmp_socket_cpu(X) (&__icmp_inode[(X)].u.socket_i)
 
-/* ICMPv4 socket is only a bit non-reenterable (unlike ICMPv6,
-   which is strongly non-reenterable). A bit later it will be made
-   reenterable and the lock may be removed then.
- */
-
-static int icmp_xmit_holder = -1;
-
-static int icmp_xmit_lock_bh(void)
-{
-	if (!spin_trylock(&icmp_socket->sk->lock.slock)) {
-		if (icmp_xmit_holder == smp_processor_id())
-			return -EAGAIN;
-		spin_lock(&icmp_socket->sk->lock.slock);
-	}
-	icmp_xmit_holder = smp_processor_id();
-	return 0;
-}
-
-static __inline__ int icmp_xmit_lock(void)
+static void icmp_xmit_lock(void)
 {
-	int ret;
 	local_bh_disable();
-	ret = icmp_xmit_lock_bh();
-	if (ret)
-		local_bh_enable();
-	return ret;
-}
-
-static void icmp_xmit_unlock_bh(void)
-{
-	icmp_xmit_holder = -1;
-	spin_unlock(&icmp_socket->sk->lock.slock);
+	if (unlikely(!spin_trylock(&icmp_socket->sk->lock.slock)))
+		BUG();
 }
 
-static __inline__ void icmp_xmit_unlock(void)
+static void icmp_xmit_unlock(void)
 {
-	icmp_xmit_unlock_bh();
-	local_bh_enable();
+	spin_unlock_bh(&icmp_socket->sk->lock.slock);
 }
 
-
 /*
  *	Send an ICMP frame.
  */
@@ -348,8 +320,7 @@
 	if (ip_options_echo(&icmp_param->replyopts, skb))
 		return;
 
-	if (icmp_xmit_lock_bh())
-		return;
+	icmp_xmit_lock();
 
 	icmp_param->data.icmph.checksum=0;
 	icmp_param->csum=0;
@@ -374,7 +345,7 @@
 	}
 	ip_rt_put(rt);
 out:
-	icmp_xmit_unlock_bh();
+	icmp_xmit_unlock();
 }
 
 
@@ -456,8 +427,7 @@
 		}
 	}
 
-	if (icmp_xmit_lock())
-		return;
+	icmp_xmit_lock();
 
 	/*
 	 *	Construct source address and options.
@@ -985,29 +955,32 @@
 
 void __init icmp_init(struct net_proto_family *ops)
 {
-	int err;
+	int err, i;
 
-	icmp_inode.i_mode = S_IFSOCK;
-	icmp_inode.i_sock = 1;
-	icmp_inode.i_uid = 0;
-	icmp_inode.i_gid = 0;
-	init_waitqueue_head(&icmp_inode.i_wait);
-	init_waitqueue_head(&icmp_inode.u.socket_i.wait);
-
-	icmp_socket->inode = &icmp_inode;
-	icmp_socket->state = SS_UNCONNECTED;
-	icmp_socket->type=SOCK_RAW;
-
-	if ((err=ops->create(icmp_socket, IPPROTO_ICMP))<0)
-		panic("Failed to create the ICMP control socket.\n");
-	icmp_socket->sk->allocation=GFP_ATOMIC;
-	icmp_socket->sk->sndbuf = SK_WMEM_MAX*2;
-	icmp_socket->sk->protinfo.af_inet.ttl = MAXTTL;
-	icmp_socket->sk->protinfo.af_inet.pmtudisc = IP_PMTUDISC_DONT;
-
-	/* Unhash it so that IP input processing does not even
-	 * see it, we do not wish this socket to see incoming
-	 * packets.
-	 */
-	icmp_socket->sk->prot->unhash(icmp_socket->sk);
+	for (i = 0; i < NR_CPUS; i++) {
+		__icmp_inode[i].i_mode = S_IFSOCK;
+		__icmp_inode[i].i_sock = 1;
+		__icmp_inode[i].i_uid = 0;
+		__icmp_inode[i].i_gid = 0;
+		init_waitqueue_head(&__icmp_inode[i].i_wait);
+		init_waitqueue_head(&__icmp_inode[i].u.socket_i.wait);
+
+		icmp_socket_cpu(i)->inode = &__icmp_inode[i];
+		icmp_socket_cpu(i)->state = SS_UNCONNECTED;
+		icmp_socket_cpu(i)->type = SOCK_RAW;
+
+		if ((err=ops->create(icmp_socket_cpu(i), IPPROTO_ICMP)) < 0)
+			panic("Failed to create the ICMP control socket.\n");
+
+		icmp_socket_cpu(i)->sk->allocation=GFP_ATOMIC;
+		icmp_socket_cpu(i)->sk->sndbuf = SK_WMEM_MAX*2;
+		icmp_socket_cpu(i)->sk->protinfo.af_inet.ttl = MAXTTL;
+		icmp_socket_cpu(i)->sk->protinfo.af_inet.pmtudisc = IP_PMTUDISC_DONT;
+
+		/* Unhash it so that IP input processing does not even
+		 * see it, we do not wish this socket to see incoming
+		 * packets.
+		 */
+		icmp_socket_cpu(i)->sk->prot->unhash(icmp_socket_cpu(i)->sk);
+	}
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)