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
iscsi_hba_kstat_init(iscsi_hba_t * ihp)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
iscsi_hba_kstat_term(iscsi_hba_t * ihp)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
iscsi_hba_kstat_update(kstat_t * ks,int rw)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
iscsi_sess_kstat_init(iscsi_sess_t * isp)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
iscsi_sess_kstat_term(iscsi_sess_t * isp)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
iscsi_sess_kstat_update(kstat_t * ks,int rw)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
iscsi_conn_kstat_init(iscsi_conn_t * icp)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
iscsi_conn_kstat_term(iscsi_conn_t * icp)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
iscsi_conn_kstat_update(kstat_t * ks,int rw)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