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