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 /*
25 * Copyright 2012, Nexenta Systems, Inc. All rights reserved.
26 */
27
28 #include <sys/conf.h>
29 #include <sys/file.h>
30 #include <sys/ddi.h>
31 #include <sys/sunddi.h>
32 #include <sys/modctl.h>
33 #include <sys/scsi/scsi.h>
34 #include <sys/scsi/generic/persist.h>
35 #include <sys/scsi/impl/scsi_reset_notify.h>
36 #include <sys/disp.h>
37 #include <sys/byteorder.h>
38 #include <sys/atomic.h>
39 #include <sys/ethernet.h>
40 #include <sys/sdt.h>
41 #include <sys/nvpair.h>
42 #include <sys/zone.h>
43 #include <sys/id_space.h>
44
45 #include <sys/stmf.h>
48 #include <sys/stmf_ioctl.h>
49 #include <sys/pppt_ic_if.h>
50
51 #include "stmf_impl.h"
52 #include "lun_map.h"
53 #include "stmf_state.h"
54 #include "stmf_stats.h"
55
56 /*
57 * Lock order:
58 * stmf_state_lock --> ilport_lock/iss_lockp --> ilu_task_lock
59 */
60
61 static uint64_t stmf_session_counter = 0;
62 static uint16_t stmf_rtpid_counter = 0;
63 /* start messages at 1 */
64 static uint64_t stmf_proxy_msg_id = 1;
65 #define MSG_ID_TM_BIT 0x8000000000000000
66 #define ALIGNED_TO_8BYTE_BOUNDARY(i) (((i) + 7) & ~7)
67
68 struct stmf_svc_clocks;
69
70 static int stmf_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
71 static int stmf_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
72 static int stmf_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
73 void **result);
74 static int stmf_open(dev_t *devp, int flag, int otype, cred_t *credp);
75 static int stmf_close(dev_t dev, int flag, int otype, cred_t *credp);
76 static int stmf_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
77 cred_t *credp, int *rval);
78 static int stmf_get_stmf_state(stmf_state_desc_t *std);
79 static int stmf_set_stmf_state(stmf_state_desc_t *std);
80 static void stmf_abort_task_offline(scsi_task_t *task, int offline_lu,
81 char *info);
82 static int stmf_set_alua_state(stmf_alua_state_desc_t *alua_state);
83 static void stmf_get_alua_state(stmf_alua_state_desc_t *alua_state);
84
85 static void stmf_task_audit(stmf_i_scsi_task_t *itask,
86 task_audit_event_t te, uint32_t cmd_or_iof, stmf_data_buf_t *dbuf);
87
88 static boolean_t stmf_base16_str_to_binary(char *c, int dplen, uint8_t *dp);
89 static char stmf_ctoi(char c);
90 stmf_xfer_data_t *stmf_prepare_tpgs_data(uint8_t ilu_alua);
91 void stmf_svc_init();
92 stmf_status_t stmf_svc_fini();
93 void stmf_svc(void *arg);
94 void stmf_svc_queue(int cmd, void *obj, stmf_state_change_info_t *info);
95 static void stmf_svc_kill_obj_requests(void *obj);
96 static void stmf_svc_timeout(struct stmf_svc_clocks *);
97 void stmf_check_freetask();
98 void stmf_abort_target_reset(scsi_task_t *task);
99 stmf_status_t stmf_lun_reset_poll(stmf_lu_t *lu, struct scsi_task *task,
100 int target_reset);
101 void stmf_target_reset_poll(struct scsi_task *task);
102 void stmf_handle_lun_reset(scsi_task_t *task);
103 void stmf_handle_target_reset(scsi_task_t *task);
104 void stmf_xd_to_dbuf(stmf_data_buf_t *dbuf, int set_rel_off);
105 int stmf_load_ppd_ioctl(stmf_ppioctl_data_t *ppi, uint64_t *ppi_token,
106 uint32_t *err_ret);
107 int stmf_delete_ppd_ioctl(stmf_ppioctl_data_t *ppi);
108 int stmf_get_ppd_ioctl(stmf_ppioctl_data_t *ppi, stmf_ppioctl_data_t *ppi_out,
109 uint32_t *err_ret);
110 void stmf_delete_ppd(stmf_pp_data_t *ppd);
111 void stmf_delete_all_ppds();
112 void stmf_trace_clear();
113 void stmf_worker_init();
146 static void stmf_lport_xfer_start(stmf_i_scsi_task_t *itask,
147 stmf_data_buf_t *dbuf);
148 static void stmf_lport_xfer_done(stmf_i_scsi_task_t *itask,
149 stmf_data_buf_t *dbuf);
150
151 static void stmf_update_kstat_lu_q(scsi_task_t *, void());
152 static void stmf_update_kstat_lport_q(scsi_task_t *, void());
153 static void stmf_update_kstat_lu_io(scsi_task_t *, stmf_data_buf_t *);
154 static void stmf_update_kstat_lport_io(scsi_task_t *, stmf_data_buf_t *);
155
156 static int stmf_irport_compare(const void *void_irport1,
157 const void *void_irport2);
158 static stmf_i_remote_port_t *stmf_irport_create(scsi_devid_desc_t *rport_devid);
159 static void stmf_irport_destroy(stmf_i_remote_port_t *irport);
160 static stmf_i_remote_port_t *stmf_irport_register(
161 scsi_devid_desc_t *rport_devid);
162 static stmf_i_remote_port_t *stmf_irport_lookup_locked(
163 scsi_devid_desc_t *rport_devid);
164 static void stmf_irport_deregister(stmf_i_remote_port_t *irport);
165
166 static void stmf_teardown_itl_kstats(stmf_i_itl_kstat_t *ks);
167 static void stmf_delete_itl_kstat_by_lport(char *);
168 static void stmf_delete_itl_kstat_by_guid(char *);
169 static int stmf_itl_kstat_compare(const void*, const void*);
170 static stmf_i_itl_kstat_t *stmf_itl_kstat_lookup(char *kstat_nm);
171 static stmf_i_itl_kstat_t *stmf_itl_kstat_create(stmf_itl_data_t *itl,
172 char *nm, scsi_devid_desc_t *lport, scsi_devid_desc_t *lun);
173
174 extern struct mod_ops mod_driverops;
175
176 /* =====[ Tunables ]===== */
177 /* Internal tracing */
178 volatile int stmf_trace_on = 1;
179 volatile int stmf_trace_buf_size = (1 * 1024 * 1024);
180 /*
181 * The reason default task timeout is 75 is because we want the
182 * host to timeout 1st and mostly host timeout is 60 seconds.
183 */
184 volatile int stmf_default_task_timeout = 75;
185 /*
186 * Setting this to one means, you are responsible for config load and keeping
187 * things in sync with persistent database.
188 */
189 volatile int stmf_allow_modunload = 0;
190
191 volatile int stmf_max_nworkers = 256;
192 volatile int stmf_min_nworkers = 4;
193 volatile int stmf_worker_scale_down_delay = 20;
295 stmf_trace_buf = kmem_zalloc(stmf_trace_buf_size, KM_SLEEP);
296 trace_buf_size = stmf_trace_buf_size;
297 trace_buf_curndx = 0;
298 mutex_init(&trace_buf_lock, NULL, MUTEX_DRIVER, 0);
299 bzero(&stmf_state, sizeof (stmf_state_t));
300 /* STMF service is off by default */
301 stmf_state.stmf_service_running = 0;
302 /* default lu/lport states are online */
303 stmf_state.stmf_default_lu_state = STMF_STATE_ONLINE;
304 stmf_state.stmf_default_lport_state = STMF_STATE_ONLINE;
305 mutex_init(&stmf_state.stmf_lock, NULL, MUTEX_DRIVER, NULL);
306 cv_init(&stmf_state.stmf_cv, NULL, CV_DRIVER, NULL);
307 stmf_session_counter = (uint64_t)ddi_get_lbolt();
308 avl_create(&stmf_state.stmf_irportlist,
309 stmf_irport_compare, sizeof (stmf_i_remote_port_t),
310 offsetof(stmf_i_remote_port_t, irport_ln));
311 stmf_state.stmf_ilport_inst_space =
312 id_space_create("lport-instances", 0, MAX_ILPORT);
313 stmf_state.stmf_irport_inst_space =
314 id_space_create("rport-instances", 0, MAX_IRPORT);
315 avl_create(&stmf_state.stmf_itl_kstat_list,
316 stmf_itl_kstat_compare, sizeof (stmf_i_itl_kstat_t),
317 offsetof(stmf_i_itl_kstat_t, iitl_kstat_ln));
318 stmf_view_init();
319 stmf_svc_init();
320 stmf_dlun_init();
321 return (ret);
322 }
323
324 int
325 _fini(void)
326 {
327 int ret;
328 stmf_i_remote_port_t *irport;
329 stmf_i_itl_kstat_t *ks_itl;
330 void *avl_dest_cookie = NULL;
331
332 if (stmf_state.stmf_service_running)
333 return (EBUSY);
334 if ((!stmf_allow_modunload) &&
335 (stmf_state.stmf_config_state != STMF_CONFIG_NONE)) {
336 return (EBUSY);
337 }
338 if (stmf_state.stmf_nlps || stmf_state.stmf_npps) {
339 return (EBUSY);
340 }
341 if (stmf_dlun_fini() != STMF_SUCCESS)
342 return (EBUSY);
343 if (stmf_worker_fini() != STMF_SUCCESS) {
344 stmf_dlun_init();
345 return (EBUSY);
346 }
347 if (stmf_svc_fini() != STMF_SUCCESS) {
348 stmf_dlun_init();
349 stmf_worker_init();
350 return (EBUSY);
351 }
352
353 ret = mod_remove(&modlinkage);
354 if (ret) {
355 stmf_svc_init();
356 stmf_dlun_init();
357 stmf_worker_init();
358 return (ret);
359 }
360
361 stmf_view_clear_config();
362
363 while ((irport = avl_destroy_nodes(&stmf_state.stmf_irportlist,
364 &avl_dest_cookie)) != NULL)
365 stmf_irport_destroy(irport);
366 avl_destroy(&stmf_state.stmf_irportlist);
367 id_space_destroy(stmf_state.stmf_ilport_inst_space);
368 id_space_destroy(stmf_state.stmf_irport_inst_space);
369
370 avl_dest_cookie = NULL;
371 while ((ks_itl = avl_destroy_nodes(&stmf_state.stmf_itl_kstat_list,
372 &avl_dest_cookie)) != NULL) {
373 stmf_teardown_itl_kstats(ks_itl);
374 kmem_free(ks_itl, sizeof (ks_itl));
375 }
376 avl_destroy(&stmf_state.stmf_itl_kstat_list);
377
378 kmem_free(stmf_trace_buf, stmf_trace_buf_size);
379 mutex_destroy(&trace_buf_lock);
380 mutex_destroy(&stmf_state.stmf_lock);
381 cv_destroy(&stmf_state.stmf_cv);
382 return (ret);
383 }
384
385 int
386 _info(struct modinfo *modinfop)
387 {
388 return (mod_info(&modlinkage, modinfop));
389 }
390
391 /* ARGSUSED */
392 static int
393 stmf_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
394 {
395 switch (cmd) {
396 case DDI_INFO_DEVT2DEVINFO:
397 *result = stmf_state.stmf_dip;
1575 if (ilu->ilu_state != STMF_STATE_ONLINE)
1576 continue;
1577 (void) stmf_ctl(STMF_CMD_LU_OFFLINE, ilu->ilu_lu, &ssi);
1578 }
1579 mutex_enter(&stmf_state.stmf_lock);
1580 stmf_state.stmf_inventory_locked = 0;
1581 mutex_exit(&stmf_state.stmf_lock);
1582 return (0);
1583 }
1584
1585 static int
1586 stmf_get_stmf_state(stmf_state_desc_t *std)
1587 {
1588 mutex_enter(&stmf_state.stmf_lock);
1589 std->state = stmf_get_service_state();
1590 std->config_state = stmf_state.stmf_config_state;
1591 mutex_exit(&stmf_state.stmf_lock);
1592
1593 return (0);
1594 }
1595 /*
1596 * handles registration message from pppt for a logical unit
1597 */
1598 stmf_status_t
1599 stmf_ic_lu_reg(stmf_ic_reg_dereg_lun_msg_t *msg, uint32_t type)
1600 {
1601 stmf_i_lu_provider_t *ilp;
1602 stmf_lu_provider_t *lp;
1603 mutex_enter(&stmf_state.stmf_lock);
1604 for (ilp = stmf_state.stmf_ilplist; ilp != NULL; ilp = ilp->ilp_next) {
1605 if (strcmp(msg->icrl_lu_provider_name,
1606 ilp->ilp_lp->lp_name) == 0) {
1607 lp = ilp->ilp_lp;
1608 mutex_exit(&stmf_state.stmf_lock);
1609 lp->lp_proxy_msg(msg->icrl_lun_id, msg->icrl_cb_arg,
1610 msg->icrl_cb_arg_len, type);
1611 return (STMF_SUCCESS);
1612 }
1613 }
1614 mutex_exit(&stmf_state.stmf_lock);
3042 luid = stmf_lookup_id(&stmf_state.stmf_luid_list,
3043 lu->lu_id->ident_length, lu->lu_id->ident);
3044 if (luid) {
3045 luid->id_pt_to_object = (void *)ilu;
3046 ilu->ilu_luid = luid;
3047 }
3048 ilu->ilu_alias = NULL;
3049
3050 ilu->ilu_next = stmf_state.stmf_ilulist;
3051 ilu->ilu_prev = NULL;
3052 if (ilu->ilu_next)
3053 ilu->ilu_next->ilu_prev = ilu;
3054 stmf_state.stmf_ilulist = ilu;
3055 stmf_state.stmf_nlus++;
3056 if (lu->lu_lp) {
3057 ((stmf_i_lu_provider_t *)
3058 (lu->lu_lp->lp_stmf_private))->ilp_nlus++;
3059 }
3060 ilu->ilu_cur_task_cntr = &ilu->ilu_task_cntr1;
3061 STMF_EVENT_ALLOC_HANDLE(ilu->ilu_event_hdl);
3062 stmf_create_kstat_lu(ilu);
3063 /*
3064 * register with proxy module if available and logical unit
3065 * is in active state
3066 */
3067 if (stmf_state.stmf_alua_state == 1 &&
3068 ilu->ilu_access == STMF_LU_ACTIVE) {
3069 stmf_ic_msg_status_t ic_ret = STMF_IC_MSG_SUCCESS;
3070 stmf_ic_msg_t *ic_reg_lun;
3071 if (lu->lu_lp && lu->lu_lp->lp_lpif_rev == LPIF_REV_2 &&
3072 lu->lu_lp->lp_alua_support) {
3073 ilu->ilu_alua = 1;
3074 /* allocate the register message */
3075 ic_reg_lun = ic_reg_lun_msg_alloc(p1,
3076 lu->lu_lp->lp_name, lu->lu_proxy_reg_arg_len,
3077 (uint8_t *)lu->lu_proxy_reg_arg, stmf_proxy_msg_id);
3078 /* send the message */
3079 if (ic_reg_lun) {
3080 ic_ret = ic_tx_msg(ic_reg_lun);
3081 if (ic_ret == STMF_IC_MSG_SUCCESS) {
3179 }
3180 if (ilu->ilu_luid) {
3181 ((stmf_id_data_t *)ilu->ilu_luid)->id_pt_to_object =
3182 NULL;
3183 ilu->ilu_luid = NULL;
3184 }
3185 STMF_EVENT_FREE_HANDLE(ilu->ilu_event_hdl);
3186 } else {
3187 mutex_exit(&stmf_state.stmf_lock);
3188 return (STMF_BUSY);
3189 }
3190 if (ilu->ilu_kstat_info) {
3191 kmem_free(ilu->ilu_kstat_info->ks_data,
3192 ilu->ilu_kstat_info->ks_data_size);
3193 kstat_delete(ilu->ilu_kstat_info);
3194 }
3195 if (ilu->ilu_kstat_io) {
3196 kstat_delete(ilu->ilu_kstat_io);
3197 mutex_destroy(&ilu->ilu_kstat_lock);
3198 }
3199 stmf_delete_itl_kstat_by_guid(ilu->ilu_ascii_hex_guid);
3200 mutex_exit(&stmf_state.stmf_lock);
3201 return (STMF_SUCCESS);
3202 }
3203
3204 void
3205 stmf_set_port_standby(stmf_local_port_t *lport, uint16_t rtpid)
3206 {
3207 stmf_i_local_port_t *ilport =
3208 (stmf_i_local_port_t *)lport->lport_stmf_private;
3209 ilport->ilport_rtpid = rtpid;
3210 ilport->ilport_standby = 1;
3211 }
3212
3213 void
3214 stmf_set_port_alua(stmf_local_port_t *lport)
3215 {
3216 stmf_i_local_port_t *ilport =
3217 (stmf_i_local_port_t *)lport->lport_stmf_private;
3218 ilport->ilport_alua = 1;
3219 }
3357 stmf_state.stmf_nlports--;
3358 if (lport->lport_pp) {
3359 ((stmf_i_port_provider_t *)
3360 (lport->lport_pp->pp_stmf_private))->ipp_npps--;
3361 }
3362 ilport->ilport_tg = NULL;
3363 STMF_EVENT_FREE_HANDLE(ilport->ilport_event_hdl);
3364 } else {
3365 mutex_exit(&stmf_state.stmf_lock);
3366 return (STMF_BUSY);
3367 }
3368 if (ilport->ilport_kstat_info) {
3369 kmem_free(ilport->ilport_kstat_info->ks_data,
3370 ilport->ilport_kstat_info->ks_data_size);
3371 kstat_delete(ilport->ilport_kstat_info);
3372 }
3373 if (ilport->ilport_kstat_io) {
3374 kstat_delete(ilport->ilport_kstat_io);
3375 mutex_destroy(&ilport->ilport_kstat_lock);
3376 }
3377 stmf_delete_itl_kstat_by_lport(ilport->ilport_kstat_tgt_name);
3378 mutex_exit(&stmf_state.stmf_lock);
3379 return (STMF_SUCCESS);
3380 }
3381
3382 /*
3383 * Rport id/instance mappings remain valid until STMF is unloaded
3384 */
3385 static int
3386 stmf_irport_compare(const void *void_irport1, const void *void_irport2)
3387 {
3388 const stmf_i_remote_port_t *irport1 = void_irport1;
3389 const stmf_i_remote_port_t *irport2 = void_irport2;
3390 int result;
3391
3392 /* Sort by code set then ident */
3393 if (irport1->irport_id->code_set <
3394 irport2->irport_id->code_set) {
3395 return (-1);
3396 } else if (irport1->irport_id->code_set >
3397 irport2->irport_id->code_set) {
3686
3687 mutex_enter(&stmf_state.stmf_lock);
3688 for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
3689 ilport = ilport->ilport_next) {
3690 rw_enter(&ilport->ilport_lock, RW_WRITER);
3691 for (iss = ilport->ilport_ss_list; iss != NULL;
3692 iss = iss->iss_next) {
3693 if (iss->iss_ss->ss_session_id == session_id) {
3694 if (!stay_locked)
3695 rw_exit(&ilport->ilport_lock);
3696 mutex_exit(&stmf_state.stmf_lock);
3697 return (iss);
3698 }
3699 }
3700 rw_exit(&ilport->ilport_lock);
3701 }
3702 mutex_exit(&stmf_state.stmf_lock);
3703 return (NULL);
3704 }
3705
3706 #define MAX_ALIAS 128
3707
3708 static int
3709 stmf_itl_kstat_compare(const void *itl_kstat_1, const void *itl_kstat_2)
3710 {
3711 const stmf_i_itl_kstat_t *kstat_nm1 = itl_kstat_1;
3712 const stmf_i_itl_kstat_t *kstat_nm2 = itl_kstat_2;
3713 int ret;
3714
3715 ret = strcmp(kstat_nm1->iitl_kstat_nm, kstat_nm2->iitl_kstat_nm);
3716 if (ret < 0) {
3717 return (-1);
3718 } else if (ret > 0) {
3719 return (1);
3720 }
3721 return (0);
3722 }
3723
3724 static stmf_i_itl_kstat_t *
3725 stmf_itl_kstat_lookup(char *kstat_nm)
3726 {
3727 stmf_i_itl_kstat_t tmp;
3728 stmf_i_itl_kstat_t *itl_kstat;
3729
3730 ASSERT(mutex_owned(&stmf_state.stmf_lock));
3731 (void) strcpy(tmp.iitl_kstat_nm, kstat_nm);
3732 itl_kstat = avl_find(&stmf_state.stmf_itl_kstat_list, &tmp, NULL);
3733 return (itl_kstat);
3734 }
3735
3736 static void
3737 stmf_delete_itl_kstat_by_lport(char *tgt)
3738 {
3739 stmf_i_itl_kstat_t *ks_itl, *next;
3740
3741 ASSERT(mutex_owned(&stmf_state.stmf_lock));
3742 ks_itl = avl_first(&stmf_state.stmf_itl_kstat_list);
3743 for (; ks_itl != NULL; ks_itl = next) {
3744 next = AVL_NEXT(&stmf_state.stmf_itl_kstat_list, ks_itl);
3745 if (strcmp(ks_itl->iitl_kstat_lport, tgt) == 0) {
3746 stmf_teardown_itl_kstats(ks_itl);
3747 avl_remove(&stmf_state.stmf_itl_kstat_list, ks_itl);
3748 kmem_free(ks_itl, sizeof (stmf_i_itl_kstat_t));
3749 }
3750 }
3751 }
3752
3753 static void
3754 stmf_delete_itl_kstat_by_guid(char *guid)
3755 {
3756 stmf_i_itl_kstat_t *ks_itl, *next;
3757
3758 ASSERT(mutex_owned(&stmf_state.stmf_lock));
3759 ks_itl = avl_first(&stmf_state.stmf_itl_kstat_list);
3760 for (; ks_itl != NULL; ks_itl = next) {
3761 next = AVL_NEXT(&stmf_state.stmf_itl_kstat_list, ks_itl);
3762 if (strcmp(ks_itl->iitl_kstat_guid, guid) == 0) {
3763 stmf_teardown_itl_kstats(ks_itl);
3764 avl_remove(&stmf_state.stmf_itl_kstat_list, ks_itl);
3765 kmem_free(ks_itl, sizeof (stmf_i_itl_kstat_t));
3766 }
3767 }
3768 }
3769
3770 static stmf_i_itl_kstat_t *
3771 stmf_itl_kstat_create(stmf_itl_data_t *itl, char *nm,
3772 scsi_devid_desc_t *lport, scsi_devid_desc_t *lun)
3773 {
3774 stmf_i_itl_kstat_t *ks_itl;
3775 int i, len;
3776
3777 ASSERT(mutex_owned(&stmf_state.stmf_lock));
3778 if ((ks_itl = stmf_itl_kstat_lookup(nm)) != NULL)
3779 return (ks_itl);
3780
3781 len = sizeof (stmf_i_itl_kstat_t);
3782 ks_itl = kmem_zalloc(len, KM_NOSLEEP);
3783 if (ks_itl == NULL)
3784 return (NULL);
3785
3786 (void) strcpy(ks_itl->iitl_kstat_nm, nm);
3787 bcopy(lport->ident, ks_itl->iitl_kstat_lport, lport->ident_length);
3788 ks_itl->iitl_kstat_lport[lport->ident_length] = '\0';
3789 for (i = 0; i < STMF_GUID_INPUT / 2; i++) {
3790 (void) sprintf(&ks_itl->iitl_kstat_guid[i * 2], "%02x",
3791 lun->ident[i]);
3792 }
3793 ks_itl->iitl_kstat_strbuf = itl->itl_kstat_strbuf;
3794 ks_itl->iitl_kstat_strbuflen = itl->itl_kstat_strbuflen;
3795 ks_itl->iitl_kstat_info = itl->itl_kstat_info;
3796 ks_itl->iitl_kstat_taskq = itl->itl_kstat_taskq;
3797 ks_itl->iitl_kstat_lu_xfer = itl->itl_kstat_lu_xfer;
3798 ks_itl->iitl_kstat_lport_xfer = itl->itl_kstat_lport_xfer;
3799 avl_add(&stmf_state.stmf_itl_kstat_list, ks_itl);
3800
3801 return (ks_itl);
3802 }
3803
3804 stmf_status_t
3805 stmf_setup_itl_kstats(stmf_itl_data_t *itl)
3806 {
3807 char ks_itl_id[32];
3808 char ks_nm[KSTAT_STRLEN];
3809 char ks_itl_nm[KSTAT_STRLEN];
3810 stmf_kstat_itl_info_t *ks_itl;
3811 stmf_scsi_session_t *ss;
3812 stmf_i_scsi_session_t *iss;
3813 stmf_i_local_port_t *ilport;
3814 char *strbuf;
3815 int id, len, i;
3816 char *rport_alias;
3817 char *lport_alias;
3818 char *lu_alias;
3819 stmf_i_itl_kstat_t *tmp_kstat;
3820
3821 /*
3822 * Allocate enough memory in the ITL to hold the relevant
3823 * identifiers.
3824 * rport and lport identifiers come from the stmf_scsi_session_t.
3825 * ident might not be null terminated.
3826 */
3827 ss = itl->itl_session->iss_ss;
3828 iss = ss->ss_stmf_private;
3829 ilport = ss->ss_lport->lport_stmf_private;
3830 (void) snprintf(ks_itl_id, 32, "%d.%d.%d",
3831 iss->iss_irport->irport_instance, ilport->ilport_instance,
3832 itl->itl_lun);
3833
3834 (void) snprintf(ks_itl_nm, KSTAT_STRLEN, "itl_%s", ks_itl_id);
3835 /*
3836 * let's verify this itl_kstat already exist
3837 */
3838 if ((tmp_kstat = stmf_itl_kstat_lookup(ks_itl_nm)) != NULL) {
3839 itl->itl_kstat_strbuf = tmp_kstat->iitl_kstat_strbuf;
3840 itl->itl_kstat_strbuflen = tmp_kstat->iitl_kstat_strbuflen;
3841 itl->itl_kstat_info = tmp_kstat->iitl_kstat_info;
3842 itl->itl_kstat_taskq = tmp_kstat->iitl_kstat_taskq;
3843 itl->itl_kstat_lu_xfer = tmp_kstat->iitl_kstat_lu_xfer;
3844 itl->itl_kstat_lport_xfer = tmp_kstat->iitl_kstat_lport_xfer;
3845 return (STMF_SUCCESS);
3846 }
3847
3848 /* New itl_kstat */
3849 rport_alias = (ss->ss_rport_alias == NULL) ?
3850 "" : ss->ss_rport_alias;
3851 lport_alias = (ss->ss_lport->lport_alias == NULL) ?
3852 "" : ss->ss_lport->lport_alias;
3853 lu_alias = (itl->itl_ilu->ilu_lu->lu_alias == NULL) ?
3854 "" : itl->itl_ilu->ilu_lu->lu_alias;
3855
3856 itl->itl_kstat_strbuflen = (ss->ss_rport_id->ident_length + 1) +
3857 (strnlen(rport_alias, MAX_ALIAS) + 1) +
3858 (ss->ss_lport->lport_id->ident_length + 1) +
3859 (strnlen(lport_alias, MAX_ALIAS) + 1) +
3860 (STMF_GUID_INPUT + 1) +
3861 (strnlen(lu_alias, MAX_ALIAS) + 1) +
3862 MAX_PROTO_STR_LEN;
3863 itl->itl_kstat_strbuf = kmem_zalloc(itl->itl_kstat_strbuflen,
3864 KM_NOSLEEP);
3865 if (itl->itl_kstat_strbuf == NULL) {
3866 return (STMF_ALLOC_FAILURE);
3867 }
3868
3869 ks_itl = (stmf_kstat_itl_info_t *)kmem_zalloc(sizeof (*ks_itl),
3870 KM_NOSLEEP);
3871 if (ks_itl == NULL) {
3872 kmem_free(itl->itl_kstat_strbuf, itl->itl_kstat_strbuflen);
3873 return (STMF_ALLOC_FAILURE);
3874 }
3875
3876 if ((itl->itl_kstat_info = kstat_create(STMF_MODULE_NAME,
3877 0, ks_itl_nm, "misc", KSTAT_TYPE_NAMED,
3878 sizeof (stmf_kstat_itl_info_t) / sizeof (kstat_named_t),
3879 KSTAT_FLAG_VIRTUAL)) == NULL) {
3880 goto itl_kstat_cleanup;
3881 }
3882
3883 itl->itl_kstat_info->ks_data_size += itl->itl_kstat_strbuflen;
3884 itl->itl_kstat_info->ks_data = ks_itl;
3885
3886 kstat_named_init(&ks_itl->i_rport_name, "rport-name",
3887 KSTAT_DATA_STRING);
3888 kstat_named_init(&ks_itl->i_rport_alias, "rport-alias",
3889 KSTAT_DATA_STRING);
3890 kstat_named_init(&ks_itl->i_lport_name, "lport-name",
3891 KSTAT_DATA_STRING);
3892 kstat_named_init(&ks_itl->i_lport_alias, "lport-alias",
3893 KSTAT_DATA_STRING);
3894 kstat_named_init(&ks_itl->i_protocol, "protocol",
3895 KSTAT_DATA_STRING);
3896 kstat_named_init(&ks_itl->i_lu_guid, "lu-guid",
3897 KSTAT_DATA_STRING);
3898 kstat_named_init(&ks_itl->i_lu_alias, "lu-alias",
3899 KSTAT_DATA_STRING);
3900 kstat_named_init(&ks_itl->i_lu_number, "lu-number",
3901 KSTAT_DATA_UINT64);
3902 kstat_named_init(&ks_itl->i_task_waitq_elapsed, "task-waitq-elapsed",
3903 KSTAT_DATA_UINT64);
3904 kstat_named_init(&ks_itl->i_task_read_elapsed, "task-read-elapsed",
3905 KSTAT_DATA_UINT64);
3906 kstat_named_init(&ks_itl->i_task_write_elapsed, "task-write-elapsed",
3907 KSTAT_DATA_UINT64);
3908 kstat_named_init(&ks_itl->i_lu_read_elapsed, "lu-read-elapsed",
3909 KSTAT_DATA_UINT64);
3910 kstat_named_init(&ks_itl->i_lu_write_elapsed, "lu-write-elapsed",
3911 KSTAT_DATA_UINT64);
3912 kstat_named_init(&ks_itl->i_lport_read_elapsed, "lport-read-elapsed",
3913 KSTAT_DATA_UINT64);
3914 kstat_named_init(&ks_itl->i_lport_write_elapsed, "lport-write-elapsed",
3915 KSTAT_DATA_UINT64);
3916
3917 strbuf = itl->itl_kstat_strbuf;
3918
3919 /* Rport */
3920 len = ss->ss_rport_id->ident_length;
3921 bcopy(ss->ss_rport_id->ident, strbuf, len);
3922 strbuf += len;
3923 *strbuf = '\0';
3924 kstat_named_setstr(&ks_itl->i_rport_name, strbuf - len);
3925 strbuf++;
3926
3927 len = strnlen(rport_alias, MAX_ALIAS);
3928 (void) strncpy(strbuf, rport_alias, len + 1);
3929 kstat_named_setstr(&ks_itl->i_rport_alias, strbuf);
3930 strbuf += len + 1;
3931
3932 /* Lport */
3933 len = ss->ss_lport->lport_id->ident_length;
3934 bcopy(ss->ss_lport->lport_id->ident, strbuf, len);
3935 strbuf += len;
3936 *strbuf = '\0';
3937 kstat_named_setstr(&ks_itl->i_lport_name, strbuf - len);
3938 strbuf++;
3939
3940 len = strnlen(lport_alias, MAX_ALIAS);
3941 (void) strncpy(strbuf, lport_alias, len + 1);
3942 kstat_named_setstr(&ks_itl->i_lport_alias, strbuf);
3943 strbuf += len + 1;
3944
3945 id = (ss->ss_lport->lport_id->protocol_id > PROTOCOL_ANY) ?
3946 PROTOCOL_ANY : ss->ss_lport->lport_id->protocol_id;
3947 kstat_named_setstr(&ks_itl->i_protocol, protocol_ident[id]);
3948
3949 /* LU */
3950 for (i = 0; i < STMF_GUID_INPUT / 2; i++) {
3951 (void) sprintf(&strbuf[i * 2], "%02x",
3952 itl->itl_ilu->ilu_lu->lu_id->ident[i]);
3953 }
3954 kstat_named_setstr(&ks_itl->i_lu_guid, strbuf);
3955 strbuf += STMF_GUID_INPUT + 1;
3956
3957 len = strnlen(lu_alias, MAX_ALIAS);
3958 (void) strncpy(strbuf, lu_alias, len + 1);
3959 kstat_named_setstr(&ks_itl->i_lu_alias, strbuf);
3960 strbuf += len + 1;
3961
3962 ks_itl->i_lu_number.value.ui64 = itl->itl_lun;
3963
3964 /* Now create the I/O kstats */
3965 (void) snprintf(ks_nm, KSTAT_STRLEN, "itl_tasks_%s", ks_itl_id);
3966 if ((itl->itl_kstat_taskq = kstat_create(STMF_MODULE_NAME, 0,
3967 ks_nm, "io", KSTAT_TYPE_IO, 1, 0)) == NULL) {
3968 goto itl_kstat_cleanup;
3969 }
3970
3971 (void) snprintf(ks_nm, KSTAT_STRLEN, "itl_lu_%s", ks_itl_id);
3972 if ((itl->itl_kstat_lu_xfer = kstat_create(STMF_MODULE_NAME, 0,
3973 ks_nm, "io", KSTAT_TYPE_IO, 1, 0)) == NULL) {
3974 goto itl_kstat_cleanup;
3975 }
3976
3977 (void) snprintf(ks_nm, KSTAT_STRLEN, "itl_lport_%s", ks_itl_id);
3978 if ((itl->itl_kstat_lport_xfer = kstat_create(STMF_MODULE_NAME, 0,
3979 ks_nm, "io", KSTAT_TYPE_IO, 1, 0)) == NULL) {
3980 goto itl_kstat_cleanup;
3981 }
3982
3983 /* Install all the kstats */
3984 kstat_install(itl->itl_kstat_info);
3985 kstat_install(itl->itl_kstat_taskq);
3986 kstat_install(itl->itl_kstat_lu_xfer);
3987 kstat_install(itl->itl_kstat_lport_xfer);
3988
3989 /* Add new itl_kstat to stmf_itl_kstat_list */
3990 if (stmf_itl_kstat_create(itl, ks_itl_nm, ss->ss_lport->lport_id,
3991 itl->itl_ilu->ilu_lu->lu_id) != NULL)
3992 return (STMF_SUCCESS);
3993
3994 itl_kstat_cleanup:
3995 if (itl->itl_kstat_taskq)
3996 kstat_delete(itl->itl_kstat_taskq);
3997 if (itl->itl_kstat_lu_xfer)
3998 kstat_delete(itl->itl_kstat_lu_xfer);
3999 if (itl->itl_kstat_lport_xfer)
4000 kstat_delete(itl->itl_kstat_lport_xfer);
4001 if (itl->itl_kstat_info)
4002 kstat_delete(itl->itl_kstat_info);
4003 kmem_free(ks_itl, sizeof (*ks_itl));
4004 kmem_free(itl->itl_kstat_strbuf, itl->itl_kstat_strbuflen);
4005 cmn_err(CE_WARN, "STMF: kstat_create itl failed");
4006 return (STMF_ALLOC_FAILURE);
4007 }
4008
4009 static void
4010 stmf_teardown_itl_kstats(stmf_i_itl_kstat_t *ks)
4011 {
4012 kstat_delete(ks->iitl_kstat_lport_xfer);
4013 kstat_delete(ks->iitl_kstat_lu_xfer);
4014 kstat_delete(ks->iitl_kstat_taskq);
4015 kmem_free(ks->iitl_kstat_info->ks_data, sizeof (stmf_kstat_itl_info_t));
4016 kstat_delete(ks->iitl_kstat_info);
4017 kmem_free(ks->iitl_kstat_strbuf, ks->iitl_kstat_strbuflen);
4018 }
4019
4020 void
4021 stmf_release_itl_handle(stmf_lu_t *lu, stmf_itl_data_t *itl)
4022 {
4023 stmf_itl_data_t **itlpp;
4024 stmf_i_lu_t *ilu;
4025
4026 ASSERT(itl->itl_flags & STMF_ITL_BEING_TERMINATED);
4027
4028 ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
4029 mutex_enter(&ilu->ilu_task_lock);
4030 for (itlpp = &ilu->ilu_itl_list; (*itlpp) != NULL;
4031 itlpp = &(*itlpp)->itl_next) {
4032 if ((*itlpp) == itl)
4033 break;
4034 }
4035 ASSERT((*itlpp) != NULL);
4036 *itlpp = itl->itl_next;
4037 mutex_exit(&ilu->ilu_task_lock);
4038 lu->lu_abort(lu, STMF_LU_ITL_HANDLE_REMOVED, itl->itl_handle,
4039 (uint32_t)itl->itl_hdlrm_reason);
4043
4044 stmf_status_t
4045 stmf_register_itl_handle(stmf_lu_t *lu, uint8_t *lun,
4046 stmf_scsi_session_t *ss, uint64_t session_id, void *itl_handle)
4047 {
4048 stmf_itl_data_t *itl;
4049 stmf_i_scsi_session_t *iss;
4050 stmf_lun_map_ent_t *lun_map_ent;
4051 stmf_i_lu_t *ilu;
4052 uint16_t n;
4053
4054 ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
4055 if (ss == NULL) {
4056 iss = stmf_session_id_to_issptr(session_id, 1);
4057 if (iss == NULL)
4058 return (STMF_NOT_FOUND);
4059 } else {
4060 iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private;
4061 }
4062
4063 /*
4064 * Acquire stmf_lock for stmf_itl_kstat_lookup.
4065 */
4066 mutex_enter(&stmf_state.stmf_lock);
4067 rw_enter(iss->iss_lockp, RW_WRITER);
4068 n = ((uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8));
4069 lun_map_ent = (stmf_lun_map_ent_t *)
4070 stmf_get_ent_from_map(iss->iss_sm, n);
4071 if ((lun_map_ent == NULL) || (lun_map_ent->ent_lu != lu)) {
4072 rw_exit(iss->iss_lockp);
4073 mutex_exit(&stmf_state.stmf_lock);
4074 return (STMF_NOT_FOUND);
4075 }
4076 if (lun_map_ent->ent_itl_datap != NULL) {
4077 rw_exit(iss->iss_lockp);
4078 mutex_exit(&stmf_state.stmf_lock);
4079 return (STMF_ALREADY);
4080 }
4081
4082 itl = (stmf_itl_data_t *)kmem_zalloc(sizeof (*itl), KM_NOSLEEP);
4083 if (itl == NULL) {
4084 rw_exit(iss->iss_lockp);
4085 mutex_exit(&stmf_state.stmf_lock);
4086 return (STMF_ALLOC_FAILURE);
4087 }
4088
4089 itl->itl_ilu = ilu;
4090 itl->itl_session = iss;
4091 itl->itl_counter = 1;
4092 itl->itl_lun = n;
4093 itl->itl_handle = itl_handle;
4094
4095 if (stmf_setup_itl_kstats(itl) != STMF_SUCCESS) {
4096 kmem_free(itl, sizeof (*itl));
4097 rw_exit(iss->iss_lockp);
4098 mutex_exit(&stmf_state.stmf_lock);
4099 return (STMF_ALLOC_FAILURE);
4100 }
4101
4102 mutex_enter(&ilu->ilu_task_lock);
4103 itl->itl_next = ilu->ilu_itl_list;
4104 ilu->ilu_itl_list = itl;
4105 mutex_exit(&ilu->ilu_task_lock);
4106 lun_map_ent->ent_itl_datap = itl;
4107 rw_exit(iss->iss_lockp);
4108 mutex_exit(&stmf_state.stmf_lock);
4109
4110 return (STMF_SUCCESS);
4111 }
4112
4113 void
4114 stmf_do_itl_dereg(stmf_lu_t *lu, stmf_itl_data_t *itl, uint8_t hdlrm_reason)
4115 {
4116 uint8_t old, new;
4117
4118 do {
4119 old = new = itl->itl_flags;
4120 if (old & STMF_ITL_BEING_TERMINATED)
4121 return;
4122 new |= STMF_ITL_BEING_TERMINATED;
4123 } while (atomic_cas_8(&itl->itl_flags, old, new) != old);
4124 itl->itl_hdlrm_reason = hdlrm_reason;
4125
4126 ASSERT(itl->itl_counter);
4127
4128 if (atomic_add_32_nv(&itl->itl_counter, -1))
4129 return;
4130
4131 drv_usecwait(10);
4132 if (itl->itl_counter)
4133 return;
4134
4135 stmf_release_itl_handle(lu, itl);
4136 }
4137
4138 stmf_status_t
4139 stmf_deregister_all_lu_itl_handles(stmf_lu_t *lu)
4140 {
4141 stmf_i_lu_t *ilu;
4142 stmf_i_local_port_t *ilport;
4143 stmf_i_scsi_session_t *iss;
4144 stmf_lun_map_t *lm;
4145 stmf_lun_map_ent_t *ent;
4146 uint32_t nmaps, nu;
4147 stmf_itl_data_t **itl_list;
4148 int i;
4149
4150 ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
4151
4152 dereg_itl_start:;
4153 nmaps = ilu->ilu_ref_cnt;
4154 if (nmaps == 0)
4185 }
4186 }
4187 } /* lun table for a session */
4188 } /* sessions */
4189 rw_exit(&ilport->ilport_lock);
4190 } /* ports */
4191
4192 dai_scan_done:
4193 mutex_exit(&stmf_state.stmf_lock);
4194
4195 for (i = 0; i < nu; i++) {
4196 stmf_do_itl_dereg(lu, itl_list[i],
4197 STMF_ITL_REASON_DEREG_REQUEST);
4198 }
4199 kmem_free(itl_list, nmaps * sizeof (stmf_itl_data_t *));
4200
4201 return (STMF_SUCCESS);
4202 }
4203
4204 stmf_status_t
4205 stmf_deregister_itl_handle(stmf_lu_t *lu, uint8_t *lun,
4206 stmf_scsi_session_t *ss, uint64_t session_id, void *itl_handle)
4207 {
4208 stmf_i_scsi_session_t *iss;
4209 stmf_itl_data_t *itl;
4210 stmf_lun_map_ent_t *ent;
4211 stmf_lun_map_t *lm;
4212 int i;
4213 uint16_t n;
4214
4215 if (ss == NULL) {
4216 if (session_id == STMF_SESSION_ID_NONE)
4217 return (STMF_INVALID_ARG);
4218 iss = stmf_session_id_to_issptr(session_id, 1);
4219 if (iss == NULL)
4220 return (STMF_NOT_FOUND);
4221 } else {
4222 iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private;
4223 rw_enter(iss->iss_lockp, RW_WRITER);
4224 }
4225 lm = iss->iss_sm;
4226 if (lm == NULL) {
4227 rw_exit(iss->iss_lockp);
4228 return (STMF_NOT_FOUND);
4229 }
4230
4231 if (lun) {
4232 n = ((uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8));
4233 ent = (stmf_lun_map_ent_t *)
4234 stmf_get_ent_from_map(iss->iss_sm, n);
4235 } else {
4236 if (itl_handle == NULL) {
4237 rw_exit(iss->iss_lockp);
4238 return (STMF_INVALID_ARG);
4239 }
4240 ent = NULL;
4241 for (i = 0; i < lm->lm_nentries; i++) {
4242 if (lm->lm_plus[i] == NULL)
4243 continue;
4244 ent = (stmf_lun_map_ent_t *)lm->lm_plus[i];
4245 if (ent->ent_itl_datap &&
4246 (ent->ent_itl_datap->itl_handle == itl_handle)) {
4247 break;
4248 }
4249 }
4250 }
4251 if ((ent == NULL) || (ent->ent_lu != lu) ||
4252 (ent->ent_itl_datap == NULL)) {
4253 rw_exit(iss->iss_lockp);
4254 return (STMF_NOT_FOUND);
4255 }
4256 itl = ent->ent_itl_datap;
4257 ent->ent_itl_datap = NULL;
4258 rw_exit(iss->iss_lockp);
4259 stmf_do_itl_dereg(lu, itl, STMF_ITL_REASON_DEREG_REQUEST);
4260
4261 return (STMF_SUCCESS);
4262 }
4263
4264 stmf_status_t
4265 stmf_get_itl_handle(stmf_lu_t *lu, uint8_t *lun, stmf_scsi_session_t *ss,
4266 uint64_t session_id, void **itl_handle_retp)
4267 {
4268 stmf_i_scsi_session_t *iss;
4269 stmf_lun_map_ent_t *ent;
4270 stmf_lun_map_t *lm;
4271 stmf_status_t ret;
4272 int i;
4273 uint16_t n;
4274
4275 if (ss == NULL) {
4276 iss = stmf_session_id_to_issptr(session_id, 1);
4277 if (iss == NULL)
4278 return (STMF_NOT_FOUND);
4279 } else {
4280 iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private;
4281 rw_enter(iss->iss_lockp, RW_WRITER);
4282 }
4283
4284 ent = NULL;
4430 */
4431 if (cdb_length_in >= 16)
4432 cdb_length = cdb_length_in + 7;
4433 else
4434 cdb_length = 16 + 7;
4435 iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private;
4436 luNbr = ((uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8));
4437 rw_enter(iss->iss_lockp, RW_READER);
4438 lun_map_ent =
4439 (stmf_lun_map_ent_t *)stmf_get_ent_from_map(iss->iss_sm, luNbr);
4440 if (!lun_map_ent) {
4441 lu = dlun0;
4442 } else {
4443 lu = lun_map_ent->ent_lu;
4444 }
4445 ilu = lu->lu_stmf_private;
4446 if (ilu->ilu_flags & ILU_RESET_ACTIVE) {
4447 rw_exit(iss->iss_lockp);
4448 return (NULL);
4449 }
4450 do {
4451 if (ilu->ilu_free_tasks == NULL) {
4452 new_task = 1;
4453 break;
4454 }
4455 mutex_enter(&ilu->ilu_task_lock);
4456 for (ppitask = &ilu->ilu_free_tasks; (*ppitask != NULL) &&
4457 ((*ppitask)->itask_cdb_buf_size < cdb_length);
4458 ppitask = &((*ppitask)->itask_lu_free_next))
4459 ;
4460 if (*ppitask) {
4461 itask = *ppitask;
4462 *ppitask = (*ppitask)->itask_lu_free_next;
4463 ilu->ilu_ntasks_free--;
4464 if (ilu->ilu_ntasks_free < ilu->ilu_ntasks_min_free)
4465 ilu->ilu_ntasks_min_free = ilu->ilu_ntasks_free;
4466 } else {
4467 new_task = 1;
4468 }
4469 mutex_exit(&ilu->ilu_task_lock);
4558 }
4559
4560 rw_exit(iss->iss_lockp);
4561 return (task);
4562 }
4563
4564 static void
4565 stmf_task_lu_free(scsi_task_t *task, stmf_i_scsi_session_t *iss)
4566 {
4567 stmf_i_scsi_task_t *itask =
4568 (stmf_i_scsi_task_t *)task->task_stmf_private;
4569 stmf_i_lu_t *ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
4570
4571 ASSERT(rw_lock_held(iss->iss_lockp));
4572 itask->itask_flags = ITASK_IN_FREE_LIST;
4573 itask->itask_proxy_msg_id = 0;
4574 mutex_enter(&ilu->ilu_task_lock);
4575 itask->itask_lu_free_next = ilu->ilu_free_tasks;
4576 ilu->ilu_free_tasks = itask;
4577 ilu->ilu_ntasks_free++;
4578 mutex_exit(&ilu->ilu_task_lock);
4579 atomic_add_32(itask->itask_ilu_task_cntr, -1);
4580 }
4581
4582 void
4583 stmf_task_lu_check_freelist(stmf_i_lu_t *ilu)
4584 {
4585 uint32_t num_to_release, ndx;
4586 stmf_i_scsi_task_t *itask;
4587 stmf_lu_t *lu = ilu->ilu_lu;
4588
4589 ASSERT(ilu->ilu_ntasks_min_free <= ilu->ilu_ntasks_free);
4590
4591 /* free half of the minimal free of the free tasks */
4592 num_to_release = (ilu->ilu_ntasks_min_free + 1) / 2;
4593 if (!num_to_release) {
4594 return;
4595 }
4596 for (ndx = 0; ndx < num_to_release; ndx++) {
4597 mutex_enter(&ilu->ilu_task_lock);
6074 }
6075
6076 static uint16_t stmf_lu_id_gen_number = 0;
6077
6078 stmf_status_t
6079 stmf_scsilib_uniq_lu_id(uint32_t company_id, scsi_devid_desc_t *lu_id)
6080 {
6081 return (stmf_scsilib_uniq_lu_id2(company_id, 0, lu_id));
6082 }
6083
6084 stmf_status_t
6085 stmf_scsilib_uniq_lu_id2(uint32_t company_id, uint32_t host_id,
6086 scsi_devid_desc_t *lu_id)
6087 {
6088 uint8_t *p;
6089 struct timeval32 timestamp32;
6090 uint32_t *t = (uint32_t *)×tamp32;
6091 struct ether_addr mac;
6092 uint8_t *e = (uint8_t *)&mac;
6093 int hid = (int)host_id;
6094
6095 if (company_id == COMPANY_ID_NONE)
6096 company_id = COMPANY_ID_SUN;
6097
6098 if (lu_id->ident_length != 0x10)
6099 return (STMF_INVALID_ARG);
6100
6101 p = (uint8_t *)lu_id;
6102
6103 atomic_add_16(&stmf_lu_id_gen_number, 1);
6104
6105 p[0] = 0xf1; p[1] = 3; p[2] = 0; p[3] = 0x10;
6106 p[4] = ((company_id >> 20) & 0xf) | 0x60;
6107 p[5] = (company_id >> 12) & 0xff;
6108 p[6] = (company_id >> 4) & 0xff;
6109 p[7] = (company_id << 4) & 0xf0;
6110 if (hid == 0 && !localetheraddr((struct ether_addr *)NULL, &mac)) {
6111 hid = BE_32((int)zone_get_hostid(NULL));
6112 }
6113 if (hid != 0) {
6114 e[0] = (hid >> 24) & 0xff;
6115 e[1] = (hid >> 16) & 0xff;
6116 e[2] = (hid >> 8) & 0xff;
6117 e[3] = hid & 0xff;
6118 e[4] = e[5] = 0;
6119 }
6120 bcopy(e, p+8, 6);
6121 uniqtime32(×tamp32);
6122 *t = BE_32(*t);
6123 bcopy(t, p+14, 4);
6124 p[18] = (stmf_lu_id_gen_number >> 8) & 0xff;
6125 p[19] = stmf_lu_id_gen_number & 0xff;
6126
6127 return (STMF_SUCCESS);
6128 }
6129
6130 /*
6131 * saa is sense key, ASC, ASCQ
6132 */
6133 void
6134 stmf_scsilib_send_status(scsi_task_t *task, uint8_t st, uint32_t saa)
6135 {
6136 uint8_t sd[18];
6137 task->task_scsi_status = st;
6138 if (st == 2) {
6139 bzero(sd, 18);
6140 sd[0] = 0x70;
6141 sd[2] = (saa >> 16) & 0xf;
6142 sd[7] = 10;
6143 sd[12] = (saa >> 8) & 0xff;
6144 sd[13] = saa & 0xff;
6145 task->task_sense_data = sd;
7527 ilport->ilport_lport, eventid, arg, flags);
7528 }
7529 }
7530
7531 /*
7532 * With the possibility of having multiple itl sessions pointing to the
7533 * same itl_kstat_info, the ilu_kstat_lock mutex is used to synchronize
7534 * the kstat update of the ilu_kstat_io, itl_kstat_taskq and itl_kstat_lu_xfer
7535 * statistics.
7536 */
7537 void
7538 stmf_itl_task_start(stmf_i_scsi_task_t *itask)
7539 {
7540 stmf_itl_data_t *itl = itask->itask_itl_datap;
7541 scsi_task_t *task = itask->itask_task;
7542 stmf_i_lu_t *ilu;
7543
7544 if (itl == NULL || task->task_lu == dlun0)
7545 return;
7546 ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
7547 mutex_enter(ilu->ilu_kstat_io->ks_lock);
7548 itask->itask_start_timestamp = gethrtime();
7549 kstat_waitq_enter(KSTAT_IO_PTR(itl->itl_kstat_taskq));
7550 stmf_update_kstat_lu_q(itask->itask_task, kstat_waitq_enter);
7551 mutex_exit(ilu->ilu_kstat_io->ks_lock);
7552
7553 stmf_update_kstat_lport_q(itask->itask_task, kstat_waitq_enter);
7554 }
7555
7556 void
7557 stmf_itl_lu_new_task(stmf_i_scsi_task_t *itask)
7558 {
7559 stmf_itl_data_t *itl = itask->itask_itl_datap;
7560 scsi_task_t *task = itask->itask_task;
7561 stmf_i_lu_t *ilu;
7562
7563 if (itl == NULL || task->task_lu == dlun0)
7564 return;
7565 ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
7566 mutex_enter(ilu->ilu_kstat_io->ks_lock);
7567 kstat_waitq_to_runq(KSTAT_IO_PTR(itl->itl_kstat_taskq));
7568 stmf_update_kstat_lu_q(itask->itask_task, kstat_waitq_to_runq);
7569 mutex_exit(ilu->ilu_kstat_io->ks_lock);
7570
7571 stmf_update_kstat_lport_q(itask->itask_task, kstat_waitq_to_runq);
7572 }
7573
7574 void
7575 stmf_itl_task_done(stmf_i_scsi_task_t *itask)
7576 {
7577 stmf_itl_data_t *itl = itask->itask_itl_datap;
7578 scsi_task_t *task = itask->itask_task;
7579 kstat_io_t *kip;
7580 hrtime_t elapsed_time;
7581 stmf_kstat_itl_info_t *itli;
7582 stmf_i_lu_t *ilu;
7583
7584 if (itl == NULL || task->task_lu == dlun0)
7585 return;
7586 ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
7587
7588 mutex_enter(ilu->ilu_kstat_io->ks_lock);
7589 itli = (stmf_kstat_itl_info_t *)KSTAT_NAMED_PTR(itl->itl_kstat_info);
7590 kip = KSTAT_IO_PTR(itl->itl_kstat_taskq);
7591
7592 itli->i_task_waitq_elapsed.value.ui64 += itask->itask_waitq_time;
7593
7594 itask->itask_done_timestamp = gethrtime();
7595 elapsed_time =
7596 itask->itask_done_timestamp - itask->itask_start_timestamp;
7597
7598 if (task->task_flags & TF_READ_DATA) {
7599 kip->reads++;
7600 kip->nread += itask->itask_read_xfer;
7601 itli->i_task_read_elapsed.value.ui64 += elapsed_time;
7602 itli->i_lu_read_elapsed.value.ui64 +=
7603 itask->itask_lu_read_time;
7604 itli->i_lport_read_elapsed.value.ui64 +=
7605 itask->itask_lport_read_time;
7606 }
7607
7608 if (task->task_flags & TF_WRITE_DATA) {
7609 kip->writes++;
7610 kip->nwritten += itask->itask_write_xfer;
7611 itli->i_task_write_elapsed.value.ui64 += elapsed_time;
7612 itli->i_lu_write_elapsed.value.ui64 +=
7613 itask->itask_lu_write_time;
7614 itli->i_lport_write_elapsed.value.ui64 +=
7615 itask->itask_lport_write_time;
7616 }
7617
7618 if (itask->itask_flags & ITASK_KSTAT_IN_RUNQ) {
7619 kstat_runq_exit(kip);
7620 stmf_update_kstat_lu_q(task, kstat_runq_exit);
7621 mutex_exit(ilu->ilu_kstat_io->ks_lock);
7622 stmf_update_kstat_lport_q(task, kstat_runq_exit);
7623 } else {
7624 kstat_waitq_exit(kip);
7625 stmf_update_kstat_lu_q(task, kstat_waitq_exit);
7626 mutex_exit(ilu->ilu_kstat_io->ks_lock);
7627 stmf_update_kstat_lport_q(task, kstat_waitq_exit);
7628 }
7629 }
7630
7631 void
7632 stmf_lu_xfer_start(scsi_task_t *task)
7633 {
7634 stmf_i_scsi_task_t *itask = task->task_stmf_private;
7635 stmf_itl_data_t *itl = itask->itask_itl_datap;
7636 stmf_i_lu_t *ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
7637 kstat_io_t *kip;
7638
7639 if (itl == NULL || task->task_lu == dlun0)
7640 return;
7641
7642 kip = KSTAT_IO_PTR(itl->itl_kstat_lu_xfer);
7643 mutex_enter(ilu->ilu_kstat_io->ks_lock);
7644 kstat_runq_enter(kip);
7645 mutex_exit(ilu->ilu_kstat_io->ks_lock);
7646 }
7647
7648 void
7649 stmf_lu_xfer_done(scsi_task_t *task, boolean_t read, uint64_t xfer_bytes,
7650 hrtime_t elapsed_time)
7651 {
7652 stmf_i_scsi_task_t *itask = task->task_stmf_private;
7653 stmf_itl_data_t *itl = itask->itask_itl_datap;
7654 stmf_i_lu_t *ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
7655 kstat_io_t *kip;
7656
7657 if (itl == NULL || task->task_lu == dlun0)
7658 return;
7659
7660 if (read) {
7661 atomic_add_64((uint64_t *)&itask->itask_lu_read_time,
7662 elapsed_time);
7663 } else {
7664 atomic_add_64((uint64_t *)&itask->itask_lu_write_time,
7665 elapsed_time);
7666 }
7667
7668 kip = KSTAT_IO_PTR(itl->itl_kstat_lu_xfer);
7669 mutex_enter(ilu->ilu_kstat_io->ks_lock);
7670 kstat_runq_exit(kip);
7671 if (read) {
7672 kip->reads++;
7673 kip->nread += xfer_bytes;
7674 } else {
7675 kip->writes++;
7676 kip->nwritten += xfer_bytes;
7677 }
7678 mutex_exit(ilu->ilu_kstat_io->ks_lock);
7679 }
7680
7681 static void
7682 stmf_lport_xfer_start(stmf_i_scsi_task_t *itask, stmf_data_buf_t *dbuf)
7683 {
7684 stmf_itl_data_t *itl = itask->itask_itl_datap;
7685
7686 if (itl == NULL)
7687 return;
7688
7689 DTRACE_PROBE2(scsi__xfer__start, scsi_task_t *, itask->itask_task,
7690 stmf_data_buf_t *, dbuf);
7691
7692 dbuf->db_xfer_start_timestamp = gethrtime();
7693 }
7694
7695 static void
7696 stmf_lport_xfer_done(stmf_i_scsi_task_t *itask, stmf_data_buf_t *dbuf)
7697 {
7698 stmf_itl_data_t *itl = itask->itask_itl_datap;
7699 scsi_task_t *task;
7700 stmf_i_local_port_t *ilp;
7701 kstat_io_t *kip;
7702 hrtime_t elapsed_time;
7703 uint64_t xfer_size;
7704
7705 if (itl == NULL)
7706 return;
7707
7708 task = (scsi_task_t *)itask->itask_task;
7709 ilp = (stmf_i_local_port_t *)task->task_lport->lport_stmf_private;
7710 xfer_size = (dbuf->db_xfer_status == STMF_SUCCESS) ?
7711 dbuf->db_data_size : 0;
7712
7713 elapsed_time = gethrtime() - dbuf->db_xfer_start_timestamp;
7714 if (dbuf->db_flags & DB_DIRECTION_TO_RPORT) {
7715 atomic_add_64((uint64_t *)&itask->itask_lport_read_time,
7716 elapsed_time);
7717 atomic_add_64((uint64_t *)&itask->itask_read_xfer,
7718 xfer_size);
7719 } else {
7720 atomic_add_64((uint64_t *)&itask->itask_lport_write_time,
7721 elapsed_time);
7722 atomic_add_64((uint64_t *)&itask->itask_write_xfer,
7723 xfer_size);
7724 }
7725
7726 DTRACE_PROBE3(scsi__xfer__end, scsi_task_t *, itask->itask_task,
7727 stmf_data_buf_t *, dbuf, hrtime_t, elapsed_time);
7728
7729 kip = KSTAT_IO_PTR(itl->itl_kstat_lport_xfer);
7730 mutex_enter(ilp->ilport_kstat_io->ks_lock);
7731 if (dbuf->db_flags & DB_DIRECTION_TO_RPORT) {
7732 kip->reads++;
7733 kip->nread += xfer_size;
7734 } else {
7735 kip->writes++;
7736 kip->nwritten += xfer_size;
7737 }
7738 mutex_exit(ilp->ilport_kstat_io->ks_lock);
7739
7740 dbuf->db_xfer_start_timestamp = 0;
7741 }
7742
7743 void
7744 stmf_svc_init()
7745 {
7746 if (stmf_state.stmf_svc_flags & STMF_SVC_STARTED)
7747 return;
7748 stmf_state.stmf_svc_tailp = &stmf_state.stmf_svc_active;
7749 stmf_state.stmf_svc_taskq = ddi_taskq_create(0, "STMF_SVC_TASKQ", 1,
7750 TASKQ_DEFAULTPRI, 0);
7751 (void) ddi_taskq_dispatch(stmf_state.stmf_svc_taskq,
7752 stmf_svc, 0, DDI_SLEEP);
7753 }
7754
7755 stmf_status_t
7756 stmf_svc_fini()
7757 {
7758 uint32_t i;
7759
7821 /* Fallthrough */
7822 case STMF_CMD_LPORT_OFFLINE:
7823 mutex_exit(&stmf_state.stmf_lock);
7824 lport = (stmf_local_port_t *)req->svc_obj;
7825 lport->lport_ctl(lport, req->svc_cmd, &req->svc_info);
7826 break;
7827 case STMF_CMD_LU_ONLINE:
7828 mutex_exit(&stmf_state.stmf_lock);
7829 lu = (stmf_lu_t *)req->svc_obj;
7830 lu->lu_ctl(lu, req->svc_cmd, &req->svc_info);
7831 break;
7832 case STMF_CMD_LU_OFFLINE:
7833 /* Remove all mappings of this LU */
7834 stmf_session_lu_unmapall((stmf_lu_t *)req->svc_obj);
7835 /* Kill all the pending I/Os for this LU */
7836 mutex_exit(&stmf_state.stmf_lock);
7837 stmf_task_lu_killall((stmf_lu_t *)req->svc_obj, NULL,
7838 STMF_ABORTED);
7839 lu = (stmf_lu_t *)req->svc_obj;
7840 ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
7841 if (ilu->ilu_ntasks != ilu->ilu_ntasks_free)
7842 break;
7843 lu->lu_ctl(lu, req->svc_cmd, &req->svc_info);
7844 break;
7845 default:
7846 cmn_err(CE_PANIC, "stmf_svc: unknown cmd %d",
7847 req->svc_cmd);
7848 }
7849
7850 mutex_enter(&stmf_state.stmf_lock);
7851 }
7852
7853 stmf_state.stmf_svc_flags &= ~(STMF_SVC_STARTED | STMF_SVC_ACTIVE);
7854 mutex_exit(&stmf_state.stmf_lock);
7855 }
7856
7857 static void
7858 stmf_svc_timeout(struct stmf_svc_clocks *clks)
7859 {
7860 clock_t td;
7861 stmf_i_local_port_t *ilport, *next_ilport;
7862 stmf_i_scsi_session_t *iss;
7863
7864 ASSERT(mutex_owned(&stmf_state.stmf_lock));
7865
7866 td = drv_usectohz(20000);
7867
7868 /* Do timeouts */
7869 if (stmf_state.stmf_nlus &&
7974 ~ILPORT_SS_GOT_INITIAL_LUNS);
7975 /* drop the lock if we are holding it. */
7976 if (ilport_lock_held == 1)
7977 rw_exit(&ilport->ilport_lock);
7978
7979 /* Max 4 session at a time */
7980 if (stmf_level >= 4)
7981 break;
7982 }
7983
7984 if (stmf_level == 0)
7985 stmf_state.stmf_process_initial_luns = 0;
7986 }
7987
7988 stmf_state.stmf_svc_flags &= ~STMF_SVC_ACTIVE;
7989 (void) cv_reltimedwait(&stmf_state.stmf_cv,
7990 &stmf_state.stmf_lock, td, TR_CLOCK_TICK);
7991 stmf_state.stmf_svc_flags |= STMF_SVC_ACTIVE;
7992 }
7993
7994 void
7995 stmf_svc_queue(int cmd, void *obj, stmf_state_change_info_t *info)
7996 {
7997 stmf_svc_req_t *req;
7998 int s;
7999
8000 ASSERT(!mutex_owned(&stmf_state.stmf_lock));
8001 s = sizeof (stmf_svc_req_t);
8002 if (info->st_additional_info) {
8003 s += strlen(info->st_additional_info) + 1;
8004 }
8005 req = kmem_zalloc(s, KM_SLEEP);
8006
8007 req->svc_cmd = cmd;
8008 req->svc_obj = obj;
8009 req->svc_info.st_rflags = info->st_rflags;
8010 if (info->st_additional_info) {
8011 req->svc_info.st_additional_info = (char *)(GET_BYTE_OFFSET(req,
8012 sizeof (stmf_svc_req_t)));
8013 (void) strcpy(req->svc_info.st_additional_info,
|
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 /*
25 * Copyright 2012, Nexenta Systems, Inc. All rights reserved.
26 * Copyright (c) 2013 by Delphix. All rights reserved.
27 * Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
28 */
29
30 #include <sys/conf.h>
31 #include <sys/file.h>
32 #include <sys/ddi.h>
33 #include <sys/sunddi.h>
34 #include <sys/modctl.h>
35 #include <sys/scsi/scsi.h>
36 #include <sys/scsi/generic/persist.h>
37 #include <sys/scsi/impl/scsi_reset_notify.h>
38 #include <sys/disp.h>
39 #include <sys/byteorder.h>
40 #include <sys/atomic.h>
41 #include <sys/ethernet.h>
42 #include <sys/sdt.h>
43 #include <sys/nvpair.h>
44 #include <sys/zone.h>
45 #include <sys/id_space.h>
46
47 #include <sys/stmf.h>
50 #include <sys/stmf_ioctl.h>
51 #include <sys/pppt_ic_if.h>
52
53 #include "stmf_impl.h"
54 #include "lun_map.h"
55 #include "stmf_state.h"
56 #include "stmf_stats.h"
57
58 /*
59 * Lock order:
60 * stmf_state_lock --> ilport_lock/iss_lockp --> ilu_task_lock
61 */
62
63 static uint64_t stmf_session_counter = 0;
64 static uint16_t stmf_rtpid_counter = 0;
65 /* start messages at 1 */
66 static uint64_t stmf_proxy_msg_id = 1;
67 #define MSG_ID_TM_BIT 0x8000000000000000
68 #define ALIGNED_TO_8BYTE_BOUNDARY(i) (((i) + 7) & ~7)
69
70 /*
71 * When stmf_io_deadman_enabled is set to B_TRUE, we check that finishing up
72 * I/O operations on an offlining LU doesn't take longer than stmf_io_deadman
73 * seconds. If it does, we trigger a panic to inform the user of hung I/O
74 * blocking us for too long.
75 */
76 boolean_t stmf_io_deadman_enabled = B_TRUE;
77 int stmf_io_deadman = 1000; /* seconds */
78
79 struct stmf_svc_clocks;
80
81 static int stmf_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
82 static int stmf_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
83 static int stmf_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
84 void **result);
85 static int stmf_open(dev_t *devp, int flag, int otype, cred_t *credp);
86 static int stmf_close(dev_t dev, int flag, int otype, cred_t *credp);
87 static int stmf_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
88 cred_t *credp, int *rval);
89 static int stmf_get_stmf_state(stmf_state_desc_t *std);
90 static int stmf_set_stmf_state(stmf_state_desc_t *std);
91 static void stmf_abort_task_offline(scsi_task_t *task, int offline_lu,
92 char *info);
93 static int stmf_set_alua_state(stmf_alua_state_desc_t *alua_state);
94 static void stmf_get_alua_state(stmf_alua_state_desc_t *alua_state);
95
96 static void stmf_task_audit(stmf_i_scsi_task_t *itask,
97 task_audit_event_t te, uint32_t cmd_or_iof, stmf_data_buf_t *dbuf);
98
99 static boolean_t stmf_base16_str_to_binary(char *c, int dplen, uint8_t *dp);
100 static char stmf_ctoi(char c);
101 stmf_xfer_data_t *stmf_prepare_tpgs_data(uint8_t ilu_alua);
102 void stmf_svc_init();
103 stmf_status_t stmf_svc_fini();
104 void stmf_svc(void *arg);
105 static void stmf_wait_ilu_tasks_finish(stmf_i_lu_t *ilu);
106 void stmf_svc_queue(int cmd, void *obj, stmf_state_change_info_t *info);
107 static void stmf_svc_kill_obj_requests(void *obj);
108 static void stmf_svc_timeout(struct stmf_svc_clocks *);
109 void stmf_check_freetask();
110 void stmf_abort_target_reset(scsi_task_t *task);
111 stmf_status_t stmf_lun_reset_poll(stmf_lu_t *lu, struct scsi_task *task,
112 int target_reset);
113 void stmf_target_reset_poll(struct scsi_task *task);
114 void stmf_handle_lun_reset(scsi_task_t *task);
115 void stmf_handle_target_reset(scsi_task_t *task);
116 void stmf_xd_to_dbuf(stmf_data_buf_t *dbuf, int set_rel_off);
117 int stmf_load_ppd_ioctl(stmf_ppioctl_data_t *ppi, uint64_t *ppi_token,
118 uint32_t *err_ret);
119 int stmf_delete_ppd_ioctl(stmf_ppioctl_data_t *ppi);
120 int stmf_get_ppd_ioctl(stmf_ppioctl_data_t *ppi, stmf_ppioctl_data_t *ppi_out,
121 uint32_t *err_ret);
122 void stmf_delete_ppd(stmf_pp_data_t *ppd);
123 void stmf_delete_all_ppds();
124 void stmf_trace_clear();
125 void stmf_worker_init();
158 static void stmf_lport_xfer_start(stmf_i_scsi_task_t *itask,
159 stmf_data_buf_t *dbuf);
160 static void stmf_lport_xfer_done(stmf_i_scsi_task_t *itask,
161 stmf_data_buf_t *dbuf);
162
163 static void stmf_update_kstat_lu_q(scsi_task_t *, void());
164 static void stmf_update_kstat_lport_q(scsi_task_t *, void());
165 static void stmf_update_kstat_lu_io(scsi_task_t *, stmf_data_buf_t *);
166 static void stmf_update_kstat_lport_io(scsi_task_t *, stmf_data_buf_t *);
167
168 static int stmf_irport_compare(const void *void_irport1,
169 const void *void_irport2);
170 static stmf_i_remote_port_t *stmf_irport_create(scsi_devid_desc_t *rport_devid);
171 static void stmf_irport_destroy(stmf_i_remote_port_t *irport);
172 static stmf_i_remote_port_t *stmf_irport_register(
173 scsi_devid_desc_t *rport_devid);
174 static stmf_i_remote_port_t *stmf_irport_lookup_locked(
175 scsi_devid_desc_t *rport_devid);
176 static void stmf_irport_deregister(stmf_i_remote_port_t *irport);
177
178 extern struct mod_ops mod_driverops;
179
180 /* =====[ Tunables ]===== */
181 /* Internal tracing */
182 volatile int stmf_trace_on = 1;
183 volatile int stmf_trace_buf_size = (1 * 1024 * 1024);
184 /*
185 * The reason default task timeout is 75 is because we want the
186 * host to timeout 1st and mostly host timeout is 60 seconds.
187 */
188 volatile int stmf_default_task_timeout = 75;
189 /*
190 * Setting this to one means, you are responsible for config load and keeping
191 * things in sync with persistent database.
192 */
193 volatile int stmf_allow_modunload = 0;
194
195 volatile int stmf_max_nworkers = 256;
196 volatile int stmf_min_nworkers = 4;
197 volatile int stmf_worker_scale_down_delay = 20;
299 stmf_trace_buf = kmem_zalloc(stmf_trace_buf_size, KM_SLEEP);
300 trace_buf_size = stmf_trace_buf_size;
301 trace_buf_curndx = 0;
302 mutex_init(&trace_buf_lock, NULL, MUTEX_DRIVER, 0);
303 bzero(&stmf_state, sizeof (stmf_state_t));
304 /* STMF service is off by default */
305 stmf_state.stmf_service_running = 0;
306 /* default lu/lport states are online */
307 stmf_state.stmf_default_lu_state = STMF_STATE_ONLINE;
308 stmf_state.stmf_default_lport_state = STMF_STATE_ONLINE;
309 mutex_init(&stmf_state.stmf_lock, NULL, MUTEX_DRIVER, NULL);
310 cv_init(&stmf_state.stmf_cv, NULL, CV_DRIVER, NULL);
311 stmf_session_counter = (uint64_t)ddi_get_lbolt();
312 avl_create(&stmf_state.stmf_irportlist,
313 stmf_irport_compare, sizeof (stmf_i_remote_port_t),
314 offsetof(stmf_i_remote_port_t, irport_ln));
315 stmf_state.stmf_ilport_inst_space =
316 id_space_create("lport-instances", 0, MAX_ILPORT);
317 stmf_state.stmf_irport_inst_space =
318 id_space_create("rport-instances", 0, MAX_IRPORT);
319 stmf_view_init();
320 stmf_svc_init();
321 stmf_dlun_init();
322 return (ret);
323 }
324
325 int
326 _fini(void)
327 {
328 int ret;
329 stmf_i_remote_port_t *irport;
330 void *avl_dest_cookie = NULL;
331
332 if (stmf_state.stmf_service_running)
333 return (EBUSY);
334 if ((!stmf_allow_modunload) &&
335 (stmf_state.stmf_config_state != STMF_CONFIG_NONE)) {
336 return (EBUSY);
337 }
338 if (stmf_state.stmf_nlps || stmf_state.stmf_npps) {
339 return (EBUSY);
340 }
341 if (stmf_dlun_fini() != STMF_SUCCESS)
342 return (EBUSY);
343 if (stmf_worker_fini() != STMF_SUCCESS) {
344 stmf_dlun_init();
345 return (EBUSY);
346 }
347 if (stmf_svc_fini() != STMF_SUCCESS) {
348 stmf_dlun_init();
349 stmf_worker_init();
350 return (EBUSY);
351 }
352
353 ret = mod_remove(&modlinkage);
354 if (ret) {
355 stmf_svc_init();
356 stmf_dlun_init();
357 stmf_worker_init();
358 return (ret);
359 }
360
361 stmf_view_clear_config();
362
363 while ((irport = avl_destroy_nodes(&stmf_state.stmf_irportlist,
364 &avl_dest_cookie)) != NULL)
365 stmf_irport_destroy(irport);
366 avl_destroy(&stmf_state.stmf_irportlist);
367 id_space_destroy(stmf_state.stmf_ilport_inst_space);
368 id_space_destroy(stmf_state.stmf_irport_inst_space);
369
370 kmem_free(stmf_trace_buf, stmf_trace_buf_size);
371 mutex_destroy(&trace_buf_lock);
372 mutex_destroy(&stmf_state.stmf_lock);
373 cv_destroy(&stmf_state.stmf_cv);
374 return (ret);
375 }
376
377 int
378 _info(struct modinfo *modinfop)
379 {
380 return (mod_info(&modlinkage, modinfop));
381 }
382
383 /* ARGSUSED */
384 static int
385 stmf_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
386 {
387 switch (cmd) {
388 case DDI_INFO_DEVT2DEVINFO:
389 *result = stmf_state.stmf_dip;
1567 if (ilu->ilu_state != STMF_STATE_ONLINE)
1568 continue;
1569 (void) stmf_ctl(STMF_CMD_LU_OFFLINE, ilu->ilu_lu, &ssi);
1570 }
1571 mutex_enter(&stmf_state.stmf_lock);
1572 stmf_state.stmf_inventory_locked = 0;
1573 mutex_exit(&stmf_state.stmf_lock);
1574 return (0);
1575 }
1576
1577 static int
1578 stmf_get_stmf_state(stmf_state_desc_t *std)
1579 {
1580 mutex_enter(&stmf_state.stmf_lock);
1581 std->state = stmf_get_service_state();
1582 std->config_state = stmf_state.stmf_config_state;
1583 mutex_exit(&stmf_state.stmf_lock);
1584
1585 return (0);
1586 }
1587
1588 /*
1589 * handles registration message from pppt for a logical unit
1590 */
1591 stmf_status_t
1592 stmf_ic_lu_reg(stmf_ic_reg_dereg_lun_msg_t *msg, uint32_t type)
1593 {
1594 stmf_i_lu_provider_t *ilp;
1595 stmf_lu_provider_t *lp;
1596 mutex_enter(&stmf_state.stmf_lock);
1597 for (ilp = stmf_state.stmf_ilplist; ilp != NULL; ilp = ilp->ilp_next) {
1598 if (strcmp(msg->icrl_lu_provider_name,
1599 ilp->ilp_lp->lp_name) == 0) {
1600 lp = ilp->ilp_lp;
1601 mutex_exit(&stmf_state.stmf_lock);
1602 lp->lp_proxy_msg(msg->icrl_lun_id, msg->icrl_cb_arg,
1603 msg->icrl_cb_arg_len, type);
1604 return (STMF_SUCCESS);
1605 }
1606 }
1607 mutex_exit(&stmf_state.stmf_lock);
3035 luid = stmf_lookup_id(&stmf_state.stmf_luid_list,
3036 lu->lu_id->ident_length, lu->lu_id->ident);
3037 if (luid) {
3038 luid->id_pt_to_object = (void *)ilu;
3039 ilu->ilu_luid = luid;
3040 }
3041 ilu->ilu_alias = NULL;
3042
3043 ilu->ilu_next = stmf_state.stmf_ilulist;
3044 ilu->ilu_prev = NULL;
3045 if (ilu->ilu_next)
3046 ilu->ilu_next->ilu_prev = ilu;
3047 stmf_state.stmf_ilulist = ilu;
3048 stmf_state.stmf_nlus++;
3049 if (lu->lu_lp) {
3050 ((stmf_i_lu_provider_t *)
3051 (lu->lu_lp->lp_stmf_private))->ilp_nlus++;
3052 }
3053 ilu->ilu_cur_task_cntr = &ilu->ilu_task_cntr1;
3054 STMF_EVENT_ALLOC_HANDLE(ilu->ilu_event_hdl);
3055 cv_init(&ilu->ilu_offline_pending_cv, NULL, CV_DRIVER, NULL);
3056 stmf_create_kstat_lu(ilu);
3057 /*
3058 * register with proxy module if available and logical unit
3059 * is in active state
3060 */
3061 if (stmf_state.stmf_alua_state == 1 &&
3062 ilu->ilu_access == STMF_LU_ACTIVE) {
3063 stmf_ic_msg_status_t ic_ret = STMF_IC_MSG_SUCCESS;
3064 stmf_ic_msg_t *ic_reg_lun;
3065 if (lu->lu_lp && lu->lu_lp->lp_lpif_rev == LPIF_REV_2 &&
3066 lu->lu_lp->lp_alua_support) {
3067 ilu->ilu_alua = 1;
3068 /* allocate the register message */
3069 ic_reg_lun = ic_reg_lun_msg_alloc(p1,
3070 lu->lu_lp->lp_name, lu->lu_proxy_reg_arg_len,
3071 (uint8_t *)lu->lu_proxy_reg_arg, stmf_proxy_msg_id);
3072 /* send the message */
3073 if (ic_reg_lun) {
3074 ic_ret = ic_tx_msg(ic_reg_lun);
3075 if (ic_ret == STMF_IC_MSG_SUCCESS) {
3173 }
3174 if (ilu->ilu_luid) {
3175 ((stmf_id_data_t *)ilu->ilu_luid)->id_pt_to_object =
3176 NULL;
3177 ilu->ilu_luid = NULL;
3178 }
3179 STMF_EVENT_FREE_HANDLE(ilu->ilu_event_hdl);
3180 } else {
3181 mutex_exit(&stmf_state.stmf_lock);
3182 return (STMF_BUSY);
3183 }
3184 if (ilu->ilu_kstat_info) {
3185 kmem_free(ilu->ilu_kstat_info->ks_data,
3186 ilu->ilu_kstat_info->ks_data_size);
3187 kstat_delete(ilu->ilu_kstat_info);
3188 }
3189 if (ilu->ilu_kstat_io) {
3190 kstat_delete(ilu->ilu_kstat_io);
3191 mutex_destroy(&ilu->ilu_kstat_lock);
3192 }
3193 cv_destroy(&ilu->ilu_offline_pending_cv);
3194 mutex_exit(&stmf_state.stmf_lock);
3195 return (STMF_SUCCESS);
3196 }
3197
3198 void
3199 stmf_set_port_standby(stmf_local_port_t *lport, uint16_t rtpid)
3200 {
3201 stmf_i_local_port_t *ilport =
3202 (stmf_i_local_port_t *)lport->lport_stmf_private;
3203 ilport->ilport_rtpid = rtpid;
3204 ilport->ilport_standby = 1;
3205 }
3206
3207 void
3208 stmf_set_port_alua(stmf_local_port_t *lport)
3209 {
3210 stmf_i_local_port_t *ilport =
3211 (stmf_i_local_port_t *)lport->lport_stmf_private;
3212 ilport->ilport_alua = 1;
3213 }
3351 stmf_state.stmf_nlports--;
3352 if (lport->lport_pp) {
3353 ((stmf_i_port_provider_t *)
3354 (lport->lport_pp->pp_stmf_private))->ipp_npps--;
3355 }
3356 ilport->ilport_tg = NULL;
3357 STMF_EVENT_FREE_HANDLE(ilport->ilport_event_hdl);
3358 } else {
3359 mutex_exit(&stmf_state.stmf_lock);
3360 return (STMF_BUSY);
3361 }
3362 if (ilport->ilport_kstat_info) {
3363 kmem_free(ilport->ilport_kstat_info->ks_data,
3364 ilport->ilport_kstat_info->ks_data_size);
3365 kstat_delete(ilport->ilport_kstat_info);
3366 }
3367 if (ilport->ilport_kstat_io) {
3368 kstat_delete(ilport->ilport_kstat_io);
3369 mutex_destroy(&ilport->ilport_kstat_lock);
3370 }
3371 mutex_exit(&stmf_state.stmf_lock);
3372 return (STMF_SUCCESS);
3373 }
3374
3375 /*
3376 * Rport id/instance mappings remain valid until STMF is unloaded
3377 */
3378 static int
3379 stmf_irport_compare(const void *void_irport1, const void *void_irport2)
3380 {
3381 const stmf_i_remote_port_t *irport1 = void_irport1;
3382 const stmf_i_remote_port_t *irport2 = void_irport2;
3383 int result;
3384
3385 /* Sort by code set then ident */
3386 if (irport1->irport_id->code_set <
3387 irport2->irport_id->code_set) {
3388 return (-1);
3389 } else if (irport1->irport_id->code_set >
3390 irport2->irport_id->code_set) {
3679
3680 mutex_enter(&stmf_state.stmf_lock);
3681 for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
3682 ilport = ilport->ilport_next) {
3683 rw_enter(&ilport->ilport_lock, RW_WRITER);
3684 for (iss = ilport->ilport_ss_list; iss != NULL;
3685 iss = iss->iss_next) {
3686 if (iss->iss_ss->ss_session_id == session_id) {
3687 if (!stay_locked)
3688 rw_exit(&ilport->ilport_lock);
3689 mutex_exit(&stmf_state.stmf_lock);
3690 return (iss);
3691 }
3692 }
3693 rw_exit(&ilport->ilport_lock);
3694 }
3695 mutex_exit(&stmf_state.stmf_lock);
3696 return (NULL);
3697 }
3698
3699 void
3700 stmf_release_itl_handle(stmf_lu_t *lu, stmf_itl_data_t *itl)
3701 {
3702 stmf_itl_data_t **itlpp;
3703 stmf_i_lu_t *ilu;
3704
3705 ASSERT(itl->itl_flags & STMF_ITL_BEING_TERMINATED);
3706
3707 ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
3708 mutex_enter(&ilu->ilu_task_lock);
3709 for (itlpp = &ilu->ilu_itl_list; (*itlpp) != NULL;
3710 itlpp = &(*itlpp)->itl_next) {
3711 if ((*itlpp) == itl)
3712 break;
3713 }
3714 ASSERT((*itlpp) != NULL);
3715 *itlpp = itl->itl_next;
3716 mutex_exit(&ilu->ilu_task_lock);
3717 lu->lu_abort(lu, STMF_LU_ITL_HANDLE_REMOVED, itl->itl_handle,
3718 (uint32_t)itl->itl_hdlrm_reason);
3722
3723 stmf_status_t
3724 stmf_register_itl_handle(stmf_lu_t *lu, uint8_t *lun,
3725 stmf_scsi_session_t *ss, uint64_t session_id, void *itl_handle)
3726 {
3727 stmf_itl_data_t *itl;
3728 stmf_i_scsi_session_t *iss;
3729 stmf_lun_map_ent_t *lun_map_ent;
3730 stmf_i_lu_t *ilu;
3731 uint16_t n;
3732
3733 ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
3734 if (ss == NULL) {
3735 iss = stmf_session_id_to_issptr(session_id, 1);
3736 if (iss == NULL)
3737 return (STMF_NOT_FOUND);
3738 } else {
3739 iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private;
3740 }
3741
3742 mutex_enter(&stmf_state.stmf_lock);
3743 rw_enter(iss->iss_lockp, RW_WRITER);
3744 n = ((uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8));
3745 lun_map_ent = (stmf_lun_map_ent_t *)
3746 stmf_get_ent_from_map(iss->iss_sm, n);
3747 if ((lun_map_ent == NULL) || (lun_map_ent->ent_lu != lu)) {
3748 rw_exit(iss->iss_lockp);
3749 mutex_exit(&stmf_state.stmf_lock);
3750 return (STMF_NOT_FOUND);
3751 }
3752 if (lun_map_ent->ent_itl_datap != NULL) {
3753 rw_exit(iss->iss_lockp);
3754 mutex_exit(&stmf_state.stmf_lock);
3755 return (STMF_ALREADY);
3756 }
3757
3758 itl = (stmf_itl_data_t *)kmem_zalloc(sizeof (*itl), KM_NOSLEEP);
3759 if (itl == NULL) {
3760 rw_exit(iss->iss_lockp);
3761 mutex_exit(&stmf_state.stmf_lock);
3762 return (STMF_ALLOC_FAILURE);
3763 }
3764
3765 itl->itl_ilu = ilu;
3766 itl->itl_session = iss;
3767 itl->itl_counter = 1;
3768 itl->itl_lun = n;
3769 itl->itl_handle = itl_handle;
3770
3771 mutex_enter(&ilu->ilu_task_lock);
3772 itl->itl_next = ilu->ilu_itl_list;
3773 ilu->ilu_itl_list = itl;
3774 mutex_exit(&ilu->ilu_task_lock);
3775 lun_map_ent->ent_itl_datap = itl;
3776 rw_exit(iss->iss_lockp);
3777 mutex_exit(&stmf_state.stmf_lock);
3778
3779 return (STMF_SUCCESS);
3780 }
3781
3782 void
3783 stmf_do_itl_dereg(stmf_lu_t *lu, stmf_itl_data_t *itl, uint8_t hdlrm_reason)
3784 {
3785 uint8_t old, new;
3786
3787 do {
3788 old = new = itl->itl_flags;
3789 if (old & STMF_ITL_BEING_TERMINATED)
3790 return;
3791 new |= STMF_ITL_BEING_TERMINATED;
3792 } while (atomic_cas_8(&itl->itl_flags, old, new) != old);
3793 itl->itl_hdlrm_reason = hdlrm_reason;
3794
3795 ASSERT(itl->itl_counter);
3796
3797 if (atomic_add_32_nv(&itl->itl_counter, -1))
3798 return;
3799
3800 stmf_release_itl_handle(lu, itl);
3801 }
3802
3803 stmf_status_t
3804 stmf_deregister_all_lu_itl_handles(stmf_lu_t *lu)
3805 {
3806 stmf_i_lu_t *ilu;
3807 stmf_i_local_port_t *ilport;
3808 stmf_i_scsi_session_t *iss;
3809 stmf_lun_map_t *lm;
3810 stmf_lun_map_ent_t *ent;
3811 uint32_t nmaps, nu;
3812 stmf_itl_data_t **itl_list;
3813 int i;
3814
3815 ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
3816
3817 dereg_itl_start:;
3818 nmaps = ilu->ilu_ref_cnt;
3819 if (nmaps == 0)
3850 }
3851 }
3852 } /* lun table for a session */
3853 } /* sessions */
3854 rw_exit(&ilport->ilport_lock);
3855 } /* ports */
3856
3857 dai_scan_done:
3858 mutex_exit(&stmf_state.stmf_lock);
3859
3860 for (i = 0; i < nu; i++) {
3861 stmf_do_itl_dereg(lu, itl_list[i],
3862 STMF_ITL_REASON_DEREG_REQUEST);
3863 }
3864 kmem_free(itl_list, nmaps * sizeof (stmf_itl_data_t *));
3865
3866 return (STMF_SUCCESS);
3867 }
3868
3869 stmf_status_t
3870 stmf_get_itl_handle(stmf_lu_t *lu, uint8_t *lun, stmf_scsi_session_t *ss,
3871 uint64_t session_id, void **itl_handle_retp)
3872 {
3873 stmf_i_scsi_session_t *iss;
3874 stmf_lun_map_ent_t *ent;
3875 stmf_lun_map_t *lm;
3876 stmf_status_t ret;
3877 int i;
3878 uint16_t n;
3879
3880 if (ss == NULL) {
3881 iss = stmf_session_id_to_issptr(session_id, 1);
3882 if (iss == NULL)
3883 return (STMF_NOT_FOUND);
3884 } else {
3885 iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private;
3886 rw_enter(iss->iss_lockp, RW_WRITER);
3887 }
3888
3889 ent = NULL;
4035 */
4036 if (cdb_length_in >= 16)
4037 cdb_length = cdb_length_in + 7;
4038 else
4039 cdb_length = 16 + 7;
4040 iss = (stmf_i_scsi_session_t *)ss->ss_stmf_private;
4041 luNbr = ((uint16_t)lun[1] | (((uint16_t)(lun[0] & 0x3F)) << 8));
4042 rw_enter(iss->iss_lockp, RW_READER);
4043 lun_map_ent =
4044 (stmf_lun_map_ent_t *)stmf_get_ent_from_map(iss->iss_sm, luNbr);
4045 if (!lun_map_ent) {
4046 lu = dlun0;
4047 } else {
4048 lu = lun_map_ent->ent_lu;
4049 }
4050 ilu = lu->lu_stmf_private;
4051 if (ilu->ilu_flags & ILU_RESET_ACTIVE) {
4052 rw_exit(iss->iss_lockp);
4053 return (NULL);
4054 }
4055 ASSERT(lu == dlun0 || (ilu->ilu_state != STMF_STATE_OFFLINING &&
4056 ilu->ilu_state != STMF_STATE_OFFLINE));
4057 do {
4058 if (ilu->ilu_free_tasks == NULL) {
4059 new_task = 1;
4060 break;
4061 }
4062 mutex_enter(&ilu->ilu_task_lock);
4063 for (ppitask = &ilu->ilu_free_tasks; (*ppitask != NULL) &&
4064 ((*ppitask)->itask_cdb_buf_size < cdb_length);
4065 ppitask = &((*ppitask)->itask_lu_free_next))
4066 ;
4067 if (*ppitask) {
4068 itask = *ppitask;
4069 *ppitask = (*ppitask)->itask_lu_free_next;
4070 ilu->ilu_ntasks_free--;
4071 if (ilu->ilu_ntasks_free < ilu->ilu_ntasks_min_free)
4072 ilu->ilu_ntasks_min_free = ilu->ilu_ntasks_free;
4073 } else {
4074 new_task = 1;
4075 }
4076 mutex_exit(&ilu->ilu_task_lock);
4165 }
4166
4167 rw_exit(iss->iss_lockp);
4168 return (task);
4169 }
4170
4171 static void
4172 stmf_task_lu_free(scsi_task_t *task, stmf_i_scsi_session_t *iss)
4173 {
4174 stmf_i_scsi_task_t *itask =
4175 (stmf_i_scsi_task_t *)task->task_stmf_private;
4176 stmf_i_lu_t *ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
4177
4178 ASSERT(rw_lock_held(iss->iss_lockp));
4179 itask->itask_flags = ITASK_IN_FREE_LIST;
4180 itask->itask_proxy_msg_id = 0;
4181 mutex_enter(&ilu->ilu_task_lock);
4182 itask->itask_lu_free_next = ilu->ilu_free_tasks;
4183 ilu->ilu_free_tasks = itask;
4184 ilu->ilu_ntasks_free++;
4185 if (ilu->ilu_ntasks == ilu->ilu_ntasks_free)
4186 cv_signal(&ilu->ilu_offline_pending_cv);
4187 mutex_exit(&ilu->ilu_task_lock);
4188 atomic_add_32(itask->itask_ilu_task_cntr, -1);
4189 }
4190
4191 void
4192 stmf_task_lu_check_freelist(stmf_i_lu_t *ilu)
4193 {
4194 uint32_t num_to_release, ndx;
4195 stmf_i_scsi_task_t *itask;
4196 stmf_lu_t *lu = ilu->ilu_lu;
4197
4198 ASSERT(ilu->ilu_ntasks_min_free <= ilu->ilu_ntasks_free);
4199
4200 /* free half of the minimal free of the free tasks */
4201 num_to_release = (ilu->ilu_ntasks_min_free + 1) / 2;
4202 if (!num_to_release) {
4203 return;
4204 }
4205 for (ndx = 0; ndx < num_to_release; ndx++) {
4206 mutex_enter(&ilu->ilu_task_lock);
5683 }
5684
5685 static uint16_t stmf_lu_id_gen_number = 0;
5686
5687 stmf_status_t
5688 stmf_scsilib_uniq_lu_id(uint32_t company_id, scsi_devid_desc_t *lu_id)
5689 {
5690 return (stmf_scsilib_uniq_lu_id2(company_id, 0, lu_id));
5691 }
5692
5693 stmf_status_t
5694 stmf_scsilib_uniq_lu_id2(uint32_t company_id, uint32_t host_id,
5695 scsi_devid_desc_t *lu_id)
5696 {
5697 uint8_t *p;
5698 struct timeval32 timestamp32;
5699 uint32_t *t = (uint32_t *)×tamp32;
5700 struct ether_addr mac;
5701 uint8_t *e = (uint8_t *)&mac;
5702 int hid = (int)host_id;
5703 uint16_t gen_number;
5704
5705 if (company_id == COMPANY_ID_NONE)
5706 company_id = COMPANY_ID_SUN;
5707
5708 if (lu_id->ident_length != 0x10)
5709 return (STMF_INVALID_ARG);
5710
5711 p = (uint8_t *)lu_id;
5712
5713 gen_number = atomic_add_16_nv(&stmf_lu_id_gen_number, 1);
5714
5715 p[0] = 0xf1; p[1] = 3; p[2] = 0; p[3] = 0x10;
5716 p[4] = ((company_id >> 20) & 0xf) | 0x60;
5717 p[5] = (company_id >> 12) & 0xff;
5718 p[6] = (company_id >> 4) & 0xff;
5719 p[7] = (company_id << 4) & 0xf0;
5720 if (hid == 0 && !localetheraddr((struct ether_addr *)NULL, &mac)) {
5721 hid = BE_32((int)zone_get_hostid(NULL));
5722 }
5723 if (hid != 0) {
5724 e[0] = (hid >> 24) & 0xff;
5725 e[1] = (hid >> 16) & 0xff;
5726 e[2] = (hid >> 8) & 0xff;
5727 e[3] = hid & 0xff;
5728 e[4] = e[5] = 0;
5729 }
5730 bcopy(e, p+8, 6);
5731 uniqtime32(×tamp32);
5732 *t = BE_32(*t);
5733 bcopy(t, p+14, 4);
5734 p[18] = (gen_number >> 8) & 0xff;
5735 p[19] = gen_number & 0xff;
5736
5737 return (STMF_SUCCESS);
5738 }
5739
5740 /*
5741 * saa is sense key, ASC, ASCQ
5742 */
5743 void
5744 stmf_scsilib_send_status(scsi_task_t *task, uint8_t st, uint32_t saa)
5745 {
5746 uint8_t sd[18];
5747 task->task_scsi_status = st;
5748 if (st == 2) {
5749 bzero(sd, 18);
5750 sd[0] = 0x70;
5751 sd[2] = (saa >> 16) & 0xf;
5752 sd[7] = 10;
5753 sd[12] = (saa >> 8) & 0xff;
5754 sd[13] = saa & 0xff;
5755 task->task_sense_data = sd;
7137 ilport->ilport_lport, eventid, arg, flags);
7138 }
7139 }
7140
7141 /*
7142 * With the possibility of having multiple itl sessions pointing to the
7143 * same itl_kstat_info, the ilu_kstat_lock mutex is used to synchronize
7144 * the kstat update of the ilu_kstat_io, itl_kstat_taskq and itl_kstat_lu_xfer
7145 * statistics.
7146 */
7147 void
7148 stmf_itl_task_start(stmf_i_scsi_task_t *itask)
7149 {
7150 stmf_itl_data_t *itl = itask->itask_itl_datap;
7151 scsi_task_t *task = itask->itask_task;
7152 stmf_i_lu_t *ilu;
7153
7154 if (itl == NULL || task->task_lu == dlun0)
7155 return;
7156 ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
7157 itask->itask_start_timestamp = gethrtime();
7158 if (ilu->ilu_kstat_io != NULL) {
7159 mutex_enter(ilu->ilu_kstat_io->ks_lock);
7160 stmf_update_kstat_lu_q(itask->itask_task, kstat_waitq_enter);
7161 mutex_exit(ilu->ilu_kstat_io->ks_lock);
7162 }
7163
7164 stmf_update_kstat_lport_q(itask->itask_task, kstat_waitq_enter);
7165 }
7166
7167 void
7168 stmf_itl_lu_new_task(stmf_i_scsi_task_t *itask)
7169 {
7170 stmf_itl_data_t *itl = itask->itask_itl_datap;
7171 scsi_task_t *task = itask->itask_task;
7172 stmf_i_lu_t *ilu;
7173
7174 if (itl == NULL || task->task_lu == dlun0)
7175 return;
7176 ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
7177 if (ilu->ilu_kstat_io != NULL) {
7178 mutex_enter(ilu->ilu_kstat_io->ks_lock);
7179 stmf_update_kstat_lu_q(itask->itask_task, kstat_waitq_to_runq);
7180 mutex_exit(ilu->ilu_kstat_io->ks_lock);
7181 }
7182
7183 stmf_update_kstat_lport_q(itask->itask_task, kstat_waitq_to_runq);
7184 }
7185
7186 void
7187 stmf_itl_task_done(stmf_i_scsi_task_t *itask)
7188 {
7189 stmf_itl_data_t *itl = itask->itask_itl_datap;
7190 scsi_task_t *task = itask->itask_task;
7191 stmf_i_lu_t *ilu;
7192
7193 itask->itask_done_timestamp = gethrtime();
7194
7195 if (itl == NULL || task->task_lu == dlun0)
7196 return;
7197 ilu = (stmf_i_lu_t *)task->task_lu->lu_stmf_private;
7198
7199 if (ilu->ilu_kstat_io == NULL)
7200 return;
7201
7202 mutex_enter(ilu->ilu_kstat_io->ks_lock);
7203
7204 if (itask->itask_flags & ITASK_KSTAT_IN_RUNQ) {
7205 stmf_update_kstat_lu_q(task, kstat_runq_exit);
7206 mutex_exit(ilu->ilu_kstat_io->ks_lock);
7207 stmf_update_kstat_lport_q(task, kstat_runq_exit);
7208 } else {
7209 stmf_update_kstat_lu_q(task, kstat_waitq_exit);
7210 mutex_exit(ilu->ilu_kstat_io->ks_lock);
7211 stmf_update_kstat_lport_q(task, kstat_waitq_exit);
7212 }
7213 }
7214
7215 static void
7216 stmf_lport_xfer_start(stmf_i_scsi_task_t *itask, stmf_data_buf_t *dbuf)
7217 {
7218 stmf_itl_data_t *itl = itask->itask_itl_datap;
7219
7220 if (itl == NULL)
7221 return;
7222
7223 DTRACE_PROBE2(scsi__xfer__start, scsi_task_t *, itask->itask_task,
7224 stmf_data_buf_t *, dbuf);
7225
7226 dbuf->db_xfer_start_timestamp = gethrtime();
7227 }
7228
7229 static void
7230 stmf_lport_xfer_done(stmf_i_scsi_task_t *itask, stmf_data_buf_t *dbuf)
7231 {
7232 stmf_itl_data_t *itl = itask->itask_itl_datap;
7233 hrtime_t elapsed_time;
7234 uint64_t xfer_size;
7235
7236 if (itl == NULL)
7237 return;
7238
7239 xfer_size = (dbuf->db_xfer_status == STMF_SUCCESS) ?
7240 dbuf->db_data_size : 0;
7241
7242 elapsed_time = gethrtime() - dbuf->db_xfer_start_timestamp;
7243 if (dbuf->db_flags & DB_DIRECTION_TO_RPORT) {
7244 atomic_add_64((uint64_t *)&itask->itask_lport_read_time,
7245 elapsed_time);
7246 atomic_add_64((uint64_t *)&itask->itask_read_xfer,
7247 xfer_size);
7248 } else {
7249 atomic_add_64((uint64_t *)&itask->itask_lport_write_time,
7250 elapsed_time);
7251 atomic_add_64((uint64_t *)&itask->itask_write_xfer,
7252 xfer_size);
7253 }
7254
7255 DTRACE_PROBE3(scsi__xfer__end, scsi_task_t *, itask->itask_task,
7256 stmf_data_buf_t *, dbuf, hrtime_t, elapsed_time);
7257
7258 dbuf->db_xfer_start_timestamp = 0;
7259 }
7260
7261 void
7262 stmf_svc_init()
7263 {
7264 if (stmf_state.stmf_svc_flags & STMF_SVC_STARTED)
7265 return;
7266 stmf_state.stmf_svc_tailp = &stmf_state.stmf_svc_active;
7267 stmf_state.stmf_svc_taskq = ddi_taskq_create(0, "STMF_SVC_TASKQ", 1,
7268 TASKQ_DEFAULTPRI, 0);
7269 (void) ddi_taskq_dispatch(stmf_state.stmf_svc_taskq,
7270 stmf_svc, 0, DDI_SLEEP);
7271 }
7272
7273 stmf_status_t
7274 stmf_svc_fini()
7275 {
7276 uint32_t i;
7277
7339 /* Fallthrough */
7340 case STMF_CMD_LPORT_OFFLINE:
7341 mutex_exit(&stmf_state.stmf_lock);
7342 lport = (stmf_local_port_t *)req->svc_obj;
7343 lport->lport_ctl(lport, req->svc_cmd, &req->svc_info);
7344 break;
7345 case STMF_CMD_LU_ONLINE:
7346 mutex_exit(&stmf_state.stmf_lock);
7347 lu = (stmf_lu_t *)req->svc_obj;
7348 lu->lu_ctl(lu, req->svc_cmd, &req->svc_info);
7349 break;
7350 case STMF_CMD_LU_OFFLINE:
7351 /* Remove all mappings of this LU */
7352 stmf_session_lu_unmapall((stmf_lu_t *)req->svc_obj);
7353 /* Kill all the pending I/Os for this LU */
7354 mutex_exit(&stmf_state.stmf_lock);
7355 stmf_task_lu_killall((stmf_lu_t *)req->svc_obj, NULL,
7356 STMF_ABORTED);
7357 lu = (stmf_lu_t *)req->svc_obj;
7358 ilu = (stmf_i_lu_t *)lu->lu_stmf_private;
7359 stmf_wait_ilu_tasks_finish(ilu);
7360 lu->lu_ctl(lu, req->svc_cmd, &req->svc_info);
7361 break;
7362 default:
7363 cmn_err(CE_PANIC, "stmf_svc: unknown cmd %d",
7364 req->svc_cmd);
7365 }
7366
7367 kmem_free(req, req->svc_req_alloc_size);
7368 mutex_enter(&stmf_state.stmf_lock);
7369 }
7370
7371 stmf_state.stmf_svc_flags &= ~(STMF_SVC_STARTED | STMF_SVC_ACTIVE);
7372 mutex_exit(&stmf_state.stmf_lock);
7373 }
7374
7375 static void
7376 stmf_svc_timeout(struct stmf_svc_clocks *clks)
7377 {
7378 clock_t td;
7379 stmf_i_local_port_t *ilport, *next_ilport;
7380 stmf_i_scsi_session_t *iss;
7381
7382 ASSERT(mutex_owned(&stmf_state.stmf_lock));
7383
7384 td = drv_usectohz(20000);
7385
7386 /* Do timeouts */
7387 if (stmf_state.stmf_nlus &&
7492 ~ILPORT_SS_GOT_INITIAL_LUNS);
7493 /* drop the lock if we are holding it. */
7494 if (ilport_lock_held == 1)
7495 rw_exit(&ilport->ilport_lock);
7496
7497 /* Max 4 session at a time */
7498 if (stmf_level >= 4)
7499 break;
7500 }
7501
7502 if (stmf_level == 0)
7503 stmf_state.stmf_process_initial_luns = 0;
7504 }
7505
7506 stmf_state.stmf_svc_flags &= ~STMF_SVC_ACTIVE;
7507 (void) cv_reltimedwait(&stmf_state.stmf_cv,
7508 &stmf_state.stmf_lock, td, TR_CLOCK_TICK);
7509 stmf_state.stmf_svc_flags |= STMF_SVC_ACTIVE;
7510 }
7511
7512 /*
7513 * Waits for ongoing I/O tasks to finish on an LU in preparation for
7514 * the LU's offlining. The LU should already be in an Offlining state
7515 * (otherwise I/O to the LU might never end). There is an additional
7516 * enforcement of this via a deadman timer check.
7517 */
7518 static void
7519 stmf_wait_ilu_tasks_finish(stmf_i_lu_t *ilu)
7520 {
7521 clock_t start, now, deadline;
7522
7523 start = now = ddi_get_lbolt();
7524 deadline = start + drv_usectohz(stmf_io_deadman * 1000000llu);
7525 mutex_enter(&ilu->ilu_task_lock);
7526 while (ilu->ilu_ntasks != ilu->ilu_ntasks_free) {
7527 (void) cv_timedwait(&ilu->ilu_offline_pending_cv,
7528 &ilu->ilu_task_lock, deadline);
7529 now = ddi_get_lbolt();
7530 if (now > deadline) {
7531 if (stmf_io_deadman_enabled) {
7532 cmn_err(CE_PANIC, "stmf_svc: I/O deadman hit "
7533 "on STMF_CMD_LU_OFFLINE after %d seconds",
7534 stmf_io_deadman);
7535 } else {
7536 /* keep on spinning */
7537 deadline = now + drv_usectohz(stmf_io_deadman *
7538 1000000llu);
7539 }
7540 }
7541 }
7542 mutex_exit(&ilu->ilu_task_lock);
7543 DTRACE_PROBE1(deadman__timeout__wait, clock_t, now - start);
7544 }
7545
7546 void
7547 stmf_svc_queue(int cmd, void *obj, stmf_state_change_info_t *info)
7548 {
7549 stmf_svc_req_t *req;
7550 int s;
7551
7552 ASSERT(!mutex_owned(&stmf_state.stmf_lock));
7553 s = sizeof (stmf_svc_req_t);
7554 if (info->st_additional_info) {
7555 s += strlen(info->st_additional_info) + 1;
7556 }
7557 req = kmem_zalloc(s, KM_SLEEP);
7558
7559 req->svc_cmd = cmd;
7560 req->svc_obj = obj;
7561 req->svc_info.st_rflags = info->st_rflags;
7562 if (info->st_additional_info) {
7563 req->svc_info.st_additional_info = (char *)(GET_BYTE_OFFSET(req,
7564 sizeof (stmf_svc_req_t)));
7565 (void) strcpy(req->svc_info.st_additional_info,
|