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>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/os/netstack.c
          +++ new/usr/src/uts/common/os/netstack.c
↓ open down ↓ 115 lines elided ↑ open up ↑
 116  116  static void     apply_all_netstacks(int, applyfn_t *);
 117  117  static void     apply_all_modules(netstack_t *, applyfn_t *);
 118  118  static void     apply_all_modules_reverse(netstack_t *, applyfn_t *);
 119  119  static boolean_t netstack_apply_create(kmutex_t *, netstack_t *, int);
 120  120  static boolean_t netstack_apply_shutdown(kmutex_t *, netstack_t *, int);
 121  121  static boolean_t netstack_apply_destroy(kmutex_t *, netstack_t *, int);
 122  122  static boolean_t wait_for_zone_creator(netstack_t *, kmutex_t *);
 123  123  static boolean_t wait_for_nms_inprogress(netstack_t *, nm_state_t *,
 124  124      kmutex_t *);
 125  125  
      126 +static void netstack_hold_locked(netstack_t *);
      127 +
 126  128  static ksema_t netstack_reap_limiter;
 127  129  /*
 128  130   * Hard-coded constant, but since this is not tunable in real-time, it seems
 129  131   * making it an /etc/system tunable is better than nothing.
 130  132   */
 131  133  uint_t netstack_outstanding_reaps = 1024;
 132  134  
 133  135  void
 134  136  netstack_init(void)
 135  137  {
↓ open down ↓ 784 lines elided ↑ open up ↑
 920  922   * Increases the reference count, caller must do a netstack_rele.
 921  923   * It can't be called after zone_destroy() has started.
 922  924   */
 923  925  netstack_t *
 924  926  netstack_get_current(void)
 925  927  {
 926  928          netstack_t *ns;
 927  929  
 928  930          ns = curproc->p_zone->zone_netstack;
 929  931          ASSERT(ns != NULL);
 930      -        if (ns->netstack_flags & (NSF_UNINIT|NSF_CLOSING))
 931      -                return (NULL);
 932      -
 933      -        netstack_hold(ns);
 934      -
 935      -        return (ns);
      932 +        return (netstack_hold_if_active(ns));
 936  933  }
 937  934  
 938  935  /*
 939  936   * Find a stack instance given the cred.
 940  937   * This is used by the modules to potentially allow for a future when
 941  938   * something other than the zoneid is used to determine the stack.
 942  939   */
 943  940  netstack_t *
 944  941  netstack_find_by_cred(const cred_t *cr)
 945  942  {
↓ open down ↓ 11 lines elided ↑ open up ↑
 957  954  }
 958  955  
 959  956  /*
 960  957   * Find a stack instance given the zoneid.
 961  958   * Increases the reference count if found; caller must do a
 962  959   * netstack_rele().
 963  960   *
 964  961   * If there is no exact match then assume the shared stack instance
 965  962   * matches.
 966  963   *
 967      - * Skip the unitialized ones.
      964 + * Skip the uninitialized and closing ones.
 968  965   */
 969  966  netstack_t *
 970  967  netstack_find_by_zoneid(zoneid_t zoneid)
 971  968  {
 972  969          netstack_t *ns;
 973  970          zone_t *zone;
 974  971  
 975  972          zone = zone_find_by_id(zoneid);
 976  973  
 977  974          if (zone == NULL)
 978  975                  return (NULL);
 979  976  
 980      -        ns = zone->zone_netstack;
 981      -        ASSERT(ns != NULL);
 982      -        if (ns->netstack_flags & (NSF_UNINIT|NSF_CLOSING))
 983      -                ns = NULL;
 984      -        else
 985      -                netstack_hold(ns);
      977 +        ASSERT(zone->zone_netstack != NULL);
      978 +        ns = netstack_hold_if_active(zone->zone_netstack);
 986  979  
 987  980          zone_rele(zone);
 988  981          return (ns);
 989  982  }
 990  983  
 991  984  /*
 992  985   * Find a stack instance given the zoneid. Can only be called from
 993  986   * the create callback. See the comments in zone_find_by_id_nolock why
 994  987   * that limitation exists.
 995  988   *
↓ open down ↓ 1 lines elided ↑ open up ↑
 997  990   * netstack_rele().
 998  991   *
 999  992   * If there is no exact match then assume the shared stack instance
1000  993   * matches.
1001  994   *
1002  995   * Skip the unitialized ones.
1003  996   */
1004  997  netstack_t *
1005  998  netstack_find_by_zoneid_nolock(zoneid_t zoneid)
1006  999  {
1007      -        netstack_t *ns;
1008 1000          zone_t *zone;
1009 1001  
1010 1002          zone = zone_find_by_id_nolock(zoneid);
1011 1003  
1012 1004          if (zone == NULL)
1013 1005                  return (NULL);
1014 1006  
1015      -        ns = zone->zone_netstack;
1016      -        ASSERT(ns != NULL);
1017      -
1018      -        if (ns->netstack_flags & (NSF_UNINIT|NSF_CLOSING))
1019      -                ns = NULL;
1020      -        else
1021      -                netstack_hold(ns);
1022      -
     1007 +        ASSERT(zone->zone_netstack != NULL);
1023 1008          /* zone_find_by_id_nolock does not have a hold on the zone */
1024      -        return (ns);
     1009 +        return (netstack_hold_if_active(zone->zone_netstack));
1025 1010  }
1026 1011  
1027 1012  /*
1028 1013   * Find a stack instance given the stackid with exact match?
1029 1014   * Increases the reference count if found; caller must do a
1030 1015   * netstack_rele().
1031 1016   *
1032 1017   * Skip the unitialized ones.
1033 1018   */
1034 1019  netstack_t *
1035 1020  netstack_find_by_stackid(netstackid_t stackid)
1036 1021  {
1037 1022          netstack_t *ns;
1038 1023  
1039 1024          mutex_enter(&netstack_g_lock);
1040 1025          for (ns = netstack_head; ns != NULL; ns = ns->netstack_next) {
     1026 +                /* Can't use hold_if_active because of stackid check. */
1041 1027                  mutex_enter(&ns->netstack_lock);
1042 1028                  if (ns->netstack_stackid == stackid &&
1043 1029                      !(ns->netstack_flags & (NSF_UNINIT|NSF_CLOSING))) {
     1030 +                        netstack_hold_locked(ns);
1044 1031                          mutex_exit(&ns->netstack_lock);
1045      -                        netstack_hold(ns);
1046 1032                          mutex_exit(&netstack_g_lock);
1047 1033                          return (ns);
1048 1034                  }
1049 1035                  mutex_exit(&ns->netstack_lock);
1050 1036          }
1051 1037          mutex_exit(&netstack_g_lock);
1052 1038          return (NULL);
1053 1039  }
1054 1040  
1055 1041  boolean_t
↓ open down ↓ 109 lines elided ↑ open up ↑
1165 1151                          DTRACE_PROBE1(netstack__reap__rate__limited,
1166 1152                              hrtime_t, gethrtime() - measurement);
1167 1153                  }
1168 1154  
1169 1155                  /* TQ_SLEEP should prevent taskq_dispatch() from failing. */
1170 1156                  (void) taskq_dispatch(system_taskq, netstack_reap, ns,
1171 1157                      TQ_SLEEP);
1172 1158          }
1173 1159  }
1174 1160  
     1161 +static void
     1162 +netstack_hold_locked(netstack_t *ns)
     1163 +{
     1164 +        ASSERT(MUTEX_HELD(&ns->netstack_lock));
     1165 +        ns->netstack_refcnt++;
     1166 +        ASSERT(ns->netstack_refcnt > 0);
     1167 +        DTRACE_PROBE1(netstack__inc__ref, netstack_t *, ns);
     1168 +}
     1169 +
     1170 +/*
     1171 + * If the passed-in netstack isn't active (i.e. it's uninitialized or closing),
     1172 + * return NULL, otherwise return it with its reference held.  Common code
     1173 + * for many netstack_find*() functions.
     1174 + */
     1175 +netstack_t *
     1176 +netstack_hold_if_active(netstack_t *ns)
     1177 +{
     1178 +        netstack_t *retval;
     1179 +
     1180 +        mutex_enter(&ns->netstack_lock);
     1181 +        if (ns->netstack_flags & (NSF_UNINIT | NSF_CLOSING)) {
     1182 +                retval = NULL;
     1183 +        } else {
     1184 +                netstack_hold_locked(ns);
     1185 +                retval = ns;
     1186 +        }
     1187 +        mutex_exit(&ns->netstack_lock);
     1188 +
     1189 +        return (retval);
     1190 +}
     1191 +
1175 1192  void
1176 1193  netstack_hold(netstack_t *ns)
1177 1194  {
1178 1195          mutex_enter(&ns->netstack_lock);
1179      -        ns->netstack_refcnt++;
1180      -        ASSERT(ns->netstack_refcnt > 0);
     1196 +        netstack_hold_locked(ns);
1181 1197          mutex_exit(&ns->netstack_lock);
1182      -        DTRACE_PROBE1(netstack__inc__ref, netstack_t *, ns);
1183 1198  }
1184 1199  
1185 1200  /*
1186 1201   * To support kstat_create_netstack() using kstat_zone_add we need
1187 1202   * to track both
1188 1203   *  - all zoneids that use the global/shared stack
1189 1204   *  - all kstats that have been added for the shared stack
1190 1205   */
1191 1206  kstat_t *
1192 1207  kstat_create_netstack(char *ks_module, int ks_instance, char *ks_name,
↓ open down ↓ 220 lines elided ↑ open up ↑
1413 1428          /* Walk skipping *handle number of instances */
1414 1429  
1415 1430          /* Look if there is a matching stack instance */
1416 1431          mutex_enter(&netstack_g_lock);
1417 1432          ns = netstack_head;
1418 1433          for (i = 0; i < end; i++) {
1419 1434                  if (ns == NULL)
1420 1435                          break;
1421 1436                  ns = ns->netstack_next;
1422 1437          }
1423      -        /* skip those with that aren't really here */
     1438 +        /*
     1439 +         * Skip those that aren't really here (uninitialized or closing).
     1440 +         * Can't use hold_if_active because of "end" tracking.
     1441 +         */
1424 1442          while (ns != NULL) {
1425 1443                  mutex_enter(&ns->netstack_lock);
1426 1444                  if ((ns->netstack_flags & (NSF_UNINIT|NSF_CLOSING)) == 0) {
     1445 +                        *handle = end + 1;
     1446 +                        netstack_hold_locked(ns);
1427 1447                          mutex_exit(&ns->netstack_lock);
1428 1448                          break;
1429 1449                  }
1430 1450                  mutex_exit(&ns->netstack_lock);
1431 1451                  end++;
1432 1452                  ns = ns->netstack_next;
1433 1453          }
1434      -        if (ns != NULL) {
1435      -                *handle = end + 1;
1436      -                netstack_hold(ns);
1437      -        }
1438 1454          mutex_exit(&netstack_g_lock);
1439 1455          return (ns);
1440 1456  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX