1 /*******************************************************************************
2 * Filename: target_core_mib.c
4 * Copyright (c) 2006-2007 SBE, Inc. All Rights Reserved.
5 * Copyright (c) 2007-2010 Rising Tide Systems
6 * Copyright (c) 2008-2010 Linux-iSCSI.org
8 * Nicholas A. Bellinger <nab@linux-iscsi.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 ******************************************************************************/
27 #include <linux/kernel.h>
28 #include <linux/module.h>
29 #include <linux/delay.h>
30 #include <linux/timer.h>
31 #include <linux/string.h>
32 #include <linux/version.h>
33 #include <generated/utsrelease.h>
34 #include <linux/utsname.h>
35 #include <linux/proc_fs.h>
36 #include <linux/seq_file.h>
37 #include <linux/blkdev.h>
38 #include <scsi/scsi.h>
39 #include <scsi/scsi_device.h>
40 #include <scsi/scsi_host.h>
42 #include <target/target_core_base.h>
43 #include <target/target_core_transport.h>
44 #include <target/target_core_fabric_ops.h>
45 #include <target/target_core_configfs.h>
47 #include "target_core_hba.h"
48 #include "target_core_mib.h"
50 /* SCSI mib table index */
51 static struct scsi_index_table scsi_index_table;
53 #ifndef INITIAL_JIFFIES
54 #define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ))
57 /* SCSI Instance Table */
58 #define SCSI_INST_SW_INDEX 1
59 #define SCSI_TRANSPORT_INDEX 1
62 #define ISPRINT(a) ((a >= ' ') && (a <= '~'))
64 static inline int list_is_first(const struct list_head *list,
65 const struct list_head *head)
67 return list->prev == head;
70 static void *locate_hba_start(
74 spin_lock(&se_global->g_device_lock);
75 return seq_list_start(&se_global->g_se_dev_list, *pos);
78 static void *locate_hba_next(
83 return seq_list_next(v, &se_global->g_se_dev_list, pos);
86 static void locate_hba_stop(struct seq_file *seq, void *v)
88 spin_unlock(&se_global->g_device_lock);
91 /****************************************************************************
93 ****************************************************************************/
98 static void *scsi_inst_seq_start(
102 spin_lock(&se_global->hba_lock);
103 return seq_list_start(&se_global->g_hba_list, *pos);
106 static void *scsi_inst_seq_next(
107 struct seq_file *seq,
111 return seq_list_next(v, &se_global->g_hba_list, pos);
114 static void scsi_inst_seq_stop(struct seq_file *seq, void *v)
116 spin_unlock(&se_global->hba_lock);
119 static int scsi_inst_seq_show(struct seq_file *seq, void *v)
121 struct se_hba *hba = list_entry(v, struct se_hba, hba_list);
123 if (list_is_first(&hba->hba_list, &se_global->g_hba_list))
124 seq_puts(seq, "inst sw_indx\n");
126 seq_printf(seq, "%u %u\n", hba->hba_index, SCSI_INST_SW_INDEX);
127 seq_printf(seq, "plugin: %s version: %s\n",
128 hba->transport->name, TARGET_CORE_VERSION);
133 static const struct seq_operations scsi_inst_seq_ops = {
134 .start = scsi_inst_seq_start,
135 .next = scsi_inst_seq_next,
136 .stop = scsi_inst_seq_stop,
137 .show = scsi_inst_seq_show
140 static int scsi_inst_seq_open(struct inode *inode, struct file *file)
142 return seq_open(file, &scsi_inst_seq_ops);
145 static const struct file_operations scsi_inst_seq_fops = {
146 .owner = THIS_MODULE,
147 .open = scsi_inst_seq_open,
150 .release = seq_release,
156 static void *scsi_dev_seq_start(struct seq_file *seq, loff_t *pos)
158 return locate_hba_start(seq, pos);
161 static void *scsi_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
163 return locate_hba_next(seq, v, pos);
166 static void scsi_dev_seq_stop(struct seq_file *seq, void *v)
168 locate_hba_stop(seq, v);
171 static int scsi_dev_seq_show(struct seq_file *seq, void *v)
174 struct se_subsystem_dev *se_dev = list_entry(v, struct se_subsystem_dev,
176 struct se_device *dev = se_dev->se_dev_ptr;
180 if (list_is_first(&se_dev->g_se_dev_list, &se_global->g_se_dev_list))
181 seq_puts(seq, "inst indx role ports\n");
192 seq_printf(seq, "%u %u %s %u\n", hba->hba_index,
193 dev->dev_index, "Target", dev->dev_port_count);
195 memcpy(&str[0], (void *)DEV_T10_WWN(dev), 28);
198 for (k = 0; k < 8; k++)
199 str[k] = ISPRINT(DEV_T10_WWN(dev)->vendor[k]) ?
200 DEV_T10_WWN(dev)->vendor[k] : 0x20;
204 for (k = 0; k < 16; k++)
205 str[k+9] = ISPRINT(DEV_T10_WWN(dev)->model[k]) ?
206 DEV_T10_WWN(dev)->model[k] : 0x20;
209 seq_printf(seq, "dev_alias: %s\n", str);
214 static const struct seq_operations scsi_dev_seq_ops = {
215 .start = scsi_dev_seq_start,
216 .next = scsi_dev_seq_next,
217 .stop = scsi_dev_seq_stop,
218 .show = scsi_dev_seq_show
221 static int scsi_dev_seq_open(struct inode *inode, struct file *file)
223 return seq_open(file, &scsi_dev_seq_ops);
226 static const struct file_operations scsi_dev_seq_fops = {
227 .owner = THIS_MODULE,
228 .open = scsi_dev_seq_open,
231 .release = seq_release,
237 static void *scsi_port_seq_start(struct seq_file *seq, loff_t *pos)
239 return locate_hba_start(seq, pos);
242 static void *scsi_port_seq_next(struct seq_file *seq, void *v, loff_t *pos)
244 return locate_hba_next(seq, v, pos);
247 static void scsi_port_seq_stop(struct seq_file *seq, void *v)
249 locate_hba_stop(seq, v);
252 static int scsi_port_seq_show(struct seq_file *seq, void *v)
255 struct se_subsystem_dev *se_dev = list_entry(v, struct se_subsystem_dev,
257 struct se_device *dev = se_dev->se_dev_ptr;
258 struct se_port *sep, *sep_tmp;
260 if (list_is_first(&se_dev->g_se_dev_list, &se_global->g_se_dev_list))
261 seq_puts(seq, "inst device indx role busy_count\n");
272 /* FIXME: scsiPortBusyStatuses count */
273 spin_lock(&dev->se_port_lock);
274 list_for_each_entry_safe(sep, sep_tmp, &dev->dev_sep_list, sep_list) {
275 seq_printf(seq, "%u %u %u %s%u %u\n", hba->hba_index,
276 dev->dev_index, sep->sep_index, "Device",
279 spin_unlock(&dev->se_port_lock);
284 static const struct seq_operations scsi_port_seq_ops = {
285 .start = scsi_port_seq_start,
286 .next = scsi_port_seq_next,
287 .stop = scsi_port_seq_stop,
288 .show = scsi_port_seq_show
291 static int scsi_port_seq_open(struct inode *inode, struct file *file)
293 return seq_open(file, &scsi_port_seq_ops);
296 static const struct file_operations scsi_port_seq_fops = {
297 .owner = THIS_MODULE,
298 .open = scsi_port_seq_open,
301 .release = seq_release,
305 * SCSI Transport Table
307 static void *scsi_transport_seq_start(struct seq_file *seq, loff_t *pos)
309 return locate_hba_start(seq, pos);
312 static void *scsi_transport_seq_next(struct seq_file *seq, void *v, loff_t *pos)
314 return locate_hba_next(seq, v, pos);
317 static void scsi_transport_seq_stop(struct seq_file *seq, void *v)
319 locate_hba_stop(seq, v);
322 static int scsi_transport_seq_show(struct seq_file *seq, void *v)
325 struct se_subsystem_dev *se_dev = list_entry(v, struct se_subsystem_dev,
327 struct se_device *dev = se_dev->se_dev_ptr;
328 struct se_port *se, *se_tmp;
329 struct se_portal_group *tpg;
333 if (list_is_first(&se_dev->g_se_dev_list, &se_global->g_se_dev_list))
334 seq_puts(seq, "inst device indx dev_name\n");
345 wwn = DEV_T10_WWN(dev);
347 spin_lock(&dev->se_port_lock);
348 list_for_each_entry_safe(se, se_tmp, &dev->dev_sep_list, sep_list) {
350 sprintf(buf, "scsiTransport%s",
351 TPG_TFO(tpg)->get_fabric_name());
353 seq_printf(seq, "%u %s %u %s+%s\n",
354 hba->hba_index, /* scsiTransportIndex */
355 buf, /* scsiTransportType */
356 (TPG_TFO(tpg)->tpg_get_inst_index != NULL) ?
357 TPG_TFO(tpg)->tpg_get_inst_index(tpg) :
359 TPG_TFO(tpg)->tpg_get_wwn(tpg),
360 (strlen(wwn->unit_serial)) ?
361 /* scsiTransportDevName */
362 wwn->unit_serial : wwn->vendor);
364 spin_unlock(&dev->se_port_lock);
369 static const struct seq_operations scsi_transport_seq_ops = {
370 .start = scsi_transport_seq_start,
371 .next = scsi_transport_seq_next,
372 .stop = scsi_transport_seq_stop,
373 .show = scsi_transport_seq_show
376 static int scsi_transport_seq_open(struct inode *inode, struct file *file)
378 return seq_open(file, &scsi_transport_seq_ops);
381 static const struct file_operations scsi_transport_seq_fops = {
382 .owner = THIS_MODULE,
383 .open = scsi_transport_seq_open,
386 .release = seq_release,
390 * SCSI Target Device Table
392 static void *scsi_tgt_dev_seq_start(struct seq_file *seq, loff_t *pos)
394 return locate_hba_start(seq, pos);
397 static void *scsi_tgt_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
399 return locate_hba_next(seq, v, pos);
402 static void scsi_tgt_dev_seq_stop(struct seq_file *seq, void *v)
404 locate_hba_stop(seq, v);
408 #define LU_COUNT 1 /* for now */
409 static int scsi_tgt_dev_seq_show(struct seq_file *seq, void *v)
412 struct se_subsystem_dev *se_dev = list_entry(v, struct se_subsystem_dev,
414 struct se_device *dev = se_dev->se_dev_ptr;
415 int non_accessible_lus = 0;
418 if (list_is_first(&se_dev->g_se_dev_list, &se_global->g_se_dev_list))
419 seq_puts(seq, "inst indx num_LUs status non_access_LUs"
431 switch (dev->dev_status) {
432 case TRANSPORT_DEVICE_ACTIVATED:
433 strcpy(status, "activated");
435 case TRANSPORT_DEVICE_DEACTIVATED:
436 strcpy(status, "deactivated");
437 non_accessible_lus = 1;
439 case TRANSPORT_DEVICE_SHUTDOWN:
440 strcpy(status, "shutdown");
441 non_accessible_lus = 1;
443 case TRANSPORT_DEVICE_OFFLINE_ACTIVATED:
444 case TRANSPORT_DEVICE_OFFLINE_DEACTIVATED:
445 strcpy(status, "offline");
446 non_accessible_lus = 1;
449 sprintf(status, "unknown(%d)", dev->dev_status);
450 non_accessible_lus = 1;
453 seq_printf(seq, "%u %u %u %s %u %u\n",
454 hba->hba_index, dev->dev_index, LU_COUNT,
455 status, non_accessible_lus, dev->num_resets);
460 static const struct seq_operations scsi_tgt_dev_seq_ops = {
461 .start = scsi_tgt_dev_seq_start,
462 .next = scsi_tgt_dev_seq_next,
463 .stop = scsi_tgt_dev_seq_stop,
464 .show = scsi_tgt_dev_seq_show
467 static int scsi_tgt_dev_seq_open(struct inode *inode, struct file *file)
469 return seq_open(file, &scsi_tgt_dev_seq_ops);
472 static const struct file_operations scsi_tgt_dev_seq_fops = {
473 .owner = THIS_MODULE,
474 .open = scsi_tgt_dev_seq_open,
477 .release = seq_release,
481 * SCSI Target Port Table
483 static void *scsi_tgt_port_seq_start(struct seq_file *seq, loff_t *pos)
485 return locate_hba_start(seq, pos);
488 static void *scsi_tgt_port_seq_next(struct seq_file *seq, void *v, loff_t *pos)
490 return locate_hba_next(seq, v, pos);
493 static void scsi_tgt_port_seq_stop(struct seq_file *seq, void *v)
495 locate_hba_stop(seq, v);
498 static int scsi_tgt_port_seq_show(struct seq_file *seq, void *v)
501 struct se_subsystem_dev *se_dev = list_entry(v, struct se_subsystem_dev,
503 struct se_device *dev = se_dev->se_dev_ptr;
504 struct se_port *sep, *sep_tmp;
505 struct se_portal_group *tpg;
506 u32 rx_mbytes, tx_mbytes;
507 unsigned long long num_cmds;
510 if (list_is_first(&se_dev->g_se_dev_list, &se_global->g_se_dev_list))
511 seq_puts(seq, "inst device indx name port_index in_cmds"
512 " write_mbytes read_mbytes hs_in_cmds\n");
523 spin_lock(&dev->se_port_lock);
524 list_for_each_entry_safe(sep, sep_tmp, &dev->dev_sep_list, sep_list) {
526 sprintf(buf, "%sPort#",
527 TPG_TFO(tpg)->get_fabric_name());
529 seq_printf(seq, "%u %u %u %s%d %s%s%d ",
534 TPG_TFO(tpg)->tpg_get_wwn(tpg), "+t+",
535 TPG_TFO(tpg)->tpg_get_tag(tpg));
537 spin_lock(&sep->sep_lun->lun_sep_lock);
538 num_cmds = sep->sep_stats.cmd_pdus;
539 rx_mbytes = (sep->sep_stats.rx_data_octets >> 20);
540 tx_mbytes = (sep->sep_stats.tx_data_octets >> 20);
541 spin_unlock(&sep->sep_lun->lun_sep_lock);
543 seq_printf(seq, "%llu %u %u %u\n", num_cmds,
544 rx_mbytes, tx_mbytes, 0);
546 spin_unlock(&dev->se_port_lock);
551 static const struct seq_operations scsi_tgt_port_seq_ops = {
552 .start = scsi_tgt_port_seq_start,
553 .next = scsi_tgt_port_seq_next,
554 .stop = scsi_tgt_port_seq_stop,
555 .show = scsi_tgt_port_seq_show
558 static int scsi_tgt_port_seq_open(struct inode *inode, struct file *file)
560 return seq_open(file, &scsi_tgt_port_seq_ops);
563 static const struct file_operations scsi_tgt_port_seq_fops = {
564 .owner = THIS_MODULE,
565 .open = scsi_tgt_port_seq_open,
568 .release = seq_release,
572 * SCSI Authorized Initiator Table:
573 * It contains the SCSI Initiators authorized to be attached to one of the
574 * local Target ports.
575 * Iterates through all active TPGs and extracts the info from the ACLs
577 static void *scsi_auth_intr_seq_start(struct seq_file *seq, loff_t *pos)
579 spin_lock_bh(&se_global->se_tpg_lock);
580 return seq_list_start(&se_global->g_se_tpg_list, *pos);
583 static void *scsi_auth_intr_seq_next(struct seq_file *seq, void *v,
586 return seq_list_next(v, &se_global->g_se_tpg_list, pos);
589 static void scsi_auth_intr_seq_stop(struct seq_file *seq, void *v)
591 spin_unlock_bh(&se_global->se_tpg_lock);
594 static int scsi_auth_intr_seq_show(struct seq_file *seq, void *v)
596 struct se_portal_group *se_tpg = list_entry(v, struct se_portal_group,
598 struct se_dev_entry *deve;
600 struct se_node_acl *se_nacl;
603 if (list_is_first(&se_tpg->se_tpg_list,
604 &se_global->g_se_tpg_list))
605 seq_puts(seq, "inst dev port indx dev_or_port intr_name "
606 "map_indx att_count num_cmds read_mbytes "
607 "write_mbytes hs_num_cmds creation_time row_status\n");
612 spin_lock(&se_tpg->acl_node_lock);
613 list_for_each_entry(se_nacl, &se_tpg->acl_node_list, acl_list) {
615 atomic_inc(&se_nacl->mib_ref_count);
616 smp_mb__after_atomic_inc();
617 spin_unlock(&se_tpg->acl_node_lock);
619 spin_lock_irq(&se_nacl->device_list_lock);
620 for (j = 0; j < TRANSPORT_MAX_LUNS_PER_TPG; j++) {
621 deve = &se_nacl->device_list[j];
622 if (!(deve->lun_flags &
623 TRANSPORT_LUNFLAGS_INITIATOR_ACCESS) ||
627 if (!lun->lun_se_dev)
630 seq_printf(seq, "%u %u %u %u %u %s %u %u %u %u %u %u"
633 (TPG_TFO(se_tpg)->tpg_get_inst_index != NULL) ?
634 TPG_TFO(se_tpg)->tpg_get_inst_index(se_tpg) :
636 /* scsiDeviceIndex */
637 lun->lun_se_dev->dev_index,
638 /* scsiAuthIntrTgtPortIndex */
639 TPG_TFO(se_tpg)->tpg_get_tag(se_tpg),
640 /* scsiAuthIntrIndex */
642 /* scsiAuthIntrDevOrPort */
644 /* scsiAuthIntrName */
645 se_nacl->initiatorname[0] ?
646 se_nacl->initiatorname : NONE,
647 /* FIXME: scsiAuthIntrLunMapIndex */
649 /* scsiAuthIntrAttachedTimes */
651 /* scsiAuthIntrOutCommands */
653 /* scsiAuthIntrReadMegaBytes */
654 (u32)(deve->read_bytes >> 20),
655 /* scsiAuthIntrWrittenMegaBytes */
656 (u32)(deve->write_bytes >> 20),
657 /* FIXME: scsiAuthIntrHSOutCommands */
659 /* scsiAuthIntrLastCreation */
660 (u32)(((u32)deve->creation_time -
661 INITIAL_JIFFIES) * 100 / HZ),
662 /* FIXME: scsiAuthIntrRowStatus */
665 spin_unlock_irq(&se_nacl->device_list_lock);
667 spin_lock(&se_tpg->acl_node_lock);
668 atomic_dec(&se_nacl->mib_ref_count);
669 smp_mb__after_atomic_dec();
671 spin_unlock(&se_tpg->acl_node_lock);
676 static const struct seq_operations scsi_auth_intr_seq_ops = {
677 .start = scsi_auth_intr_seq_start,
678 .next = scsi_auth_intr_seq_next,
679 .stop = scsi_auth_intr_seq_stop,
680 .show = scsi_auth_intr_seq_show
683 static int scsi_auth_intr_seq_open(struct inode *inode, struct file *file)
685 return seq_open(file, &scsi_auth_intr_seq_ops);
688 static const struct file_operations scsi_auth_intr_seq_fops = {
689 .owner = THIS_MODULE,
690 .open = scsi_auth_intr_seq_open,
693 .release = seq_release,
697 * SCSI Attached Initiator Port Table:
698 * It lists the SCSI Initiators attached to one of the local Target ports.
699 * Iterates through all active TPGs and use active sessions from each TPG
700 * to list the info fo this table.
702 static void *scsi_att_intr_port_seq_start(struct seq_file *seq, loff_t *pos)
704 spin_lock_bh(&se_global->se_tpg_lock);
705 return seq_list_start(&se_global->g_se_tpg_list, *pos);
708 static void *scsi_att_intr_port_seq_next(struct seq_file *seq, void *v,
711 return seq_list_next(v, &se_global->g_se_tpg_list, pos);
714 static void scsi_att_intr_port_seq_stop(struct seq_file *seq, void *v)
716 spin_unlock_bh(&se_global->se_tpg_lock);
719 static int scsi_att_intr_port_seq_show(struct seq_file *seq, void *v)
721 struct se_portal_group *se_tpg = list_entry(v, struct se_portal_group,
723 struct se_dev_entry *deve;
725 struct se_node_acl *se_nacl;
726 struct se_session *se_sess;
727 unsigned char buf[64];
730 if (list_is_first(&se_tpg->se_tpg_list,
731 &se_global->g_se_tpg_list))
732 seq_puts(seq, "inst dev port indx port_auth_indx port_name"
738 spin_lock(&se_tpg->session_lock);
739 list_for_each_entry(se_sess, &se_tpg->tpg_sess_list, sess_list) {
740 if ((TPG_TFO(se_tpg)->sess_logged_in(se_sess)) ||
741 (!se_sess->se_node_acl) ||
742 (!se_sess->se_node_acl->device_list))
745 atomic_inc(&se_sess->mib_ref_count);
746 smp_mb__after_atomic_inc();
747 se_nacl = se_sess->se_node_acl;
748 atomic_inc(&se_nacl->mib_ref_count);
749 smp_mb__after_atomic_inc();
750 spin_unlock(&se_tpg->session_lock);
752 spin_lock_irq(&se_nacl->device_list_lock);
753 for (j = 0; j < TRANSPORT_MAX_LUNS_PER_TPG; j++) {
754 deve = &se_nacl->device_list[j];
755 if (!(deve->lun_flags &
756 TRANSPORT_LUNFLAGS_INITIATOR_ACCESS) ||
761 if (!lun->lun_se_dev)
765 if (TPG_TFO(se_tpg)->sess_get_initiator_sid != NULL)
766 TPG_TFO(se_tpg)->sess_get_initiator_sid(
767 se_sess, (unsigned char *)&buf[0], 64);
769 seq_printf(seq, "%u %u %u %u %u %s+i+%s\n",
771 (TPG_TFO(se_tpg)->tpg_get_inst_index != NULL) ?
772 TPG_TFO(se_tpg)->tpg_get_inst_index(se_tpg) :
774 /* scsiDeviceIndex */
775 lun->lun_se_dev->dev_index,
777 TPG_TFO(se_tpg)->tpg_get_tag(se_tpg),
778 /* scsiAttIntrPortIndex */
779 (TPG_TFO(se_tpg)->sess_get_index != NULL) ?
780 TPG_TFO(se_tpg)->sess_get_index(se_sess) :
782 /* scsiAttIntrPortAuthIntrIdx */
784 /* scsiAttIntrPortName */
785 se_nacl->initiatorname[0] ?
786 se_nacl->initiatorname : NONE,
787 /* scsiAttIntrPortIdentifier */
790 spin_unlock_irq(&se_nacl->device_list_lock);
792 spin_lock(&se_tpg->session_lock);
793 atomic_dec(&se_nacl->mib_ref_count);
794 smp_mb__after_atomic_dec();
795 atomic_dec(&se_sess->mib_ref_count);
796 smp_mb__after_atomic_dec();
798 spin_unlock(&se_tpg->session_lock);
803 static const struct seq_operations scsi_att_intr_port_seq_ops = {
804 .start = scsi_att_intr_port_seq_start,
805 .next = scsi_att_intr_port_seq_next,
806 .stop = scsi_att_intr_port_seq_stop,
807 .show = scsi_att_intr_port_seq_show
810 static int scsi_att_intr_port_seq_open(struct inode *inode, struct file *file)
812 return seq_open(file, &scsi_att_intr_port_seq_ops);
815 static const struct file_operations scsi_att_intr_port_seq_fops = {
816 .owner = THIS_MODULE,
817 .open = scsi_att_intr_port_seq_open,
820 .release = seq_release,
824 * SCSI Logical Unit Table
826 static void *scsi_lu_seq_start(struct seq_file *seq, loff_t *pos)
828 return locate_hba_start(seq, pos);
831 static void *scsi_lu_seq_next(struct seq_file *seq, void *v, loff_t *pos)
833 return locate_hba_next(seq, v, pos);
836 static void scsi_lu_seq_stop(struct seq_file *seq, void *v)
838 locate_hba_stop(seq, v);
841 #define SCSI_LU_INDEX 1
842 static int scsi_lu_seq_show(struct seq_file *seq, void *v)
845 struct se_subsystem_dev *se_dev = list_entry(v, struct se_subsystem_dev,
847 struct se_device *dev = se_dev->se_dev_ptr;
851 if (list_is_first(&se_dev->g_se_dev_list, &se_global->g_se_dev_list))
852 seq_puts(seq, "inst dev indx LUN lu_name vend prod rev"
853 " dev_type status state-bit num_cmds read_mbytes"
854 " write_mbytes resets full_stat hs_num_cmds creation_time\n");
865 /* Fix LU state, if we can read it from the device */
866 seq_printf(seq, "%u %u %u %llu %s", hba->hba_index,
867 dev->dev_index, SCSI_LU_INDEX,
868 (unsigned long long)0, /* FIXME: scsiLuDefaultLun */
869 (strlen(DEV_T10_WWN(dev)->unit_serial)) ?
871 (char *)&DEV_T10_WWN(dev)->unit_serial[0] :
874 memcpy(&str[0], (void *)DEV_T10_WWN(dev), 28);
876 for (j = 0; j < 8; j++)
877 str[j] = ISPRINT(DEV_T10_WWN(dev)->vendor[j]) ?
878 DEV_T10_WWN(dev)->vendor[j] : 0x20;
880 seq_printf(seq, " %s", str);
882 /* scsiLuProductId */
883 for (j = 0; j < 16; j++)
884 str[j] = ISPRINT(DEV_T10_WWN(dev)->model[j]) ?
885 DEV_T10_WWN(dev)->model[j] : 0x20;
887 seq_printf(seq, " %s", str);
889 /* scsiLuRevisionId */
890 for (j = 0; j < 4; j++)
891 str[j] = ISPRINT(DEV_T10_WWN(dev)->revision[j]) ?
892 DEV_T10_WWN(dev)->revision[j] : 0x20;
894 seq_printf(seq, " %s", str);
896 seq_printf(seq, " %u %s %s %llu %u %u %u %u %u %u\n",
897 /* scsiLuPeripheralType */
898 TRANSPORT(dev)->get_device_type(dev),
899 (dev->dev_status == TRANSPORT_DEVICE_ACTIVATED) ?
900 "available" : "notavailable", /* scsiLuStatus */
901 "exposed", /* scsiLuState */
902 (unsigned long long)dev->num_cmds,
903 /* scsiLuReadMegaBytes */
904 (u32)(dev->read_bytes >> 20),
905 /* scsiLuWrittenMegaBytes */
906 (u32)(dev->write_bytes >> 20),
907 dev->num_resets, /* scsiLuInResets */
908 0, /* scsiLuOutTaskSetFullStatus */
909 0, /* scsiLuHSInCommands */
910 (u32)(((u32)dev->creation_time - INITIAL_JIFFIES) *
916 static const struct seq_operations scsi_lu_seq_ops = {
917 .start = scsi_lu_seq_start,
918 .next = scsi_lu_seq_next,
919 .stop = scsi_lu_seq_stop,
920 .show = scsi_lu_seq_show
923 static int scsi_lu_seq_open(struct inode *inode, struct file *file)
925 return seq_open(file, &scsi_lu_seq_ops);
928 static const struct file_operations scsi_lu_seq_fops = {
929 .owner = THIS_MODULE,
930 .open = scsi_lu_seq_open,
933 .release = seq_release,
936 /****************************************************************************/
939 * Remove proc fs entries
941 void remove_scsi_target_mib(void)
943 remove_proc_entry("scsi_target/mib/scsi_inst", NULL);
944 remove_proc_entry("scsi_target/mib/scsi_dev", NULL);
945 remove_proc_entry("scsi_target/mib/scsi_port", NULL);
946 remove_proc_entry("scsi_target/mib/scsi_transport", NULL);
947 remove_proc_entry("scsi_target/mib/scsi_tgt_dev", NULL);
948 remove_proc_entry("scsi_target/mib/scsi_tgt_port", NULL);
949 remove_proc_entry("scsi_target/mib/scsi_auth_intr", NULL);
950 remove_proc_entry("scsi_target/mib/scsi_att_intr_port", NULL);
951 remove_proc_entry("scsi_target/mib/scsi_lu", NULL);
952 remove_proc_entry("scsi_target/mib", NULL);
956 * Create proc fs entries for the mib tables
958 int init_scsi_target_mib(void)
960 struct proc_dir_entry *dir_entry;
961 struct proc_dir_entry *scsi_inst_entry;
962 struct proc_dir_entry *scsi_dev_entry;
963 struct proc_dir_entry *scsi_port_entry;
964 struct proc_dir_entry *scsi_transport_entry;
965 struct proc_dir_entry *scsi_tgt_dev_entry;
966 struct proc_dir_entry *scsi_tgt_port_entry;
967 struct proc_dir_entry *scsi_auth_intr_entry;
968 struct proc_dir_entry *scsi_att_intr_port_entry;
969 struct proc_dir_entry *scsi_lu_entry;
971 dir_entry = proc_mkdir("scsi_target/mib", NULL);
973 printk(KERN_ERR "proc_mkdir() failed.\n");
978 create_proc_entry("scsi_target/mib/scsi_inst", 0, NULL);
980 scsi_inst_entry->proc_fops = &scsi_inst_seq_fops;
985 create_proc_entry("scsi_target/mib/scsi_dev", 0, NULL);
987 scsi_dev_entry->proc_fops = &scsi_dev_seq_fops;
992 create_proc_entry("scsi_target/mib/scsi_port", 0, NULL);
994 scsi_port_entry->proc_fops = &scsi_port_seq_fops;
998 scsi_transport_entry =
999 create_proc_entry("scsi_target/mib/scsi_transport", 0, NULL);
1000 if (scsi_transport_entry)
1001 scsi_transport_entry->proc_fops = &scsi_transport_seq_fops;
1005 scsi_tgt_dev_entry =
1006 create_proc_entry("scsi_target/mib/scsi_tgt_dev", 0, NULL);
1007 if (scsi_tgt_dev_entry)
1008 scsi_tgt_dev_entry->proc_fops = &scsi_tgt_dev_seq_fops;
1012 scsi_tgt_port_entry =
1013 create_proc_entry("scsi_target/mib/scsi_tgt_port", 0, NULL);
1014 if (scsi_tgt_port_entry)
1015 scsi_tgt_port_entry->proc_fops = &scsi_tgt_port_seq_fops;
1019 scsi_auth_intr_entry =
1020 create_proc_entry("scsi_target/mib/scsi_auth_intr", 0, NULL);
1021 if (scsi_auth_intr_entry)
1022 scsi_auth_intr_entry->proc_fops = &scsi_auth_intr_seq_fops;
1026 scsi_att_intr_port_entry =
1027 create_proc_entry("scsi_target/mib/scsi_att_intr_port", 0, NULL);
1028 if (scsi_att_intr_port_entry)
1029 scsi_att_intr_port_entry->proc_fops =
1030 &scsi_att_intr_port_seq_fops;
1034 scsi_lu_entry = create_proc_entry("scsi_target/mib/scsi_lu", 0, NULL);
1036 scsi_lu_entry->proc_fops = &scsi_lu_seq_fops;
1043 printk(KERN_ERR "create_proc_entry() failed.\n");
1044 remove_scsi_target_mib();
1049 * Initialize the index table for allocating unique row indexes to various mib
1052 void init_scsi_index_table(void)
1054 memset(&scsi_index_table, 0, sizeof(struct scsi_index_table));
1055 spin_lock_init(&scsi_index_table.lock);
1059 * Allocate a new row index for the entry type specified
1061 u32 scsi_get_new_index(scsi_index_t type)
1065 if ((type < 0) || (type >= SCSI_INDEX_TYPE_MAX)) {
1066 printk(KERN_ERR "Invalid index type %d\n", type);
1070 spin_lock(&scsi_index_table.lock);
1071 new_index = ++scsi_index_table.scsi_mib_index[type];
1073 new_index = ++scsi_index_table.scsi_mib_index[type];
1074 spin_unlock(&scsi_index_table.lock);
1078 EXPORT_SYMBOL(scsi_get_new_index);