Print this page
NEX-6018 Return of the walking dead idm_refcnt_wait_ref comstar threads
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5428 Backout the 5.0 changes
NEX-2937 Continuous write_same starves all other commands
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Steve Peng <steve.peng@nexenta.com>
NEX-3622 COMSTAR should have per remote port kstats for I/O and latency
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-3169 STMF has duplicate code in 6 places which is error prone.
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewby by: Steve Ping <steve.ping@nexenta.com>
Re #6790 backspace should perform delete on console
VAAI (XXX ATS support for COMSTAR, YYY Block-copy support for COMSTAR)
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/io/comstar/stmf/stmf_impl.h
+++ new/usr/src/uts/common/io/comstar/stmf/stmf_impl.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 *
|
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
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.
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 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23 + *
24 + * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
23 25 * Copyright (c) 2013 by Delphix. All rights reserved.
24 26 */
25 27 #ifndef _STMF_IMPL_H
26 28 #define _STMF_IMPL_H
27 29
28 30 #include <sys/stmf_defines.h>
29 31 #include <sys/stmf_ioctl.h>
30 32
31 33 #ifdef __cplusplus
32 34 extern "C" {
33 35 #endif
34 36
35 37 typedef uint32_t stmf_event_handle_t;
36 38 #define STMF_MAX_NUM_EVENTS (sizeof (stmf_event_handle_t) * 8)
37 39 #define STMF_EVENT_ADD(h, e) (atomic_or_32(&(h), \
38 40 ((uint32_t)1) << (e)))
39 41 #define STMF_EVENT_REMOVE(h, e) (atomic_and_32(&(h), \
40 42 ~(((uint32_t)1) << (e))))
41 43 #define STMF_EVENT_ENABLED(h, e) (((h) & ((uint32_t)1) << (e)) != 0)
42 44 #define STMF_EVENT_CLEAR_ALL(h) ((h) = 0)
43 45 #define STMF_EVENT_ALLOC_HANDLE(h) ((h) = 0)
44 46 #define STMF_EVENT_FREE_HANDLE(h) ((h) = 0)
45 47
46 48 #define STMF_TGT_NAME_LEN 256
47 49 #define STMF_GUID_INPUT 32
48 50
49 51 #define STMF_UPDATE_KSTAT_IO(kip, dbuf) \
50 52 if (dbuf->db_flags & DB_DIRECTION_TO_RPORT) { \
51 53 kip->reads++; \
52 54 kip->nread += dbuf->db_data_size; \
53 55 } else { \
54 56 kip->writes++; \
55 57 kip->nwritten += dbuf->db_data_size; \
56 58 }
57 59
58 60 struct stmf_i_scsi_task;
59 61 struct stmf_itl_data;
60 62
61 63 typedef struct stmf_i_lu_provider {
62 64 stmf_lu_provider_t *ilp_lp;
63 65 uint32_t ilp_alloc_size;
64 66 uint32_t ilp_nlus; /* # LUNs being exported */
65 67 uint32_t ilp_cb_in_progress:1,
66 68 ilp_rsvd:31;
67 69 struct stmf_i_lu_provider *ilp_next;
68 70 struct stmf_pp_data *ilp_ppd;
69 71 } stmf_i_lu_provider_t;
70 72
71 73 typedef struct stmf_i_lu {
72 74 stmf_lu_t *ilu_lu;
73 75 uint32_t ilu_alloc_size;
74 76 uint32_t ilu_flags;
75 77 uint32_t ilu_ref_cnt;
76 78 uint8_t ilu_state;
77 79 uint8_t ilu_prev_state;
78 80 uint8_t ilu_access;
79 81 uint8_t ilu_alua;
80 82 stmf_event_handle_t ilu_event_hdl;
81 83 struct stmf_i_lu *ilu_next;
|
↓ open down ↓ |
49 lines elided |
↑ open up ↑ |
82 84 struct stmf_i_lu *ilu_prev;
83 85 char *ilu_alias;
84 86 char ilu_ascii_hex_guid[STMF_GUID_INPUT + 1];
85 87 kmutex_t ilu_task_lock;
86 88 uint32_t ilu_task_cntr1;
87 89 uint32_t ilu_task_cntr2;
88 90 uint32_t *ilu_cur_task_cntr;
89 91 uint32_t ilu_ntasks; /* # of tasks in the ilu_task list */
90 92 uint32_t ilu_ntasks_free; /* # of tasks that are free */
91 93 uint32_t ilu_ntasks_min_free; /* # minimal free tasks */
92 - uint32_t rsvd1;
94 + uint32_t ilu_additional_ref;
93 95 uint32_t ilu_proxy_registered;
94 96 uint64_t ilu_reg_msgid;
95 97 struct stmf_i_scsi_task *ilu_tasks;
96 98 struct stmf_i_scsi_task *ilu_free_tasks;
97 99 struct stmf_itl_data *ilu_itl_list;
98 100 kstat_t *ilu_kstat_info;
99 101 kstat_t *ilu_kstat_io;
100 102 kmutex_t ilu_kstat_lock;
101 103 kcondvar_t ilu_offline_pending_cv;
102 104
103 105 /* point to the luid entry in stmf_state.stmf_luid_list */
104 106 void *ilu_luid;
105 107 } stmf_i_lu_t;
106 108
107 109 /*
108 110 * ilu_flags
109 111 */
110 112 #define ILU_STALL_DEREGISTER 0x0001
111 113 #define ILU_RESET_ACTIVE 0x0002
112 114
113 115 typedef struct stmf_i_port_provider {
114 116 stmf_port_provider_t *ipp_pp;
115 117 uint32_t ipp_alloc_size;
116 118 uint32_t ipp_npps;
117 119 uint32_t ipp_cb_in_progress:1,
118 120 ipp_rsvd:31;
119 121 struct stmf_i_port_provider *ipp_next;
120 122 struct stmf_pp_data *ipp_ppd;
121 123 } stmf_i_port_provider_t;
122 124
123 125 #define MAX_ILPORT 0x10000
124 126
125 127 typedef struct stmf_i_local_port {
126 128 stmf_local_port_t *ilport_lport;
127 129 uint32_t ilport_alloc_size;
128 130 uint32_t ilport_nsessions;
129 131 struct stmf_i_scsi_session *ilport_ss_list;
130 132 krwlock_t ilport_lock;
131 133 struct stmf_i_local_port *ilport_next;
132 134 struct stmf_i_local_port *ilport_prev;
133 135 uint8_t ilport_state;
134 136 uint8_t ilport_prev_state;
135 137 uint8_t ilport_standby;
136 138 uint8_t ilport_alua;
137 139 uint16_t ilport_rtpid; /* relative tpid */
138 140 uint16_t ilport_proxy_registered;
139 141 uint64_t ilport_reg_msgid;
140 142 uint8_t ilport_no_standby_lu;
141 143 uint32_t ilport_unexpected_comp;
142 144 stmf_event_handle_t ilport_event_hdl;
143 145 clock_t ilport_last_online_clock;
144 146 clock_t ilport_avg_interval;
145 147 uint32_t ilport_online_times;
146 148 uint32_t ilport_flags;
147 149 kstat_t *ilport_kstat_info;
148 150 kstat_t *ilport_kstat_io;
149 151 kmutex_t ilport_kstat_lock;
150 152 char ilport_kstat_tgt_name[STMF_TGT_NAME_LEN];
151 153 /* which target group this port belongs to in stmf_state.stmf_tg_list */
152 154 void *ilport_tg;
153 155 id_t ilport_instance;
154 156 /* XXX Need something to track all the remote ports also */
155 157 } stmf_i_local_port_t;
156 158
|
↓ open down ↓ |
54 lines elided |
↑ open up ↑ |
157 159 #define STMF_AVG_ONLINE_INTERVAL (30 * drv_usectohz(1000000))
158 160
159 161 #define MAX_IRPORT 0x10000
160 162
161 163 typedef struct stmf_i_remote_port {
162 164 struct scsi_devid_desc *irport_id;
163 165 kmutex_t irport_mutex;
164 166 int irport_refcnt;
165 167 id_t irport_instance;
166 168 avl_node_t irport_ln;
169 + /* number of active read tasks */
170 + uint32_t irport_nread_tasks;
171 + /* number of active write tasks */
172 + uint32_t irport_nwrite_tasks;
173 + hrtime_t irport_rdstart_timestamp;
174 + hrtime_t irport_rddone_timestamp;
175 + hrtime_t irport_wrstart_timestamp;
176 + hrtime_t irport_wrdone_timestamp;
177 + kstat_t *irport_kstat_info;
178 + kstat_t *irport_kstat_io;
179 + kstat_t *irport_kstat_estat; /* extended stats */
180 + boolean_t irport_info_dirty;
167 181 } stmf_i_remote_port_t;
168 182
169 183 /*
170 184 * ilport flags
171 185 */
172 186 #define ILPORT_FORCED_OFFLINE 0x01
173 187 #define ILPORT_SS_GOT_INITIAL_LUNS 0x02
174 188
175 189 typedef struct stmf_i_scsi_session {
176 190 stmf_scsi_session_t *iss_ss;
177 191 uint32_t iss_alloc_size;
178 192 uint32_t iss_flags;
179 193 stmf_i_remote_port_t *iss_irport;
180 194 struct stmf_i_scsi_session *iss_next;
181 195 /*
182 196 * Ideally we should maintain 2 maps. One would indicate a new map
183 197 * which will become available only upon receipt of a REPORT LUN
184 198 * cmd.
185 199 */
186 200 struct stmf_lun_map *iss_sm;
187 201 /*
188 202 * which host group the host of this session belongs to in
189 203 * stmf_state.stmf_hg_list
190 204 */
191 205 void *iss_hg;
192 206 krwlock_t *iss_lockp;
193 207 time_t iss_creation_time;
194 208 } stmf_i_scsi_session_t;
195 209
196 210 /*
197 211 * iss flags
198 212 */
199 213 #define ISS_LUN_INVENTORY_CHANGED 0x0001
200 214 #define ISS_RESET_ACTIVE 0x0002
201 215 #define ISS_BEING_CREATED 0x0004
202 216 #define ISS_GOT_INITIAL_LUNS 0x0008
203 217 #define ISS_EVENT_ACTIVE 0x0010
204 218 #define ISS_NULL_TPTID 0x0020
205 219
206 220 #define ITASK_MAX_NCMDS 14
207 221 #define ITASK_DEFAULT_POLL_TIMEOUT 0
208 222
209 223 #define ITASK_TASK_AUDIT_DEPTH 32 /* Must be a power of 2 */
210 224
211 225 typedef enum {
212 226 TE_UNDEFINED,
213 227 TE_TASK_START,
214 228 TE_XFER_START,
215 229 TE_XFER_DONE,
216 230 TE_SEND_STATUS,
217 231 TE_SEND_STATUS_DONE,
218 232 TE_TASK_FREE,
219 233 TE_TASK_ABORT,
220 234 TE_TASK_LPORT_ABORTED,
221 235 TE_TASK_LU_ABORTED,
222 236 TE_PROCESS_CMD
223 237 } task_audit_event_t;
224 238
225 239 #define CMD_OR_IOF_NA 0xffffffff
226 240
227 241 typedef struct stmf_task_audit_rec {
228 242 task_audit_event_t ta_event;
229 243 uint32_t ta_cmd_or_iof;
|
↓ open down ↓ |
53 lines elided |
↑ open up ↑ |
230 244 uint32_t ta_itask_flags;
231 245 stmf_data_buf_t *ta_dbuf;
232 246 timespec_t ta_timestamp;
233 247 } stmf_task_audit_rec_t;
234 248
235 249 struct stmf_worker;
236 250 typedef struct stmf_i_scsi_task {
237 251 scsi_task_t *itask_task;
238 252 uint32_t itask_alloc_size;
239 253 uint32_t itask_flags;
254 + kmutex_t itask_mutex; /* protects flags and lists */
240 255 uint64_t itask_proxy_msg_id;
241 256 stmf_data_buf_t *itask_proxy_dbuf;
242 257 struct stmf_worker *itask_worker;
243 258 uint32_t *itask_ilu_task_cntr;
244 259 struct stmf_i_scsi_task *itask_worker_next;
245 260 struct stmf_i_scsi_task *itask_lu_next;
246 261 struct stmf_i_scsi_task *itask_lu_prev;
247 262 struct stmf_i_scsi_task *itask_lu_free_next;
248 - struct stmf_i_scsi_task *itask_abort_next;
249 263 struct stmf_itl_data *itask_itl_datap;
250 264 clock_t itask_start_time; /* abort and normal */
251 265 /* For now we only support 4 parallel buffers. Should be enough. */
252 266 stmf_data_buf_t *itask_dbufs[4];
253 267 clock_t itask_poll_timeout;
254 268 uint8_t itask_cmd_stack[ITASK_MAX_NCMDS];
255 269 uint8_t itask_ncmds;
256 270 uint8_t itask_allocated_buf_map;
257 271 uint16_t itask_cdb_buf_size;
258 272
259 273 /* Task profile data */
260 274 hrtime_t itask_start_timestamp;
261 275 hrtime_t itask_done_timestamp;
276 + hrtime_t itask_xfer_done_timestamp;
262 277 hrtime_t itask_waitq_enter_timestamp;
263 278 hrtime_t itask_waitq_time;
264 279 hrtime_t itask_lu_read_time;
265 280 hrtime_t itask_lu_write_time;
266 281 hrtime_t itask_lport_read_time;
267 282 hrtime_t itask_lport_write_time;
268 283 uint64_t itask_read_xfer;
269 284 uint64_t itask_write_xfer;
270 285 kmutex_t itask_audit_mutex;
271 286 uint8_t itask_audit_index;
272 287 stmf_task_audit_rec_t itask_audit_records[ITASK_TASK_AUDIT_DEPTH];
273 288 } stmf_i_scsi_task_t;
274 289
275 290 #define ITASK_DEFAULT_ABORT_TIMEOUT 5
276 291
277 292 /*
293 + * Common code to encode an itask onto the worker_task queue is placed
294 + * in this macro to simplify future maintenace activity.
295 + */
296 +#define STMF_ENQUEUE_ITASK(w, i) \
297 + ASSERT((itask->itask_flags & ITASK_IN_FREE_LIST) == 0); \
298 + ASSERT(mutex_owned(&itask->itask_mutex)); \
299 + ASSERT(mutex_owned(&w->worker_lock)); \
300 + i->itask_worker_next = NULL; \
301 + if (w->worker_task_tail) { \
302 + w->worker_task_tail->itask_worker_next = i; \
303 + } else { \
304 + w->worker_task_head = i; \
305 + } \
306 + w->worker_task_tail = i; \
307 + if (++(w->worker_queue_depth) > w->worker_max_qdepth_pu) { \
308 + w->worker_max_qdepth_pu = w->worker_queue_depth; \
309 + } \
310 + atomic_inc_32(&w->worker_ref_count); \
311 + atomic_or_32(&itask->itask_flags, ITASK_IN_WORKER_QUEUE); \
312 + i->itask_waitq_enter_timestamp = gethrtime(); \
313 + if ((w->worker_flags & STMF_WORKER_ACTIVE) == 0) \
314 + cv_signal(&w->worker_cv);
315 +
316 +#define STMF_DEQUEUE_ITASK(w, itask) \
317 + ASSERT(mutex_owned(&w->worker_lock)); \
318 + if ((itask = w->worker_task_head) != NULL) { \
319 + w->worker_task_head = itask->itask_worker_next; \
320 + if (w->worker_task_head == NULL) { \
321 + w->worker_task_tail = NULL; \
322 + } \
323 + } else { \
324 + w->worker_task_tail = NULL; \
325 + }
326 +
327 +/*
278 328 * itask_flags
279 329 */
280 330 #define ITASK_IN_FREE_LIST 0x0001
281 331 #define ITASK_IN_TRANSITION 0x0002
282 332 #define ITASK_IN_WORKER_QUEUE 0x0004
283 333 #define ITASK_BEING_ABORTED 0x0008
284 334 #define ITASK_BEING_COMPLETED 0x0010
285 335 #define ITASK_KNOWN_TO_TGT_PORT 0x0020
286 336 #define ITASK_KNOWN_TO_LU 0x0040
287 337 #define ITASK_LU_ABORT_CALLED 0x0080
288 338 #define ITASK_TGT_PORT_ABORT_CALLED 0x0100
289 339 #define ITASK_DEFAULT_HANDLING 0x0200
290 340 #define ITASK_CAUSING_LU_RESET 0x0400
291 341 #define ITASK_CAUSING_TARGET_RESET 0x0800
292 342 #define ITASK_KSTAT_IN_RUNQ 0x1000
293 343 #define ITASK_PROXY_TASK 0x2000
294 344
295 345 /*
296 346 * itask cmds.
297 347 */
298 348 #define ITASK_CMD_MASK 0x1F
299 349 #define ITASK_CMD_BUF_NDX(cmd) (((uint8_t)(cmd)) >> 5)
300 350 #define ITASK_CMD_NEW_TASK 0x1
301 351 #define ITASK_CMD_DATA_XFER_DONE 0x2
302 352 #define ITASK_CMD_STATUS_DONE 0x3
303 353 #define ITASK_CMD_ABORT 0x4
304 354 #define ITASK_CMD_SEND_STATUS 0x5
305 355 #define ITASK_CMD_POLL 0x10
306 356 #define ITASK_CMD_POLL_LU (ITASK_CMD_POLL | 1)
307 357 #define ITASK_CMD_POLL_LPORT (ITASK_CMD_POLL | 2)
308 358
309 359 /*
310 360 * struct maintained on a per itl basis when the lu registers ITL handle.
311 361 */
312 362 typedef struct stmf_itl_data {
313 363 uint32_t itl_counter;
314 364 uint8_t itl_flags;
315 365 uint8_t itl_hdlrm_reason;
316 366 uint16_t itl_lun;
317 367 void *itl_handle;
318 368 struct stmf_i_lu *itl_ilu;
319 369 struct stmf_i_scsi_session *itl_session;
320 370 struct stmf_itl_data *itl_next;
321 371 } stmf_itl_data_t;
322 372
323 373 /*
324 374 * itl flags
325 375 */
326 376 #define STMF_ITL_BEING_TERMINATED 0x01
327 377
328 378 /*
329 379 * data structures to maintain provider private data.
330 380 */
331 381 typedef struct stmf_pp_data {
332 382 struct stmf_pp_data *ppd_next;
333 383 void *ppd_provider;
334 384 nvlist_t *ppd_nv;
335 385 uint32_t ppd_lu_provider:1,
336 386 ppd_port_provider:1,
337 387 ppd_rsvd:30;
338 388 uint32_t ppd_alloc_size;
339 389 uint64_t ppd_token;
340 390 char ppd_name[8];
341 391 } stmf_pp_data_t;
342 392
343 393 typedef struct stmf_worker {
344 394 kthread_t *worker_tid;
345 395 stmf_i_scsi_task_t *worker_task_head;
346 396 stmf_i_scsi_task_t *worker_task_tail;
347 397 stmf_i_scsi_task_t *worker_wait_head;
348 398 stmf_i_scsi_task_t *worker_wait_tail;
349 399 kmutex_t worker_lock;
350 400 kcondvar_t worker_cv;
351 401 uint32_t worker_flags;
352 402 uint32_t worker_queue_depth; /* ntasks cur queued */
353 403 uint32_t worker_max_qdepth_pu; /* maxqd / unit time */
354 404 uint32_t worker_max_sys_qdepth_pu; /* for all workers */
355 405 uint32_t worker_ref_count; /* # IOs referencing */
356 406 hrtime_t worker_signal_timestamp;
357 407 } stmf_worker_t;
358 408
359 409 /*
360 410 * worker flags
361 411 */
362 412 #define STMF_WORKER_STARTED 1
363 413 #define STMF_WORKER_ACTIVE 2
364 414 #define STMF_WORKER_TERMINATE 4
365 415
366 416 /*
367 417 * data struct for managing transfers.
368 418 */
369 419 typedef struct stmf_xfer_data {
370 420 uint32_t alloc_size; /* Including this struct */
371 421 uint32_t size_done;
372 422 uint32_t size_left;
373 423 uint8_t buf[4];
374 424 } stmf_xfer_data_t;
375 425
376 426 /*
377 427 * Define frequently used macros
378 428 */
379 429 #define TASK_TO_ITASK(x_task) \
380 430 ((stmf_i_scsi_task_t *)(x_task)->task_stmf_private)
381 431
382 432 void stmf_dlun_init();
383 433 stmf_status_t stmf_dlun_fini();
384 434 void stmf_worker_init();
385 435 stmf_status_t stmf_worker_fini();
386 436 void stmf_task_free(scsi_task_t *task);
387 437 void stmf_do_task_abort(scsi_task_t *task);
388 438 void stmf_do_itl_dereg(stmf_lu_t *lu, stmf_itl_data_t *itl,
389 439 uint8_t hdlrm_reason);
390 440 void stmf_generate_lu_event(stmf_i_lu_t *ilu, int eventid,
391 441 void *arg, uint32_t flags);
392 442 void stmf_generate_lport_event(stmf_i_local_port_t *ilport, int eventid,
393 443 void *arg, uint32_t flags);
394 444
395 445 #ifdef __cplusplus
396 446 }
397 447 #endif
398 448
399 449 #endif /* _STMF_IMPL_H */
|
↓ open down ↓ |
112 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX