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);
}