Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 5 May 2018 14:12:04 -0700
From:      Matthew Macy <mmacy@freebsd.org>
To:        "O. Hartmann" <ohartmann@walstatt.org>
Cc:        svn-src-head@freebsd.org, Sean Bruno <sbruno@freebsd.org>,  Stephen Hurd <shurd@freebsd.org>, bde@freebsd.org
Subject:   Re: svn commit: r333175 - in head/sys: kern net netinet netinet6 sys: TRAP 12
Message-ID:  <CAPrugNobRcsMjkFGr55WqyEk0J22DOEBboLibXV86nMPn-QS4g@mail.gmail.com>
In-Reply-To: <20180505225508.12bcee0c@thor.intern.walstatt.dynvpn.de>
References:  <201805021936.w42JaTlq039053@repo.freebsd.org> <20180503213206.7fba052c@thor.intern.walstatt.dynvpn.de> <CAHM0Q_OeFG5bKiUMqi5G3roGNnjUHJ_W2KmQeCCkSnW8zCW_RQ@mail.gmail.com> <20180503222419.4228e8e8@thor.intern.walstatt.dynvpn.de> <20180505110138.6cae0f75@thor.intern.walstatt.dynvpn.de> <CAPrugNp5zXeG50aUN5gEHp-Z5Db7y%2BiSRNGO-r%2BW5xzjhsqp7Q@mail.gmail.com> <20180505223151.580b6522@thor.intern.walstatt.dynvpn.de> <CAPrugNoL4jvO2yXNp4SGXQEDRUjJT_=LtbSBgt0fEQMkR8M2Gg@mail.gmail.com> <20180505225508.12bcee0c@thor.intern.walstatt.dynvpn.de>

next in thread | previous in thread | raw e-mail | index | archive | help
it's in the same place as before but I'll attach just to be clear.
Gzipped to keep gmail from inserting carriage returns.
-M

On Sat, May 5, 2018 at 1:54 PM, O. Hartmann <ohartmann@walstatt.org> wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA512
>
> Am Sat, 5 May 2018 13:45:13 -0700
> Matthew Macy <mmacy@freebsd.org> schrieb:
>
>> actually can you try the updated patch please, it turns out I need to
>> workaround this little shop of horrors:
>>
>>
>> static void
>> tcp_usr_detach(struct socket *so)
>> {
>>     struct inpcb *inp;
>>     int rlock =3D 0;
>>
>>     inp =3D sotoinpcb(so);
>>     KASSERT(inp !=3D NULL, ("tcp_usr_detach: inp =3D=3D NULL"));
>>     if (!INP_INFO_WLOCKED(&V_tcbinfo)) {
>>         INP_INFO_RLOCK(&V_tcbinfo);
>>         rlock =3D 1;
>>     }
>>     INP_WLOCK(inp);
>>     KASSERT(inp->inp_socket !=3D NULL,
>>         ("tcp_usr_detach: inp_socket =3D=3D NULL"));
>>     tcp_detach(so, inp);
>>     if (rlock)
>>         INP_INFO_RUNLOCK(&V_tcbinfo);
>> }
>>
>> We're still acquiring a sleepable mutex out of order with a read lock
>> held with the former version of the patch.
>>
>
> Well, I'd appreciate a patch file, if possible, please.
>
>
>>
>> On Sat, May 5, 2018 at 1:31 PM, O. Hartmann <o.hartmann@walstatt.org> wr=
ote:
>> > -----BEGIN PGP SIGNED MESSAGE-----
>> > Hash: SHA512
>> >
>> > Am Sat, 5 May 2018 11:21:47 -0700
>> > Matthew Macy <mmacy@freebsd.org> schrieb:
>> >
>> >> pho@ and sbruno@ tested the patch before commit, I can't readily
>> >> reproduce even though the detach path should be common enough. Please
>> >> tell me if this helps:
>> >>
>> >> https://people.freebsd.org/~mmacy/inpcb.diff
>> >>
>> >>
>> >> Thanks.
>> >>
>> >
>> >
>> > The privided patch seemingly work so far (FreeBSD 12.0-CURRENT #4 r333=
274M: Sat May  5
>> > 22:19:04 CEST 2018 amd64). I just recompile world and kernel of revisi=
on 333276 and
>> > try to push the box with ne traffic (NFS mostly).
>> >
>> > May I ask on what hardware the mentioned tests of yours has been perfo=
rmed? I can
>> > tell, that ALL(!) boxes equipted with Intel's i350 NICs are suffering =
the very same
>> > problem. I didn't dare to move on on the other systems with i210, i217=
 or i219, but
>> > with the patch provided working so far, I'll test.
>> >
>> > Thanks.
>> >
>> >>
>> >> On Sat, May 5, 2018 at 2:01 AM, O. Hartmann <o.hartmann@walstatt.org>=
 wrote:
>> >> > -----BEGIN PGP SIGNED MESSAGE-----
>> >> > Hash: SHA512
>> >> >
>> >> > Am Thu, 3 May 2018 22:23:52 +0200
>> >> > "O. Hartmann" <ohartmann@walstatt.org> schrieb:
>> >> >
>> >> >
>> >> > I'm not familiar with kernel debugging, so there are some struggles=
.
>> >> >
>> >> > After compiling a debugging kernel on
>> >> >
>> >> > Version String: FreeBSD 12.0-CURRENT #2 r333269: Sat May  5 08:10:3=
2 CEST 2018
>> >> >
>> >> > Panic String: Lock tcp not exclusively locked @ /usr/src/sys/netine=
t/in_pcb.c:1391
>> >> >
>> >> >
>> >> > And this is what I can provide you with:
>> >> >
>> >> >
>> >> > Reading symbols
>> >> > from /usr/obj/usr/src/amd64.amd64/sys/WALHALL-DEBUG/kernel.full...d=
one.
>> >> >
>> >> > Unread portion of the kernel message buffer:
>> >> > panic: Lock tcp not exclusively locked @ /usr/src/sys/netinet/in_pc=
b.c:1391
>> >> >
>> >> > cpuid =3D 4
>> >> > time =3D 1525510291
>> >> > KDB: stack backtrace:
>> >> > db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffff=
e00e485e670
>> >> > vpanic() at vpanic+0x1a3/frame 0xfffffe00e485e6d0
>> >> > panic() at panic+0x43/frame 0xfffffe00e485e730
>> >> > _rw_wunlock_cookie() at _rw_wunlock_cookie+0x137/frame 0xfffffe00e4=
85e760
>> >> > in_pcbfree() at in_pcbfree+0x51a/frame 0xfffffe00e485e7b0
>> >> > tcp_usr_detach() at tcp_usr_detach+0x15e/frame 0xfffffe00e485e7f0
>> >> > sofree() at sofree+0x2f4/frame 0xfffffe00e485e840
>> >> > soclose() at soclose+0x387/frame 0xfffffe00e485e8b0
>> >> > closef() at closef+0x1f5/frame 0xfffffe00e485e940
>> >> > closefp() at closefp+0xa0/frame 0xfffffe00e485e980
>> >> > amd64_syscall() at amd64_syscall+0x6d3/frame 0xfffffe00e485eab0
>> >> > fast_syscall_common() at fast_syscall_common+0x101/frame 0xfffffe00=
e485eab0
>> >> > - --- syscall (6, FreeBSD ELF64, sys_close), rip =3D 0x80111adda, r=
sp =3D
>> >> > 0x7fffdf3f7228, rbp =3D 0x7fffdf3f7240 --- KDB: enter: panic
>> >> >
>> >> > __curthread () at ./machine/pcpu.h:231
>> >> > 231             __asm("movq %%gs:%1,%0" : "=3Dr" (td)
>> >> > (kgdb) bt
>> >> > (kgdb) bt
>> >> > #0  __curthread () at ./machine/pcpu.h:231
>> >> > #1  doadump (textdump=3D0) at /usr/src/sys/kern/kern_shutdown.c:365
>> >> > #2  0xffffffff80597d5b in db_dump (dummy=3D<optimized out>, dummy2=
=3D<unavailable>,
>> >> > dummy3=3D<unavailable>, dummy4=3D<unavailable>) at /usr/src/sys/ddb=
/db_command.c:574
>> >> > #3  0xffffffff80597ae6 in db_command (last_cmdp=3D<optimized out>,
>> >> > cmd_table=3D<optimized
>> >> > out>, dopager=3D<optimized out>) at /usr/src/sys/ddb/db_command.c:4=
81 #4
>> >> > out>0xffffffff80597814 in db_command_loop () at /usr/src/sys/ddb/db=
_command.c:534
>> >> > #5  0xffffffff8059b04f in db_trap (type=3D<optimized out>, code=3D<=
optimized out>)
>> >> > at /usr/src/sys/ddb/db_main.c:250 #6  0xffffffff80924463 in kdb_tra=
p (type=3D3,
>> >> > code=3D-61456, tf=3D<optimized out>) at /usr/src/sys/kern/subr_kdb.=
c:697 #7
>> >> > 0xffffffff80c80ab7 in trap (frame=3D0xfffffe00e485e5a0)
>> >> > at /usr/src/sys/amd64/amd64/trap.c:550 #8  <signal handler called> =
#9  kdb_enter
>> >> > (why=3D0xffffffff80dd7b54 "panic", msg=3D<optimized out>)
>> >> > at /usr/src/sys/kern/subr_kdb.c:479 #10 0xffffffff808db500 in vpani=
c
>> >> > (fmt=3D<optimized
>> >> > out>, ap=3D0xfffffe00e485e710) at /usr/src/sys/kern/kern_shutdown.c=
:851 #11
>> >> > out>0xffffffff808db593 in panic
>> >> > (fmt=3D0xffffffff8125bbd8 <cnputs_mtx> "\251\312\332\200\377\377\37=
7\377")
>> >> > at /usr/src/sys/kern/kern_shutdown.c:789 #12 0xffffffff808d65b7 in =
__rw_assert
>> >> > (c=3D0xfffffe00111ee650, what=3D4, file=3D0xffffffff80dc5157
>> >> > "/usr/src/sys/netinet/in_pcb.c", line=3D1391) at /usr/src/sys/kern/=
kern_rwlock.c:1426
>> >> > #13 _rw_wunlock_cookie (c=3D0xfffffe00111ee650, file=3D0xffffffff80=
dc5157
>> >> > "/usr/src/sys/netinet/in_pcb.c", line=3D1391) at /usr/src/sys/kern/=
kern_rwlock.c:362
>> >> > #14 0xffffffff80a68caa in in_pcbfree (inp=3D0xfffff80066058b10)
>> >> > at /usr/src/sys/netinet/in_pcb.c:1391 #15 0xffffffff80b09a6e in tcp=
_detach
>> >> > (so=3D<optimized out>, inp=3D<optimized out>) at /usr/src/sys/netin=
et/tcp_usrreq.c:258
>> >> > #16 tcp_usr_detach (so=3D<optimized out>) at /usr/src/sys/netinet/t=
cp_usrreq.c:289
>> >> > #17 0xffffffff8097c394 in sofree (so=3D0xfffff8001988d358)
>> >> > at /usr/src/sys/kern/uipc_socket.c:1032 #18 0xffffffff8097d487 in s=
oclose
>> >> > (so=3D0xfffff8001988d358) at /usr/src/sys/kern/uipc_socket.c:1126 #=
19
>> >> > 0xffffffff80885ad5 in fo_close (fp=3D<optimized out>, td=3D<optimiz=
ed out>)
>> >> > at /usr/src/sys/sys/file.h:348 #20 _fdrop (fp=3D<optimized out>, td=
=3D<optimized out>)
>> >> > at /usr/src/sys/kern/kern_descrip.c:2957 #21 closef (fp=3D0xfffff80=
004ef4eb0,
>> >> > td=3D0xfffff80019891560) at /usr/src/sys/kern/kern_descrip.c:2538 #=
22
>> >> > 0xffffffff80882920 in closefp (fdp=3D0xfffff80019553450, fd=3D12,
>> >> > fp=3D0xfffff80004ef4eb0, td=3D0xfffff80019891560, holdleaders=3D0)
>> >> > at /usr/src/sys/kern/kern_descrip.c:1208 #23 0xffffffff80c82033 in =
syscallenter
>> >> > (td=3D0xfffff80019891560) at /usr/src/sys/amd64/amd64/../../kern/su=
br_syscall.c:135
>> >> > #24 amd64_syscall (td=3D0xfffff80019891560, traced=3D0)
>> >> > at /usr/src/sys/amd64/amd64/trap.c:945 #25 <signal handler called> =
#26
>> >> > 0x000000080111adda in ?? () Backtrace stopped: Cannot access memory=
 at address
>> >> > 0x7fffdf3f7228 (kgdb)
>> >> >
>> >> >
>> >> >
>> >> >
>> >> >> -----BEGIN PGP SIGNED MESSAGE-----
>> >> >> Hash: SHA512
>> >> >>
>> >> >> Am Thu, 3 May 2018 12:53:05 -0700
>> >> >> "K. Macy" <kmacy@freebsd.org> schrieb:
>> >> >>
>> >> >> > Can you give any context on what they're doing? In addition - ev=
en on
>> >> >> > a production kernel it's possible to compile in DDB to at least =
get a
>> >> >> > backtrace. Your report only gives us enough information to know =
that
>> >> >>
>> >> >> Not at the moment. The immediate crash corrupted the /usr/src file=
system so I can
>> >> >> not recompile a kernel. Every attempt to /etc/netstart the network=
 on the buggy
>> >> >> kernel ends up in a further destruction, so I stopped at this very=
 moment and
>> >> >> hopefully I can copy /usr/src from a r33153 box (r333153 is for me=
 the last
>> >> >> working revision) via USB flash drive and recompile the kernel. Bu=
t I'll go for
>> >> >> r333153 first since I need the server up tomorrow and I'll try on =
the other box
>> >> >> which is also affected, but also equipted with the i350 NIC on whi=
ch the problem
>> >> >> occurs very quickly.
>> >> >> > there is _an_ issue. It's difficult to proceed on this alone. I =
do
>> >> >> > have a report from the FreeBSD CI infrastructure that we're look=
ing in
>> >> >> > to now.  With luck that is the same issue.
>> >> >> >
>> >> >> > -M
>> >> >> >
>> >> >> > On Thu, May 3, 2018 at 12:31 PM, O. Hartmann <ohartmann@walstatt=
.org> wrote:
>> >> >> > > -----BEGIN PGP SIGNED MESSAGE-----
>> >> >> > > Hash: SHA512
>> >> >> > >
>> >> >> > > Am Wed, 2 May 2018 19:36:29 +0000 (UTC)
>> >> >> > > Stephen Hurd <shurd@FreeBSD.org> schrieb:
>> >> >> > >
>> >> >> > >> Author: shurd
>> >> >> > >> Date: Wed May  2 19:36:29 2018
>> >> >> > >> New Revision: 333175
>> >> >> > >> URL: https://svnweb.freebsd.org/changeset/base/333175
>> >> >> > >>
>> >> >> > >> Log:
>> >> >> > >>   Separate list manipulation locking from state change in mul=
ticast
>> >> >> > >>
>> >> >> > >>   Multicast incorrectly calls in to drivers with a mutex held=
 causing drivers
>> >> >> > >>   to have to go through all manner of contortions to use a no=
n sleepable
>> >> >> > >> lock. Serialize multicast updates instead.
>> >> >> > >>
>> >> >> > >>   Submitted by:       mmacy <mmacy@mattmacy.io>
>> >> >> > >>   Reviewed by:        shurd, sbruno
>> >> >> > >>   Sponsored by:       Limelight Networks
>> >> >> > >>   Differential Revision:      https://reviews.freebsd.org/D14=
969
>> >> >> > >>
>> >> >> > >> Modified:
>> >> >> > >>   head/sys/kern/subr_gtaskqueue.c
>> >> >> > >>   head/sys/kern/subr_witness.c
>> >> >> > >>   head/sys/net/if.c
>> >> >> > >>   head/sys/netinet/igmp.c
>> >> >> > >>   head/sys/netinet/igmp_var.h
>> >> >> > >>   head/sys/netinet/in.c
>> >> >> > >>   head/sys/netinet/in_mcast.c
>> >> >> > >>   head/sys/netinet/in_pcb.c
>> >> >> > >>   head/sys/netinet/in_var.h
>> >> >> > >>   head/sys/netinet/ip_carp.c
>> >> >> > >>   head/sys/netinet6/in6.c
>> >> >> > >>   head/sys/netinet6/in6_ifattach.c
>> >> >> > >>   head/sys/netinet6/in6_mcast.c
>> >> >> > >>   head/sys/netinet6/in6_pcb.c
>> >> >> > >>   head/sys/netinet6/in6_var.h
>> >> >> > >>   head/sys/netinet6/mld6.c
>> >> >> > >>   head/sys/netinet6/mld6_var.h
>> >> >> > >>   head/sys/sys/gtaskqueue.h
>> >> >> > >>
>> >> >> > >> Modified: head/sys/kern/subr_gtaskqueue.c
>> >> >> > >> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D
>> >> >> > >> --- head/sys/kern/subr_gtaskqueue.c   Wed May  2 17:41:00 201=
8
>> >> >> > >> (r333174) +++ head/sys/kern/subr_gtaskqueue.c   Wed May  2 19=
:36:29
>> >> >> > >> 2018        (r333175) @@ -53,6 +53,7 @@ static void
>> >> >> > >> gtaskqueue_thread_enqueue(void *); static void  gtaskqueue_th=
read_loop(void
>> >> >> > >> *arg);
>> >> >> > >>
>> >> >> > >>  TASKQGROUP_DEFINE(softirq, mp_ncpus, 1);
>> >> >> > >> +TASKQGROUP_DEFINE(config, 1, 1);
>> >> >> > >>
>> >> >> > >>  struct gtaskqueue_busy {
>> >> >> > >>       struct gtask    *tb_running;
>> >> >> > >> @@ -662,7 +663,7 @@ SYSINIT(tqg_record_smp_started, SI_SUB_SM=
P, SI_ORDER_F
>> >> >> > >>
>> >> >> > >>  void
>> >> >> > >>  taskqgroup_attach(struct taskqgroup *qgroup, struct grouptas=
k *gtask,
>> >> >> > >> -    void *uniq, int irq, char *name)
>> >> >> > >> +    void *uniq, int irq, const char *name)
>> >> >> > >>  {
>> >> >> > >>       cpuset_t mask;
>> >> >> > >>       int qid, error;
>> >> >> > >> @@ -976,4 +977,13 @@ void
>> >> >> > >>  taskqgroup_destroy(struct taskqgroup *qgroup)
>> >> >> > >>  {
>> >> >> > >>
>> >> >> > >> +}
>> >> >> > >> +
>> >> >> > >> +void
>> >> >> > >> +taskqgroup_config_gtask_init(void *ctx, struct grouptask *gt=
ask, gtask_fn_t
>> >> >> > >> *fn,
>> >> >> > >> +     const char *name)
>> >> >> > >> +{
>> >> >> > >> +
>> >> >> > >> +     GROUPTASK_INIT(gtask, 0, fn, ctx);
>> >> >> > >> +     taskqgroup_attach(qgroup_config, gtask, gtask, -1, name=
);
>> >> >> > >>  }
>> >> >> > >>
>> >> >> > >> Modified: head/sys/kern/subr_witness.c
>> >> >> > >> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D
>> >> >> > >> --- head/sys/kern/subr_witness.c      Wed May  2 17:41:00 201=
8
>> >> >> > >> (r333174) +++ head/sys/kern/subr_witness.c      Wed May  2 19=
:36:29
>> >> >> > >> 2018        (r333175) @@ -532,18 +532,22 @@ static struct
>> >> >> > >> witness_order_list_entry order_lists[] =3D
>> >> >> > >>        * IPv4 multicast:
>> >> >> > >>        * protocol locks before interface locks, after UDP loc=
ks.
>> >> >> > >>        */
>> >> >> > >> +     { "in_multi_sx", &lock_class_sx },
>> >> >> > >>       { "udpinp", &lock_class_rw },
>> >> >> > >> -     { "in_multi_mtx", &lock_class_mtx_sleep },
>> >> >> > >> +     { "in_multi_list_mtx", &lock_class_mtx_sleep },
>> >> >> > >>       { "igmp_mtx", &lock_class_mtx_sleep },
>> >> >> > >> +     { "ifnet_rw", &lock_class_rw },
>> >> >> > >>       { "if_addr_lock", &lock_class_rw },
>> >> >> > >>       { NULL, NULL },
>> >> >> > >>       /*
>> >> >> > >>        * IPv6 multicast:
>> >> >> > >>        * protocol locks before interface locks, after UDP loc=
ks.
>> >> >> > >>        */
>> >> >> > >> +     { "in6_multi_sx", &lock_class_sx },
>> >> >> > >>       { "udpinp", &lock_class_rw },
>> >> >> > >> -     { "in6_multi_mtx", &lock_class_mtx_sleep },
>> >> >> > >> +     { "in6_multi_list_mtx", &lock_class_mtx_sleep },
>> >> >> > >>       { "mld_mtx", &lock_class_mtx_sleep },
>> >> >> > >> +     { "ifnet_rw", &lock_class_rw },
>> >> >> > >>       { "if_addr_lock", &lock_class_rw },
>> >> >> > >>       { NULL, NULL },
>> >> >> > >>       /*
>> >> >> > >>
>> >> >> > >> Modified: head/sys/net/if.c
>> >> >> > >> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D
>> >> >> > >> --- head/sys/net/if.c Wed May  2 17:41:00 2018        (r33317=
4)
>> >> >> > >> +++ head/sys/net/if.c Wed May  2 19:36:29 2018        (r33317=
5)
>> >> >> > >> @@ -985,11 +985,13 @@ static void
>> >> >> > >>  if_purgemaddrs(struct ifnet *ifp)
>> >> >> > >>  {
>> >> >> > >>       struct ifmultiaddr *ifma;
>> >> >> > >> -     struct ifmultiaddr *next;
>> >> >> > >>
>> >> >> > >>       IF_ADDR_WLOCK(ifp);
>> >> >> > >> -     TAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link=
, next)
>> >> >> > >> +     while (!TAILQ_EMPTY(&ifp->if_multiaddrs)) {
>> >> >> > >> +             ifma =3D TAILQ_FIRST(&ifp->if_multiaddrs);
>> >> >> > >> +             TAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifma_li=
nk);
>> >> >> > >>               if_delmulti_locked(ifp, ifma, 1);
>> >> >> > >> +     }
>> >> >> > >>       IF_ADDR_WUNLOCK(ifp);
>> >> >> > >>  }
>> >> >> > >>
>> >> >> > >> @@ -3429,6 +3431,12 @@ if_addmulti(struct ifnet *ifp, struct =
sockaddr *sa,
>> >> >> > >>       struct sockaddr_dl sdl;
>> >> >> > >>       int error;
>> >> >> > >>
>> >> >> > >> +#ifdef INET
>> >> >> > >> +     IN_MULTI_LIST_UNLOCK_ASSERT();
>> >> >> > >> +#endif
>> >> >> > >> +#ifdef INET6
>> >> >> > >> +     IN6_MULTI_LIST_UNLOCK_ASSERT();
>> >> >> > >> +#endif
>> >> >> > >>       /*
>> >> >> > >>        * If the address is already present, return a new refe=
rence to it;
>> >> >> > >>        * otherwise, allocate storage and set up a new address=
.
>> >> >> > >> @@ -3610,6 +3618,9 @@ if_delmulti_ifma(struct ifmultiaddr *if=
ma)
>> >> >> > >>       struct ifnet *ifp;
>> >> >> > >>       int lastref;
>> >> >> > >>
>> >> >> > >> +#ifdef INET
>> >> >> > >> +     IN_MULTI_LIST_UNLOCK_ASSERT();
>> >> >> > >> +#endif
>> >> >> > >>       ifp =3D ifma->ifma_ifp;
>> >> >> > >>  #ifdef DIAGNOSTIC
>> >> >> > >>       if (ifp =3D=3D NULL) {
>> >> >> > >> @@ -3711,8 +3722,7 @@ if_delmulti_locked(struct ifnet *ifp, s=
truct ifmultiad
>> >> >> > >>                       if_freemulti(ll_ifma);
>> >> >> > >>               }
>> >> >> > >>       }
>> >> >> > >> -
>> >> >> > >> -     if (ifp !=3D NULL)
>> >> >> > >> +     if (ifp !=3D NULL && detaching =3D=3D 0)
>> >> >> > >>               TAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifma_li=
nk);
>> >> >> > >>
>> >> >> > >>       if_freemulti(ifma);
>> >> >> > >>
>> >> >> > >> Modified: head/sys/netinet/igmp.c
>> >> >> > >> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D
>> >> >> > >> --- head/sys/netinet/igmp.c   Wed May  2 17:41:00 2018       =
 (r333174)
>> >> >> > >> +++ head/sys/netinet/igmp.c   Wed May  2 19:36:29 2018       =
 (r333175)
>> >> >> > >> @@ -136,7 +136,7 @@ static int        igmp_v3_enqueue_group_r=
ecord(struct
>> >> >> > >> mbufq
>> >> >> > >> * struct in_multi *, const int, const int, const int);
>> >> >> > >>  static int   igmp_v3_enqueue_filter_change(struct mbufq *,
>> >> >> > >>                   struct in_multi *);
>> >> >> > >> -static void  igmp_v3_process_group_timers(struct igmp_ifsoft=
c *,
>> >> >> > >> +static void  igmp_v3_process_group_timers(struct in_multi_he=
ad *,
>> >> >> > >>                   struct mbufq *, struct mbufq *, struct in_m=
ulti *,
>> >> >> > >>                   const int);
>> >> >> > >>  static int   igmp_v3_merge_state_changes(struct in_multi *,
>> >> >> > >> @@ -162,12 +162,12 @@ static const struct netisr_handler igmp=
_nh =3D {
>> >> >> > >>   * themselves are not virtualized.
>> >> >> > >>   *
>> >> >> > >>   * Locking:
>> >> >> > >> - *  * The permitted lock order is: IN_MULTI_LOCK, IGMP_LOCK,=
 IF_ADDR_LOCK.
>> >> >> > >> + *  * The permitted lock order is: IN_MULTI_LIST_LOCK, IGMP_=
LOCK,
>> >> >> > >> IF_ADDR_LOCK.
>> >> >> > >>   *    Any may be taken independently; if any are held at the=
 same
>> >> >> > >>   *    time, the above lock order must be followed.
>> >> >> > >>   *  * All output is delegated to the netisr.
>> >> >> > >>   *    Now that Giant has been eliminated, the netisr may be =
inlined.
>> >> >> > >> - *  * IN_MULTI_LOCK covers in_multi.
>> >> >> > >> + *  * IN_MULTI_LIST_LOCK covers in_multi.
>> >> >> > >>   *  * IGMP_LOCK covers igmp_ifsoftc and any global variables=
 in this file,
>> >> >> > >>   *    including the output queue.
>> >> >> > >>   *  * IF_ADDR_LOCK covers if_multiaddrs, which is used for a=
 variety of
>> >> >> > >> @@ -441,7 +441,7 @@ sysctl_igmp_ifinfo(SYSCTL_HANDLER_ARGS)
>> >> >> > >>       if (error)
>> >> >> > >>               return (error);
>> >> >> > >>
>> >> >> > >> -     IN_MULTI_LOCK();
>> >> >> > >> +     IN_MULTI_LIST_LOCK();
>> >> >> > >>       IGMP_LOCK();
>> >> >> > >>
>> >> >> > >>       if (name[0] <=3D 0 || name[0] > V_if_index) {
>> >> >> > >> @@ -475,7 +475,7 @@ sysctl_igmp_ifinfo(SYSCTL_HANDLER_ARGS)
>> >> >> > >>
>> >> >> > >>  out_locked:
>> >> >> > >>       IGMP_UNLOCK();
>> >> >> > >> -     IN_MULTI_UNLOCK();
>> >> >> > >> +     IN_MULTI_LIST_UNLOCK();
>> >> >> > >>       return (error);
>> >> >> > >>  }
>> >> >> > >>
>> >> >> > >> @@ -586,7 +586,6 @@ igi_alloc_locked(/*const*/ struct ifnet *=
ifp)
>> >> >> > >>       igi->igi_qi =3D IGMP_QI_INIT;
>> >> >> > >>       igi->igi_qri =3D IGMP_QRI_INIT;
>> >> >> > >>       igi->igi_uri =3D IGMP_URI_INIT;
>> >> >> > >> -     SLIST_INIT(&igi->igi_relinmhead);
>> >> >> > >>       mbufq_init(&igi->igi_gq, IGMP_MAX_RESPONSE_PACKETS);
>> >> >> > >>
>> >> >> > >>       LIST_INSERT_HEAD(&V_igi_head, igi, igi_link);
>> >> >> > >> @@ -612,11 +611,12 @@ igmp_ifdetach(struct ifnet *ifp)
>> >> >> > >>  {
>> >> >> > >>       struct igmp_ifsoftc     *igi;
>> >> >> > >>       struct ifmultiaddr      *ifma;
>> >> >> > >> -     struct in_multi         *inm, *tinm;
>> >> >> > >> -
>> >> >> > >> +     struct in_multi         *inm;
>> >> >> > >> +     struct in_multi_head inm_free_tmp;
>> >> >> > >>       CTR3(KTR_IGMPV3, "%s: called for ifp %p(%s)", __func__,=
 ifp,
>> >> >> > >>           ifp->if_xname);
>> >> >> > >>
>> >> >> > >> +     SLIST_INIT(&inm_free_tmp);
>> >> >> > >>       IGMP_LOCK();
>> >> >> > >>
>> >> >> > >>       igi =3D ((struct in_ifinfo *)ifp->if_afdata[AF_INET])->=
ii_igmp;
>> >> >> > >> @@ -631,24 +631,15 @@ igmp_ifdetach(struct ifnet *ifp)
>> >> >> > >>                           ("%s: ifma_protospec is NULL", __fu=
nc__));
>> >> >> > >>  #endif
>> >> >> > >>                       inm =3D (struct in_multi *)ifma->ifma_p=
rotospec;
>> >> >> > >> -                     if (inm->inm_state =3D=3D IGMP_LEAVING_=
MEMBER) {
>> >> >> > >> -                             SLIST_INSERT_HEAD(&igi->igi_rel=
inmhead,
>> >> >> > >> -                                 inm, inm_nrele);
>> >> >> > >> -                     }
>> >> >> > >> +                     if (inm->inm_state =3D=3D IGMP_LEAVING_=
MEMBER)
>> >> >> > >> +                             inm_rele_locked(&inm_free_tmp, =
inm);
>> >> >> > >>                       inm_clear_recorded(inm);
>> >> >> > >>               }
>> >> >> > >>               IF_ADDR_RUNLOCK(ifp);
>> >> >> > >> -             /*
>> >> >> > >> -              * Free the in_multi reference(s) for this IGMP=
 lifecycle.
>> >> >> > >> -              */
>> >> >> > >> -             SLIST_FOREACH_SAFE(inm, &igi->igi_relinmhead, i=
nm_nrele,
>> >> >> > >> -                 tinm) {
>> >> >> > >> -                     SLIST_REMOVE_HEAD(&igi->igi_relinmhead,=
 inm_nrele);
>> >> >> > >> -                     inm_release_locked(inm);
>> >> >> > >> -             }
>> >> >> > >> +             inm_release_list_deferred(&inm_free_tmp);
>> >> >> > >>       }
>> >> >> > >> -
>> >> >> > >>       IGMP_UNLOCK();
>> >> >> > >> +
>> >> >> > >>  }
>> >> >> > >>
>> >> >> > >>  /*
>> >> >> > >> @@ -684,11 +675,6 @@ igi_delete_locked(const struct ifnet *if=
p)
>> >> >> > >>                       mbufq_drain(&igi->igi_gq);
>> >> >> > >>
>> >> >> > >>                       LIST_REMOVE(igi, igi_link);
>> >> >> > >> -
>> >> >> > >> -                     KASSERT(SLIST_EMPTY(&igi->igi_relinmhea=
d),
>> >> >> > >> -                         ("%s: there are dangling in_multi r=
eferences",
>> >> >> > >> -                         __func__));
>> >> >> > >> -
>> >> >> > >>                       free(igi, M_IGMP);
>> >> >> > >>                       return;
>> >> >> > >>               }
>> >> >> > >> @@ -722,7 +708,7 @@ igmp_input_v1_query(struct ifnet *ifp, co=
nst struct ip
>> >> >> > >>       }
>> >> >> > >>       IGMPSTAT_INC(igps_rcv_gen_queries);
>> >> >> > >>
>> >> >> > >> -     IN_MULTI_LOCK();
>> >> >> > >> +     IN_MULTI_LIST_LOCK();
>> >> >> > >>       IGMP_LOCK();
>> >> >> > >>
>> >> >> > >>       igi =3D ((struct in_ifinfo *)ifp->if_afdata[AF_INET])->=
ii_igmp;
>> >> >> > >> @@ -778,7 +764,7 @@ igmp_input_v1_query(struct ifnet *ifp, co=
nst struct ip
>> >> >> > >>
>> >> >> > >>  out_locked:
>> >> >> > >>       IGMP_UNLOCK();
>> >> >> > >> -     IN_MULTI_UNLOCK();
>> >> >> > >> +     IN_MULTI_LIST_UNLOCK();
>> >> >> > >>
>> >> >> > >>       return (0);
>> >> >> > >>  }
>> >> >> > >> @@ -816,7 +802,7 @@ igmp_input_v2_query(struct ifnet *ifp, co=
nst struct ip
>> >> >> > >>               IGMPSTAT_INC(igps_rcv_group_queries);
>> >> >> > >>       }
>> >> >> > >>
>> >> >> > >> -     IN_MULTI_LOCK();
>> >> >> > >> +     IN_MULTI_LIST_LOCK();
>> >> >> > >>       IGMP_LOCK();
>> >> >> > >>
>> >> >> > >>       igi =3D ((struct in_ifinfo *)ifp->if_afdata[AF_INET])->=
ii_igmp;
>> >> >> > >> @@ -872,7 +858,7 @@ igmp_input_v2_query(struct ifnet *ifp, co=
nst struct ip
>> >> >> > >>
>> >> >> > >>  out_locked:
>> >> >> > >>       IGMP_UNLOCK();
>> >> >> > >> -     IN_MULTI_UNLOCK();
>> >> >> > >> +     IN_MULTI_LIST_UNLOCK();
>> >> >> > >>
>> >> >> > >>       return (0);
>> >> >> > >>  }
>> >> >> > >> @@ -899,7 +885,7 @@ igmp_v2_update_group(struct in_multi *inm=
, const int t
>> >> >> > >>       CTR4(KTR_IGMPV3, "0x%08x: %s/%s timer=3D%d", __func__,
>> >> >> > >>           ntohl(inm->inm_addr.s_addr), inm->inm_ifp->if_xname=
, timer);
>> >> >> > >>
>> >> >> > >> -     IN_MULTI_LOCK_ASSERT();
>> >> >> > >> +     IN_MULTI_LIST_LOCK_ASSERT();
>> >> >> > >>
>> >> >> > >>       switch (inm->inm_state) {
>> >> >> > >>       case IGMP_NOT_MEMBER:
>> >> >> > >> @@ -1011,7 +997,7 @@ igmp_input_v3_query(struct ifnet *ifp, c=
onst struct ip
>> >> >> > >>                       IGMPSTAT_INC(igps_rcv_gsr_queries);
>> >> >> > >>       }
>> >> >> > >>
>> >> >> > >> -     IN_MULTI_LOCK();
>> >> >> > >> +     IN_MULTI_LIST_LOCK();
>> >> >> > >>       IGMP_LOCK();
>> >> >> > >>
>> >> >> > >>       igi =3D ((struct in_ifinfo *)ifp->if_afdata[AF_INET])->=
ii_igmp;
>> >> >> > >> @@ -1092,7 +1078,7 @@ igmp_input_v3_query(struct ifnet *ifp, =
const struct ip
>> >> >> > >>
>> >> >> > >>  out_locked:
>> >> >> > >>       IGMP_UNLOCK();
>> >> >> > >> -     IN_MULTI_UNLOCK();
>> >> >> > >> +     IN_MULTI_LIST_UNLOCK();
>> >> >> > >>
>> >> >> > >>       return (0);
>> >> >> > >>  }
>> >> >> > >> @@ -1109,7 +1095,7 @@ igmp_input_v3_group_query(struct in_mul=
ti *inm, struct
>> >> >> > >>       int                      retval;
>> >> >> > >>       uint16_t                 nsrc;
>> >> >> > >>
>> >> >> > >> -     IN_MULTI_LOCK_ASSERT();
>> >> >> > >> +     IN_MULTI_LIST_LOCK_ASSERT();
>> >> >> > >>       IGMP_LOCK_ASSERT();
>> >> >> > >>
>> >> >> > >>       retval =3D 0;
>> >> >> > >> @@ -1246,7 +1232,7 @@ igmp_input_v1_report(struct ifnet *ifp,=
 /*const*/ stru
>> >> >> > >>        * If we are a member of this group, and our membership=
 should be
>> >> >> > >>        * reported, stop our group timer and transition to the=
 'lazy' state.
>> >> >> > >>        */
>> >> >> > >> -     IN_MULTI_LOCK();
>> >> >> > >> +     IN_MULTI_LIST_LOCK();
>> >> >> > >>       inm =3D inm_lookup(ifp, igmp->igmp_group);
>> >> >> > >>       if (inm !=3D NULL) {
>> >> >> > >>               struct igmp_ifsoftc *igi;
>> >> >> > >> @@ -1305,7 +1291,7 @@ igmp_input_v1_report(struct ifnet *ifp,=
 /*const*/ stru
>> >> >> > >>       }
>> >> >> > >>
>> >> >> > >>  out_locked:
>> >> >> > >> -     IN_MULTI_UNLOCK();
>> >> >> > >> +     IN_MULTI_LIST_UNLOCK();
>> >> >> > >>
>> >> >> > >>       return (0);
>> >> >> > >>  }
>> >> >> > >> @@ -1373,7 +1359,7 @@ igmp_input_v2_report(struct ifnet *ifp,=
 /*const*/ stru
>> >> >> > >>        * reported, and our group timer is pending or about to=
 be reset,
>> >> >> > >>        * stop our group timer by transitioning to the 'lazy' =
state.
>> >> >> > >>        */
>> >> >> > >> -     IN_MULTI_LOCK();
>> >> >> > >> +     IN_MULTI_LIST_LOCK();
>> >> >> > >>       inm =3D inm_lookup(ifp, igmp->igmp_group);
>> >> >> > >>       if (inm !=3D NULL) {
>> >> >> > >>               struct igmp_ifsoftc *igi;
>> >> >> > >> @@ -1418,7 +1404,7 @@ igmp_input_v2_report(struct ifnet *ifp,=
 /*const*/ stru
>> >> >> > >>       }
>> >> >> > >>
>> >> >> > >>  out_locked:
>> >> >> > >> -     IN_MULTI_UNLOCK();
>> >> >> > >> +     IN_MULTI_LIST_UNLOCK();
>> >> >> > >>
>> >> >> > >>       return (0);
>> >> >> > >>  }
>> >> >> > >> @@ -1647,6 +1633,7 @@ igmp_fasttimo_vnet(void)
>> >> >> > >>       struct igmp_ifsoftc     *igi;
>> >> >> > >>       struct ifmultiaddr      *ifma;
>> >> >> > >>       struct in_multi         *inm;
>> >> >> > >> +     struct in_multi_head inm_free_tmp;
>> >> >> > >>       int                      loop, uri_fasthz;
>> >> >> > >>
>> >> >> > >>       loop =3D 0;
>> >> >> > >> @@ -1662,7 +1649,8 @@ igmp_fasttimo_vnet(void)
>> >> >> > >>           !V_state_change_timers_running)
>> >> >> > >>               return;
>> >> >> > >>
>> >> >> > >> -     IN_MULTI_LOCK();
>> >> >> > >> +     SLIST_INIT(&inm_free_tmp);
>> >> >> > >> +     IN_MULTI_LIST_LOCK();
>> >> >> > >>       IGMP_LOCK();
>> >> >> > >>
>> >> >> > >>       /*
>> >> >> > >> @@ -1720,7 +1708,7 @@ igmp_fasttimo_vnet(void)
>> >> >> > >>                                   igi->igi_version);
>> >> >> > >>                               break;
>> >> >> > >>                       case IGMP_VERSION_3:
>> >> >> > >> -                             igmp_v3_process_group_timers(ig=
i, &qrq,
>> >> >> > >> +                             igmp_v3_process_group_timers(&i=
nm_free_tmp,
>> >> >> > >> &qrq, &scq, inm, uri_fasthz);
>> >> >> > >>                               break;
>> >> >> > >>                       }
>> >> >> > >> @@ -1728,8 +1716,6 @@ igmp_fasttimo_vnet(void)
>> >> >> > >>               IF_ADDR_RUNLOCK(ifp);
>> >> >> > >>
>> >> >> > >>               if (igi->igi_version =3D=3D IGMP_VERSION_3) {
>> >> >> > >> -                     struct in_multi         *tinm;
>> >> >> > >> -
>> >> >> > >>                       igmp_dispatch_queue(&qrq, 0, loop);
>> >> >> > >>                       igmp_dispatch_queue(&scq, 0, loop);
>> >> >> > >>
>> >> >> > >> @@ -1737,18 +1723,13 @@ igmp_fasttimo_vnet(void)
>> >> >> > >>                        * Free the in_multi reference(s) for t=
his
>> >> >> > >>                        * IGMP lifecycle.
>> >> >> > >>                        */
>> >> >> > >> -                     SLIST_FOREACH_SAFE(inm, &igi->igi_relin=
mhead,
>> >> >> > >> -                         inm_nrele, tinm) {
>> >> >> > >> -                             SLIST_REMOVE_HEAD(&igi->igi_rel=
inmhead,
>> >> >> > >> -                                 inm_nrele);
>> >> >> > >> -                             inm_release_locked(inm);
>> >> >> > >> -                     }
>> >> >> > >> +                     inm_release_list_deferred(&inm_free_tmp=
);
>> >> >> > >>               }
>> >> >> > >>       }
>> >> >> > >>
>> >> >> > >>  out_locked:
>> >> >> > >>       IGMP_UNLOCK();
>> >> >> > >> -     IN_MULTI_UNLOCK();
>> >> >> > >> +     IN_MULTI_LIST_UNLOCK();
>> >> >> > >>  }
>> >> >> > >>
>> >> >> > >>  /*
>> >> >> > >> @@ -1760,7 +1741,7 @@ igmp_v1v2_process_group_timer(struct in=
_multi *inm, co
>> >> >> > >>  {
>> >> >> > >>       int report_timer_expired;
>> >> >> > >>
>> >> >> > >> -     IN_MULTI_LOCK_ASSERT();
>> >> >> > >> +     IN_MULTI_LIST_LOCK_ASSERT();
>> >> >> > >>       IGMP_LOCK_ASSERT();
>> >> >> > >>
>> >> >> > >>       if (inm->inm_timer =3D=3D 0) {
>> >> >> > >> @@ -1802,14 +1783,14 @@ igmp_v1v2_process_group_timer(struct =
in_multi *inm,
>> >> >> > >> co
>> >> >> > >>   * Note: Unlocked read from igi.
>> >> >> > >>   */
>> >> >> > >>  static void
>> >> >> > >> -igmp_v3_process_group_timers(struct igmp_ifsoftc *igi,
>> >> >> > >> +igmp_v3_process_group_timers(struct in_multi_head *inmh,
>> >> >> > >>      struct mbufq *qrq, struct mbufq *scq,
>> >> >> > >>      struct in_multi *inm, const int uri_fasthz)
>> >> >> > >>  {
>> >> >> > >>       int query_response_timer_expired;
>> >> >> > >>       int state_change_retransmit_timer_expired;
>> >> >> > >>
>> >> >> > >> -     IN_MULTI_LOCK_ASSERT();
>> >> >> > >> +     IN_MULTI_LIST_LOCK_ASSERT();
>> >> >> > >>       IGMP_LOCK_ASSERT();
>> >> >> > >>
>> >> >> > >>       query_response_timer_expired =3D 0;
>> >> >> > >> @@ -1907,8 +1888,7 @@ igmp_v3_process_group_timers(struct igm=
p_ifsoftc *igi,
>> >> >> > >>                       if (inm->inm_state =3D=3D IGMP_LEAVING_=
MEMBER &&
>> >> >> > >>                           inm->inm_scrv =3D=3D 0) {
>> >> >> > >>                               inm->inm_state =3D IGMP_NOT_MEM=
BER;
>> >> >> > >> -                             SLIST_INSERT_HEAD(&igi->igi_rel=
inmhead,
>> >> >> > >> -                                 inm, inm_nrele);
>> >> >> > >> +                             inm_rele_locked(inmh, inm);
>> >> >> > >>                       }
>> >> >> > >>               }
>> >> >> > >>               break;
>> >> >> > >> @@ -1929,7 +1909,7 @@ static void
>> >> >> > >>  igmp_v3_suppress_group_record(struct in_multi *inm)
>> >> >> > >>  {
>> >> >> > >>
>> >> >> > >> -     IN_MULTI_LOCK_ASSERT();
>> >> >> > >> +     IN_MULTI_LIST_LOCK_ASSERT();
>> >> >> > >>
>> >> >> > >>       KASSERT(inm->inm_igi->igi_version =3D=3D IGMP_VERSION_3=
,
>> >> >> > >>               ("%s: not IGMPv3 mode on link", __func__));
>> >> >> > >> @@ -2003,13 +1983,15 @@ igmp_v3_cancel_link_timers(struct igm=
p_ifsoftc *igi)
>> >> >> > >>  {
>> >> >> > >>       struct ifmultiaddr      *ifma;
>> >> >> > >>       struct ifnet            *ifp;
>> >> >> > >> -     struct in_multi         *inm, *tinm;
>> >> >> > >> +     struct in_multi         *inm;
>> >> >> > >> +     struct in_multi_head inm_free_tmp;
>> >> >> > >>
>> >> >> > >>       CTR3(KTR_IGMPV3, "%s: cancel v3 timers on ifp %p(%s)", =
__func__,
>> >> >> > >>           igi->igi_ifp, igi->igi_ifp->if_xname);
>> >> >> > >>
>> >> >> > >> -     IN_MULTI_LOCK_ASSERT();
>> >> >> > >> +     IN_MULTI_LIST_LOCK_ASSERT();
>> >> >> > >>       IGMP_LOCK_ASSERT();
>> >> >> > >> +     SLIST_INIT(&inm_free_tmp);
>> >> >> > >>
>> >> >> > >>       /*
>> >> >> > >>        * Stop the v3 General Query Response on this link ston=
e dead.
>> >> >> > >> @@ -2050,7 +2032,7 @@ igmp_v3_cancel_link_timers(struct igmp_=
ifsoftc *igi)
>> >> >> > >>                        * message is sent upstream to the old =
querier --
>> >> >> > >>                        * transition to NOT would lose the lea=
ve and race.
>> >> >> > >>                        */
>> >> >> > >> -                     SLIST_INSERT_HEAD(&igi->igi_relinmhead,=
 inm,
>> >> >> > >> inm_nrele);
>> >> >> > >> +                     inm_rele_locked(&inm_free_tmp, inm);
>> >> >> > >>                       /* FALLTHROUGH */
>> >> >> > >>               case IGMP_G_QUERY_PENDING_MEMBER:
>> >> >> > >>               case IGMP_SG_QUERY_PENDING_MEMBER:
>> >> >> > >> @@ -2069,10 +2051,8 @@ igmp_v3_cancel_link_timers(struct igmp=
_ifsoftc *igi)
>> >> >> > >>               mbufq_drain(&inm->inm_scq);
>> >> >> > >>       }
>> >> >> > >>       IF_ADDR_RUNLOCK(ifp);
>> >> >> > >> -     SLIST_FOREACH_SAFE(inm, &igi->igi_relinmhead, inm_nrele=
, tinm) {
>> >> >> > >> -             SLIST_REMOVE_HEAD(&igi->igi_relinmhead, inm_nre=
le);
>> >> >> > >> -             inm_release_locked(inm);
>> >> >> > >> -     }
>> >> >> > >> +
>> >> >> > >> +     inm_release_list_deferred(&inm_free_tmp);
>> >> >> > >>  }
>> >> >> > >>
>> >> >> > >>  /*
>> >> >> > >> @@ -2199,7 +2179,7 @@ igmp_v1v2_queue_report(struct in_multi =
*inm, const int
>> >> >> > >>       struct ip               *ip;
>> >> >> > >>       struct mbuf             *m;
>> >> >> > >>
>> >> >> > >> -     IN_MULTI_LOCK_ASSERT();
>> >> >> > >> +     IN_MULTI_LIST_LOCK_ASSERT();
>> >> >> > >>       IGMP_LOCK_ASSERT();
>> >> >> > >>
>> >> >> > >>       ifp =3D inm->inm_ifp;
>> >> >> > >> @@ -2276,10 +2256,8 @@ igmp_change_state(struct in_multi *inm=
)
>> >> >> > >>       struct ifnet *ifp;
>> >> >> > >>       int error;
>> >> >> > >>
>> >> >> > >> -     IN_MULTI_LOCK_ASSERT();
>> >> >> > >> -
>> >> >> > >>       error =3D 0;
>> >> >> > >> -
>> >> >> > >> +     IN_MULTI_LOCK_ASSERT();
>> >> >> > >>       /*
>> >> >> > >>        * Try to detect if the upper layer just asked us to ch=
ange state
>> >> >> > >>        * for an interface which has now gone away.
>> >> >> > >> @@ -2379,9 +2357,10 @@ igmp_initial_join(struct in_multi *inm=
, struct igmp_if
>> >> >> > >>                * group around for the final INCLUDE {} enqueu=
e.
>> >> >> > >>                */
>> >> >> > >>               if (igi->igi_version =3D=3D IGMP_VERSION_3 &&
>> >> >> > >> -                 inm->inm_state =3D=3D IGMP_LEAVING_MEMBER)
>> >> >> > >> -                     inm_release_locked(inm);
>> >> >> > >> -
>> >> >> > >> +                 inm->inm_state =3D=3D IGMP_LEAVING_MEMBER) =
{
>> >> >> > >> +                     MPASS(inm->inm_refcount > 1);
>> >> >> > >> +                     inm_rele_locked(NULL, inm);
>> >> >> > >> +             }
>> >> >> > >>               inm->inm_state =3D IGMP_REPORTING_MEMBER;
>> >> >> > >>
>> >> >> > >>               switch (igi->igi_version) {
>> >> >> > >> @@ -2473,7 +2452,7 @@ igmp_handle_state_change(struct in_mult=
i *inm, struct
>> >> >> > >>
>> >> >> > >>       ifp =3D inm->inm_ifp;
>> >> >> > >>
>> >> >> > >> -     IN_MULTI_LOCK_ASSERT();
>> >> >> > >> +     IN_MULTI_LIST_LOCK_ASSERT();
>> >> >> > >>       IGMP_LOCK_ASSERT();
>> >> >> > >>
>> >> >> > >>       KASSERT(igi && igi->igi_ifp =3D=3D ifp, ("%s: inconsist=
ent ifp",
>> >> >> > >> __func__)); @@ -2531,7 +2510,7 @@ igmp_final_leave(struct in_=
multi *inm,
>> >> >> > >> struct igmp_ifs __func__, ntohl(inm->inm_addr.s_addr), inm->i=
nm_ifp,
>> >> >> > >>           inm->inm_ifp->if_xname);
>> >> >> > >>
>> >> >> > >> -     IN_MULTI_LOCK_ASSERT();
>> >> >> > >> +     IN_MULTI_LIST_LOCK_ASSERT();
>> >> >> > >>       IGMP_LOCK_ASSERT();
>> >> >> > >>
>> >> >> > >>       switch (inm->inm_state) {
>> >> >> > >> @@ -2658,7 +2637,7 @@ igmp_v3_enqueue_group_record(struct mbu=
fq *mq, struct
>> >> >> > >>       in_addr_t                naddr;
>> >> >> > >>       uint8_t                  mode;
>> >> >> > >>
>> >> >> > >> -     IN_MULTI_LOCK_ASSERT();
>> >> >> > >> +     IN_MULTI_LIST_LOCK_ASSERT();
>> >> >> > >>
>> >> >> > >>       error =3D 0;
>> >> >> > >>       ifp =3D inm->inm_ifp;
>> >> >> > >> @@ -3018,7 +2997,7 @@ igmp_v3_enqueue_filter_change(struct mb=
ufq *mq, struct
>> >> >> > >>       uint8_t                  mode, now, then;
>> >> >> > >>       rectype_t                crt, drt, nrt;
>> >> >> > >>
>> >> >> > >> -     IN_MULTI_LOCK_ASSERT();
>> >> >> > >> +     IN_MULTI_LIST_LOCK_ASSERT();
>> >> >> > >>
>> >> >> > >>       if (inm->inm_nsrc =3D=3D 0 ||
>> >> >> > >>           (inm->inm_st[0].iss_asm > 0 && inm->inm_st[1].iss_a=
sm > 0))
>> >> >> > >> @@ -3221,7 +3200,7 @@ igmp_v3_merge_state_changes(struct in_m=
ulti *inm, stru
>> >> >> > >>       domerge =3D 0;
>> >> >> > >>       recslen =3D 0;
>> >> >> > >>
>> >> >> > >> -     IN_MULTI_LOCK_ASSERT();
>> >> >> > >> +     IN_MULTI_LIST_LOCK_ASSERT();
>> >> >> > >>       IGMP_LOCK_ASSERT();
>> >> >> > >>
>> >> >> > >>       /*
>> >> >> > >> @@ -3320,7 +3299,7 @@ igmp_v3_dispatch_general_query(struct i=
gmp_ifsoftc *ig
>> >> >> > >>       struct in_multi         *inm;
>> >> >> > >>       int                      retval, loop;
>> >> >> > >>
>> >> >> > >> -     IN_MULTI_LOCK_ASSERT();
>> >> >> > >> +     IN_MULTI_LIST_LOCK_ASSERT();
>> >> >> > >>       IGMP_LOCK_ASSERT();
>> >> >> > >>
>> >> >> > >>       KASSERT(igi->igi_version =3D=3D IGMP_VERSION_3,
>> >> >> > >> @@ -3632,7 +3611,6 @@ DB_SHOW_COMMAND(igi_list, db_show_igi_l=
ist)
>> >> >> > >>               db_printf("    qi %u\n", igi->igi_qi);
>> >> >> > >>               db_printf("    qri %u\n", igi->igi_qri);
>> >> >> > >>               db_printf("    uri %u\n", igi->igi_uri);
>> >> >> > >> -             /* SLIST_HEAD(,in_multi)   igi_relinmhead */
>> >> >> > >>               /* struct mbufq    igi_gq; */
>> >> >> > >>               db_printf("\n");
>> >> >> > >>       }
>> >> >> > >>
>> >> >> > >> Modified: head/sys/netinet/igmp_var.h
>> >> >> > >> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D
>> >> >> > >> --- head/sys/netinet/igmp_var.h       Wed May  2 17:41:00 201=
8
>> >> >> > >> (r333174) +++ head/sys/netinet/igmp_var.h       Wed May  2 19=
:36:29
>> >> >> > >> 2018        (r333175) @@ -214,7 +214,6 @@ struct igmp_ifsoftc=
 {
>> >> >> > >>       uint32_t igi_qi;        /* IGMPv3 Query Interval (s) */
>> >> >> > >>       uint32_t igi_qri;       /* IGMPv3 Query Response Interv=
al (s) */
>> >> >> > >>       uint32_t igi_uri;       /* IGMPv3 Unsolicited Report In=
terval (s) */
>> >> >> > >> -     SLIST_HEAD(,in_multi)   igi_relinmhead; /* released gro=
ups */
>> >> >> > >>       struct mbufq    igi_gq;         /* general query respon=
ses queue */
>> >> >> > >>  };
>> >> >> > >>
>> >> >> > >>
>> >> >> > >> Modified: head/sys/netinet/in.c
>> >> >> > >> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D
>> >> >> > >> --- head/sys/netinet/in.c     Wed May  2 17:41:00 2018       =
 (r333174)
>> >> >> > >> +++ head/sys/netinet/in.c     Wed May  2 19:36:29 2018       =
 (r333175)
>> >> >> > >> @@ -632,12 +632,10 @@ in_difaddr_ioctl(u_long cmd, caddr_t da=
ta, struct ifne
>> >> >> > >>               struct in_ifinfo *ii;
>> >> >> > >>
>> >> >> > >>               ii =3D ((struct in_ifinfo *)ifp->if_afdata[AF_I=
NET]);
>> >> >> > >> -             IN_MULTI_LOCK();
>> >> >> > >>               if (ii->ii_allhosts) {
>> >> >> > >> -                     (void)in_leavegroup_locked(ii->ii_allho=
sts, NULL);
>> >> >> > >> +                     (void)in_leavegroup(ii->ii_allhosts, NU=
LL);
>> >> >> > >>                       ii->ii_allhosts =3D NULL;
>> >> >> > >>               }
>> >> >> > >> -             IN_MULTI_UNLOCK();
>> >> >> > >>       }
>> >> >> > >>
>> >> >> > >>       IF_ADDR_WLOCK(ifp);
>> >> >> > >> @@ -994,11 +992,12 @@ in_broadcast(struct in_addr in, struct =
ifnet *ifp)
>> >> >> > >>  void
>> >> >> > >>  in_ifdetach(struct ifnet *ifp)
>> >> >> > >>  {
>> >> >> > >> -
>> >> >> > >> +     IN_MULTI_LOCK();
>> >> >> > >>       in_pcbpurgeif0(&V_ripcbinfo, ifp);
>> >> >> > >>       in_pcbpurgeif0(&V_udbinfo, ifp);
>> >> >> > >>       in_pcbpurgeif0(&V_ulitecbinfo, ifp);
>> >> >> > >>       in_purgemaddrs(ifp);
>> >> >> > >> +     IN_MULTI_UNLOCK();
>> >> >> > >>  }
>> >> >> > >>
>> >> >> > >>  /*
>> >> >> > >> @@ -1011,12 +1010,12 @@ in_ifdetach(struct ifnet *ifp)
>> >> >> > >>  static void
>> >> >> > >>  in_purgemaddrs(struct ifnet *ifp)
>> >> >> > >>  {
>> >> >> > >> -     LIST_HEAD(,in_multi) purgeinms;
>> >> >> > >> -     struct in_multi         *inm, *tinm;
>> >> >> > >> +     struct in_multi_head purgeinms;
>> >> >> > >> +     struct in_multi         *inm;
>> >> >> > >>       struct ifmultiaddr      *ifma;
>> >> >> > >>
>> >> >> > >> -     LIST_INIT(&purgeinms);
>> >> >> > >> -     IN_MULTI_LOCK();
>> >> >> > >> +     SLIST_INIT(&purgeinms);
>> >> >> > >> +     IN_MULTI_LIST_LOCK();
>> >> >> > >>
>> >> >> > >>       /*
>> >> >> > >>        * Extract list of in_multi associated with the detachi=
ng ifp
>> >> >> > >> @@ -1034,17 +1033,13 @@ in_purgemaddrs(struct ifnet *ifp)
>> >> >> > >>                   ("%s: ifma_protospec is NULL", __func__));
>> >> >> > >>  #endif
>> >> >> > >>               inm =3D (struct in_multi *)ifma->ifma_protospec=
;
>> >> >> > >> -             LIST_INSERT_HEAD(&purgeinms, inm, inm_link);
>> >> >> > >> +             inm_rele_locked(&purgeinms, inm);
>> >> >> > >>       }
>> >> >> > >>       IF_ADDR_RUNLOCK(ifp);
>> >> >> > >>
>> >> >> > >> -     LIST_FOREACH_SAFE(inm, &purgeinms, inm_link, tinm) {
>> >> >> > >> -             LIST_REMOVE(inm, inm_link);
>> >> >> > >> -             inm_release_locked(inm);
>> >> >> > >> -     }
>> >> >> > >> +     inm_release_list_deferred(&purgeinms);
>> >> >> > >>       igmp_ifdetach(ifp);
>> >> >> > >> -
>> >> >> > >> -     IN_MULTI_UNLOCK();
>> >> >> > >> +     IN_MULTI_LIST_UNLOCK();
>> >> >> > >>  }
>> >> >> > >>
>> >> >> > >>  struct in_llentry {
>> >> >> > >>
>> >> >> > >> Modified: head/sys/netinet/in_mcast.c
>> >> >> > >> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D
>> >> >> > >> --- head/sys/netinet/in_mcast.c       Wed May  2 17:41:00 201=
8
>> >> >> > >> (r333174) +++ head/sys/netinet/in_mcast.c       Wed May  2 19=
:36:29
>> >> >> > >> 2018        (r333175) @@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$")=
;
>> >> >> > >>  #include <sys/sysctl.h>
>> >> >> > >>  #include <sys/ktr.h>
>> >> >> > >>  #include <sys/taskqueue.h>
>> >> >> > >> +#include <sys/gtaskqueue.h>
>> >> >> > >>  #include <sys/tree.h>
>> >> >> > >>
>> >> >> > >>  #include <net/if.h>
>> >> >> > >> @@ -59,6 +60,8 @@ __FBSDID("$FreeBSD$");
>> >> >> > >>  #include <net/route.h>
>> >> >> > >>  #include <net/vnet.h>
>> >> >> > >>
>> >> >> > >> +#include <net/ethernet.h>
>> >> >> > >> +
>> >> >> > >>  #include <netinet/in.h>
>> >> >> > >>  #include <netinet/in_systm.h>
>> >> >> > >>  #include <netinet/in_fib.h>
>> >> >> > >> @@ -91,18 +94,24 @@ static MALLOC_DEFINE(M_IPMSOURCE, "ip_mso=
urce",
>> >> >> > >>
>> >> >> > >>  /*
>> >> >> > >>   * Locking:
>> >> >> > >> - * - Lock order is: Giant, INP_WLOCK, IN_MULTI_LOCK, IGMP_LO=
CK,
>> >> >> > >> IF_ADDR_LOCK.
>> >> >> > >> + * - Lock order is: Giant, INP_WLOCK, IN_MULTI_LIST_LOCK, IG=
MP_LOCK,
>> >> >> > >> IF_ADDR_LOCK.
>> >> >> > >>   * - The IF_ADDR_LOCK is implicitly taken by inm_lookup() ea=
rlier, however
>> >> >> > >>   *   it can be taken by code in net/if.c also.
>> >> >> > >>   * - ip_moptions and in_mfilter are covered by the INP_WLOCK=
.
>> >> >> > >>   *
>> >> >> > >> - * struct in_multi is covered by IN_MULTI_LOCK. There isn't =
strictly
>> >> >> > >> + * struct in_multi is covered by IN_MULTI_LIST_LOCK. There i=
sn't strictly
>> >> >> > >>   * any need for in_multi itself to be virtualized -- it is b=
ound to an ifp
>> >> >> > >>   * anyway no matter what happens.
>> >> >> > >>   */
>> >> >> > >> -struct mtx in_multi_mtx;
>> >> >> > >> -MTX_SYSINIT(in_multi_mtx, &in_multi_mtx, "in_multi_mtx", MTX=
_DEF);
>> >> >> > >> +struct mtx in_multi_list_mtx;
>> >> >> > >> +MTX_SYSINIT(in_multi_mtx, &in_multi_list_mtx, "in_multi_list=
_mtx", MTX_DEF);
>> >> >> > >>
>> >> >> > >> +struct mtx in_multi_free_mtx;
>> >> >> > >> +MTX_SYSINIT(in_multi_free_mtx, &in_multi_free_mtx, "in_multi=
_free_mtx",
>> >> >> > >> MTX_DEF); +
>> >> >> > >> +struct sx in_multi_sx;
>> >> >> > >> +SX_SYSINIT(in_multi_sx, &in_multi_sx, "in_multi_sx");
>> >> >> > >> +
>> >> >> > >>  /*
>> >> >> > >>   * Functions with non-static linkage defined in this file sh=
ould be
>> >> >> > >>   * declared in in_var.h:
>> >> >> > >> @@ -151,6 +160,7 @@ static int        inm_is_ifp_detached(con=
st struct
>> >> >> > >> in_multi
>> >> >> > >> * static int   inm_merge(struct in_multi *, /*const*/ struct =
in_mfilter *);
>> >> >> > >>  static void  inm_purge(struct in_multi *);
>> >> >> > >>  static void  inm_reap(struct in_multi *);
>> >> >> > >> +static void inm_release(struct in_multi *);
>> >> >> > >>  static struct ip_moptions *
>> >> >> > >>               inp_findmoptions(struct inpcb *);
>> >> >> > >>  static void  inp_freemoptions_internal(struct ip_moptions *)=
;
>> >> >> > >> @@ -216,6 +226,65 @@ inm_is_ifp_detached(const struct in_mult=
i *inm)
>> >> >> > >>  }
>> >> >> > >>  #endif
>> >> >> > >>
>> >> >> > >> +static struct grouptask free_gtask;
>> >> >> > >> +static struct in_multi_head inm_free_list;
>> >> >> > >> +static void inm_release_task(void *arg __unused);
>> >> >> > >> +static void inm_init(void)
>> >> >> > >> +{
>> >> >> > >> +     SLIST_INIT(&inm_free_list);
>> >> >> > >> +     taskqgroup_config_gtask_init(NULL, &free_gtask, inm_rel=
ease_task, "inm
>> >> >> > >> release task"); +}
>> >> >> > >> +
>> >> >> > >> +SYSINIT(inm_init, SI_SUB_SMP + 1, SI_ORDER_FIRST,
>> >> >> > >> +     inm_init, NULL);
>> >> >> > >> +
>> >> >> > >> +
>> >> >> > >> +void
>> >> >> > >> +inm_release_list_deferred(struct in_multi_head *inmh)
>> >> >> > >> +{
>> >> >> > >> +
>> >> >> > >> +     if (SLIST_EMPTY(inmh))
>> >> >> > >> +             return;
>> >> >> > >> +     mtx_lock(&in_multi_free_mtx);
>> >> >> > >> +     SLIST_CONCAT(&inm_free_list, inmh, in_multi, inm_nrele)=
;
>> >> >> > >> +     mtx_unlock(&in_multi_free_mtx);
>> >> >> > >> +     GROUPTASK_ENQUEUE(&free_gtask);
>> >> >> > >> +}
>> >> >> > >> +
>> >> >> > >> +void
>> >> >> > >> +inm_release_deferred(struct in_multi *inm)
>> >> >> > >> +{
>> >> >> > >> +     struct in_multi_head tmp;
>> >> >> > >> +
>> >> >> > >> +     IN_MULTI_LIST_LOCK_ASSERT();
>> >> >> > >> +     MPASS(inm->inm_refcount > 0);
>> >> >> > >> +     if (--inm->inm_refcount =3D=3D 0) {
>> >> >> > >> +             SLIST_INIT(&tmp);
>> >> >> > >> +             inm->inm_ifma->ifma_protospec =3D NULL;
>> >> >> > >> +             SLIST_INSERT_HEAD(&tmp, inm, inm_nrele);
>> >> >> > >> +             inm_release_list_deferred(&tmp);
>> >> >> > >> +     }
>> >> >> > >> +}
>> >> >> > >> +
>> >> >> > >> +static void
>> >> >> > >> +inm_release_task(void *arg __unused)
>> >> >> > >> +{
>> >> >> > >> +     struct in_multi_head inm_free_tmp;
>> >> >> > >> +     struct in_multi *inm, *tinm;
>> >> >> > >> +
>> >> >> > >> +     SLIST_INIT(&inm_free_tmp);
>> >> >> > >> +     mtx_lock(&in_multi_free_mtx);
>> >> >> > >> +     SLIST_CONCAT(&inm_free_tmp, &inm_free_list, in_multi, i=
nm_nrele);
>> >> >> > >> +     mtx_unlock(&in_multi_free_mtx);
>> >> >> > >> +     IN_MULTI_LOCK();
>> >> >> > >> +     SLIST_FOREACH_SAFE(inm, &inm_free_tmp, inm_nrele, tinm)=
 {
>> >> >> > >> +             SLIST_REMOVE_HEAD(&inm_free_tmp, inm_nrele);
>> >> >> > >> +             MPASS(inm);
>> >> >> > >> +             inm_release(inm);
>> >> >> > >> +     }
>> >> >> > >> +     IN_MULTI_UNLOCK();
>> >> >> > >> +}
>> >> >> > >> +
>> >> >> > >>  /*
>> >> >> > >>   * Initialize an in_mfilter structure to a known state at t0=
, t1
>> >> >> > >>   * with an empty source filter list.
>> >> >> > >> @@ -232,7 +301,7 @@ imf_init(struct in_mfilter *imf, const in=
t st0, const
>> >> >> > >>  /*
>> >> >> > >>   * Function for looking up an in_multi record for an IPv4 mu=
lticast address
>> >> >> > >>   * on a given interface. ifp must be valid. If no record fou=
nd, return NULL.
>> >> >> > >> - * The IN_MULTI_LOCK and IF_ADDR_LOCK on ifp must be held.
>> >> >> > >> + * The IN_MULTI_LIST_LOCK and IF_ADDR_LOCK on ifp must be he=
ld.
>> >> >> > >>   */
>> >> >> > >>  struct in_multi *
>> >> >> > >>  inm_lookup_locked(struct ifnet *ifp, const struct in_addr in=
a)
>> >> >> > >> @@ -240,7 +309,7 @@ inm_lookup_locked(struct ifnet *ifp, cons=
t struct in_a
>> >> >> > >>       struct ifmultiaddr *ifma;
>> >> >> > >>       struct in_multi *inm;
>> >> >> > >>
>> >> >> > >> -     IN_MULTI_LOCK_ASSERT();
>> >> >> > >> +     IN_MULTI_LIST_LOCK_ASSERT();
>> >> >> > >>       IF_ADDR_LOCK_ASSERT(ifp);
>> >> >> > >>
>> >> >> > >>       inm =3D NULL;
>> >> >> > >> @@ -264,7 +333,7 @@ inm_lookup(struct ifnet *ifp, const struc=
t in_addr ina
>> >> >> > >>  {
>> >> >> > >>       struct in_multi *inm;
>> >> >> > >>
>> >> >> > >> -     IN_MULTI_LOCK_ASSERT();
>> >> >> > >> +     IN_MULTI_LIST_LOCK_ASSERT();
>> >> >> > >>       IF_ADDR_RLOCK(ifp);
>> >> >> > >>       inm =3D inm_lookup_locked(ifp, ina);
>> >> >> > >>       IF_ADDR_RUNLOCK(ifp);
>> >> >> > >> @@ -451,7 +520,7 @@ in_getmulti(struct ifnet *ifp, const stru=
ct in_addr *g
>> >> >> > >>       IN_MULTI_LOCK_ASSERT();
>> >> >> > >>
>> >> >> > >>       ii =3D (struct in_ifinfo *)ifp->if_afdata[AF_INET];
>> >> >> > >> -
>> >> >> > >> +     IN_MULTI_LIST_LOCK();
>> >> >> > >>       inm =3D inm_lookup(ifp, *group);
>> >> >> > >>       if (inm !=3D NULL) {
>> >> >> > >>               /*
>> >> >> > >> @@ -460,11 +529,13 @@ in_getmulti(struct ifnet *ifp, const st=
ruct in_addr *g
>> >> >> > >>                */
>> >> >> > >>               KASSERT(inm->inm_refcount >=3D 1,
>> >> >> > >>                   ("%s: bad refcount %d", __func__, inm->inm_=
refcount));
>> >> >> > >> -             ++inm->inm_refcount;
>> >> >> > >> +             inm_acquire_locked(inm);
>> >> >> > >>               *pinm =3D inm;
>> >> >> > >> -             return (0);
>> >> >> > >>       }
>> >> >> > >> -
>> >> >> > >> +     IN_MULTI_LIST_UNLOCK();
>> >> >> > >> +     if (inm !=3D NULL)
>> >> >> > >> +             return (0);
>> >> >> > >> +
>> >> >> > >>       memset(&gsin, 0, sizeof(gsin));
>> >> >> > >>       gsin.sin_family =3D AF_INET;
>> >> >> > >>       gsin.sin_len =3D sizeof(struct sockaddr_in);
>> >> >> > >> @@ -479,6 +550,7 @@ in_getmulti(struct ifnet *ifp, const stru=
ct in_addr *g
>> >> >> > >>               return (error);
>> >> >> > >>
>> >> >> > >>       /* XXX ifma_protospec must be covered by IF_ADDR_LOCK *=
/
>> >> >> > >> +     IN_MULTI_LIST_LOCK();
>> >> >> > >>       IF_ADDR_WLOCK(ifp);
>> >> >> > >>
>> >> >> > >>       /*
>> >> >> > >> @@ -504,10 +576,9 @@ in_getmulti(struct ifnet *ifp, const str=
uct in_addr *g
>> >> >> > >>                           __func__, ifma, inm, inet_ntoa_r(*g=
roup, addrbuf));
>> >> >> > >>               }
>> >> >> > >>  #endif
>> >> >> > >> -             ++inm->inm_refcount;
>> >> >> > >> +             inm_acquire_locked(inm);
>> >> >> > >>               *pinm =3D inm;
>> >> >> > >> -             IF_ADDR_WUNLOCK(ifp);
>> >> >> > >> -             return (0);
>> >> >> > >> +             goto out_locked;
>> >> >> > >>       }
>> >> >> > >>
>> >> >> > >>       IF_ADDR_WLOCK_ASSERT(ifp);
>> >> >> > >> @@ -522,6 +593,7 @@ in_getmulti(struct ifnet *ifp, const stru=
ct in_addr *g
>> >> >> > >>       inm =3D malloc(sizeof(*inm), M_IPMADDR, M_NOWAIT | M_ZE=
RO);
>> >> >> > >>       if (inm =3D=3D NULL) {
>> >> >> > >>               IF_ADDR_WUNLOCK(ifp);
>> >> >> > >> +             IN_MULTI_LIST_UNLOCK();
>> >> >> > >>               if_delmulti_ifma(ifma);
>> >> >> > >>               return (ENOMEM);
>> >> >> > >>       }
>> >> >> > >> @@ -539,8 +611,9 @@ in_getmulti(struct ifnet *ifp, const stru=
ct in_addr *g
>> >> >> > >>       ifma->ifma_protospec =3D inm;
>> >> >> > >>
>> >> >> > >>       *pinm =3D inm;
>> >> >> > >> -
>> >> >> > >> + out_locked:
>> >> >> > >>       IF_ADDR_WUNLOCK(ifp);
>> >> >> > >> +     IN_MULTI_LIST_UNLOCK();
>> >> >> > >>       return (0);
>> >> >> > >>  }
>> >> >> > >>
>> >> >> > >> @@ -550,36 +623,29 @@ in_getmulti(struct ifnet *ifp, const st=
ruct in_addr *g
>> >> >> > >>   * If the refcount drops to 0, free the in_multi record and
>> >> >> > >>   * delete the underlying link-layer membership.
>> >> >> > >>   */
>> >> >> > >> -void
>> >> >> > >> -inm_release_locked(struct in_multi *inm)
>> >> >> > >> +static void
>> >> >> > >> +inm_release(struct in_multi *inm)
>> >> >> > >>  {
>> >> >> > >>       struct ifmultiaddr *ifma;
>> >> >> > >> +     struct ifnet *ifp;
>> >> >> > >>
>> >> >> > >> -     IN_MULTI_LOCK_ASSERT();
>> >> >> > >> -
>> >> >> > >>       CTR2(KTR_IGMPV3, "%s: refcount is %d", __func__, inm->i=
nm_refcount);
>> >> >> > >> -
>> >> >> > >> -     if (--inm->inm_refcount > 0) {
>> >> >> > >> -             CTR2(KTR_IGMPV3, "%s: refcount is now %d", __fu=
nc__,
>> >> >> > >> -                 inm->inm_refcount);
>> >> >> > >> -             return;
>> >> >> > >> -     }
>> >> >> > >> -
>> >> >> > >> +     MPASS(inm->inm_refcount =3D=3D 0);
>> >> >> > >>       CTR2(KTR_IGMPV3, "%s: freeing inm %p", __func__, inm);
>> >> >> > >>
>> >> >> > >>       ifma =3D inm->inm_ifma;
>> >> >> > >> +     ifp =3D inm->inm_ifp;
>> >> >> > >>
>> >> >> > >>       /* XXX this access is not covered by IF_ADDR_LOCK */
>> >> >> > >>       CTR2(KTR_IGMPV3, "%s: purging ifma %p", __func__, ifma)=
;
>> >> >> > >> -     KASSERT(ifma->ifma_protospec =3D=3D inm,
>> >> >> > >> -         ("%s: ifma_protospec !=3D inm", __func__));
>> >> >> > >> -     ifma->ifma_protospec =3D NULL;
>> >> >> > >> -
>> >> >> > >> +     if (ifp)
>> >> >> > >> +             CURVNET_SET(ifp->if_vnet);
>> >> >> > >>       inm_purge(inm);
>> >> >> > >> -
>> >> >> > >>       free(inm, M_IPMADDR);
>> >> >> > >>
>> >> >> > >>       if_delmulti_ifma(ifma);
>> >> >> > >> +     if (ifp)
>> >> >> > >> +             CURVNET_RESTORE();
>> >> >> > >>  }
>> >> >> > >>
>> >> >> > >>  /*
>> >> >> > >> @@ -592,7 +658,7 @@ inm_clear_recorded(struct in_multi *inm)
>> >> >> > >>  {
>> >> >> > >>       struct ip_msource       *ims;
>> >> >> > >>
>> >> >> > >> -     IN_MULTI_LOCK_ASSERT();
>> >> >> > >> +     IN_MULTI_LIST_LOCK_ASSERT();
>> >> >> > >>
>> >> >> > >>       RB_FOREACH(ims, ip_msource_tree, &inm->inm_srcs) {
>> >> >> > >>               if (ims->ims_stp) {
>> >> >> > >> @@ -632,7 +698,7 @@ inm_record_source(struct in_multi *inm, c=
onst in_addr_
>> >> >> > >>       struct ip_msource        find;
>> >> >> > >>       struct ip_msource       *ims, *nims;
>> >> >> > >>
>> >> >> > >> -     IN_MULTI_LOCK_ASSERT();
>> >> >> > >> +     IN_MULTI_LIST_LOCK_ASSERT();
>> >> >> > >>
>> >> >> > >>       find.ims_haddr =3D ntohl(naddr);
>> >> >> > >>       ims =3D RB_FIND(ip_msource_tree, &inm->inm_srcs, &find)=
;
>> >> >> > >> @@ -959,6 +1025,7 @@ inm_merge(struct in_multi *inm, /*const*=
/ struct in_mf
>> >> >> > >>       schanged =3D 0;
>> >> >> > >>       error =3D 0;
>> >> >> > >>       nsrc1 =3D nsrc0 =3D 0;
>> >> >> > >> +     IN_MULTI_LIST_LOCK_ASSERT();
>> >> >> > >>
>> >> >> > >>       /*
>> >> >> > >>        * Update the source filters first, as this may fail.
>> >> >> > >> @@ -1165,6 +1232,7 @@ in_joingroup_locked(struct ifnet *ifp, =
const struct in
>> >> >> > >>       int                      error;
>> >> >> > >>
>> >> >> > >>       IN_MULTI_LOCK_ASSERT();
>> >> >> > >> +     IN_MULTI_LIST_UNLOCK_ASSERT();
>> >> >> > >>
>> >> >> > >>       CTR4(KTR_IGMPV3, "%s: join 0x%08x on %p(%s))", __func__=
,
>> >> >> > >>           ntohl(gina->s_addr), ifp, ifp->if_xname);
>> >> >> > >> @@ -1186,7 +1254,7 @@ in_joingroup_locked(struct ifnet *ifp, =
const struct in
>> >> >> > >>               CTR1(KTR_IGMPV3, "%s: in_getmulti() failure", _=
_func__);
>> >> >> > >>               return (error);
>> >> >> > >>       }
>> >> >> > >> -
>> >> >> > >> +     IN_MULTI_LIST_LOCK();
>> >> >> > >>       CTR1(KTR_IGMPV3, "%s: merge inm state", __func__);
>> >> >> > >>       error =3D inm_merge(inm, imf);
>> >> >> > >>       if (error) {
>> >> >> > >> @@ -1201,10 +1269,12 @@ in_joingroup_locked(struct ifnet *ifp=
, const struct
>> >> >> > >> in goto out_inm_release;
>> >> >> > >>       }
>> >> >> > >>
>> >> >> > >> -out_inm_release:
>> >> >> > >> + out_inm_release:
>> >> >> > >> +     IN_MULTI_LIST_UNLOCK();
>> >> >> > >>       if (error) {
>> >> >> > >> +
>> >> >> > >>               CTR2(KTR_IGMPV3, "%s: dropping ref on %p", __fu=
nc__, inm);
>> >> >> > >> -             inm_release_locked(inm);
>> >> >> > >> +             inm_release_deferred(inm);
>> >> >> > >>       } else {
>> >> >> > >>               *pinm =3D inm;
>> >> >> > >>       }
>> >> >> > >> @@ -1249,6 +1319,7 @@ in_leavegroup_locked(struct in_multi *i=
nm, /*const*/ s
>> >> >> > >>       error =3D 0;
>> >> >> > >>
>> >> >> > >>       IN_MULTI_LOCK_ASSERT();
>> >> >> > >> +     IN_MULTI_LIST_UNLOCK_ASSERT();
>> >> >> > >>
>> >> >> > >>       CTR5(KTR_IGMPV3, "%s: leave inm %p, 0x%08x/%s, imf %p",=
 __func__,
>> >> >> > >>           inm, ntohl(inm->inm_addr.s_addr),
>> >> >> > >> @@ -1272,18 +1343,20 @@ in_leavegroup_locked(struct in_multi =
*inm, /*const*/
>> >> >> > >> s
>> >> >> > >>        * the transaction, it MUST NOT fail.
>> >> >> > >>        */
>> >> >> > >>       CTR1(KTR_IGMPV3, "%s: merge inm state", __func__);
>> >> >> > >> +     IN_MULTI_LIST_LOCK();
>> >> >> > >>       error =3D inm_merge(inm, imf);
>> >> >> > >>       KASSERT(error =3D=3D 0, ("%s: failed to merge inm state=
", __func__));
>> >> >> > >>
>> >> >> > >>       CTR1(KTR_IGMPV3, "%s: doing igmp downcall", __func__);
>> >> >> > >>       CURVNET_SET(inm->inm_ifp->if_vnet);
>> >> >> > >>       error =3D igmp_change_state(inm);
>> >> >> > >> +     inm_release_deferred(inm);
>> >> >> > >> +     IN_MULTI_LIST_UNLOCK();
>> >> >> > >>       CURVNET_RESTORE();
>> >> >> > >>       if (error)
>> >> >> > >>               CTR1(KTR_IGMPV3, "%s: failed igmp downcall", __=
func__);
>> >> >> > >>
>> >> >> > >>       CTR2(KTR_IGMPV3, "%s: dropping ref on %p", __func__, in=
m);
>> >> >> > >> -     inm_release_locked(inm);
>> >> >> > >>
>> >> >> > >>       return (error);
>> >> >> > >>  }
>> >> >> > >> @@ -1315,18 +1388,6 @@ in_addmulti(struct in_addr *ap, struct=
 ifnet *ifp)
>> >> >> > >>  }
>> >> >> > >>
>> >> >> > >>  /*
>> >> >> > >> - * Leave an IPv4 multicast group, assumed to be in exclusive=
 (*,G) mode.
>> >> >> > >> - * This KPI is for legacy kernel consumers only.
>> >> >> > >> - */
>> >> >> > >>
>> >> >> > >> *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
>> >> >> > >> _______________________________________________
>> >> >> > >> svn-src-head@freebsd.org mailing list
>> >> >> > >> https://lists.freebsd.org/mailman/listinfo/svn-src-head
>> >> >> > >> To unsubscribe, send any mail to "svn-src-head-unsubscribe@fr=
eebsd.org"
>> >> >> > >
>> >> >> > >
>> >> >> > > After (around!) this update, some boxes with i350 dual port NI=
Cs immediately
>> >> >> > > crash with Fatal trap 12: page fault and something with
>> >> >> > >
>> >> >> > > current process: (isc-worker0006)
>> >> >> > >
>> >> >> > > ....
>> >> >> > >
>> >> >> > > Those boxes do not have debugging kernel. The symptombs are th=
e same. Single
>> >> >> > > user kernel works, but the moment I perform /etc/netstart and =
any kind of net
>> >> >> > > traffic establishes, this crap bails out.
>> >> >> > >
>> >> >> > >
>> >> >> > > - --
>> >> >> > > O. Hartmann
>> >> >> > >
>> >> >> > > Ich widerspreche der Nutzung oder =C3=9Cbermittlung meiner Dat=
en f=C3=BCr
>> >> >> > > Werbezwecke oder f=C3=BCr die Markt- oder Meinungsforschung (=
=C2=A7 28 Abs. 4 BDSG).
>> >> >> > > -----BEGIN PGP SIGNATURE-----
>> >> >> > >
>> >> >> > > iLUEARMKAB0WIQQZVZMzAtwC2T/86TrS528fyFhYlAUCWutjtgAKCRDS528fyF=
hY
>> >> >> > > lAkzAf9PhaFTwNhQD2zF7xSHJ2wfvLtoUEjZlzGsusACp1pa7JAfz0Pyv+lm+X=
NJ
>> >> >> > > vLElrIf1CmDzuA8yblZ/x/wOVSJkAf9C+50DVEtGq5H/bHSDNwzmqrj8YgB7Xp=
Ss
>> >> >> > > PMRXc+IwIa1Jgi2yM+6TCSNSs1N5bEUhU9Bi8eXy6Y0FSkAZeV+s
>> >> >> > > =3DS0bC
>> >> >> > > -----END PGP SIGNATURE-----
>> >> >> > > _______________________________________________
>> >> >> > > svn-src-head@freebsd.org mailing list
>> >> >> > > https://lists.freebsd.org/mailman/listinfo/svn-src-head
>> >> >> > > To unsubscribe, send any mail to "svn-src-head-unsubscribe@fre=
ebsd.org"
>> >> >>
>> >> >>
>> >> >>
>> >> >> - --
>> >> >> O. Hartmann
>> >> >>
>> >> >> Ich widerspreche der Nutzung oder =C3=9Cbermittlung meiner Daten f=
=C3=BCr
>> >> >> Werbezwecke oder f=C3=BCr die Markt- oder Meinungsforschung (=C2=
=A7 28 Abs. 4 BDSG).
>> >> >> -----BEGIN PGP SIGNATURE-----
>> >> >>
>> >> >> iLUEARMKAB0WIQQZVZMzAtwC2T/86TrS528fyFhYlAUCWutv8wAKCRDS528fyFhY
>> >> >> lIe1AfwOCAigpXawZ7KAjLNpWjRT4DsrzfqcC57MoziVQyK+X9qoQA2v0plVNpP0
>> >> >> FLqh5dkRXiiOLryr9auILUKyLCNyAfwL7cFe1YRX7VnsK5w//8Xm25tJ74CXC8P0
>> >> >> gaoSqvDqCKWTj6iN+Q/PjoNohWoIK76tiZAWPjkaHeuFbypPa2G+
>> >> >> =3DEpJa
>> >> >> -----END PGP SIGNATURE-----
>> >> >> _______________________________________________
>> >> >> svn-src-head@freebsd.org mailing list
>> >> >> https://lists.freebsd.org/mailman/listinfo/svn-src-head
>> >> >> To unsubscribe, send any mail to "svn-src-head-unsubscribe@freebsd=
.org"
>> >> >
>> >> >
>> >> >
>> >> > - --
>> >> > O. Hartmann
>> >> >
>> >> > Ich widerspreche der Nutzung oder =C3=9Cbermittlung meiner Daten f=
=C3=BCr
>> >> > Werbezwecke oder f=C3=BCr die Markt- oder Meinungsforschung (=C2=A7=
 28 Abs. 4 BDSG).
>> >> > -----BEGIN PGP SIGNATURE-----
>> >> >
>> >> > iLUEARMKAB0WIQQZVZMzAtwC2T/86TrS528fyFhYlAUCWu1y8gAKCRDS528fyFhY
>> >> > lFEoAf4iW+4tSAOcG0EQ1/Y2PNqLCX4AnpYTlSlaECxtFlDZ/XbNOw3TyVB9RbQC
>> >> > qGE9Ux2xQBD48a1Nb1IHVVC9ji7jAgCLOXzKUqmcXkPNvjSgZWZ+Sdyd55ChoLgY
>> >> > SkyY8FSU3GEDm28WgaXjQ4oJh+7/Ff69NsuDZlt7iC24KZdRKH00
>> >> > =3D4bY+
>> >> > -----END PGP SIGNATURE-----
>> >> _______________________________________________
>> >> svn-src-head@freebsd.org mailing list
>> >> https://lists.freebsd.org/mailman/listinfo/svn-src-head
>> >> To unsubscribe, send any mail to "svn-src-head-unsubscribe@freebsd.or=
g"
>> >
>> >
>> >
>> > - --
>> > O. Hartmann
>> >
>> > Ich widerspreche der Nutzung oder =C3=9Cbermittlung meiner Daten f=C3=
=BCr
>> > Werbezwecke oder f=C3=BCr die Markt- oder Meinungsforschung (=C2=A7 28=
 Abs. 4 BDSG).
>> > -----BEGIN PGP SIGNATURE-----
>> >
>> > iLUEARMKAB0WIQQZVZMzAtwC2T/86TrS528fyFhYlAUCWu4UtwAKCRDS528fyFhY
>> > lIz2Af9nqrSGQsaNVZ9DcSTX4oro3SR/8eftbC41dat67gjYIub9xDKUlbfUPIkT
>> > oGdPP9xO35+XOnmzOK6xmLyJbwv5AgCXe7XbcBcGfQ380zhGgmeZ5ich2Td1Lgxo
>> > 8t7iFo+xTv+TicQ27uRqCwKPcYEbz06UKKgq9ttYqgXZV1UIzs5h
>> > =3D/UZf
>> > -----END PGP SIGNATURE-----
>> _______________________________________________
>> svn-src-head@freebsd.org mailing list
>> https://lists.freebsd.org/mailman/listinfo/svn-src-head
>> To unsubscribe, send any mail to "svn-src-head-unsubscribe@freebsd.org"
>
>
>
> - --
> O. Hartmann
>
> Ich widerspreche der Nutzung oder =C3=9Cbermittlung meiner Daten f=C3=BCr
> Werbezwecke oder f=C3=BCr die Markt- oder Meinungsforschung (=C2=A7 28 Ab=
s. 4 BDSG).
> -----BEGIN PGP SIGNATURE-----
>
> iLUEARMKAB0WIQQZVZMzAtwC2T/86TrS528fyFhYlAUCWu4aLQAKCRDS528fyFhY
> lNsoAf0fFnE7nGankm387xskOAHKxbGPfzQcNJyWVV3ZBZoxe49/TnbLXrg4PDqC
> 7kXfIuz30egQWV5oHzZwYeORftxUAf0U3f82TFHTFPyVUQWLOarSXh9ZDc8w4ub9
> HeupxtFU0NyPorDb48aR34RyfGTVBfVpcmd7j4pqV5DAyb6mUT0u
> =3Dv8oR
> -----END PGP SIGNATURE-----



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAPrugNobRcsMjkFGr55WqyEk0J22DOEBboLibXV86nMPn-QS4g>