Index: if_etherbridge.c =================================================================== RCS file: /cvs/src/sys/net/if_etherbridge.c,v retrieving revision 1.6 diff -u -p -r1.6 if_etherbridge.c --- if_etherbridge.c 10 Mar 2021 10:21:47 -0000 1.6 +++ if_etherbridge.c 24 Jun 2021 03:51:15 -0000 @@ -44,7 +44,6 @@ #include -static inline void ebe_take(struct eb_entry *); static inline void ebe_rele(struct eb_entry *); static void ebe_free(void *); @@ -233,16 +232,9 @@ ebt_remove(struct etherbridge *eb, struc } static inline void -ebe_take(struct eb_entry *ebe) -{ - refcnt_take(&ebe->ebe_refs); -} - -static void ebe_rele(struct eb_entry *ebe) { - if (refcnt_rele(&ebe->ebe_refs)) - smr_call(&ebe->ebe_smr_entry, ebe_free, ebe); + smr_call(&ebe->ebe_smr_entry, ebe_free, ebe); } static void @@ -317,14 +309,20 @@ etherbridge_map(struct etherbridge *eb, /* does this entry need to be replaced? */ if (oebe->ebe_type == EBE_DYNAMIC && - !eb_port_eq(eb, oebe->ebe_port, port)) { + !eb_port_eq(eb, oebe->ebe_port, port)) new = 1; - ebe_take(oebe); - } else + else oebe = NULL; } smr_read_leave(); + /* + * note that we don't own or hold a valid reference to oebe + * here until we get it back again inside the eb->eb_lock + * critical section below. until then it's just a value we + * can compare against, not a pointer we can deref. + */ + if (!new) return; @@ -342,7 +340,6 @@ etherbridge_map(struct etherbridge *eb, } smr_init(&nebe->ebe_smr_entry); - refcnt_init(&nebe->ebe_refs); nebe->ebe_etherbridge = eb; nebe->ebe_addr = eba; @@ -359,16 +356,13 @@ etherbridge_map(struct etherbridge *eb, if (oebe != NULL) { ebl_remove(ebl, oebe); ebt_replace(eb, oebe, nebe); - - /* take the table reference away */ - if (refcnt_rele(&oebe->ebe_refs)) { - panic("%s: eb %p oebe %p refcnt", - __func__, eb, oebe); - } } - nebe = NULL; + nebe = NULL; /* give nebe reference to the table */ eb->eb_num = num; + } else { + /* we lost, we didn't end up replacing oebe */ + oebe = NULL; } mtx_leave(&eb->eb_lock); @@ -381,11 +375,7 @@ etherbridge_map(struct etherbridge *eb, } if (oebe != NULL) { - /* - * the old entry could be referenced in - * multiple places, including an smr read - * section, so release it properly. - */ + /* we removed this entry, so it's ours to release. */ ebe_rele(oebe); } } @@ -415,7 +405,6 @@ etherbridge_add_addr(struct etherbridge } smr_init(&nebe->ebe_smr_entry); - refcnt_init(&nebe->ebe_refs); nebe->ebe_etherbridge = eb; nebe->ebe_addr = eba; @@ -551,12 +540,18 @@ etherbridge_detach_port(struct etherbrid mtx_leave(&eb->eb_lock); } - smr_barrier(); /* try and do it once for all the entries */ + if (TAILQ_EMPTY(&ebq)) + return; + + /* + * do one smr barrier for all the entries rather than an + * smr_call each. + */ + smr_barrier(); TAILQ_FOREACH_SAFE(ebe, &ebq, ebe_qentry, nebe) { TAILQ_REMOVE(&ebq, ebe, ebe_qentry); - if (refcnt_rele(&ebe->ebe_refs)) - ebe_free(ebe); + ebe_free(ebe); } } @@ -587,12 +582,18 @@ etherbridge_flush(struct etherbridge *eb mtx_leave(&eb->eb_lock); } - smr_barrier(); /* try and do it once for all the entries */ + if (TAILQ_EMPTY(&ebq)) + return; + + /* + * do one smr barrier for all the entries rather than an + * smr_call each. + */ + smr_barrier(); TAILQ_FOREACH_SAFE(ebe, &ebq, ebe_qentry, nebe) { TAILQ_REMOVE(&ebq, ebe, ebe_qentry); - if (refcnt_rele(&ebe->ebe_refs)) - ebe_free(ebe); + ebe_free(ebe); } } Index: if_etherbridge.h =================================================================== RCS file: /cvs/src/sys/net/if_etherbridge.h,v retrieving revision 1.3 diff -u -p -r1.3 if_etherbridge.h --- if_etherbridge.h 26 Feb 2021 01:28:51 -0000 1.3 +++ if_etherbridge.h 24 Jun 2021 03:51:15 -0000 @@ -51,7 +51,6 @@ struct eb_entry { time_t ebe_age; struct etherbridge *ebe_etherbridge; - struct refcnt ebe_refs; struct smr_entry ebe_smr_entry; };