106 static void netstack_zone_shutdown(zoneid_t zoneid, void *arg);
107 static void netstack_zone_destroy(zoneid_t zoneid, void *arg);
108
109 static void netstack_shared_zone_add(zoneid_t zoneid);
110 static void netstack_shared_zone_remove(zoneid_t zoneid);
111 static void netstack_shared_kstat_add(kstat_t *ks);
112 static void netstack_shared_kstat_remove(kstat_t *ks);
113
114 typedef boolean_t applyfn_t(kmutex_t *, netstack_t *, int);
115
116 static void apply_all_netstacks(int, applyfn_t *);
117 static void apply_all_modules(netstack_t *, applyfn_t *);
118 static void apply_all_modules_reverse(netstack_t *, applyfn_t *);
119 static boolean_t netstack_apply_create(kmutex_t *, netstack_t *, int);
120 static boolean_t netstack_apply_shutdown(kmutex_t *, netstack_t *, int);
121 static boolean_t netstack_apply_destroy(kmutex_t *, netstack_t *, int);
122 static boolean_t wait_for_zone_creator(netstack_t *, kmutex_t *);
123 static boolean_t wait_for_nms_inprogress(netstack_t *, nm_state_t *,
124 kmutex_t *);
125
126 static void netstack_reap_work(netstack_t *, boolean_t);
127 ksema_t netstack_reap_limiter;
128
129 void
130 netstack_init(void)
131 {
132 mutex_init(&netstack_g_lock, NULL, MUTEX_DEFAULT, NULL);
133 mutex_init(&netstack_shared_lock, NULL, MUTEX_DEFAULT, NULL);
134
135 /* XXX KEBE SAYS hard-coded constant needs to be fixed. */
136 sema_init(&netstack_reap_limiter, 1024, NULL, SEMA_DRIVER, NULL);
137
138 netstack_initialized = 1;
139
140 /*
141 * We want to be informed each time a zone is created or
142 * destroyed in the kernel, so we can maintain the
143 * stack instance information.
144 */
145 zone_key_create(&netstack_zone_key, netstack_zone_create,
1020 return (ns);
1021 }
1022
1023 /*
1024 * Find a stack instance given the stackid with exact match?
1025 * Increases the reference count if found; caller must do a
1026 * netstack_rele().
1027 *
1028 * Skip the unitialized ones.
1029 */
1030 netstack_t *
1031 netstack_find_by_stackid(netstackid_t stackid)
1032 {
1033 netstack_t *ns;
1034
1035 mutex_enter(&netstack_g_lock);
1036 for (ns = netstack_head; ns != NULL; ns = ns->netstack_next) {
1037 mutex_enter(&ns->netstack_lock);
1038 if (ns->netstack_stackid == stackid &&
1039 !(ns->netstack_flags & (NSF_UNINIT|NSF_CLOSING))) {
1040 mutex_exit(&ns->netstack_lock);
1041 netstack_hold(ns);
1042 mutex_exit(&netstack_g_lock);
1043 return (ns);
1044 }
1045 mutex_exit(&ns->netstack_lock);
1046 }
1047 mutex_exit(&netstack_g_lock);
1048 return (NULL);
1049 }
1050
1051 boolean_t
1052 netstack_inuse_by_stackid(netstackid_t stackid)
1053 {
1054 netstack_t *ns;
1055 boolean_t rval = B_FALSE;
1056
1057 mutex_enter(&netstack_g_lock);
1058
1059 for (ns = netstack_head; ns != NULL; ns = ns->netstack_next) {
1060 if (ns->netstack_stackid == stackid) {
1061 rval = B_TRUE;
1178 sema_p(&netstack_reap_limiter);
1179 /* Caputre delay in ns. */
1180 DTRACE_PROBE1(netstack__reap__rate__limited,
1181 hrtime_t *, gethrtime() - measurement);
1182 }
1183
1184 if (taskq_dispatch(system_taskq,
1185 is_not_intr ? netstack_reap : netstack_reap_intr, ns,
1186 TQ_NOSLEEP) == NULL) {
1187 /*
1188 * Well shoot, why can't we taskq_dispatch?
1189 * Take our chances with a direct call.
1190 */
1191 DTRACE_PROBE1(netstack__reap__taskq__fail,
1192 netstack_t *, ns);
1193 netstack_reap_work(ns, is_not_intr);
1194 }
1195 }
1196 }
1197
1198 void
1199 netstack_hold(netstack_t *ns)
1200 {
1201 mutex_enter(&ns->netstack_lock);
1202 ns->netstack_refcnt++;
1203 ASSERT(ns->netstack_refcnt > 0);
1204 mutex_exit(&ns->netstack_lock);
1205 DTRACE_PROBE1(netstack__inc__ref, netstack_t *, ns);
1206 }
1207
1208 /*
1209 * To support kstat_create_netstack() using kstat_zone_add we need
1210 * to track both
1211 * - all zoneids that use the global/shared stack
1212 * - all kstats that have been added for the shared stack
1213 */
1214 kstat_t *
1215 kstat_create_netstack(char *ks_module, int ks_instance, char *ks_name,
1216 char *ks_class, uchar_t ks_type, uint_t ks_ndata, uchar_t ks_flags,
1217 netstackid_t ks_netstackid)
1218 {
1219 kstat_t *ks;
1220
1221 if (ks_netstackid == GLOBAL_NETSTACKID) {
1222 ks = kstat_create_zone(ks_module, ks_instance, ks_name,
1223 ks_class, ks_type, ks_ndata, ks_flags, GLOBAL_ZONEID);
1224 if (ks != NULL)
1225 netstack_shared_kstat_add(ks);
|
106 static void netstack_zone_shutdown(zoneid_t zoneid, void *arg);
107 static void netstack_zone_destroy(zoneid_t zoneid, void *arg);
108
109 static void netstack_shared_zone_add(zoneid_t zoneid);
110 static void netstack_shared_zone_remove(zoneid_t zoneid);
111 static void netstack_shared_kstat_add(kstat_t *ks);
112 static void netstack_shared_kstat_remove(kstat_t *ks);
113
114 typedef boolean_t applyfn_t(kmutex_t *, netstack_t *, int);
115
116 static void apply_all_netstacks(int, applyfn_t *);
117 static void apply_all_modules(netstack_t *, applyfn_t *);
118 static void apply_all_modules_reverse(netstack_t *, applyfn_t *);
119 static boolean_t netstack_apply_create(kmutex_t *, netstack_t *, int);
120 static boolean_t netstack_apply_shutdown(kmutex_t *, netstack_t *, int);
121 static boolean_t netstack_apply_destroy(kmutex_t *, netstack_t *, int);
122 static boolean_t wait_for_zone_creator(netstack_t *, kmutex_t *);
123 static boolean_t wait_for_nms_inprogress(netstack_t *, nm_state_t *,
124 kmutex_t *);
125
126 static void netstack_hold_locked(netstack_t *);
127 static void netstack_reap_work(netstack_t *, boolean_t);
128 ksema_t netstack_reap_limiter;
129
130 void
131 netstack_init(void)
132 {
133 mutex_init(&netstack_g_lock, NULL, MUTEX_DEFAULT, NULL);
134 mutex_init(&netstack_shared_lock, NULL, MUTEX_DEFAULT, NULL);
135
136 /* XXX KEBE SAYS hard-coded constant needs to be fixed. */
137 sema_init(&netstack_reap_limiter, 1024, NULL, SEMA_DRIVER, NULL);
138
139 netstack_initialized = 1;
140
141 /*
142 * We want to be informed each time a zone is created or
143 * destroyed in the kernel, so we can maintain the
144 * stack instance information.
145 */
146 zone_key_create(&netstack_zone_key, netstack_zone_create,
1021 return (ns);
1022 }
1023
1024 /*
1025 * Find a stack instance given the stackid with exact match?
1026 * Increases the reference count if found; caller must do a
1027 * netstack_rele().
1028 *
1029 * Skip the unitialized ones.
1030 */
1031 netstack_t *
1032 netstack_find_by_stackid(netstackid_t stackid)
1033 {
1034 netstack_t *ns;
1035
1036 mutex_enter(&netstack_g_lock);
1037 for (ns = netstack_head; ns != NULL; ns = ns->netstack_next) {
1038 mutex_enter(&ns->netstack_lock);
1039 if (ns->netstack_stackid == stackid &&
1040 !(ns->netstack_flags & (NSF_UNINIT|NSF_CLOSING))) {
1041 netstack_hold_locked(ns);
1042 mutex_exit(&ns->netstack_lock);
1043 mutex_exit(&netstack_g_lock);
1044 return (ns);
1045 }
1046 mutex_exit(&ns->netstack_lock);
1047 }
1048 mutex_exit(&netstack_g_lock);
1049 return (NULL);
1050 }
1051
1052 boolean_t
1053 netstack_inuse_by_stackid(netstackid_t stackid)
1054 {
1055 netstack_t *ns;
1056 boolean_t rval = B_FALSE;
1057
1058 mutex_enter(&netstack_g_lock);
1059
1060 for (ns = netstack_head; ns != NULL; ns = ns->netstack_next) {
1061 if (ns->netstack_stackid == stackid) {
1062 rval = B_TRUE;
1179 sema_p(&netstack_reap_limiter);
1180 /* Caputre delay in ns. */
1181 DTRACE_PROBE1(netstack__reap__rate__limited,
1182 hrtime_t *, gethrtime() - measurement);
1183 }
1184
1185 if (taskq_dispatch(system_taskq,
1186 is_not_intr ? netstack_reap : netstack_reap_intr, ns,
1187 TQ_NOSLEEP) == NULL) {
1188 /*
1189 * Well shoot, why can't we taskq_dispatch?
1190 * Take our chances with a direct call.
1191 */
1192 DTRACE_PROBE1(netstack__reap__taskq__fail,
1193 netstack_t *, ns);
1194 netstack_reap_work(ns, is_not_intr);
1195 }
1196 }
1197 }
1198
1199 static void
1200 netstack_hold_locked(netstack_t *ns)
1201 {
1202 ASSERT(MUTEX_HELD(&ns->netstack_lock));
1203 ns->netstack_refcnt++;
1204 ASSERT(ns->netstack_refcnt > 0);
1205 DTRACE_PROBE1(netstack__inc__ref, netstack_t *, ns);
1206 }
1207
1208 void
1209 netstack_hold(netstack_t *ns)
1210 {
1211 mutex_enter(&ns->netstack_lock);
1212 netstack_hold_locked(ns);
1213 mutex_exit(&ns->netstack_lock);
1214 }
1215
1216 /*
1217 * To support kstat_create_netstack() using kstat_zone_add we need
1218 * to track both
1219 * - all zoneids that use the global/shared stack
1220 * - all kstats that have been added for the shared stack
1221 */
1222 kstat_t *
1223 kstat_create_netstack(char *ks_module, int ks_instance, char *ks_name,
1224 char *ks_class, uchar_t ks_type, uint_t ks_ndata, uchar_t ks_flags,
1225 netstackid_t ks_netstackid)
1226 {
1227 kstat_t *ks;
1228
1229 if (ks_netstackid == GLOBAL_NETSTACKID) {
1230 ks = kstat_create_zone(ks_module, ks_instance, ks_name,
1231 ks_class, ks_type, ks_ndata, ks_flags, GLOBAL_ZONEID);
1232 if (ks != NULL)
1233 netstack_shared_kstat_add(ks);
|