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>
