svn commit: r301199 - head/sys/dev/xen/netfront

Roger Pau Monné royger at FreeBSD.org
Thu Jun 2 11:18:03 UTC 2016


Author: royger
Date: Thu Jun  2 11:18:02 2016
New Revision: 301199
URL: https://svnweb.freebsd.org/changeset/base/301199

Log:
  xen-netfront: fix two hotplug related issues
  
  This patch fixes two issues seen on hot-unplug. The first one is a panic
  caused by calling ether_ifdetach after freeing the internal netfront queue
  structures. ether_ifdetach will call xn_qflush, and this needs to be done
  before freeing the queues. This prevents the following panic:
  
  Fatal trap 9: general protection fault while in kernel mode
  cpuid = 2; apic id = 04
  instruction pointer	= 0x20:0xffffffff80b1687f
  stack pointer	        = 0x28:0xfffffe009239e770
  frame pointer	        = 0x28:0xfffffe009239e780
  code segment		= base 0x0, limit 0xfffff, type 0x1b
  			= DPL 0, pres 1, long 1, def32 0, gran 1
  processor eflags	= interrupt enabled, resume, IOPL = 0
  current process		= 0 (thread taskq)
  [ thread pid 0 tid 100015 ]
  Stopped at      strlen+0x1f:    movq    (%rcx),%rax
  db> bt
  Tracing pid 0 tid 100015 td 0xfffff800038a6000
  strlen() at strlen+0x1f/frame 0xfffffe009239e780
  kvprintf() at kvprintf+0xfa0/frame 0xfffffe009239e890
  vsnprintf() at vsnprintf+0x31/frame 0xfffffe009239e8b0
  kassert_panic() at kassert_panic+0x5a/frame 0xfffffe009239e920
  __mtx_lock_flags() at __mtx_lock_flags+0x164/frame 0xfffffe009239e970
  xn_qflush() at xn_qflush+0x59/frame 0xfffffe009239e9b0
  if_detach() at if_detach+0x17e/frame 0xfffffe009239ea10
  netif_free() at netif_free+0x97/frame 0xfffffe009239ea30
  netfront_detach() at netfront_detach+0x11/frame 0xfffffe009239ea40
  [...]
  
  Another panic can be triggered by hot-plugging a NIC:
  
  Fatal trap 18: integer divide fault while in kernel mode
  cpuid = 0; apic id = 00
  instruction pointer	= 0x20:0xffffffff80902203
  stack pointer	        = 0x28:0xfffffe00508d3660
  frame pointer	        = 0x28:0xfffffe00508d36a0
  code segment		= base 0x0, limit 0xfffff, type 0x1b
  			= DPL 0, pres 1, long 1, def32 0, gran 1
  processor eflags	= interrupt enabled, resume, IOPL = 0
  current process		= 2960 (ifconfig)
  [ thread pid 2960 tid 100088 ]
  Stopped at      xn_txq_mq_start+0x33:   divl    %esi,%eax
  db> bt
  Tracing pid 2960 tid 100088 td 0xfffff8000850aa00
  xn_txq_mq_start() at xn_txq_mq_start+0x33/frame 0xfffffe00508d36a0
  ether_output() at ether_output+0x570/frame 0xfffffe00508d3720
  arprequest() at arprequest+0x433/frame 0xfffffe00508d3820
  arp_ifinit() at arp_ifinit+0x49/frame 0xfffffe00508d3850
  xn_ioctl() at xn_ioctl+0x1a2/frame 0xfffffe00508d3890
  in_control() at in_control+0x882/frame 0xfffffe00508d3910
  ifioctl() at ifioctl+0xda1/frame 0xfffffe00508d39a0
  kern_ioctl() at kern_ioctl+0x246/frame 0xfffffe00508d3a00
  sys_ioctl() at sys_ioctl+0x171/frame 0xfffffe00508d3ae0
  amd64_syscall() at amd64_syscall+0x2db/frame 0xfffffe00508d3bf0
  Xfast_syscall() at Xfast_syscall+0xfb/frame 0xfffffe00508d3bf0
  --- syscall (54, FreeBSD ELF64, sys_ioctl), rip = 0x8011e185a, rsp =
  0x7fffffffe478, rbp = 0x7fffffffe4c0 ---
  
  This is caused by marking the driver as active before it's fully
  initialized, and thus calling xn_txq_mq_start with num_queues set to 0.
  
  Reviewed by:		Wei Liu <wei.liu2 at citrix.com>
  Sponsored by:		Citrix Systems R&D
  Differential revision:	https://reviews.freebsd.org/D6646

Modified:
  head/sys/dev/xen/netfront/netfront.c

Modified: head/sys/dev/xen/netfront/netfront.c
==============================================================================
--- head/sys/dev/xen/netfront/netfront.c	Thu Jun  2 11:16:35 2016	(r301198)
+++ head/sys/dev/xen/netfront/netfront.c	Thu Jun  2 11:18:02 2016	(r301199)
@@ -1704,7 +1704,7 @@ xn_ifinit_locked(struct netfront_info *n
 
 	ifp = np->xn_ifp;
 
-	if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+	if (ifp->if_drv_flags & IFF_DRV_RUNNING || !netfront_carrier_ok(np))
 		return;
 
 	xn_stop(np);
@@ -2088,6 +2088,8 @@ xn_txq_mq_start(struct ifnet *ifp, struc
 	np = ifp->if_softc;
 	npairs = np->num_queues;
 
+	KASSERT(npairs != 0, ("called with 0 available queues"));
+
 	/* check if flowid is set */
 	if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE)
 		i = m->m_pkthdr.flowid % npairs;
@@ -2202,9 +2204,9 @@ netif_free(struct netfront_info *np)
 	xn_stop(np);
 	XN_UNLOCK(np);
 	netif_disconnect_backend(np);
+	ether_ifdetach(np->xn_ifp);
 	free(np->rxq, M_DEVBUF);
 	free(np->txq, M_DEVBUF);
-	ether_ifdetach(np->xn_ifp);
 	if_free(np->xn_ifp);
 	np->xn_ifp = NULL;
 	ifmedia_removeall(&np->sc_media);


More information about the svn-src-all mailing list