Re: panic: mutex inp not owned at /usr/src/sys/netinet/tcp_output.c:140

From: Robert Watson <rwatson_at_FreeBSD.org>
Date: Thu, 5 Aug 2004 09:43:41 -0400 (EDT)
On Thu, 5 Aug 2004, Jun Kuriyama wrote:

> 
> This is "2004-08-05 00:35:00 UTC"'s kernel.  (Just before rwatson's
> bpf commit)
> 
> 
> panic: mutex inp not owned at /usr/src/sys/netinet/tcp_output.c:140

Could you try the attached patch?  This modifies the IPv6 code to match
the IPv4 code in passing in the "inpcbinfo" reference for a protocol,
rather than just its inpcb list.  This allows in6_pcbnotify() to lock the
structure before walking it.  It also acquires the per-pcb locks before
notifying each pcb of an event.

Sorry about the panic!

Index: in6_pcb.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet6/in6_pcb.c,v
retrieving revision 1.57
diff -u -r1.57 in6_pcb.c
--- in6_pcb.c	28 Jul 2004 13:03:07 -0000	1.57
+++ in6_pcb.c	5 Aug 2004 13:42:44 -0000
_at__at_ -610,8 +610,8 _at__at_
  * Must be called at splnet.
  */
 void
-in6_pcbnotify(head, dst, fport_arg, src, lport_arg, cmd, cmdarg, notify)
-	struct inpcbhead *head;
+in6_pcbnotify(pcbinfo, dst, fport_arg, src, lport_arg, cmd, cmdarg, notify)
+	struct inpcbinfo *pcbinfo;
 	struct sockaddr *dst;
 	const struct sockaddr *src;
 	u_int fport_arg, lport_arg;
_at__at_ -619,6 +619,7 _at__at_
 	void *cmdarg;
 	struct inpcb *(*notify) __P((struct inpcb *, int));
 {
+	struct inpcbhead *head;
 	struct inpcb *inp, *ninp;
 	struct sockaddr_in6 sa6_src, *sa6_dst;
 	u_short	fport = fport_arg, lport = lport_arg;
_at__at_ -656,11 +657,16 _at__at_
 	}
 	errno = inet6ctlerrmap[cmd];
 	s = splnet();
+	head = pcbinfo->listhead;
+	INP_INFO_WLOCK(pcbinfo);
  	for (inp = LIST_FIRST(head); inp != NULL; inp = ninp) {
+		INP_LOCK(inp);
  		ninp = LIST_NEXT(inp, inp_list);
 
- 		if ((inp->inp_vflag & INP_IPV6) == 0)
+ 		if ((inp->inp_vflag & INP_IPV6) == 0) {
+			INP_UNLOCK(inp);
 			continue;
+		}
 
 		/*
 		 * If the error designates a new path MTU for a destination
_at__at_ -698,13 +704,17 _at__at_
 			 (!IN6_IS_ADDR_UNSPECIFIED(&sa6_src.sin6_addr) &&
 			  !IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr,
 					      &sa6_src.sin6_addr)) ||
-			 (fport && inp->inp_fport != fport))
+			 (fport && inp->inp_fport != fport)) {
+			INP_UNLOCK(inp);
 			continue;
+		}
 
 	  do_notify:
 		if (notify)
 			(*notify)(inp, errno);
+		INP_UNLOCK(inp);
 	}
+	INP_INFO_WUNLOCK(pcbinfo);
 	splx(s);
 }
 
Index: in6_pcb.h
===================================================================
RCS file: /home/ncvs/src/sys/netinet6/in6_pcb.h,v
retrieving revision 1.14
diff -u -r1.14 in6_pcb.h
--- in6_pcb.h	7 Apr 2004 20:46:15 -0000	1.14
+++ in6_pcb.h	5 Aug 2004 13:37:55 -0000
_at__at_ -85,7 +85,7 _at__at_
 	in6_pcblookup_hash __P((struct inpcbinfo *,
 				struct in6_addr *, u_int, struct in6_addr *,
 				u_int, int, struct ifnet *));
-void	in6_pcbnotify __P((struct inpcbhead *, struct sockaddr *,
+void	in6_pcbnotify __P((struct inpcbinfo *, struct sockaddr *,
 			   u_int, const struct sockaddr *, u_int, int, void *,
 			   struct inpcb *(*)(struct inpcb *, int)));
 struct inpcb *
Index: raw_ip6.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet6/raw_ip6.c,v
retrieving revision 1.43
diff -u -r1.43 raw_ip6.c
--- raw_ip6.c	27 Jul 2004 23:45:19 -0000	1.43
+++ raw_ip6.c	5 Aug 2004 13:40:50 -0000
_at__at_ -298,7 +298,8 _at__at_
 		sa6_src = &sa6_any;
 	}
 
-	(void) in6_pcbnotify(&ripcb, sa, 0, (const struct sockaddr *)sa6_src,
+	(void) in6_pcbnotify(&ripcbinfo, sa, 0,
+			     (const struct sockaddr *)sa6_src,
 			     0, cmd, cmdarg, notify);
 }
 
Index: udp6_usrreq.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet6/udp6_usrreq.c,v
retrieving revision 1.50
diff -u -r1.50 udp6_usrreq.c
--- udp6_usrreq.c	27 Jul 2004 23:45:19 -0000	1.50
+++ udp6_usrreq.c	5 Aug 2004 13:41:22 -0000
_at__at_ -444,11 +444,11 _at__at_
 		bzero(&uh, sizeof(uh));
 		m_copydata(m, off, sizeof(*uhp), (caddr_t)&uh);
 
-		(void) in6_pcbnotify(&udb, sa, uh.uh_dport,
+		(void) in6_pcbnotify(&udbinfo, sa, uh.uh_dport,
 				     (struct sockaddr *)ip6cp->ip6c_src,
 				     uh.uh_sport, cmd, cmdarg, notify);
 	} else
-		(void) in6_pcbnotify(&udb, sa, 0,
+		(void) in6_pcbnotify(&udbinfo, sa, 0,
 				     (const struct sockaddr *)sa6_src,
 				     0, cmd, cmdarg, notify);
 }
Received on Thu Aug 05 2004 - 11:45:00 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:38:04 UTC