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 25 Jun 2021 03:56:37 -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 @@ -309,19 +301,21 @@ etherbridge_map(struct etherbridge *eb, smr_read_enter(); oebe = ebl_find(ebl, eba); - if (oebe == NULL) - new = 1; - else { + if (oebe == NULL) { + /* + * peek at the space to see if it's worth trying + * to make a new entry. + */ + if (eb->eb_num < eb->eb_max) + new = 1; + } else { if (oebe->ebe_age != now) oebe->ebe_age = now; /* 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 - oebe = NULL; } smr_read_leave(); @@ -342,7 +336,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; @@ -351,40 +344,49 @@ etherbridge_map(struct etherbridge *eb, nebe->ebe_age = now; mtx_enter(&eb->eb_lock); - num = eb->eb_num + (oebe == NULL); - if (num <= eb->eb_max && ebt_insert(eb, nebe) == oebe) { - /* we won, do the update */ - ebl_insert(ebl, nebe); - - 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); + oebe = ebt_find(eb, nebe); + if (oebe == NULL) { + num = eb->eb_num + 1; + if (num <= eb->eb_max) { + ebl_insert(ebl, nebe); + + oebe = ebt_insert(eb, nebe); + if (oebe != NULL) { + panic("etherbridge %p changed while locked", + eb); } + + /* great success */ + eb->eb_num = num; + nebe = NULL; /* give ref to table */ } + } else if (oebe->ebe_type == EBE_DYNAMIC) { + /* do the update */ + ebl_insert(ebl, nebe); - nebe = NULL; - eb->eb_num = num; + ebl_remove(ebl, oebe); + ebt_replace(eb, oebe, nebe); + + nebe = NULL; /* give ref to table */ + } else { + /* + * oebe is not a dynamic entry, so don't replace it. + */ + oebe = NULL; } mtx_leave(&eb->eb_lock); if (nebe != NULL) { /* * the new entry didn't make it into the - * table, so it can be freed directly. + * table so it can be freed directly. */ ebe_free(nebe); } if (oebe != NULL) { /* - * the old entry could be referenced in - * multiple places, including an smr read - * section, so release it properly. + * we replaced this entry, it needs to be released. */ ebe_rele(oebe); } @@ -415,7 +417,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 +552,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 +594,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 25 Jun 2021 03:56:37 -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; };