Print this page
6742 Freed and reused idm_conn_t buffer leads to system panic.
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Steve Ping <steve.ping@nexenta.com>
Reviewed by: Dan McDonald <danmcd@omniti.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/sys/idm/idm_conn_sm.h
+++ new/usr/src/uts/common/sys/idm/idm_conn_sm.h
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 + * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
25 26 */
26 27 #ifndef _IDM_CONN_SM_H_
27 28 #define _IDM_CONN_SM_H_
28 29
29 30 #ifdef __cplusplus
30 31 extern "C" {
31 32 #endif
32 33
33 34
34 35 /*
35 36 * IDM connection state machine events. Most events get generated internally
36 37 * either by the state machine or by the IDM TX/RX code. For example when IDM
37 38 * receives a login request for a target connectionit will generate a
38 39 * CE_LOGIN_RCV event. Similarly when the target sends a successful login
39 40 * response IDM generate a "CE_LOGIN_SUCCESS_SND" event. The following
40 41 * events are not detected on the TX/RX path and must be generated explicitly
41 42 * by the client when appropriate:
42 43 *
43 44 * CE_LOGOUT_OTHER_CONN_RCV
44 45 * CE_ASYNC_DROP_CONN_RCV (Only because the message may be received on
45 46 * a different connection from the connection being dropped)
46 47 * CE_ASYNC_DROP_ALL_CONN_RCV
47 48 * CE_LOGOUT_OTHER_CONN_SND
48 49 * CE_ASYNC_DROP_ALL_CONN_SND
49 50 *
50 51 * The following events might occur in any state since they are driven
51 52 * by the PDU's that IDM receives:
52 53 *
53 54 * CE_LOGIN_RCV
54 55 * CE_LOGIN_SUCCESS_RCV
55 56 * CE_LOGIN_FAIL_RCV
56 57 * CE_LOGOUT_SUCCESS_RCV
57 58 * CE_LOGOUT_FAIL_RCV
58 59 * CE_ASYNC_LOGOUT_RCV
59 60 * CE_MISC_RCV
60 61 * CE_RX_PROTOCOL_ERROR
61 62 */
62 63
63 64 #define IDM_LOGIN_SECONDS 20
64 65 #define IDM_LOGOUT_SECONDS 20
65 66 #define IDM_CLEANUP_SECONDS 0
66 67
67 68 /* Update idm_ce_name table whenever connection events are modified */
68 69 typedef enum {
69 70 CE_UNDEFINED = 0,
70 71
71 72 /* Initiator events */
72 73 CE_CONNECT_REQ,
73 74 CE_CONNECT_FAIL,
74 75 CE_CONNECT_SUCCESS,
75 76 CE_LOGIN_SND,
76 77 CE_LOGIN_SUCCESS_RCV,
77 78 CE_LOGIN_FAIL_RCV,
78 79 CE_LOGOUT_THIS_CONN_SND,
79 80 CE_LOGOUT_OTHER_CONN_SND,
80 81 CE_LOGOUT_SESSION_SND,
81 82 CE_LOGOUT_SUCCESS_RCV,
82 83 CE_LOGOUT_FAIL_RCV,
83 84 CE_ASYNC_LOGOUT_RCV,
84 85 CE_ASYNC_DROP_CONN_RCV,
85 86 CE_ASYNC_DROP_ALL_CONN_RCV,
86 87
87 88 /* Target events */
88 89 CE_CONNECT_ACCEPT,
89 90 CE_CONNECT_REJECT,
90 91 CE_LOGIN_RCV,
91 92 CE_LOGIN_TIMEOUT,
92 93 CE_LOGIN_SUCCESS_SND,
93 94 CE_LOGIN_FAIL_SND,
94 95 CE_LOGIN_FAIL_SND_DONE,
95 96 CE_LOGOUT_THIS_CONN_RCV,
96 97 CE_LOGOUT_OTHER_CONN_RCV,
97 98 CE_LOGOUT_SESSION_RCV,
98 99 CE_LOGOUT_SUCCESS_SND,
99 100 CE_LOGOUT_SUCCESS_SND_DONE,
100 101 CE_LOGOUT_FAIL_SND,
101 102 CE_LOGOUT_FAIL_SND_DONE,
102 103 CE_CLEANUP_TIMEOUT,
103 104 CE_ASYNC_LOGOUT_SND,
104 105 CE_ASYNC_DROP_CONN_SND,
105 106 CE_ASYNC_DROP_ALL_CONN_SND,
106 107 CE_LOGOUT_TIMEOUT,
107 108
108 109 /* Common events */
109 110 CE_TRANSPORT_FAIL,
110 111 CE_MISC_TX,
111 112 CE_TX_PROTOCOL_ERROR,
112 113 CE_MISC_RX,
113 114 CE_RX_PROTOCOL_ERROR,
114 115 CE_LOGOUT_SESSION_SUCCESS,
115 116 CE_CONN_REINSTATE,
116 117 CE_CONN_REINSTATE_SUCCESS,
117 118 CE_CONN_REINSTATE_FAIL,
118 119 CE_ENABLE_DM_SUCCESS,
119 120 CE_ENABLE_DM_FAIL,
120 121
121 122 /* Add new events above CE_MAX_EVENT */
122 123 CE_MAX_EVENT
123 124 } idm_conn_event_t;
124 125
125 126 #ifdef IDM_CONN_SM_STRINGS
126 127 /* An array of event text values, for use in logging events */
127 128 static const char *idm_ce_name[CE_MAX_EVENT+1] = {
128 129 "CE_UNDEFINED",
129 130 "CE_CONNECT_REQ",
130 131 "CE_CONNECT_FAIL",
131 132 "CE_CONNECT_SUCCESS",
132 133 "CE_LOGIN_SND",
133 134 "CE_LOGIN_SUCCESS_RCV",
134 135 "CE_LOGIN_FAIL_RCV",
135 136 "CE_LOGOUT_THIS_CONN_SND",
136 137 "CE_LOGOUT_OTHER_CONN_SND",
137 138 "CE_LOGOUT_SESSION_SND",
138 139 "CE_LOGOUT_SUCCESS_RCV",
139 140 "CE_LOGOUT_FAIL_RCV",
140 141 "CE_ASYNC_LOGOUT_RCV",
141 142 "CE_ASYNC_DROP_CONN_RCV",
142 143 "CE_ASYNC_DROP_ALL_CONN_RCV",
143 144 "CE_CONNECT_ACCEPT",
144 145 "CE_CONNECT_REJECT",
145 146 "CE_LOGIN_RCV",
146 147 "CE_LOGIN_TIMEOUT",
147 148 "CE_LOGIN_SUCCESS_SND",
148 149 "CE_LOGIN_FAIL_SND",
149 150 "CE_LOGIN_FAIL_SND_DONE",
150 151 "CE_LOGOUT_THIS_CONN_RCV",
151 152 "CE_LOGOUT_OTHER_CONN_RCV",
152 153 "CE_LOGOUT_SESSION_RCV",
153 154 "CE_LOGOUT_SUCCESS_SND",
154 155 "CE_LOGOUT_SUCCESS_SND_DONE",
155 156 "CE_LOGOUT_FAIL_SND",
156 157 "CE_LOGOUT_FAIL_SND_DONE",
157 158 "CE_CLEANUP_TIMEOUT",
158 159 "CE_ASYNC_LOGOUT_SND",
159 160 "CE_ASYNC_DROP_CONN_SND",
160 161 "CE_ASYNC_DROP_ALL_CONN_SND",
161 162 "CE_LOGOUT_TIMEOUT",
162 163 "CE_TRANSPORT_FAIL",
163 164 "CE_MISC_TX",
164 165 "CE_TX_PROTOCOL_ERROR",
165 166 "CE_MISC_RX",
166 167 "CE_RX_PROTOCOL_ERROR",
167 168 "CE_LOGOUT_SESSION_SUCCESS",
168 169 "CE_CONN_REINSTATE",
169 170 "CE_CONN_REINSTATE_SUCCESS",
170 171 "CE_CONN_REINSTATE_FAIL",
171 172 "CE_ENABLE_DM_SUCCESS",
172 173 "CE_ENABLE_DM_FAIL",
173 174 "CE_MAX_EVENT"
174 175 };
175 176 #endif
176 177
177 178 /* Update idm_cs_name table whenever connection states are modified */
178 179 typedef enum {
179 180 CS_S0_UNDEFINED = 0,
180 181
181 182 CS_S1_FREE,
182 183 CS_S2_XPT_WAIT,
183 184 CS_S3_XPT_UP,
184 185 CS_S4_IN_LOGIN,
185 186 CS_S5_LOGGED_IN,
186 187 CS_S6_IN_LOGOUT,
187 188 CS_S7_LOGOUT_REQ,
188 189 CS_S8_CLEANUP,
189 190 CS_S9_INIT_ERROR,
190 191 CS_S10_IN_CLEANUP,
191 192 CS_S11_COMPLETE,
192 193 CS_S12_ENABLE_DM,
193 194 CS_S9A_REJECTED,
194 195 CS_S9B_WAIT_SND_DONE,
195 196
196 197 /* Add new connection states above CS_MAX_STATE */
197 198 CS_MAX_STATE
198 199 } idm_conn_state_t;
199 200
200 201 #ifdef IDM_CONN_SM_STRINGS
201 202 /* An array of state text values, for use in logging state transitions */
202 203 static const char *idm_cs_name[CS_MAX_STATE+1] = {
203 204 "CS_S0_UNDEFINED",
204 205 "CS_S1_FREE",
205 206 "CS_S2_XPT_WAIT",
206 207 "CS_S3_XPT_UP",
207 208 "CS_S4_IN_LOGIN",
208 209 "CS_S5_LOGGED_IN",
209 210 "CS_S6_IN_LOGOUT",
210 211 "CS_S7_LOGOUT_REQ",
211 212 "CS_S8_CLEANUP",
|
↓ open down ↓ |
177 lines elided |
↑ open up ↑ |
212 213 "CS_S9_INIT_ERROR",
213 214 "CS_S10_IN_CLEANUP",
214 215 "CS_S11_COMPLETE",
215 216 "CS_S12_ENABLE_DM",
216 217 "CS_S9A_REJECTED",
217 218 "CS_S9B_WAIT_SND_DONE",
218 219 "CS_MAX_STATE"
219 220 };
220 221 #endif
221 222
223 +/*
224 + * Currently the state machine has a condition where idm_login_timeout() is
225 + * left active after the connection has been closed. This causes the system
226 + * to panic when idm_login_timeout() modifies the freed memory. In an attempt
227 + * to isolate and find this issue special attention is being placed on
228 + * the ic_state_timeout value. After each untimeout call the value will now
229 + * be cleared. Just before the value is set the code will check for 0 and
230 + * display an error. One final change is being done in idm_conn_sm_fini() which
231 + * if ic_state_machine is not 0, an error message will be displayed and
232 + * untimeout() called. That should prevent customer sites from seeing the
233 + * panic. The code also calls ASSERT(0) which should cause a panic during
234 + * system test.
235 + */
236 +#define IDM_SM_TIMER_CHECK(ic) \
237 + if (ic->ic_state_timeout) { \
238 + cmn_err(CE_WARN, "%s: existing timeout still set. " \
239 + "state: %s, last: %s\n", __func__, \
240 + idm_cs_name[ic->ic_state], \
241 + idm_cs_name[ic->ic_last_state]); \
242 + ASSERT(0); \
243 + }
244 +
245 +#define IDM_SM_TIMER_CLEAR(ic) \
246 + (void) untimeout(ic->ic_state_timeout); \
247 + ic->ic_state_timeout = 0;
248 +
222 249 typedef enum {
223 250 CT_NONE = 0,
224 251 CT_RX_PDU,
225 252 CT_TX_PDU
226 253 } idm_pdu_event_type_t;
227 254
228 255 typedef enum {
229 256 CA_TX_PROTOCOL_ERROR, /* Send "protocol error" to state machine */
230 257 CA_RX_PROTOCOL_ERROR, /* Send "protocol error" to state machine */
231 258 CA_FORWARD, /* State machine event and forward to client */
232 259 CA_DROP /* Drop PDU */
233 260 } idm_pdu_event_action_t;
234 261
235 262 typedef struct {
236 263 struct idm_conn_s *iec_ic;
237 264 idm_conn_event_t iec_event;
238 265 uintptr_t iec_info;
239 266 idm_pdu_event_type_t iec_pdu_event_type;
240 267 boolean_t iec_pdu_forwarded;
241 268 } idm_conn_event_ctx_t;
242 269
243 270 idm_status_t
244 271 idm_conn_sm_init(struct idm_conn_s *ic);
245 272
246 273 void
247 274 idm_conn_sm_fini(struct idm_conn_s *ic);
248 275
249 276 idm_status_t
250 277 idm_notify_client(struct idm_conn_s *ic, idm_client_notify_t cn,
251 278 uintptr_t data);
252 279
253 280 void
254 281 idm_conn_event(struct idm_conn_s *ic, idm_conn_event_t event, uintptr_t data);
255 282
256 283 void
257 284 idm_conn_event(struct idm_conn_s *ic, idm_conn_event_t event, uintptr_t data);
258 285
259 286 void
260 287 idm_conn_event_locked(struct idm_conn_s *ic, idm_conn_event_t event,
261 288 uintptr_t event_info, idm_pdu_event_type_t pdu_event_type);
262 289
263 290 idm_status_t
264 291 idm_conn_reinstate_event(struct idm_conn_s *old_ic, struct idm_conn_s *new_ic);
265 292
266 293 void
267 294 idm_conn_tx_pdu_event(struct idm_conn_s *ic, idm_conn_event_t event,
268 295 uintptr_t data);
269 296
270 297 void
271 298 idm_conn_rx_pdu_event(struct idm_conn_s *ic, idm_conn_event_t event,
272 299 uintptr_t data);
273 300
274 301 char *
275 302 idm_conn_state_str(struct idm_conn_s *ic);
276 303
277 304 #ifdef __cplusplus
278 305 }
279 306 #endif
280 307
281 308 #endif /* _IDM_CONN_SM_H_ */
|
↓ open down ↓ |
50 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX