Date: Tue, 16 Mar 2010 08:45:28 +0200 From: Mikolaj Golub <to.my.trociny@gmail.com> To: freebsd-net@freebsd.org Cc: Kostik Belousov <kostikbel@gmail.com> Subject: Re: kmem leakage on tun/tap device removal Message-ID: <86634wdat3.fsf@zhuzha.ua1> References: <mailpost.1267356711.2478384.62287.mailing.freebsd.net@FreeBSD.cs.nctu.edu.tw>
next in thread | previous in thread | raw e-mail | index | archive | help
--=-=-= Content-Type: text/plain; charset=gb2312 Content-Transfer-Encoding: quoted-printable On Feb 28, 1:30 pm, to.my.trociny@gmail.com (Mikolaj Golub) wrote: > But I have faced with another issue (not related to your patch, as it is > observed with unpatched kernel too). When I try to run concurrently two > create/destroy scripts with the same interface the system panics: >=20 > Unread portion of the kernel message buffer: > panic: Bad link elm 0xc5f1a800 next->prev !=3D elm > cpuid =3D 2 > KDB: enter: panic > exclusive sleep mutex if_clone lock (if_clone lock) r =3D 0 (0xc0da1cf0) = locked @ /usr/src/sys/net/if_clone.c:248 > exclusive sleep mutex if_clone lock (if_clone lock) r =3D 0 (0xc0da1cf0) = locked @ /usr/src/sys/net/if_clone.c:248 > exclusive sx so_rcv_sx (so_rcv_sx) r =3D 0 (0xc6cd3560) locked @ /usr/src= /sys/kern/uipc_sockbuf.c:148 > exclusive sx so_rcv_sx (so_rcv_sx) r =3D 0 (0xc6b4dbd0) locked @ /usr/src= /sys/kern/uipc_sockbuf.c:148 > Physical memory: 2019 MB > Dumping 160 MB: 145 129 113 97 81 65 49 33 17 1 >=20 > #0 doadump () at pcpu.h:246 > 246 __asm __volatile("movl %%fs:0,%0" : "=3Dr" (td)); > (kgdb) bt > #0 doadump () at pcpu.h:246 > #1 0xc04e8bb9 in db_fncall (dummy1=3D-1064515926, dummy2=3D0, dummy3=3D-= 1, dummy4=3D0xe83f4834 "HH?=A8=A8") > at /usr/src/sys/ddb/db_command.c:548 > #2 0xc04e8fef in db_command (last_cmdp=3D0xc0de14dc, cmd_table=3D0x0, do= pager=3D0) > at /usr/src/sys/ddb/db_command.c:445 > #3 0xc04e90a4 in db_command_script (command=3D0xc0de2404 "call doadump") > at /usr/src/sys/ddb/db_command.c:516 > #4 0xc04ed1d0 in db_script_exec (scriptname=3D0xe83f4940 "kdb.enter.pani= c", warnifnotfound=3DVariable "warnifnotfound" is not available. > ) > at /usr/src/sys/ddb/db_script.c:302 > #5 0xc04ed2b7 in db_script_kdbenter (eventname=3D0xc0ca1948 "panic") at = /usr/src/sys/ddb/db_script.c:324 > #6 0xc04eaf98 in db_trap (type=3D3, code=3D0) at /usr/src/sys/ddb/db_mai= n.c:228 > #7 0xc08cc526 in kdb_trap (type=3D3, code=3D0, tf=3D0xe83f4a7c) at /usr/= src/sys/kern/subr_kdb.c:535 > #8 0xc0bdd38b in trap (frame=3D0xe83f4a7c) at /usr/src/sys/i386/i386/tra= p.c:690 > #9 0xc0bbef1b in calltrap () at /usr/src/sys/i386/i386/exception.s:165 > #10 0xc08cc6aa in kdb_enter (why=3D0xc0ca1948 "panic", msg=3D0xc0ca1948 "= panic") at cpufunc.h:71 > #11 0xc089d716 in panic (fmt=3D0xc0c3c80c "Bad link elm %p next->prev != =3D elm") > at /usr/src/sys/kern/kern_shutdown.c:562 > #12 0xc094e7fb in if_clone_destroyif (ifc=3D0xc0da1cc0, ifp=3D0xc5f1a800)= at /usr/src/sys/net/if_clone.c:249 > #13 0xc094eb52 in if_clone_destroy (name=3D0xc664ac20 "tun0") at /usr/src= /sys/net/if_clone.c:227 > #14 0xc094c8a6 in ifioctl (so=3D0xc6e0a9a8, cmd=3D2149607801, data=3D0xc6= 64ac20 "tun0", td=3D0xc66c0d80) > at /usr/src/sys/net/if.c:2412 > #15 0xc08e8b25 in soo_ioctl (fp=3D0xc6d46af0, cmd=3D2149607801, data=3D0x= c664ac20, active_cred=3D0xc5f62280, > td=3D0xc66c0d80) at /usr/src/sys/kern/sys_socket.c:212 > #16 0xc08e31bd in kern_ioctl (td=3D0xc66c0d80, fd=3D3, com=3D2149607801, = data=3D0xc664ac20 "tun0") at file.h:262 > #17 0xc08e3344 in ioctl (td=3D0xc66c0d80, uap=3D0xe83f4cf8) at /usr/src/s= ys/kern/sys_generic.c:678 > #18 0xc0bdca33 in syscall (frame=3D0xe83f4d38) at /usr/src/sys/i386/i386/= trap.c:1078 > #19 0xc0bbefb0 in Xint0x80_syscall () at /usr/src/sys/i386/i386/exception= .s:261 > #20 0x00000033 in ?? () > Previous frame inner to this frame (corrupt stack?) > (kgdb) fr 12 > #12 0xc094e7fb in if_clone_destroyif (ifc=3D0xc0da1cc0, ifp=3D0xc5f1a800)= at /usr/src/sys/net/if_clone.c:249 > 249 IFC_IFLIST_REMOVE(ifc, ifp); > (kgdb) list > 244 * switch to the vnet context of the target vnet. > 245 */ > 246 CURVNET_SET_QUIET(ifp->if_vnet); > 247 > 248 IF_CLONE_LOCK(ifc); > 249 IFC_IFLIST_REMOVE(ifc, ifp); > 250 IF_CLONE_UNLOCK(ifc); > 251 > 252 if_delgroup(ifp, ifc->ifc_name); > 253 >=20 Actually, this issue has already been reported (kern/116837, see the bottom= of the discussion) and there was a patch provided by Takahiro Kurosawa [check that ifp is on ifc->ifc_iflist before calling IFC_IFLIST_REMOVE(ifc, ifp)]. Although he mentioned that another race was still possible. I have tried the patch and yes it makes the situation much better: the box did not crush when running two "ifconfig tun0 create/destroy" scripts concurrently, but when I tried 8 concurrent processes :-) it crashed after a couple minutes in anoth= er place: (kgdb) bt #0 doadump () at pcpu.h:246 #1 0xc04ec379 in db_fncall (dummy1=3D1, dummy2=3D0, dummy3=3D-1056947200, = dummy4=3D0xe86848e4 "") at /usr/src/sys/ddb/db_command.c:548 #2 0xc04ec771 in db_command (last_cmdp=3D0xc0e04d1c, cmd_table=3D0x0, dopa= ger=3D1) at /usr/src/sys/ddb/db_command.c:445 #3 0xc04ec8ca in db_command_loop () at /usr/src/sys/ddb/db_command.c:498 #4 0xc04ee76d in db_trap (type=3D12, code=3D0) at /usr/src/sys/ddb/db_main= .c:229 #5 0xc08d7d06 in kdb_trap (type=3D12, code=3D0, tf=3D0xe8684ad0) at /usr/s= rc/sys/kern/subr_kdb.c:535 #6 0xc0bea66f in trap_fatal (frame=3D0xe8684ad0, eva=3D3735929054) at /usr= /src/sys/i386/i386/trap.c:929 #7 0xc0beaf90 in trap (frame=3D0xe8684ad0) at /usr/src/sys/i386/i386/trap.= c:328 #8 0xc0bccd7b in calltrap () at /usr/src/sys/i386/i386/exception.s:165 #9 0xc094bfa6 in strcmp (s1=3D0xc663686b "vmnet", s2=3D0xdeadc0de <Address= 0xdeadc0de out of bounds>) at /usr/src/sys/libkern/strcmp.c:45 #10 0xc095a9c2 in if_clone_destroy (name=3D0xc5f7d840 "tun0") at /usr/src/s= ys/net/if_clone.c:209 #11 0xc09584d6 in ifioctl (so=3D0xc721a80c, cmd=3D2149607801, data=3D0xc5f7= d840 "tun0", td=3D0xc731fb90) at /usr/src/sys/net/if.c:2486 #12 0xc08f4615 in soo_ioctl (fp=3D0xc5f1ca80, cmd=3D2149607801, data=3D0xc5= f7d840, active_cred=3D0xc5ed4180,=20 td=3D0xc731fb90) at /usr/src/sys/kern/sys_socket.c:212 #13 0xc08eec8d in kern_ioctl (td=3D0xc731fb90, fd=3D3, com=3D2149607801, da= ta=3D0xc5f7d840 "tun0") at file.h:262 #14 0xc08eee14 in ioctl (td=3D0xc731fb90, uap=3D0xe8684cf8) at /usr/src/sys= /kern/sys_generic.c:678 #15 0xc0beab40 in syscall (frame=3D0xe8684d38) at /usr/src/sys/i386/i386/tr= ap.c:1111 #16 0xc0bcce10 in Xint0x80_syscall () at /usr/src/sys/i386/i386/exception.s= :261 #17 0x00000033 in ?? () Previous frame inner to this frame (corrupt stack?) (kgdb) fr 10 #10 0xc095a9c2 in if_clone_destroy (name=3D0xc5f7d840 "tun0") at /usr/src/s= ys/net/if_clone.c:209 209 if (strcmp(ifc->ifc_name, ifp->if_dname) =3D=3D 0) { (kgdb) list 204 return (ENXIO); 205=20=20=20=20=20 206 /* Find the cloner for this interface */ 207 IF_CLONERS_LOCK(); 208 LIST_FOREACH(ifc, &V_if_cloners, ifc_list) { 209 if (strcmp(ifc->ifc_name, ifp->if_dname) =3D=3D 0) { 210 break; 211 } 212 } 213 #ifdef VIMAGE (kgdb) p ifc->ifc_name $1 =3D 0xc663686b "vmnet" (kgdb) p ifp->if_dname $2 =3D 0xdeadc0de <Address 0xdeadc0de out of bounds> (kgdb)=20 May be we can use ifunit_ref() instead of ifunit() like in the patch below = to avoid this race (the patch also includes Takahiro Kurosawa's patch from kern/116837)? I was running 32 "ifconfig tun0 create/destroy" on the patched kernel throu= gh all the night and did not manage to crash the system. --=20 Mikolaj Golub --=-=-= Content-Type: text/x-patch Content-Disposition: inline; filename=if_clone.c.if_clone_destroy.patch --- sys/net/if_clone.c.orig 2010-02-28 16:39:30.000000000 +0200 +++ sys/net/if_clone.c 2010-03-15 23:46:56.000000000 +0200 @@ -196,10 +196,11 @@ if_clone_createif(struct if_clone *ifc, int if_clone_destroy(const char *name) { + int err; struct if_clone *ifc; struct ifnet *ifp; - ifp = ifunit(name); + ifp = ifunit_ref(name); if (ifp == NULL) return (ENXIO); @@ -221,10 +222,14 @@ if_clone_destroy(const char *name) } #endif IF_CLONERS_UNLOCK(); - if (ifc == NULL) + if (ifc == NULL) { + if_rele(ifp); return (EINVAL); + } - return (if_clone_destroyif(ifc, ifp)); + err = if_clone_destroyif(ifc, ifp); + if_rele(ifp); + return err; } /* @@ -234,6 +239,7 @@ int if_clone_destroyif(struct if_clone *ifc, struct ifnet *ifp) { int err; + struct ifnet *tmp; if (ifc->ifc_destroy == NULL) return(EOPNOTSUPP); @@ -246,8 +252,15 @@ if_clone_destroyif(struct if_clone *ifc, CURVNET_SET_QUIET(ifp->if_vnet); IF_CLONE_LOCK(ifc); - IFC_IFLIST_REMOVE(ifc, ifp); + LIST_FOREACH(tmp, &ifc->ifc_iflist, if_clones) { + if (tmp == ifp) { + IFC_IFLIST_REMOVE(ifc, ifp); + break; + } + } IF_CLONE_UNLOCK(ifc); + if (tmp == NULL) + return (ENXIO); /* ifp is not on the list. */ if_delgroup(ifp, ifc->ifc_name); --=-=-=--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?86634wdat3.fsf>