* Helper function to remove a group out of an interface. Expects the global * ifnet lock to be write-locked, and drops it before returning. */
| 1563 | * ifnet lock to be write-locked, and drops it before returning. |
| 1564 | */ |
| 1565 | static void |
| 1566 | _if_delgroup_locked(struct ifnet *ifp, struct ifg_list *ifgl, |
| 1567 | const char *groupname) |
| 1568 | { |
| 1569 | struct ifg_member *ifgm; |
| 1570 | bool freeifgl; |
| 1571 | |
| 1572 | IFNET_WLOCK_ASSERT(); |
| 1573 | |
| 1574 | IF_ADDR_WLOCK(ifp); |
| 1575 | CK_STAILQ_REMOVE(&ifp->if_groups, ifgl, ifg_list, ifgl_next); |
| 1576 | IF_ADDR_WUNLOCK(ifp); |
| 1577 | |
| 1578 | CK_STAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next) { |
| 1579 | if (ifgm->ifgm_ifp == ifp) { |
| 1580 | CK_STAILQ_REMOVE(&ifgl->ifgl_group->ifg_members, ifgm, |
| 1581 | ifg_member, ifgm_next); |
| 1582 | break; |
| 1583 | } |
| 1584 | } |
| 1585 | |
| 1586 | if (--ifgl->ifgl_group->ifg_refcnt == 0) { |
| 1587 | CK_STAILQ_REMOVE(&V_ifg_head, ifgl->ifgl_group, ifg_group, |
| 1588 | ifg_next); |
| 1589 | freeifgl = true; |
| 1590 | } else { |
| 1591 | freeifgl = false; |
| 1592 | } |
| 1593 | IFNET_WUNLOCK(); |
| 1594 | |
| 1595 | epoch_wait_preempt(net_epoch_preempt); |
| 1596 | if (freeifgl) { |
| 1597 | EVENTHANDLER_INVOKE(group_detach_event, ifgl->ifgl_group); |
| 1598 | free(ifgl->ifgl_group, M_TEMP); |
| 1599 | } |
| 1600 | free(ifgm, M_TEMP); |
| 1601 | free(ifgl, M_TEMP); |
| 1602 | |
| 1603 | EVENTHANDLER_INVOKE(group_change_event, groupname); |
| 1604 | } |
| 1605 | |
| 1606 | /* |
| 1607 | * Remove a group from an interface |
no test coverage detected