syncache_socket(): fix abort path by calling pru_abort directly
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Thu, 22 Jan 2009 09:13:20 +0000 (17:13 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Sat, 31 Jan 2009 06:22:21 +0000 (14:22 +0800)
On syncache_socket() abort path, the inp's {fport,lport,faddr,laddr}
is either incomplete or half destroyed, which causes tcp_soport()
mapping the socket to a wrong CPU.  However, in syncache code, inp
is only accessed or created by its owner CPU, i.e. we are already on
the inp's owner CPU during the socket aborting.

Add soabort_oncpu(), which calls pru_abort directly.  Use it on
syncache_socket() abort path.

sys/kern/uipc_msg.c
sys/kern/uipc_socket.c
sys/netinet/tcp_syncache.c
sys/sys/socketops.h
sys/sys/socketvar.h

index cd41113..e695120 100644 (file)
@@ -92,6 +92,18 @@ so_pru_aborta(struct socket *so)
        lwkt_sendmsg(port, &msg->nm_netmsg.nm_lmsg);
 }
 
+/*
+ * Abort a socket and free it.  Called from soabort_oncpu() only.
+ * Caller must make sure that the current CPU is inpcb's owner CPU.
+ *
+ * The SS_ABORTING flag must already be set.
+ */
+void
+so_pru_abort_oncpu(struct socket *so)
+{
+       so->so_proto->pr_usrreqs->pru_abort(so);
+}
+
 int
 so_pru_accept(struct socket *so, struct sockaddr **nam)
 {
index f485de3..cd2d27c 100644 (file)
@@ -407,6 +407,15 @@ soaborta(struct socket *so)
        }
 }
 
+void
+soabort_oncpu(struct socket *so)
+{
+       if ((so->so_state & SS_ABORTING) == 0) {
+               so->so_state |= SS_ABORTING;
+               so_pru_abort_oncpu(so);
+       }
+}
+
 int
 soaccept(struct socket *so, struct sockaddr **nam)
 {
index f16ab8b..727e354 100644 (file)
@@ -800,7 +800,7 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
 
 abort:
        if (so != NULL)
-               soaborta(so);
+               soabort_oncpu(so);
        return (NULL);
 }
 
index 43def53..e6ed498 100644 (file)
@@ -75,6 +75,7 @@ so_pru_soreceive(struct socket *so, struct sockaddr **paddr, struct uio *uio,
 
 void so_pru_abort (struct socket *so);
 void so_pru_aborta (struct socket *so);
+void so_pru_abort_oncpu (struct socket *so);
 int so_pru_accept (struct socket *so, struct sockaddr **nam);
 int so_pru_attach (struct socket *so, int proto, struct pru_attach_info *ai);
 int so_pru_bind (struct socket *so, struct sockaddr *nam, struct thread *td);
index 02e3548..4300a06 100644 (file)
@@ -357,6 +357,7 @@ int _ssb_lock (struct signalsockbuf *sb);
 
 void   soabort (struct socket *so);
 void   soaborta (struct socket *so);
+void   soabort_oncpu (struct socket *so);
 int    soaccept (struct socket *so, struct sockaddr **nam);
 struct socket *soalloc (int waitok);
 int    sobind (struct socket *so, struct sockaddr *nam, struct thread *td);