xref: /illumos-gate/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_stats.c (revision a73c0fe4e90b82a478f821ef3adb5cf34f6a9346)
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