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
);