1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 23 * 24 * Copyright 2016 Nexenta Systems, Inc. All rights reserved. 25 * Copyright (c) 2013 by Delphix. All rights reserved. 26 */ 27 #ifndef _STMF_IMPL_H 28 #define _STMF_IMPL_H 29 30 #include <sys/stmf_defines.h> 31 #include <sys/stmf_ioctl.h> 32 33 #ifdef __cplusplus 34 extern "C" { 35 #endif 36 37 typedef uint32_t stmf_event_handle_t; 38 #define STMF_MAX_NUM_EVENTS (sizeof (stmf_event_handle_t) * 8) 39 #define STMF_EVENT_ADD(h, e) (atomic_or_32(&(h), \ 40 ((uint32_t)1) << (e))) 41 #define STMF_EVENT_REMOVE(h, e) (atomic_and_32(&(h), \ 42 ~(((uint32_t)1) << (e)))) 43 #define STMF_EVENT_ENABLED(h, e) (((h) & ((uint32_t)1) << (e)) != 0) 44 #define STMF_EVENT_CLEAR_ALL(h) ((h) = 0) 45 #define STMF_EVENT_ALLOC_HANDLE(h) ((h) = 0) 46 #define STMF_EVENT_FREE_HANDLE(h) ((h) = 0) 47 48 #define STMF_TGT_NAME_LEN 256 49 #define STMF_GUID_INPUT 32 50 51 #define STMF_UPDATE_KSTAT_IO(kip, dbuf) \ 52 if (dbuf->db_flags & DB_DIRECTION_TO_RPORT) { \ 53 kip->reads++; \ 54 kip->nread += dbuf->db_data_size; \ 55 } else { \ 56 kip->writes++; \ 57 kip->nwritten += dbuf->db_data_size; \ 58 } 59 60 struct stmf_i_scsi_task; 61 struct stmf_itl_data; 62 63 typedef struct stmf_i_lu_provider { 64 stmf_lu_provider_t *ilp_lp; 65 uint32_t ilp_alloc_size; 66 uint32_t ilp_nlus; /* # LUNs being exported */ 67 uint32_t ilp_cb_in_progress:1, 68 ilp_rsvd:31; 69 struct stmf_i_lu_provider *ilp_next; 70 struct stmf_pp_data *ilp_ppd; 71 } stmf_i_lu_provider_t; 72 73 typedef struct stmf_i_lu { 74 stmf_lu_t *ilu_lu; 75 uint32_t ilu_alloc_size; 76 uint32_t ilu_flags; 77 uint32_t ilu_ref_cnt; 78 uint8_t ilu_state; 79 uint8_t ilu_prev_state; 80 uint8_t ilu_access; 81 uint8_t ilu_alua; 82 stmf_event_handle_t ilu_event_hdl; 83 struct stmf_i_lu *ilu_next; 84 struct stmf_i_lu *ilu_prev; 85 char *ilu_alias; 86 char ilu_ascii_hex_guid[STMF_GUID_INPUT + 1]; 87 kmutex_t ilu_task_lock; 88 uint32_t ilu_task_cntr1; 89 uint32_t ilu_task_cntr2; 90 uint32_t *ilu_cur_task_cntr; 91 uint32_t ilu_ntasks; /* # of tasks in the ilu_task list */ 92 uint32_t ilu_ntasks_free; /* # of tasks that are free */ 93 uint32_t ilu_ntasks_min_free; /* # minimal free tasks */ 94 uint32_t ilu_additional_ref; 95 uint32_t ilu_proxy_registered; 96 uint64_t ilu_reg_msgid; 97 struct stmf_i_scsi_task *ilu_tasks; 98 struct stmf_i_scsi_task *ilu_free_tasks; 99 struct stmf_itl_data *ilu_itl_list; 100 kstat_t *ilu_kstat_info; 101 kstat_t *ilu_kstat_io; 102 kmutex_t ilu_kstat_lock; 103 kcondvar_t ilu_offline_pending_cv; 104 105 /* point to the luid entry in stmf_state.stmf_luid_list */ 106 void *ilu_luid; 107 } stmf_i_lu_t; 108 109 /* 110 * ilu_flags 111 */ 112 #define ILU_STALL_DEREGISTER 0x0001 113 #define ILU_RESET_ACTIVE 0x0002 114 115 typedef struct stmf_i_port_provider { 116 stmf_port_provider_t *ipp_pp; 117 uint32_t ipp_alloc_size; 118 uint32_t ipp_npps; 119 uint32_t ipp_cb_in_progress:1, 120 ipp_rsvd:31; 121 struct stmf_i_port_provider *ipp_next; 122 struct stmf_pp_data *ipp_ppd; 123 } stmf_i_port_provider_t; 124 125 #define MAX_ILPORT 0x10000 126 127 typedef struct stmf_i_local_port { 128 stmf_local_port_t *ilport_lport; 129 uint32_t ilport_alloc_size; 130 uint32_t ilport_nsessions; 131 struct stmf_i_scsi_session *ilport_ss_list; 132 krwlock_t ilport_lock; 133 struct stmf_i_local_port *ilport_next; 134 struct stmf_i_local_port *ilport_prev; 135 uint8_t ilport_state; 136 uint8_t ilport_prev_state; 137 uint8_t ilport_standby; 138 uint8_t ilport_alua; 139 uint16_t ilport_rtpid; /* relative tpid */ 140 uint16_t ilport_proxy_registered; 141 uint64_t ilport_reg_msgid; 142 uint8_t ilport_no_standby_lu; 143 uint32_t ilport_unexpected_comp; 144 stmf_event_handle_t ilport_event_hdl; 145 clock_t ilport_last_online_clock; 146 clock_t ilport_avg_interval; 147 uint32_t ilport_online_times; 148 uint32_t ilport_flags; 149 kstat_t *ilport_kstat_info; 150 kstat_t *ilport_kstat_io; 151 kmutex_t ilport_kstat_lock; 152 char ilport_kstat_tgt_name[STMF_TGT_NAME_LEN]; 153 /* which target group this port belongs to in stmf_state.stmf_tg_list */ 154 void *ilport_tg; 155 id_t ilport_instance; 156 /* XXX Need something to track all the remote ports also */ 157 } stmf_i_local_port_t; 158 159 #define STMF_AVG_ONLINE_INTERVAL (30 * drv_usectohz(1000000)) 160 161 #define MAX_IRPORT 0x10000 162 163 typedef struct stmf_i_remote_port { 164 struct scsi_devid_desc *irport_id; 165 kmutex_t irport_mutex; 166 int irport_refcnt; 167 id_t irport_instance; 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; 181 } stmf_i_remote_port_t; 182 183 /* 184 * ilport flags 185 */ 186 #define ILPORT_FORCED_OFFLINE 0x01 187 #define ILPORT_SS_GOT_INITIAL_LUNS 0x02 188 189 typedef struct stmf_i_scsi_session { 190 stmf_scsi_session_t *iss_ss; 191 uint32_t iss_alloc_size; 192 uint32_t iss_flags; 193 stmf_i_remote_port_t *iss_irport; 194 struct stmf_i_scsi_session *iss_next; 195 /* 196 * Ideally we should maintain 2 maps. One would indicate a new map 197 * which will become available only upon receipt of a REPORT LUN 198 * cmd. 199 */ 200 struct stmf_lun_map *iss_sm; 201 /* 202 * which host group the host of this session belongs to in 203 * stmf_state.stmf_hg_list 204 */ 205 void *iss_hg; 206 krwlock_t *iss_lockp; 207 time_t iss_creation_time; 208 } stmf_i_scsi_session_t; 209 210 /* 211 * iss flags 212 */ 213 #define ISS_LUN_INVENTORY_CHANGED 0x0001 214 #define ISS_RESET_ACTIVE 0x0002 215 #define ISS_BEING_CREATED 0x0004 216 #define ISS_GOT_INITIAL_LUNS 0x0008 217 #define ISS_EVENT_ACTIVE 0x0010 218 #define ISS_NULL_TPTID 0x0020 219 220 #define ITASK_MAX_NCMDS 14 221 #define ITASK_DEFAULT_POLL_TIMEOUT 0 222 223 #define ITASK_TASK_AUDIT_DEPTH 32 /* Must be a power of 2 */ 224 225 typedef enum { 226 TE_UNDEFINED, 227 TE_TASK_START, 228 TE_XFER_START, 229 TE_XFER_DONE, 230 TE_SEND_STATUS, 231 TE_SEND_STATUS_DONE, 232 TE_TASK_FREE, 233 TE_TASK_ABORT, 234 TE_TASK_LPORT_ABORTED, 235 TE_TASK_LU_ABORTED, 236 TE_PROCESS_CMD 237 } task_audit_event_t; 238 239 #define CMD_OR_IOF_NA 0xffffffff 240 241 typedef struct stmf_task_audit_rec { 242 task_audit_event_t ta_event; 243 uint32_t ta_cmd_or_iof; 244 uint32_t ta_itask_flags; 245 stmf_data_buf_t *ta_dbuf; 246 timespec_t ta_timestamp; 247 } stmf_task_audit_rec_t; 248 249 struct stmf_worker; 250 typedef struct stmf_i_scsi_task { 251 scsi_task_t *itask_task; 252 uint32_t itask_alloc_size; 253 uint32_t itask_flags; 254 kmutex_t itask_mutex; /* protects flags and lists */ 255 uint64_t itask_proxy_msg_id; 256 stmf_data_buf_t *itask_proxy_dbuf; 257 struct stmf_worker *itask_worker; 258 uint32_t *itask_ilu_task_cntr; 259 struct stmf_i_scsi_task *itask_worker_next; 260 struct stmf_i_scsi_task *itask_lu_next; 261 struct stmf_i_scsi_task *itask_lu_prev; 262 struct stmf_i_scsi_task *itask_lu_free_next; 263 struct stmf_itl_data *itask_itl_datap; 264 clock_t itask_start_time; /* abort and normal */ 265 /* For now we only support 4 parallel buffers. Should be enough. */ 266 stmf_data_buf_t *itask_dbufs[4]; 267 clock_t itask_poll_timeout; 268 uint8_t itask_cmd_stack[ITASK_MAX_NCMDS]; 269 uint8_t itask_ncmds; 270 uint8_t itask_allocated_buf_map; 271 uint16_t itask_cdb_buf_size; 272 273 /* Task profile data */ 274 hrtime_t itask_start_timestamp; 275 hrtime_t itask_done_timestamp; 276 hrtime_t itask_xfer_done_timestamp; 277 hrtime_t itask_waitq_enter_timestamp; 278 hrtime_t itask_waitq_time; 279 hrtime_t itask_lu_read_time; 280 hrtime_t itask_lu_write_time; 281 hrtime_t itask_lport_read_time; 282 hrtime_t itask_lport_write_time; 283 uint64_t itask_read_xfer; 284 uint64_t itask_write_xfer; 285 kmutex_t itask_audit_mutex; 286 uint8_t itask_audit_index; 287 stmf_task_audit_rec_t itask_audit_records[ITASK_TASK_AUDIT_DEPTH]; 288 } stmf_i_scsi_task_t; 289 290 #define ITASK_DEFAULT_ABORT_TIMEOUT 5 291 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 /* 328 * itask_flags 329 */ 330 #define ITASK_IN_FREE_LIST 0x0001 331 #define ITASK_IN_TRANSITION 0x0002 332 #define ITASK_IN_WORKER_QUEUE 0x0004 333 #define ITASK_BEING_ABORTED 0x0008 334 #define ITASK_BEING_COMPLETED 0x0010 335 #define ITASK_KNOWN_TO_TGT_PORT 0x0020 336 #define ITASK_KNOWN_TO_LU 0x0040 337 #define ITASK_LU_ABORT_CALLED 0x0080 338 #define ITASK_TGT_PORT_ABORT_CALLED 0x0100 339 #define ITASK_DEFAULT_HANDLING 0x0200 340 #define ITASK_CAUSING_LU_RESET 0x0400 341 #define ITASK_CAUSING_TARGET_RESET 0x0800 342 #define ITASK_KSTAT_IN_RUNQ 0x1000 343 #define ITASK_PROXY_TASK 0x2000 344 345 /* 346 * itask cmds. 347 */ 348 #define ITASK_CMD_MASK 0x1F 349 #define ITASK_CMD_BUF_NDX(cmd) (((uint8_t)(cmd)) >> 5) 350 #define ITASK_CMD_NEW_TASK 0x1 351 #define ITASK_CMD_DATA_XFER_DONE 0x2 352 #define ITASK_CMD_STATUS_DONE 0x3 353 #define ITASK_CMD_ABORT 0x4 354 #define ITASK_CMD_SEND_STATUS 0x5 355 #define ITASK_CMD_POLL 0x10 356 #define ITASK_CMD_POLL_LU (ITASK_CMD_POLL | 1) 357 #define ITASK_CMD_POLL_LPORT (ITASK_CMD_POLL | 2) 358 359 /* 360 * struct maintained on a per itl basis when the lu registers ITL handle. 361 */ 362 typedef struct stmf_itl_data { 363 uint32_t itl_counter; 364 uint8_t itl_flags; 365 uint8_t itl_hdlrm_reason; 366 uint16_t itl_lun; 367 void *itl_handle; 368 struct stmf_i_lu *itl_ilu; 369 struct stmf_i_scsi_session *itl_session; 370 struct stmf_itl_data *itl_next; 371 } stmf_itl_data_t; 372 373 /* 374 * itl flags 375 */ 376 #define STMF_ITL_BEING_TERMINATED 0x01 377 378 /* 379 * data structures to maintain provider private data. 380 */ 381 typedef struct stmf_pp_data { 382 struct stmf_pp_data *ppd_next; 383 void *ppd_provider; 384 nvlist_t *ppd_nv; 385 uint32_t ppd_lu_provider:1, 386 ppd_port_provider:1, 387 ppd_rsvd:30; 388 uint32_t ppd_alloc_size; 389 uint64_t ppd_token; 390 char ppd_name[8]; 391 } stmf_pp_data_t; 392 393 typedef struct stmf_worker { 394 kthread_t *worker_tid; 395 stmf_i_scsi_task_t *worker_task_head; 396 stmf_i_scsi_task_t *worker_task_tail; 397 stmf_i_scsi_task_t *worker_wait_head; 398 stmf_i_scsi_task_t *worker_wait_tail; 399 kmutex_t worker_lock; 400 kcondvar_t worker_cv; 401 uint32_t worker_flags; 402 uint32_t worker_queue_depth; /* ntasks cur queued */ 403 uint32_t worker_max_qdepth_pu; /* maxqd / unit time */ 404 uint32_t worker_max_sys_qdepth_pu; /* for all workers */ 405 uint32_t worker_ref_count; /* # IOs referencing */ 406 hrtime_t worker_signal_timestamp; 407 } stmf_worker_t; 408 409 /* 410 * worker flags 411 */ 412 #define STMF_WORKER_STARTED 1 413 #define STMF_WORKER_ACTIVE 2 414 #define STMF_WORKER_TERMINATE 4 415 416 /* 417 * data struct for managing transfers. 418 */ 419 typedef struct stmf_xfer_data { 420 uint32_t alloc_size; /* Including this struct */ 421 uint32_t size_done; 422 uint32_t size_left; 423 uint8_t buf[4]; 424 } stmf_xfer_data_t; 425 426 /* 427 * Define frequently used macros 428 */ 429 #define TASK_TO_ITASK(x_task) \ 430 ((stmf_i_scsi_task_t *)(x_task)->task_stmf_private) 431 432 void stmf_dlun_init(); 433 stmf_status_t stmf_dlun_fini(); 434 void stmf_worker_init(); 435 stmf_status_t stmf_worker_fini(); 436 void stmf_task_free(scsi_task_t *task); 437 void stmf_do_task_abort(scsi_task_t *task); 438 void stmf_do_itl_dereg(stmf_lu_t *lu, stmf_itl_data_t *itl, 439 uint8_t hdlrm_reason); 440 void stmf_generate_lu_event(stmf_i_lu_t *ilu, int eventid, 441 void *arg, uint32_t flags); 442 void stmf_generate_lport_event(stmf_i_local_port_t *ilport, int eventid, 443 void *arg, uint32_t flags); 444 445 #ifdef __cplusplus 446 } 447 #endif 448 449 #endif /* _STMF_IMPL_H */ 450