1 /*******************************************************************************
2  * Modern ConfigFS group context specific iSCSI statistics based on original
3  * iscsi_target_mib.c code
4  *
5  * Copyright (c) 2011-2013 Datera, Inc.
6  *
7  * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  ******************************************************************************/
19 
20 #include <linux/configfs.h>
21 #include <linux/export.h>
22 #include <scsi/iscsi_proto.h>
23 #include <target/target_core_base.h>
24 
25 #include <target/iscsi/iscsi_target_core.h>
26 #include "iscsi_target_parameters.h"
27 #include "iscsi_target_device.h"
28 #include "iscsi_target_tpg.h"
29 #include "iscsi_target_util.h"
30 #include <target/iscsi/iscsi_target_stat.h>
31 
32 #ifndef INITIAL_JIFFIES
33 #define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ))
34 #endif
35 
36 /* Instance Attributes Table */
37 #define ISCSI_INST_NUM_NODES		1
38 #define ISCSI_INST_DESCR		"Storage Engine Target"
39 #define ISCSI_INST_LAST_FAILURE_TYPE	0
40 #define ISCSI_DISCONTINUITY_TIME	0
41 
42 #define ISCSI_NODE_INDEX		1
43 
44 #define ISPRINT(a)   ((a >= ' ') && (a <= '~'))
45 
46 /****************************************************************************
47  * iSCSI MIB Tables
48  ****************************************************************************/
49 /*
50  * Instance Attributes Table
51  */
52 static struct iscsi_tiqn *iscsi_instance_tiqn(struct config_item *item)
53 {
54 	struct iscsi_wwn_stat_grps *igrps = container_of(to_config_group(item),
55 			struct iscsi_wwn_stat_grps, iscsi_instance_group);
56 	return container_of(igrps, struct iscsi_tiqn, tiqn_stat_grps);
57 }
58 
59 static ssize_t iscsi_stat_instance_inst_show(struct config_item *item,
60 		char *page)
61 {
62 	return snprintf(page, PAGE_SIZE, "%u\n",
63 			iscsi_instance_tiqn(item)->tiqn_index);
64 }
65 
66 static ssize_t iscsi_stat_instance_min_ver_show(struct config_item *item,
67 		char *page)
68 {
69 	return snprintf(page, PAGE_SIZE, "%u\n", ISCSI_DRAFT20_VERSION);
70 }
71 
72 static ssize_t iscsi_stat_instance_max_ver_show(struct config_item *item,
73 		char *page)
74 {
75 	return snprintf(page, PAGE_SIZE, "%u\n", ISCSI_DRAFT20_VERSION);
76 }
77 
78 static ssize_t iscsi_stat_instance_portals_show(struct config_item *item,
79 		char *page)
80 {
81 	return snprintf(page, PAGE_SIZE, "%u\n",
82 			iscsi_instance_tiqn(item)->tiqn_num_tpg_nps);
83 }
84 
85 static ssize_t iscsi_stat_instance_nodes_show(struct config_item *item,
86 		char *page)
87 {
88 	return snprintf(page, PAGE_SIZE, "%u\n", ISCSI_INST_NUM_NODES);
89 }
90 
91 static ssize_t iscsi_stat_instance_sessions_show(struct config_item *item,
92 		char *page)
93 {
94 	return snprintf(page, PAGE_SIZE, "%u\n",
95 		iscsi_instance_tiqn(item)->tiqn_nsessions);
96 }
97 
98 static ssize_t iscsi_stat_instance_fail_sess_show(struct config_item *item,
99 		char *page)
100 {
101 	struct iscsi_tiqn *tiqn = iscsi_instance_tiqn(item);
102 	struct iscsi_sess_err_stats *sess_err = &tiqn->sess_err_stats;
103 	u32 sess_err_count;
104 
105 	spin_lock_bh(&sess_err->lock);
106 	sess_err_count = (sess_err->digest_errors +
107 			  sess_err->cxn_timeout_errors +
108 			  sess_err->pdu_format_errors);
109 	spin_unlock_bh(&sess_err->lock);
110 
111 	return snprintf(page, PAGE_SIZE, "%u\n", sess_err_count);
112 }
113 
114 static ssize_t iscsi_stat_instance_fail_type_show(struct config_item *item,
115 		char *page)
116 {
117 	struct iscsi_tiqn *tiqn = iscsi_instance_tiqn(item);
118 	struct iscsi_sess_err_stats *sess_err = &tiqn->sess_err_stats;
119 
120 	return snprintf(page, PAGE_SIZE, "%u\n",
121 			sess_err->last_sess_failure_type);
122 }
123 
124 static ssize_t iscsi_stat_instance_fail_rem_name_show(struct config_item *item,
125 		char *page)
126 {
127 	struct iscsi_tiqn *tiqn = iscsi_instance_tiqn(item);
128 	struct iscsi_sess_err_stats *sess_err = &tiqn->sess_err_stats;
129 
130 	return snprintf(page, PAGE_SIZE, "%s\n",
131 			sess_err->last_sess_fail_rem_name[0] ?
132 			sess_err->last_sess_fail_rem_name : NONE);
133 }
134 
135 static ssize_t iscsi_stat_instance_disc_time_show(struct config_item *item,
136 		char *page)
137 {
138 	return snprintf(page, PAGE_SIZE, "%u\n", ISCSI_DISCONTINUITY_TIME);
139 }
140 
141 static ssize_t iscsi_stat_instance_description_show(struct config_item *item,
142 		char *page)
143 {
144 	return snprintf(page, PAGE_SIZE, "%s\n", ISCSI_INST_DESCR);
145 }
146 
147 static ssize_t iscsi_stat_instance_vendor_show(struct config_item *item,
148 		char *page)
149 {
150 	return snprintf(page, PAGE_SIZE, "Datera, Inc. iSCSI-Target\n");
151 }
152 
153 static ssize_t iscsi_stat_instance_version_show(struct config_item *item,
154 		char *page)
155 {
156 	return snprintf(page, PAGE_SIZE, "%s\n", ISCSIT_VERSION);
157 }
158 
159 CONFIGFS_ATTR_RO(iscsi_stat_instance_, inst);
160 CONFIGFS_ATTR_RO(iscsi_stat_instance_, min_ver);
161 CONFIGFS_ATTR_RO(iscsi_stat_instance_, max_ver);
162 CONFIGFS_ATTR_RO(iscsi_stat_instance_, portals);
163 CONFIGFS_ATTR_RO(iscsi_stat_instance_, nodes);
164 CONFIGFS_ATTR_RO(iscsi_stat_instance_, sessions);
165 CONFIGFS_ATTR_RO(iscsi_stat_instance_, fail_sess);
166 CONFIGFS_ATTR_RO(iscsi_stat_instance_, fail_type);
167 CONFIGFS_ATTR_RO(iscsi_stat_instance_, fail_rem_name);
168 CONFIGFS_ATTR_RO(iscsi_stat_instance_, disc_time);
169 CONFIGFS_ATTR_RO(iscsi_stat_instance_, description);
170 CONFIGFS_ATTR_RO(iscsi_stat_instance_, vendor);
171 CONFIGFS_ATTR_RO(iscsi_stat_instance_, version);
172 
173 static struct configfs_attribute *iscsi_stat_instance_attrs[] = {
174 	&iscsi_stat_instance_attr_inst,
175 	&iscsi_stat_instance_attr_min_ver,
176 	&iscsi_stat_instance_attr_max_ver,
177 	&iscsi_stat_instance_attr_portals,
178 	&iscsi_stat_instance_attr_nodes,
179 	&iscsi_stat_instance_attr_sessions,
180 	&iscsi_stat_instance_attr_fail_sess,
181 	&iscsi_stat_instance_attr_fail_type,
182 	&iscsi_stat_instance_attr_fail_rem_name,
183 	&iscsi_stat_instance_attr_disc_time,
184 	&iscsi_stat_instance_attr_description,
185 	&iscsi_stat_instance_attr_vendor,
186 	&iscsi_stat_instance_attr_version,
187 	NULL,
188 };
189 
190 struct config_item_type iscsi_stat_instance_cit = {
191 	.ct_attrs		= iscsi_stat_instance_attrs,
192 	.ct_owner		= THIS_MODULE,
193 };
194 
195 /*
196  * Instance Session Failure Stats Table
197  */
198 static struct iscsi_tiqn *iscsi_sess_err_tiqn(struct config_item *item)
199 {
200 	struct iscsi_wwn_stat_grps *igrps = container_of(to_config_group(item),
201 			struct iscsi_wwn_stat_grps, iscsi_sess_err_group);
202 	return container_of(igrps, struct iscsi_tiqn, tiqn_stat_grps);
203 }
204 
205 static ssize_t iscsi_stat_sess_err_inst_show(struct config_item *item,
206 		char *page)
207 {
208 	return snprintf(page, PAGE_SIZE, "%u\n",
209 		iscsi_sess_err_tiqn(item)->tiqn_index);
210 }
211 
212 static ssize_t iscsi_stat_sess_err_digest_errors_show(struct config_item *item,
213 		char *page)
214 {
215 	struct iscsi_tiqn *tiqn = iscsi_sess_err_tiqn(item);
216 	struct iscsi_sess_err_stats *sess_err = &tiqn->sess_err_stats;
217 
218 	return snprintf(page, PAGE_SIZE, "%u\n", sess_err->digest_errors);
219 }
220 
221 static ssize_t iscsi_stat_sess_err_cxn_errors_show(struct config_item *item,
222 		char *page)
223 {
224 	struct iscsi_tiqn *tiqn = iscsi_sess_err_tiqn(item);
225 	struct iscsi_sess_err_stats *sess_err = &tiqn->sess_err_stats;
226 
227 	return snprintf(page, PAGE_SIZE, "%u\n", sess_err->cxn_timeout_errors);
228 }
229 
230 static ssize_t iscsi_stat_sess_err_format_errors_show(struct config_item *item,
231 		char *page)
232 {
233 	struct iscsi_tiqn *tiqn = iscsi_sess_err_tiqn(item);
234 	struct iscsi_sess_err_stats *sess_err = &tiqn->sess_err_stats;
235 
236 	return snprintf(page, PAGE_SIZE, "%u\n", sess_err->pdu_format_errors);
237 }
238 
239 CONFIGFS_ATTR_RO(iscsi_stat_sess_err_, inst);
240 CONFIGFS_ATTR_RO(iscsi_stat_sess_err_, digest_errors);
241 CONFIGFS_ATTR_RO(iscsi_stat_sess_err_, cxn_errors);
242 CONFIGFS_ATTR_RO(iscsi_stat_sess_err_, format_errors);
243 
244 static struct configfs_attribute *iscsi_stat_sess_err_attrs[] = {
245 	&iscsi_stat_sess_err_attr_inst,
246 	&iscsi_stat_sess_err_attr_digest_errors,
247 	&iscsi_stat_sess_err_attr_cxn_errors,
248 	&iscsi_stat_sess_err_attr_format_errors,
249 	NULL,
250 };
251 
252 struct config_item_type iscsi_stat_sess_err_cit = {
253 	.ct_attrs		= iscsi_stat_sess_err_attrs,
254 	.ct_owner		= THIS_MODULE,
255 };
256 
257 /*
258  * Target Attributes Table
259  */
260 static struct iscsi_tiqn *iscsi_tgt_attr_tiqn(struct config_item *item)
261 {
262 	struct iscsi_wwn_stat_grps *igrps = container_of(to_config_group(item),
263 			struct iscsi_wwn_stat_grps, iscsi_tgt_attr_group);
264 	return container_of(igrps, struct iscsi_tiqn, tiqn_stat_grps);
265 }
266 
267 static ssize_t iscsi_stat_tgt_attr_inst_show(struct config_item *item,
268 		char *page)
269 {
270 	return snprintf(page, PAGE_SIZE, "%u\n",
271 			iscsi_tgt_attr_tiqn(item)->tiqn_index);
272 }
273 
274 static ssize_t iscsi_stat_tgt_attr_indx_show(struct config_item *item,
275 		char *page)
276 {
277 	return snprintf(page, PAGE_SIZE, "%u\n", ISCSI_NODE_INDEX);
278 }
279 
280 static ssize_t iscsi_stat_tgt_attr_login_fails_show(struct config_item *item,
281 		char *page)
282 {
283 	struct iscsi_tiqn *tiqn = iscsi_tgt_attr_tiqn(item);
284 	struct iscsi_login_stats *lstat = &tiqn->login_stats;
285 	u32 fail_count;
286 
287 	spin_lock(&lstat->lock);
288 	fail_count = (lstat->redirects + lstat->authorize_fails +
289 			lstat->authenticate_fails + lstat->negotiate_fails +
290 			lstat->other_fails);
291 	spin_unlock(&lstat->lock);
292 
293 	return snprintf(page, PAGE_SIZE, "%u\n", fail_count);
294 }
295 
296 static ssize_t iscsi_stat_tgt_attr_last_fail_time_show(struct config_item *item,
297 		char *page)
298 {
299 	struct iscsi_tiqn *tiqn = iscsi_tgt_attr_tiqn(item);
300 	struct iscsi_login_stats *lstat = &tiqn->login_stats;
301 	u32 last_fail_time;
302 
303 	spin_lock(&lstat->lock);
304 	last_fail_time = lstat->last_fail_time ?
305 			(u32)(((u32)lstat->last_fail_time -
306 				INITIAL_JIFFIES) * 100 / HZ) : 0;
307 	spin_unlock(&lstat->lock);
308 
309 	return snprintf(page, PAGE_SIZE, "%u\n", last_fail_time);
310 }
311 
312 static ssize_t iscsi_stat_tgt_attr_last_fail_type_show(struct config_item *item,
313 		char *page)
314 {
315 	struct iscsi_tiqn *tiqn = iscsi_tgt_attr_tiqn(item);
316 	struct iscsi_login_stats *lstat = &tiqn->login_stats;
317 	u32 last_fail_type;
318 
319 	spin_lock(&lstat->lock);
320 	last_fail_type = lstat->last_fail_type;
321 	spin_unlock(&lstat->lock);
322 
323 	return snprintf(page, PAGE_SIZE, "%u\n", last_fail_type);
324 }
325 
326 static ssize_t iscsi_stat_tgt_attr_fail_intr_name_show(struct config_item *item,
327 		char *page)
328 {
329 	struct iscsi_tiqn *tiqn = iscsi_tgt_attr_tiqn(item);
330 	struct iscsi_login_stats *lstat = &tiqn->login_stats;
331 	unsigned char buf[224];
332 
333 	spin_lock(&lstat->lock);
334 	snprintf(buf, 224, "%s", lstat->last_intr_fail_name[0] ?
335 				lstat->last_intr_fail_name : NONE);
336 	spin_unlock(&lstat->lock);
337 
338 	return snprintf(page, PAGE_SIZE, "%s\n", buf);
339 }
340 
341 static ssize_t iscsi_stat_tgt_attr_fail_intr_addr_type_show(struct config_item *item,
342 		char *page)
343 {
344 	struct iscsi_tiqn *tiqn = iscsi_tgt_attr_tiqn(item);
345 	struct iscsi_login_stats *lstat = &tiqn->login_stats;
346 	int ret;
347 
348 	spin_lock(&lstat->lock);
349 	if (lstat->last_intr_fail_ip_family == AF_INET6)
350 		ret = snprintf(page, PAGE_SIZE, "ipv6\n");
351 	else
352 		ret = snprintf(page, PAGE_SIZE, "ipv4\n");
353 	spin_unlock(&lstat->lock);
354 
355 	return ret;
356 }
357 
358 static ssize_t iscsi_stat_tgt_attr_fail_intr_addr_show(struct config_item *item,
359 		char *page)
360 {
361 	struct iscsi_tiqn *tiqn = iscsi_tgt_attr_tiqn(item);
362 	struct iscsi_login_stats *lstat = &tiqn->login_stats;
363 	int ret;
364 
365 	spin_lock(&lstat->lock);
366 	ret = snprintf(page, PAGE_SIZE, "%pISc\n", &lstat->last_intr_fail_sockaddr);
367 	spin_unlock(&lstat->lock);
368 
369 	return ret;
370 }
371 
372 CONFIGFS_ATTR_RO(iscsi_stat_tgt_attr_, inst);
373 CONFIGFS_ATTR_RO(iscsi_stat_tgt_attr_, indx);
374 CONFIGFS_ATTR_RO(iscsi_stat_tgt_attr_, login_fails);
375 CONFIGFS_ATTR_RO(iscsi_stat_tgt_attr_, last_fail_time);
376 CONFIGFS_ATTR_RO(iscsi_stat_tgt_attr_, last_fail_type);
377 CONFIGFS_ATTR_RO(iscsi_stat_tgt_attr_, fail_intr_name);
378 CONFIGFS_ATTR_RO(iscsi_stat_tgt_attr_, fail_intr_addr_type);
379 CONFIGFS_ATTR_RO(iscsi_stat_tgt_attr_, fail_intr_addr);
380 
381 static struct configfs_attribute *iscsi_stat_tgt_attr_attrs[] = {
382 	&iscsi_stat_tgt_attr_attr_inst,
383 	&iscsi_stat_tgt_attr_attr_indx,
384 	&iscsi_stat_tgt_attr_attr_login_fails,
385 	&iscsi_stat_tgt_attr_attr_last_fail_time,
386 	&iscsi_stat_tgt_attr_attr_last_fail_type,
387 	&iscsi_stat_tgt_attr_attr_fail_intr_name,
388 	&iscsi_stat_tgt_attr_attr_fail_intr_addr_type,
389 	&iscsi_stat_tgt_attr_attr_fail_intr_addr,
390 	NULL,
391 };
392 
393 struct config_item_type iscsi_stat_tgt_attr_cit = {
394 	.ct_attrs		= iscsi_stat_tgt_attr_attrs,
395 	.ct_owner		= THIS_MODULE,
396 };
397 
398 /*
399  * Target Login Stats Table
400  */
401 static struct iscsi_tiqn *iscsi_login_stat_tiqn(struct config_item *item)
402 {
403 	struct iscsi_wwn_stat_grps *igrps = container_of(to_config_group(item),
404 			struct iscsi_wwn_stat_grps, iscsi_login_stats_group);
405 	return container_of(igrps, struct iscsi_tiqn, tiqn_stat_grps);
406 }
407 
408 static ssize_t iscsi_stat_login_inst_show(struct config_item *item, char *page)
409 {
410 	return snprintf(page, PAGE_SIZE, "%u\n",
411 		iscsi_login_stat_tiqn(item)->tiqn_index);
412 }
413 
414 static ssize_t iscsi_stat_login_indx_show(struct config_item *item,
415 		char *page)
416 {
417 	return snprintf(page, PAGE_SIZE, "%u\n", ISCSI_NODE_INDEX);
418 }
419 
420 static ssize_t iscsi_stat_login_accepts_show(struct config_item *item,
421 		char *page)
422 {
423 	struct iscsi_tiqn *tiqn = iscsi_login_stat_tiqn(item);
424 	struct iscsi_login_stats *lstat = &tiqn->login_stats;
425 	ssize_t ret;
426 
427 	spin_lock(&lstat->lock);
428 	ret = snprintf(page, PAGE_SIZE, "%u\n", lstat->accepts);
429 	spin_unlock(&lstat->lock);
430 
431 	return ret;
432 }
433 
434 static ssize_t iscsi_stat_login_other_fails_show(struct config_item *item,
435 		char *page)
436 {
437 	struct iscsi_tiqn *tiqn = iscsi_login_stat_tiqn(item);
438 	struct iscsi_login_stats *lstat = &tiqn->login_stats;
439 	ssize_t ret;
440 
441 	spin_lock(&lstat->lock);
442 	ret = snprintf(page, PAGE_SIZE, "%u\n", lstat->other_fails);
443 	spin_unlock(&lstat->lock);
444 
445 	return ret;
446 }
447 
448 static ssize_t iscsi_stat_login_redirects_show(struct config_item *item,
449 		char *page)
450 {
451 	struct iscsi_tiqn *tiqn = iscsi_login_stat_tiqn(item);
452 	struct iscsi_login_stats *lstat = &tiqn->login_stats;
453 	ssize_t ret;
454 
455 	spin_lock(&lstat->lock);
456 	ret = snprintf(page, PAGE_SIZE, "%u\n", lstat->redirects);
457 	spin_unlock(&lstat->lock);
458 
459 	return ret;
460 }
461 
462 static ssize_t iscsi_stat_login_authorize_fails_show(struct config_item *item,
463 		char *page)
464 {
465 	struct iscsi_tiqn *tiqn = iscsi_login_stat_tiqn(item);
466 	struct iscsi_login_stats *lstat = &tiqn->login_stats;
467 	ssize_t ret;
468 
469 	spin_lock(&lstat->lock);
470 	ret = snprintf(page, PAGE_SIZE, "%u\n", lstat->authorize_fails);
471 	spin_unlock(&lstat->lock);
472 
473 	return ret;
474 }
475 
476 static ssize_t iscsi_stat_login_authenticate_fails_show(
477 		struct config_item *item, char *page)
478 {
479 	struct iscsi_tiqn *tiqn = iscsi_login_stat_tiqn(item);
480 	struct iscsi_login_stats *lstat = &tiqn->login_stats;
481 	ssize_t ret;
482 
483 	spin_lock(&lstat->lock);
484 	ret = snprintf(page, PAGE_SIZE, "%u\n", lstat->authenticate_fails);
485 	spin_unlock(&lstat->lock);
486 
487 	return ret;
488 }
489 
490 static ssize_t iscsi_stat_login_negotiate_fails_show(struct config_item *item,
491 		char *page)
492 {
493 	struct iscsi_tiqn *tiqn = iscsi_login_stat_tiqn(item);
494 	struct iscsi_login_stats *lstat = &tiqn->login_stats;
495 	ssize_t ret;
496 
497 	spin_lock(&lstat->lock);
498 	ret = snprintf(page, PAGE_SIZE, "%u\n", lstat->negotiate_fails);
499 	spin_unlock(&lstat->lock);
500 
501 	return ret;
502 }
503 
504 CONFIGFS_ATTR_RO(iscsi_stat_login_, inst);
505 CONFIGFS_ATTR_RO(iscsi_stat_login_, indx);
506 CONFIGFS_ATTR_RO(iscsi_stat_login_, accepts);
507 CONFIGFS_ATTR_RO(iscsi_stat_login_, other_fails);
508 CONFIGFS_ATTR_RO(iscsi_stat_login_, redirects);
509 CONFIGFS_ATTR_RO(iscsi_stat_login_, authorize_fails);
510 CONFIGFS_ATTR_RO(iscsi_stat_login_, authenticate_fails);
511 CONFIGFS_ATTR_RO(iscsi_stat_login_, negotiate_fails);
512 
513 static struct configfs_attribute *iscsi_stat_login_stats_attrs[] = {
514 	&iscsi_stat_login_attr_inst,
515 	&iscsi_stat_login_attr_indx,
516 	&iscsi_stat_login_attr_accepts,
517 	&iscsi_stat_login_attr_other_fails,
518 	&iscsi_stat_login_attr_redirects,
519 	&iscsi_stat_login_attr_authorize_fails,
520 	&iscsi_stat_login_attr_authenticate_fails,
521 	&iscsi_stat_login_attr_negotiate_fails,
522 	NULL,
523 };
524 
525 struct config_item_type iscsi_stat_login_cit = {
526 	.ct_attrs		= iscsi_stat_login_stats_attrs,
527 	.ct_owner		= THIS_MODULE,
528 };
529 
530 /*
531  * Target Logout Stats Table
532  */
533 static struct iscsi_tiqn *iscsi_logout_stat_tiqn(struct config_item *item)
534 {
535 	struct iscsi_wwn_stat_grps *igrps = container_of(to_config_group(item),
536 			struct iscsi_wwn_stat_grps, iscsi_logout_stats_group);
537 	return container_of(igrps, struct iscsi_tiqn, tiqn_stat_grps);
538 }
539 
540 static ssize_t iscsi_stat_logout_inst_show(struct config_item *item, char *page)
541 {
542 	return snprintf(page, PAGE_SIZE, "%u\n",
543 		iscsi_logout_stat_tiqn(item)->tiqn_index);
544 }
545 
546 static ssize_t iscsi_stat_logout_indx_show(struct config_item *item, char *page)
547 {
548 	return snprintf(page, PAGE_SIZE, "%u\n", ISCSI_NODE_INDEX);
549 }
550 
551 static ssize_t iscsi_stat_logout_normal_logouts_show(struct config_item *item,
552 		char *page)
553 {
554 	struct iscsi_tiqn *tiqn = iscsi_logout_stat_tiqn(item);
555 	struct iscsi_logout_stats *lstats = &tiqn->logout_stats;
556 
557 	return snprintf(page, PAGE_SIZE, "%u\n", lstats->normal_logouts);
558 }
559 
560 static ssize_t iscsi_stat_logout_abnormal_logouts_show(struct config_item *item,
561 		char *page)
562 {
563 	struct iscsi_tiqn *tiqn = iscsi_logout_stat_tiqn(item);
564 	struct iscsi_logout_stats *lstats = &tiqn->logout_stats;
565 
566 	return snprintf(page, PAGE_SIZE, "%u\n", lstats->abnormal_logouts);
567 }
568 
569 CONFIGFS_ATTR_RO(iscsi_stat_logout_, inst);
570 CONFIGFS_ATTR_RO(iscsi_stat_logout_, indx);
571 CONFIGFS_ATTR_RO(iscsi_stat_logout_, normal_logouts);
572 CONFIGFS_ATTR_RO(iscsi_stat_logout_, abnormal_logouts);
573 
574 static struct configfs_attribute *iscsi_stat_logout_stats_attrs[] = {
575 	&iscsi_stat_logout_attr_inst,
576 	&iscsi_stat_logout_attr_indx,
577 	&iscsi_stat_logout_attr_normal_logouts,
578 	&iscsi_stat_logout_attr_abnormal_logouts,
579 	NULL,
580 };
581 
582 struct config_item_type iscsi_stat_logout_cit = {
583 	.ct_attrs		= iscsi_stat_logout_stats_attrs,
584 	.ct_owner		= THIS_MODULE,
585 };
586 
587 /*
588  * Session Stats Table
589  */
590 static struct iscsi_node_acl *iscsi_stat_nacl(struct config_item *item)
591 {
592 	struct iscsi_node_stat_grps *igrps = container_of(to_config_group(item),
593 			struct iscsi_node_stat_grps, iscsi_sess_stats_group);
594 	return container_of(igrps, struct iscsi_node_acl, node_stat_grps);
595 }
596 
597 static ssize_t iscsi_stat_sess_inst_show(struct config_item *item, char *page)
598 {
599 	struct iscsi_node_acl *acl = iscsi_stat_nacl(item);
600 	struct se_wwn *wwn = acl->se_node_acl.se_tpg->se_tpg_wwn;
601 	struct iscsi_tiqn *tiqn = container_of(wwn,
602 			struct iscsi_tiqn, tiqn_wwn);
603 
604 	return snprintf(page, PAGE_SIZE, "%u\n", tiqn->tiqn_index);
605 }
606 
607 static ssize_t iscsi_stat_sess_node_show(struct config_item *item, char *page)
608 {
609 	struct iscsi_node_acl *acl = iscsi_stat_nacl(item);
610 	struct se_node_acl *se_nacl = &acl->se_node_acl;
611 	struct iscsi_session *sess;
612 	struct se_session *se_sess;
613 	ssize_t ret = 0;
614 
615 	spin_lock_bh(&se_nacl->nacl_sess_lock);
616 	se_sess = se_nacl->nacl_sess;
617 	if (se_sess) {
618 		sess = se_sess->fabric_sess_ptr;
619 		if (sess)
620 			ret = snprintf(page, PAGE_SIZE, "%u\n",
621 				sess->sess_ops->SessionType ? 0 : ISCSI_NODE_INDEX);
622 	}
623 	spin_unlock_bh(&se_nacl->nacl_sess_lock);
624 
625 	return ret;
626 }
627 
628 static ssize_t iscsi_stat_sess_indx_show(struct config_item *item, char *page)
629 {
630 	struct iscsi_node_acl *acl = iscsi_stat_nacl(item);
631 	struct se_node_acl *se_nacl = &acl->se_node_acl;
632 	struct iscsi_session *sess;
633 	struct se_session *se_sess;
634 	ssize_t ret = 0;
635 
636 	spin_lock_bh(&se_nacl->nacl_sess_lock);
637 	se_sess = se_nacl->nacl_sess;
638 	if (se_sess) {
639 		sess = se_sess->fabric_sess_ptr;
640 		if (sess)
641 			ret = snprintf(page, PAGE_SIZE, "%u\n",
642 					sess->session_index);
643 	}
644 	spin_unlock_bh(&se_nacl->nacl_sess_lock);
645 
646 	return ret;
647 }
648 
649 static ssize_t iscsi_stat_sess_cmd_pdus_show(struct config_item *item,
650 		char *page)
651 {
652 	struct iscsi_node_acl *acl = iscsi_stat_nacl(item);
653 	struct se_node_acl *se_nacl = &acl->se_node_acl;
654 	struct iscsi_session *sess;
655 	struct se_session *se_sess;
656 	ssize_t ret = 0;
657 
658 	spin_lock_bh(&se_nacl->nacl_sess_lock);
659 	se_sess = se_nacl->nacl_sess;
660 	if (se_sess) {
661 		sess = se_sess->fabric_sess_ptr;
662 		if (sess)
663 			ret = snprintf(page, PAGE_SIZE, "%lu\n",
664 				       atomic_long_read(&sess->cmd_pdus));
665 	}
666 	spin_unlock_bh(&se_nacl->nacl_sess_lock);
667 
668 	return ret;
669 }
670 
671 static ssize_t iscsi_stat_sess_rsp_pdus_show(struct config_item *item,
672 		char *page)
673 {
674 	struct iscsi_node_acl *acl = iscsi_stat_nacl(item);
675 	struct se_node_acl *se_nacl = &acl->se_node_acl;
676 	struct iscsi_session *sess;
677 	struct se_session *se_sess;
678 	ssize_t ret = 0;
679 
680 	spin_lock_bh(&se_nacl->nacl_sess_lock);
681 	se_sess = se_nacl->nacl_sess;
682 	if (se_sess) {
683 		sess = se_sess->fabric_sess_ptr;
684 		if (sess)
685 			ret = snprintf(page, PAGE_SIZE, "%lu\n",
686 				       atomic_long_read(&sess->rsp_pdus));
687 	}
688 	spin_unlock_bh(&se_nacl->nacl_sess_lock);
689 
690 	return ret;
691 }
692 
693 static ssize_t iscsi_stat_sess_txdata_octs_show(struct config_item *item,
694 		char *page)
695 {
696 	struct iscsi_node_acl *acl = iscsi_stat_nacl(item);
697 	struct se_node_acl *se_nacl = &acl->se_node_acl;
698 	struct iscsi_session *sess;
699 	struct se_session *se_sess;
700 	ssize_t ret = 0;
701 
702 	spin_lock_bh(&se_nacl->nacl_sess_lock);
703 	se_sess = se_nacl->nacl_sess;
704 	if (se_sess) {
705 		sess = se_sess->fabric_sess_ptr;
706 		if (sess)
707 			ret = snprintf(page, PAGE_SIZE, "%lu\n",
708 				       atomic_long_read(&sess->tx_data_octets));
709 	}
710 	spin_unlock_bh(&se_nacl->nacl_sess_lock);
711 
712 	return ret;
713 }
714 
715 static ssize_t iscsi_stat_sess_rxdata_octs_show(struct config_item *item,
716 		char *page)
717 {
718 	struct iscsi_node_acl *acl = iscsi_stat_nacl(item);
719 	struct se_node_acl *se_nacl = &acl->se_node_acl;
720 	struct iscsi_session *sess;
721 	struct se_session *se_sess;
722 	ssize_t ret = 0;
723 
724 	spin_lock_bh(&se_nacl->nacl_sess_lock);
725 	se_sess = se_nacl->nacl_sess;
726 	if (se_sess) {
727 		sess = se_sess->fabric_sess_ptr;
728 		if (sess)
729 			ret = snprintf(page, PAGE_SIZE, "%lu\n",
730 				       atomic_long_read(&sess->rx_data_octets));
731 	}
732 	spin_unlock_bh(&se_nacl->nacl_sess_lock);
733 
734 	return ret;
735 }
736 
737 static ssize_t iscsi_stat_sess_conn_digest_errors_show(struct config_item *item,
738 		char *page)
739 {
740 	struct iscsi_node_acl *acl = iscsi_stat_nacl(item);
741 	struct se_node_acl *se_nacl = &acl->se_node_acl;
742 	struct iscsi_session *sess;
743 	struct se_session *se_sess;
744 	ssize_t ret = 0;
745 
746 	spin_lock_bh(&se_nacl->nacl_sess_lock);
747 	se_sess = se_nacl->nacl_sess;
748 	if (se_sess) {
749 		sess = se_sess->fabric_sess_ptr;
750 		if (sess)
751 			ret = snprintf(page, PAGE_SIZE, "%lu\n",
752 				       atomic_long_read(&sess->conn_digest_errors));
753 	}
754 	spin_unlock_bh(&se_nacl->nacl_sess_lock);
755 
756 	return ret;
757 }
758 
759 static ssize_t iscsi_stat_sess_conn_timeout_errors_show(
760 		struct config_item *item, char *page)
761 {
762 	struct iscsi_node_acl *acl = iscsi_stat_nacl(item);
763 	struct se_node_acl *se_nacl = &acl->se_node_acl;
764 	struct iscsi_session *sess;
765 	struct se_session *se_sess;
766 	ssize_t ret = 0;
767 
768 	spin_lock_bh(&se_nacl->nacl_sess_lock);
769 	se_sess = se_nacl->nacl_sess;
770 	if (se_sess) {
771 		sess = se_sess->fabric_sess_ptr;
772 		if (sess)
773 			ret = snprintf(page, PAGE_SIZE, "%lu\n",
774 				       atomic_long_read(&sess->conn_timeout_errors));
775 	}
776 	spin_unlock_bh(&se_nacl->nacl_sess_lock);
777 
778 	return ret;
779 }
780 
781 CONFIGFS_ATTR_RO(iscsi_stat_sess_, inst);
782 CONFIGFS_ATTR_RO(iscsi_stat_sess_, node);
783 CONFIGFS_ATTR_RO(iscsi_stat_sess_, indx);
784 CONFIGFS_ATTR_RO(iscsi_stat_sess_, cmd_pdus);
785 CONFIGFS_ATTR_RO(iscsi_stat_sess_, rsp_pdus);
786 CONFIGFS_ATTR_RO(iscsi_stat_sess_, txdata_octs);
787 CONFIGFS_ATTR_RO(iscsi_stat_sess_, rxdata_octs);
788 CONFIGFS_ATTR_RO(iscsi_stat_sess_, conn_digest_errors);
789 CONFIGFS_ATTR_RO(iscsi_stat_sess_, conn_timeout_errors);
790 
791 static struct configfs_attribute *iscsi_stat_sess_stats_attrs[] = {
792 	&iscsi_stat_sess_attr_inst,
793 	&iscsi_stat_sess_attr_node,
794 	&iscsi_stat_sess_attr_indx,
795 	&iscsi_stat_sess_attr_cmd_pdus,
796 	&iscsi_stat_sess_attr_rsp_pdus,
797 	&iscsi_stat_sess_attr_txdata_octs,
798 	&iscsi_stat_sess_attr_rxdata_octs,
799 	&iscsi_stat_sess_attr_conn_digest_errors,
800 	&iscsi_stat_sess_attr_conn_timeout_errors,
801 	NULL,
802 };
803 
804 struct config_item_type iscsi_stat_sess_cit = {
805 	.ct_attrs		= iscsi_stat_sess_stats_attrs,
806 	.ct_owner		= THIS_MODULE,
807 };
808