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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 * iSCSI Software Initiator 26 */ 27 28 #define ISCSI_ICS_NAMES 29 #include "iscsi.h" /* main header */ 30 31 kstat_item_t kstat_items_hba[KN_HBA_IDX_MAX] = { 32 {"_name", KSTAT_DATA_STRING}, 33 {"_alias", KSTAT_DATA_STRING}, 34 {"_cntr_sess", KSTAT_DATA_ULONG} 35 }; 36 37 kstat_item_t kstat_items_sess[KN_SESS_IDX_MAX] = { 38 {"_state", KSTAT_DATA_STRING}, 39 {"_oid", KSTAT_DATA_ULONG}, 40 {"_hba", KSTAT_DATA_STRING}, 41 {"_cntr_conn", KSTAT_DATA_ULONG}, 42 {"_cntr_reset", KSTAT_DATA_ULONG}, 43 {"_cntr_pkt_pending", KSTAT_DATA_ULONG}, 44 {"_cmd_sn", KSTAT_DATA_ULONG}, 45 {"_cmd_sn_exp", KSTAT_DATA_ULONG}, 46 {"_cmd_sn_max", KSTAT_DATA_ULONG}, 47 {"_target_name", KSTAT_DATA_STRING}, 48 {"_target_alias", KSTAT_DATA_STRING}, 49 {"_tpgt", KSTAT_DATA_ULONG} 50 }; 51 52 kstat_item_t kstat_items_conn[KN_CONN_IDX_MAX] = { 53 {"_state", KSTAT_DATA_STRING}, 54 {"_cid", KSTAT_DATA_ULONG}, 55 {"_oid", KSTAT_DATA_ULONG}, 56 {"_session", KSTAT_DATA_STRING}, 57 {"_err_header_digest", KSTAT_DATA_ULONG}, 58 {"_err_data_digest", KSTAT_DATA_ULONG}, 59 {"_err_connection_reset", KSTAT_DATA_ULONG}, 60 {"_err_protocol_error", KSTAT_DATA_ULONG}, 61 {"_cntr_tx_bytes", KSTAT_DATA_ULONGLONG}, 62 {"_cntr_rx_bytes", KSTAT_DATA_ULONGLONG}, 63 {"_cntr_qactive", KSTAT_DATA_ULONG}, 64 {"_stat_sn_exp", KSTAT_DATA_ULONG}, 65 {"_stat_sn_last", KSTAT_DATA_ULONG} 66 }; 67 68 int iscsi_hba_kstat_update(kstat_t *ks, int rw); 69 int iscsi_sess_kstat_update(kstat_t *ks, int rw); 70 int iscsi_conn_kstat_update(kstat_t *ks, int rw); 71 72 /* 73 * HBA 74 */ 75 76 /* 77 * iscsi_hba_kstat_init - This function registers with the kstat service. 78 */ 79 boolean_t 80 iscsi_hba_kstat_init(iscsi_hba_t *ihp) 81 { 82 char ks_name[KSTAT_STRLEN]; 83 iscsi_hba_stats_t *ihs; 84 int i; 85 86 /* 87 * The name of the KSTAT structure is built. 88 */ 89 bzero(ks_name, sizeof (ks_name)); 90 91 if (snprintf(ks_name, sizeof (ks_name) - 1, iSCSI_HBA_BASE_NAME, 92 ihp->hba_oid) >= sizeof (ks_name)) { 93 return (TRUE); 94 } 95 96 ihp->stats.ks = kstat_create(iSCSI_MODULE_NAME, 97 ddi_get_instance(ihp->hba_dip), ks_name, iSCSI_CLASS_HBA, 98 KSTAT_TYPE_NAMED, 0, KSTAT_FLAG_VIRTUAL); 99 100 if (ihp->stats.ks == NULL) { 101 cmn_err(CE_NOTE, "iscsi kstat creation failed for hba(%d)", 102 ihp->hba_oid); 103 return (TRUE); 104 } 105 106 ihs = &ihp->stats.ks_data; 107 ihp->stats.ks->ks_data = &ihp->stats.ks_data; 108 ihp->stats.ks->ks_data_size = sizeof (ihp->stats.ks_data); 109 ihp->stats.ks->ks_ndata = KN_HBA_IDX_MAX; 110 111 for (i = 0; i < KN_HBA_IDX_MAX; i++) { 112 kstat_named_init(&ihs->kn[i], kstat_items_hba[i]._name, 113 kstat_items_hba[i]._data_type); 114 } 115 116 ihp->stats.ks->ks_update = iscsi_hba_kstat_update; 117 ihp->stats.ks->ks_private = (void *)ihp; 118 119 kstat_install(ihp->stats.ks); 120 121 return (FALSE); 122 } 123 124 /* 125 * iscsi_hba_kstat_term - This function deregisters from the kstat service. 126 */ 127 boolean_t 128 iscsi_hba_kstat_term(iscsi_hba_t *ihp) 129 { 130 kstat_delete(ihp->stats.ks); 131 return (FALSE); 132 } 133 134 /* 135 * iscsi_hba_kstat_update - This function update the kstat structure of the HBA. 136 */ 137 int 138 iscsi_hba_kstat_update(kstat_t *ks, int rw) 139 { 140 iscsi_hba_t *ihp = (iscsi_hba_t *)ks->ks_private; 141 iscsi_hba_stats_t *ihs = &ihp->stats.ks_data; 142 143 if (rw == KSTAT_READ) { 144 rw_enter(&ihp->hba_sess_list_rwlock, RW_READER); 145 bcopy(ihp->hba_name, ihs->name, ihp->hba_name_length); 146 147 bcopy(ihp->hba_alias, ihs->alias, ihp->hba_alias_length); 148 149 ihs->name[ihp->hba_name_length] = 0; 150 ihs->alias[ihp->hba_alias_length] = 0; 151 152 kstat_named_setstr(&ihs->kn[KN_HBA_IDX_NAME], 153 (const char *)ihs->name); 154 kstat_named_setstr(&ihs->kn[KN_HBA_IDX_ALIAS], 155 (const char *)ihs->alias); 156 rw_exit(&ihp->hba_sess_list_rwlock); 157 } 158 return (0); 159 } 160 161 /* 162 * Session 163 */ 164 165 /* 166 * iscsi_sess_kstat_init - This function registers with the kstat service. 167 */ 168 boolean_t 169 iscsi_sess_kstat_init(iscsi_sess_t *isp) 170 { 171 iscsi_hba_t *ihp; 172 char ks_name[KSTAT_STRLEN]; 173 iscsi_sess_stats_t *iss; 174 int i; 175 176 ASSERT(isp != NULL); 177 ihp = isp->sess_hba; 178 ASSERT(ihp != NULL); 179 180 /* 181 * The name of the KSTAT structure is built. 182 */ 183 bzero(ks_name, sizeof (ks_name)); 184 185 if (snprintf(ks_name, sizeof (ks_name) - 1, iSCSI_SESS_BASE_NAME, 186 isp->sess_hba->hba_oid, isp->sess_oid) >= sizeof (ks_name)) { 187 cmn_err(CE_NOTE, "iscsi kstat creation failed for " 188 "session(%u)", isp->sess_oid); 189 return (TRUE); 190 } 191 192 isp->stats.ks = kstat_create(iSCSI_MODULE_NAME, 193 ddi_get_instance(ihp->hba_dip), ks_name, iSCSI_CLASS_SESS, 194 KSTAT_TYPE_NAMED, 0, KSTAT_FLAG_VIRTUAL); 195 196 if (isp->stats.ks == NULL) { 197 cmn_err(CE_NOTE, "iscsi kstat creation failed " 198 "for session(%u)", isp->sess_oid); 199 return (TRUE); 200 } 201 202 iss = &isp->stats.ks_data; 203 isp->stats.ks->ks_data = (void *)&isp->stats.ks_data; 204 isp->stats.ks->ks_data_size = sizeof (isp->stats.ks_data); 205 isp->stats.ks->ks_ndata = KN_SESS_IDX_MAX; 206 207 for (i = 0; i < KN_SESS_IDX_MAX; i++) { 208 kstat_named_init(&iss->kn[i], kstat_items_sess[i]._name, 209 kstat_items_sess[i]._data_type); 210 } 211 212 /* The static information is updated immediately */ 213 bzero(iss->hba_str, sizeof (iss->hba_str)); 214 bcopy(ihp->stats.ks->ks_name, iss->hba_str, sizeof (iss->hba_str)); 215 kstat_named_setstr(&iss->kn[KN_SESS_IDX_HBA], 216 (const char *)iss->hba_str); 217 218 iss->kn[KN_SESS_IDX_OID].value.ul = isp->sess_oid; 219 220 isp->stats.ks->ks_update = iscsi_sess_kstat_update; 221 isp->stats.ks->ks_private = (void *)isp; 222 223 /* The IO KSTAT structure is created */ 224 bzero(ks_name, sizeof (ks_name)); 225 226 if (snprintf(ks_name, sizeof (ks_name) - 1, iSCSI_SESS_IO_BASE_NAME, 227 isp->sess_hba->hba_oid, isp->sess_oid) >= sizeof (ks_name)) { 228 cmn_err(CE_NOTE, "iscsi kstat createion failed " 229 "for session(%u)", isp->sess_oid); 230 kstat_delete(isp->stats.ks); 231 return (TRUE); 232 } 233 234 isp->stats.ks_io = kstat_create(iSCSI_MODULE_NAME, 235 ddi_get_instance(ihp->hba_dip), ks_name, iSCSI_CLASS_SESS, 236 KSTAT_TYPE_IO, 1, KSTAT_FLAG_VIRTUAL); 237 238 if (isp->stats.ks_io == NULL) { 239 kstat_delete(isp->stats.ks); 240 cmn_err(CE_NOTE, "iscsi kstat creation failed " 241 "for session(%u)", isp->sess_oid); 242 return (TRUE); 243 } 244 mutex_init(&isp->stats.ks_io_lock, NULL, MUTEX_DRIVER, NULL); 245 isp->stats.ks_io->ks_data = &isp->stats.ks_io_data; 246 isp->stats.ks_io->ks_lock = &isp->stats.ks_io_lock; 247 248 kstat_install(isp->stats.ks); 249 kstat_install(isp->stats.ks_io); 250 251 return (FALSE); 252 } 253 254 /* 255 * iscsi_sess_kstat_term - This function deregisters with the kstat service. 256 */ 257 boolean_t 258 iscsi_sess_kstat_term(iscsi_sess_t *isp) 259 { 260 kstat_delete(isp->stats.ks_io); 261 mutex_destroy(&isp->stats.ks_io_lock); 262 kstat_delete(isp->stats.ks); 263 return (FALSE); 264 } 265 266 /* 267 * iscsi_sess_kstat_update - This function update the kstat 268 * structure of the HBA. 269 */ 270 int 271 iscsi_sess_kstat_update(kstat_t *ks, int rw) 272 { 273 iscsi_sess_t *isp = (iscsi_sess_t *)ks->ks_private; 274 iscsi_sess_stats_t *iss = &isp->stats.ks_data; 275 char *ptr; 276 int len; 277 278 if (rw == KSTAT_READ) { 279 280 /* String indicating the state of the session */ 281 ptr = iscsi_sess_state_str(isp->sess_state); 282 len = strlen(ptr); 283 if (len > (sizeof (iss->state_str) - 1)) { 284 len = sizeof (iss->state_str) - 1; 285 } 286 bzero(iss->state_str, sizeof (iss->state_str)); 287 bcopy(ptr, iss->state_str, len); 288 kstat_named_setstr( 289 &iss->kn[KN_SESS_IDX_STATE], 290 (const char *)iss->state_str); 291 292 /* Target name string */ 293 if (isp->sess_name_length > sizeof (iss->target_name)) { 294 len = sizeof (iss->target_name); 295 } else { 296 len = isp->sess_name_length; 297 } 298 bzero(iss->target_name, sizeof (iss->target_name)); 299 bcopy(isp->sess_name, iss->target_name, len); 300 kstat_named_setstr(&iss->kn[KN_SESS_IDX_TARGET_NAME], 301 (const char *)iss->target_name); 302 303 /* Target alias string */ 304 if (isp->sess_alias_length > sizeof (iss->target_alias)) { 305 len = sizeof (iss->target_alias); 306 } else { 307 len = isp->sess_alias_length; 308 } 309 bzero(iss->target_alias, sizeof (iss->target_alias)); 310 bcopy(isp->sess_alias, iss->target_alias, len); 311 kstat_named_setstr( 312 &iss->kn[KN_SESS_IDX_TARGET_ALIAS], 313 (const char *)iss->target_alias); 314 315 iss->kn[KN_SESS_IDX_CNTR_PKT_PENDING].value.ul = 316 isp->sess_queue_pending.count; 317 iss->kn[KN_SESS_IDX_CMDSN].value.ul = 318 isp->sess_cmdsn; 319 iss->kn[KN_SESS_IDX_EXPCMDSN].value.ul = 320 isp->sess_expcmdsn; 321 iss->kn[KN_SESS_IDX_MAXCMDSN].value.ul = 322 isp->sess_maxcmdsn; 323 iss->kn[KN_SESS_IDX_TPGT].value.ul = 324 isp->sess_tpgt_conf; 325 326 } 327 return (0); 328 } 329 330 /* 331 * Connection 332 */ 333 334 /* 335 * iscsi_conn_kstat_init - This function registers with the kstat service. 336 */ 337 boolean_t 338 iscsi_conn_kstat_init(iscsi_conn_t *icp) 339 { 340 iscsi_sess_t *isp = icp->conn_sess; 341 iscsi_hba_t *ihp = isp->sess_hba; 342 iscsi_conn_stats_t *ics; 343 int i; 344 char ks_name[KSTAT_STRLEN]; 345 346 /* 347 * The name of the KSTAT structure is built. 348 */ 349 bzero(ks_name, sizeof (ks_name)); 350 351 if (snprintf(ks_name, sizeof (ks_name) - 1, iSCSI_CONN_BASE_NAME, 352 icp->conn_sess->sess_hba->hba_oid, icp->conn_sess->sess_oid, 353 icp->conn_oid) >= sizeof (ks_name)) { 354 return (TRUE); 355 } 356 357 icp->stats.ks = kstat_create(iSCSI_MODULE_NAME, 358 ddi_get_instance(ihp->hba_dip), ks_name, iSCSI_CLASS_CONN, 359 KSTAT_TYPE_NAMED, 0, KSTAT_FLAG_VIRTUAL); 360 361 if (icp->stats.ks == NULL) { 362 cmn_err(CE_NOTE, "iscsi kstat creation failed " 363 "for connection(%d)", icp->conn_oid); 364 return (TRUE); 365 } 366 367 ics = &icp->stats.ks_data; 368 icp->stats.ks->ks_data = (void *)ics; 369 icp->stats.ks->ks_data_size = sizeof (*ics); 370 icp->stats.ks->ks_ndata = KN_CONN_IDX_MAX; 371 372 for (i = 0; i < KN_CONN_IDX_MAX; i++) { 373 kstat_named_init(&ics->kn[i], kstat_items_conn[i]._name, 374 kstat_items_conn[i]._data_type); 375 } 376 377 /* The static information is updated immediately */ 378 bzero(ics->sess_str, sizeof (ics->sess_str)); 379 bcopy(isp->stats.ks->ks_name, 380 ics->sess_str, 381 sizeof (ics->sess_str)); 382 383 kstat_named_setstr(&ics->kn[KN_CONN_IDX_SESS], 384 (const char *)ics->sess_str); 385 386 ics->kn[KN_CONN_IDX_OID].value.ul = isp->sess_oid; 387 ics->kn[KN_CONN_IDX_CID].value.ul = icp->conn_cid; 388 icp->stats.ks->ks_update = iscsi_conn_kstat_update; 389 icp->stats.ks->ks_private = (void *)icp; 390 391 kstat_install(icp->stats.ks); 392 393 return (FALSE); 394 } 395 396 /* 397 * iscsi_conn_kstat_term - This function deregisters with the kstat service. 398 */ 399 void 400 iscsi_conn_kstat_term(iscsi_conn_t *icp) 401 { 402 kstat_delete(icp->stats.ks); 403 } 404 405 /* 406 * iscsi_conn_kstat_update - This function update the kstat 407 * structure of the HBA. 408 */ 409 int 410 iscsi_conn_kstat_update(kstat_t *ks, int rw) 411 { 412 iscsi_conn_t *icp = (iscsi_conn_t *)ks->ks_private; 413 iscsi_conn_stats_t *ics = &icp->stats.ks_data; 414 int len; 415 416 if (rw == KSTAT_READ) { 417 len = strlen(iscsi_ics_name[icp->conn_state]); 418 if (len > (sizeof (ics->state_str) - 1)) { 419 len = sizeof (ics->state_str) - 1; 420 } 421 bzero(ics->state_str, sizeof (ics->state_str)); 422 bcopy(iscsi_ics_name[icp->conn_state], ics->state_str, len); 423 kstat_named_setstr(&ics->kn[KN_CONN_IDX_STATE], 424 (const char *)ics->state_str); 425 426 ics->kn[KN_CONN_IDX_CNTR_QACTIVE].value.ul = 427 icp->conn_queue_active.count; 428 ics->kn[KN_CONN_IDX_EXPSTATSN].value.ul = 429 icp->conn_expstatsn; 430 ics->kn[KN_CONN_IDX_LASTSTATSN].value.ul = 431 icp->conn_laststatsn; 432 } 433 return (0); 434 } 435