Print this page
8901 netstack_find_by_stackid() drops-and-reacquires
Reviewed by: Jason King <jbk@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Ryan Zezeski <rpz@joyent.com>

*** 121,130 **** --- 121,132 ---- static boolean_t netstack_apply_destroy(kmutex_t *, netstack_t *, int); static boolean_t wait_for_zone_creator(netstack_t *, kmutex_t *); static boolean_t wait_for_nms_inprogress(netstack_t *, nm_state_t *, kmutex_t *); + static void netstack_hold_locked(netstack_t *); + static ksema_t netstack_reap_limiter; /* * Hard-coded constant, but since this is not tunable in real-time, it seems * making it an /etc/system tunable is better than nothing. */
*** 925,940 **** { netstack_t *ns; ns = curproc->p_zone->zone_netstack; ASSERT(ns != NULL); ! if (ns->netstack_flags & (NSF_UNINIT|NSF_CLOSING)) ! return (NULL); ! ! netstack_hold(ns); ! ! return (ns); } /* * Find a stack instance given the cred. * This is used by the modules to potentially allow for a future when --- 927,937 ---- { netstack_t *ns; ns = curproc->p_zone->zone_netstack; ASSERT(ns != NULL); ! return (netstack_hold_if_active(ns)); } /* * Find a stack instance given the cred. * This is used by the modules to potentially allow for a future when
*** 962,972 **** * netstack_rele(). * * If there is no exact match then assume the shared stack instance * matches. * ! * Skip the unitialized ones. */ netstack_t * netstack_find_by_zoneid(zoneid_t zoneid) { netstack_t *ns; --- 959,969 ---- * netstack_rele(). * * If there is no exact match then assume the shared stack instance * matches. * ! * Skip the uninitialized and closing ones. */ netstack_t * netstack_find_by_zoneid(zoneid_t zoneid) { netstack_t *ns;
*** 975,990 **** zone = zone_find_by_id(zoneid); if (zone == NULL) return (NULL); ! ns = zone->zone_netstack; ! ASSERT(ns != NULL); ! if (ns->netstack_flags & (NSF_UNINIT|NSF_CLOSING)) ! ns = NULL; ! else ! netstack_hold(ns); zone_rele(zone); return (ns); } --- 972,983 ---- zone = zone_find_by_id(zoneid); if (zone == NULL) return (NULL); ! ASSERT(zone->zone_netstack != NULL); ! ns = netstack_hold_if_active(zone->zone_netstack); zone_rele(zone); return (ns); }
*** 1002,1029 **** * Skip the unitialized ones. */ netstack_t * netstack_find_by_zoneid_nolock(zoneid_t zoneid) { - netstack_t *ns; zone_t *zone; zone = zone_find_by_id_nolock(zoneid); if (zone == NULL) return (NULL); ! ns = zone->zone_netstack; ! ASSERT(ns != NULL); ! ! if (ns->netstack_flags & (NSF_UNINIT|NSF_CLOSING)) ! ns = NULL; ! else ! netstack_hold(ns); ! /* zone_find_by_id_nolock does not have a hold on the zone */ ! return (ns); } /* * Find a stack instance given the stackid with exact match? * Increases the reference count if found; caller must do a --- 995,1014 ---- * Skip the unitialized ones. */ netstack_t * netstack_find_by_zoneid_nolock(zoneid_t zoneid) { zone_t *zone; zone = zone_find_by_id_nolock(zoneid); if (zone == NULL) return (NULL); ! ASSERT(zone->zone_netstack != NULL); /* zone_find_by_id_nolock does not have a hold on the zone */ ! return (netstack_hold_if_active(zone->zone_netstack)); } /* * Find a stack instance given the stackid with exact match? * Increases the reference count if found; caller must do a
*** 1036,1050 **** { netstack_t *ns; mutex_enter(&netstack_g_lock); for (ns = netstack_head; ns != NULL; ns = ns->netstack_next) { mutex_enter(&ns->netstack_lock); if (ns->netstack_stackid == stackid && !(ns->netstack_flags & (NSF_UNINIT|NSF_CLOSING))) { mutex_exit(&ns->netstack_lock); - netstack_hold(ns); mutex_exit(&netstack_g_lock); return (ns); } mutex_exit(&ns->netstack_lock); } --- 1021,1036 ---- { netstack_t *ns; mutex_enter(&netstack_g_lock); for (ns = netstack_head; ns != NULL; ns = ns->netstack_next) { + /* Can't use hold_if_active because of stackid check. */ mutex_enter(&ns->netstack_lock); if (ns->netstack_stackid == stackid && !(ns->netstack_flags & (NSF_UNINIT|NSF_CLOSING))) { + netstack_hold_locked(ns); mutex_exit(&ns->netstack_lock); mutex_exit(&netstack_g_lock); return (ns); } mutex_exit(&ns->netstack_lock); }
*** 1170,1187 **** (void) taskq_dispatch(system_taskq, netstack_reap, ns, TQ_SLEEP); } } void netstack_hold(netstack_t *ns) { mutex_enter(&ns->netstack_lock); ! ns->netstack_refcnt++; ! ASSERT(ns->netstack_refcnt > 0); mutex_exit(&ns->netstack_lock); - DTRACE_PROBE1(netstack__inc__ref, netstack_t *, ns); } /* * To support kstat_create_netstack() using kstat_zone_add we need * to track both --- 1156,1202 ---- (void) taskq_dispatch(system_taskq, netstack_reap, ns, TQ_SLEEP); } } + static void + netstack_hold_locked(netstack_t *ns) + { + ASSERT(MUTEX_HELD(&ns->netstack_lock)); + ns->netstack_refcnt++; + ASSERT(ns->netstack_refcnt > 0); + DTRACE_PROBE1(netstack__inc__ref, netstack_t *, ns); + } + + /* + * If the passed-in netstack isn't active (i.e. it's uninitialized or closing), + * return NULL, otherwise return it with its reference held. Common code + * for many netstack_find*() functions. + */ + netstack_t * + netstack_hold_if_active(netstack_t *ns) + { + netstack_t *retval; + + mutex_enter(&ns->netstack_lock); + if (ns->netstack_flags & (NSF_UNINIT | NSF_CLOSING)) { + retval = NULL; + } else { + netstack_hold_locked(ns); + retval = ns; + } + mutex_exit(&ns->netstack_lock); + + return (retval); + } + void netstack_hold(netstack_t *ns) { mutex_enter(&ns->netstack_lock); ! netstack_hold_locked(ns); mutex_exit(&ns->netstack_lock); } /* * To support kstat_create_netstack() using kstat_zone_add we need * to track both
*** 1418,1440 **** for (i = 0; i < end; i++) { if (ns == NULL) break; ns = ns->netstack_next; } ! /* skip those with that aren't really here */ while (ns != NULL) { mutex_enter(&ns->netstack_lock); if ((ns->netstack_flags & (NSF_UNINIT|NSF_CLOSING)) == 0) { mutex_exit(&ns->netstack_lock); break; } mutex_exit(&ns->netstack_lock); end++; ns = ns->netstack_next; } - if (ns != NULL) { - *handle = end + 1; - netstack_hold(ns); - } mutex_exit(&netstack_g_lock); return (ns); } --- 1433,1456 ---- for (i = 0; i < end; i++) { if (ns == NULL) break; ns = ns->netstack_next; } ! /* ! * Skip those that aren't really here (uninitialized or closing). ! * Can't use hold_if_active because of "end" tracking. ! */ while (ns != NULL) { mutex_enter(&ns->netstack_lock); if ((ns->netstack_flags & (NSF_UNINIT|NSF_CLOSING)) == 0) { + *handle = end + 1; + netstack_hold_locked(ns); mutex_exit(&ns->netstack_lock); break; } mutex_exit(&ns->netstack_lock); end++; ns = ns->netstack_next; } mutex_exit(&netstack_g_lock); return (ns); }