aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2011-03-14 07:06:11 -0400
committerJames Bottomley <James.Bottomley@suse.de>2011-03-23 12:36:50 -0400
commit12d233842987d9972957419e427987b94f7bd7b4 (patch)
treeb3d08872b37f08aac3a9ec66e3fef49fbedb0f19 /drivers/target
parent15fb48cc40be170423fe8ddd17666aa6175315e3 (diff)
[SCSI] target: add initial statistics
This patch adds a target_core_mib.c statistics conversion for backend context struct se_subsystem_dev + struct se_device config_group based statistics in target_core_device.c using CONFIGFS_EATTR() based struct config_item_types from target_core_stat.c code. The conversion from backend /proc/scsi_target/mib/ context output to configfs default groups+attributes include scsi_dev, scsi_lu, and scsi_tgt_dev output from within individual: /sys/kernel/config/target/core/$HBA/DEV/ The legacy procfs output now appear as individual configfs attributes under: *) $HBA/$DEV/statistics/scsi_dev: |-- indx |-- inst |-- ports `-- role *) $HBA/$DEV/statistics/scsi_lu: |-- creation_time |-- dev |-- dev_type |-- full_stat |-- hs_num_cmds |-- indx |-- inst |-- lu_name |-- lun |-- num_cmds |-- prod |-- read_mbytes |-- resets |-- rev |-- state_bit |-- status |-- vend `-- write_mbytes *) $HBA/$DEV/statistics/scsi_tgt_dev: |-- indx |-- inst |-- non_access_lus |-- num_lus |-- resets `-- status The conversion from backend /proc/scsi_target/mib/ context output to configfs default groups+attributes include scsi_port, scsi_tgt_port and scsi_transport output from within individual: /sys/kernel/config/target/fabric/$WWN/tpgt_$TPGT/lun/lun_$LUN_ID/statistics/ The legacy procfs output now appear as individual configfs attributes under: *) fabric/$WWN/tpgt_$TPGT/lun/lun_$LUN_ID/statistics/scsi_port |-- busy_count |-- dev |-- indx |-- inst `-- role *) fabric/$WWN/tpgt_$TPGT/lun/lun_$LUN_ID/statistics/scsi_tgt_port |-- dev |-- hs_in_cmds |-- in_cmds |-- indx |-- inst |-- name |-- port_index |-- read_mbytes `-- write_mbytes *) fabric/$WWN/tpgt_$TPGT/lun/lun_$LUN_ID/statistics/scsi_transport |-- dev_name |-- device |-- indx `-- inst The conversion from backend /proc/scsi_target/mib/ context output to configfs default groups+attributes include scsi_att_intr_port and scsi_auth_intr output from within individual: /sys/kernel/config/target/fabric/$WWN/tpgt_$TPGT/acls/$INITIATOR_WWN/lun_$LUN_ID/statistics/ The legacy procfs output now appear as individual configfs attributes under: *) acls/$INITIATOR_WWN/lun_$LUN_ID/statistics/scsi_att_intr_port |-- dev |-- indx |-- inst |-- port |-- port_auth_indx `-- port_ident *) acls/$INITIATOR_WWN/lun_$LUN_ID/statistics/scsi_auth_intr |-- att_count |-- creation_time |-- dev |-- dev_or_port |-- hs_num_cmds |-- indx |-- inst |-- intr_name |-- map_indx |-- num_cmds |-- port |-- read_mbytes |-- row_status `-- write_mbytes Also, this includes adding struct target_fabric_configfs_template-> tfc_wwn_fabric_stats_cit and ->tfc_tpg_nacl_stat_cit respectively for use during target_core_fabric_configfs.c:target_fabric_setup_cits() Signed-off-by: Nicholas A. Bellinger <nab@linux-iscsi.org> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/target')
-rw-r--r--drivers/target/Makefile3
-rw-r--r--drivers/target/target_core_configfs.c76
-rw-r--r--drivers/target/target_core_fabric_configfs.c209
-rw-r--r--drivers/target/target_core_stat.c1810
-rw-r--r--drivers/target/target_core_stat.h8
5 files changed, 2090 insertions, 16 deletions
diff --git a/drivers/target/Makefile b/drivers/target/Makefile
index 050ee6569b2b..4f3cb788f06a 100644
--- a/drivers/target/Makefile
+++ b/drivers/target/Makefile
@@ -12,7 +12,8 @@ target_core_mod-y := target_core_configfs.o \
12 target_core_transport.o \ 12 target_core_transport.o \
13 target_core_cdb.o \ 13 target_core_cdb.o \
14 target_core_ua.o \ 14 target_core_ua.o \
15 target_core_rd.o 15 target_core_rd.o \
16 target_core_stat.o
16 17
17obj-$(CONFIG_TARGET_CORE) += target_core_mod.o 18obj-$(CONFIG_TARGET_CORE) += target_core_mod.o
18 19
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
index a38fec4acceb..a5f44a6e6e1d 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -3,8 +3,8 @@
3 * 3 *
4 * This file contains ConfigFS logic for the Generic Target Engine project. 4 * This file contains ConfigFS logic for the Generic Target Engine project.
5 * 5 *
6 * Copyright (c) 2008-2010 Rising Tide Systems 6 * Copyright (c) 2008-2011 Rising Tide Systems
7 * Copyright (c) 2008-2010 Linux-iSCSI.org 7 * Copyright (c) 2008-2011 Linux-iSCSI.org
8 * 8 *
9 * Nicholas A. Bellinger <nab@kernel.org> 9 * Nicholas A. Bellinger <nab@kernel.org>
10 * 10 *
@@ -50,6 +50,7 @@
50#include "target_core_hba.h" 50#include "target_core_hba.h"
51#include "target_core_pr.h" 51#include "target_core_pr.h"
52#include "target_core_rd.h" 52#include "target_core_rd.h"
53#include "target_core_stat.h"
53 54
54static struct list_head g_tf_list; 55static struct list_head g_tf_list;
55static struct mutex g_tf_lock; 56static struct mutex g_tf_lock;
@@ -2709,6 +2710,34 @@ static struct config_item_type target_core_alua_cit = {
2709 2710
2710/* End functions for struct config_item_type target_core_alua_cit */ 2711/* End functions for struct config_item_type target_core_alua_cit */
2711 2712
2713/* Start functions for struct config_item_type target_core_stat_cit */
2714
2715static struct config_group *target_core_stat_mkdir(
2716 struct config_group *group,
2717 const char *name)
2718{
2719 return ERR_PTR(-ENOSYS);
2720}
2721
2722static void target_core_stat_rmdir(
2723 struct config_group *group,
2724 struct config_item *item)
2725{
2726 return;
2727}
2728
2729static struct configfs_group_operations target_core_stat_group_ops = {
2730 .make_group = &target_core_stat_mkdir,
2731 .drop_item = &target_core_stat_rmdir,
2732};
2733
2734static struct config_item_type target_core_stat_cit = {
2735 .ct_group_ops = &target_core_stat_group_ops,
2736 .ct_owner = THIS_MODULE,
2737};
2738
2739/* End functions for struct config_item_type target_core_stat_cit */
2740
2712/* Start functions for struct config_item_type target_core_hba_cit */ 2741/* Start functions for struct config_item_type target_core_hba_cit */
2713 2742
2714static struct config_group *target_core_make_subdev( 2743static struct config_group *target_core_make_subdev(
@@ -2721,10 +2750,12 @@ static struct config_group *target_core_make_subdev(
2721 struct config_item *hba_ci = &group->cg_item; 2750 struct config_item *hba_ci = &group->cg_item;
2722 struct se_hba *hba = item_to_hba(hba_ci); 2751 struct se_hba *hba = item_to_hba(hba_ci);
2723 struct config_group *dev_cg = NULL, *tg_pt_gp_cg = NULL; 2752 struct config_group *dev_cg = NULL, *tg_pt_gp_cg = NULL;
2753 struct config_group *dev_stat_grp = NULL;
2754 int errno = -ENOMEM, ret;
2724 2755
2725 if (mutex_lock_interruptible(&hba->hba_access_mutex)) 2756 ret = mutex_lock_interruptible(&hba->hba_access_mutex);
2726 return NULL; 2757 if (ret)
2727 2758 return ERR_PTR(ret);
2728 /* 2759 /*
2729 * Locate the struct se_subsystem_api from parent's struct se_hba. 2760 * Locate the struct se_subsystem_api from parent's struct se_hba.
2730 */ 2761 */
@@ -2754,7 +2785,7 @@ static struct config_group *target_core_make_subdev(
2754 se_dev->se_dev_hba = hba; 2785 se_dev->se_dev_hba = hba;
2755 dev_cg = &se_dev->se_dev_group; 2786 dev_cg = &se_dev->se_dev_group;
2756 2787
2757 dev_cg->default_groups = kzalloc(sizeof(struct config_group) * 6, 2788 dev_cg->default_groups = kzalloc(sizeof(struct config_group) * 7,
2758 GFP_KERNEL); 2789 GFP_KERNEL);
2759 if (!(dev_cg->default_groups)) 2790 if (!(dev_cg->default_groups))
2760 goto out; 2791 goto out;
@@ -2786,13 +2817,17 @@ static struct config_group *target_core_make_subdev(
2786 &target_core_dev_wwn_cit); 2817 &target_core_dev_wwn_cit);
2787 config_group_init_type_name(&se_dev->t10_alua.alua_tg_pt_gps_group, 2818 config_group_init_type_name(&se_dev->t10_alua.alua_tg_pt_gps_group,
2788 "alua", &target_core_alua_tg_pt_gps_cit); 2819 "alua", &target_core_alua_tg_pt_gps_cit);
2820 config_group_init_type_name(&se_dev->dev_stat_grps.stat_group,
2821 "statistics", &target_core_stat_cit);
2822
2789 dev_cg->default_groups[0] = &se_dev->se_dev_attrib.da_group; 2823 dev_cg->default_groups[0] = &se_dev->se_dev_attrib.da_group;
2790 dev_cg->default_groups[1] = &se_dev->se_dev_pr_group; 2824 dev_cg->default_groups[1] = &se_dev->se_dev_pr_group;
2791 dev_cg->default_groups[2] = &se_dev->t10_wwn.t10_wwn_group; 2825 dev_cg->default_groups[2] = &se_dev->t10_wwn.t10_wwn_group;
2792 dev_cg->default_groups[3] = &se_dev->t10_alua.alua_tg_pt_gps_group; 2826 dev_cg->default_groups[3] = &se_dev->t10_alua.alua_tg_pt_gps_group;
2793 dev_cg->default_groups[4] = NULL; 2827 dev_cg->default_groups[4] = &se_dev->dev_stat_grps.stat_group;
2828 dev_cg->default_groups[5] = NULL;
2794 /* 2829 /*
2795 * Add core/$HBA/$DEV/alua/tg_pt_gps/default_tg_pt_gp 2830 * Add core/$HBA/$DEV/alua/default_tg_pt_gp
2796 */ 2831 */
2797 tg_pt_gp = core_alua_allocate_tg_pt_gp(se_dev, "default_tg_pt_gp", 1); 2832 tg_pt_gp = core_alua_allocate_tg_pt_gp(se_dev, "default_tg_pt_gp", 1);
2798 if (!(tg_pt_gp)) 2833 if (!(tg_pt_gp))
@@ -2812,6 +2847,17 @@ static struct config_group *target_core_make_subdev(
2812 tg_pt_gp_cg->default_groups[0] = &tg_pt_gp->tg_pt_gp_group; 2847 tg_pt_gp_cg->default_groups[0] = &tg_pt_gp->tg_pt_gp_group;
2813 tg_pt_gp_cg->default_groups[1] = NULL; 2848 tg_pt_gp_cg->default_groups[1] = NULL;
2814 T10_ALUA(se_dev)->default_tg_pt_gp = tg_pt_gp; 2849 T10_ALUA(se_dev)->default_tg_pt_gp = tg_pt_gp;
2850 /*
2851 * Add core/$HBA/$DEV/statistics/ default groups
2852 */
2853 dev_stat_grp = &DEV_STAT_GRP(se_dev)->stat_group;
2854 dev_stat_grp->default_groups = kzalloc(sizeof(struct config_group) * 4,
2855 GFP_KERNEL);
2856 if (!dev_stat_grp->default_groups) {
2857 printk(KERN_ERR "Unable to allocate dev_stat_grp->default_groups\n");
2858 goto out;
2859 }
2860 target_stat_setup_dev_default_groups(se_dev);
2815 2861
2816 printk(KERN_INFO "Target_Core_ConfigFS: Allocated struct se_subsystem_dev:" 2862 printk(KERN_INFO "Target_Core_ConfigFS: Allocated struct se_subsystem_dev:"
2817 " %p se_dev_su_ptr: %p\n", se_dev, se_dev->se_dev_su_ptr); 2863 " %p se_dev_su_ptr: %p\n", se_dev, se_dev->se_dev_su_ptr);
@@ -2823,6 +2869,8 @@ out:
2823 core_alua_free_tg_pt_gp(T10_ALUA(se_dev)->default_tg_pt_gp); 2869 core_alua_free_tg_pt_gp(T10_ALUA(se_dev)->default_tg_pt_gp);
2824 T10_ALUA(se_dev)->default_tg_pt_gp = NULL; 2870 T10_ALUA(se_dev)->default_tg_pt_gp = NULL;
2825 } 2871 }
2872 if (dev_stat_grp)
2873 kfree(dev_stat_grp->default_groups);
2826 if (tg_pt_gp_cg) 2874 if (tg_pt_gp_cg)
2827 kfree(tg_pt_gp_cg->default_groups); 2875 kfree(tg_pt_gp_cg->default_groups);
2828 if (dev_cg) 2876 if (dev_cg)
@@ -2832,7 +2880,7 @@ out:
2832 kfree(se_dev); 2880 kfree(se_dev);
2833unlock: 2881unlock:
2834 mutex_unlock(&hba->hba_access_mutex); 2882 mutex_unlock(&hba->hba_access_mutex);
2835 return NULL; 2883 return ERR_PTR(errno);
2836} 2884}
2837 2885
2838static void target_core_drop_subdev( 2886static void target_core_drop_subdev(
@@ -2844,7 +2892,7 @@ static void target_core_drop_subdev(
2844 struct se_hba *hba; 2892 struct se_hba *hba;
2845 struct se_subsystem_api *t; 2893 struct se_subsystem_api *t;
2846 struct config_item *df_item; 2894 struct config_item *df_item;
2847 struct config_group *dev_cg, *tg_pt_gp_cg; 2895 struct config_group *dev_cg, *tg_pt_gp_cg, *dev_stat_grp;
2848 int i; 2896 int i;
2849 2897
2850 hba = item_to_hba(&se_dev->se_dev_hba->hba_group.cg_item); 2898 hba = item_to_hba(&se_dev->se_dev_hba->hba_group.cg_item);
@@ -2856,6 +2904,14 @@ static void target_core_drop_subdev(
2856 list_del(&se_dev->g_se_dev_list); 2904 list_del(&se_dev->g_se_dev_list);
2857 spin_unlock(&se_global->g_device_lock); 2905 spin_unlock(&se_global->g_device_lock);
2858 2906
2907 dev_stat_grp = &DEV_STAT_GRP(se_dev)->stat_group;
2908 for (i = 0; dev_stat_grp->default_groups[i]; i++) {
2909 df_item = &dev_stat_grp->default_groups[i]->cg_item;
2910 dev_stat_grp->default_groups[i] = NULL;
2911 config_item_put(df_item);
2912 }
2913 kfree(dev_stat_grp->default_groups);
2914
2859 tg_pt_gp_cg = &T10_ALUA(se_dev)->alua_tg_pt_gps_group; 2915 tg_pt_gp_cg = &T10_ALUA(se_dev)->alua_tg_pt_gps_group;
2860 for (i = 0; tg_pt_gp_cg->default_groups[i]; i++) { 2916 for (i = 0; tg_pt_gp_cg->default_groups[i]; i++) {
2861 df_item = &tg_pt_gp_cg->default_groups[i]->cg_item; 2917 df_item = &tg_pt_gp_cg->default_groups[i]->cg_item;
diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c
index b65d1c8e7740..07ab5a3bb8e8 100644
--- a/drivers/target/target_core_fabric_configfs.c
+++ b/drivers/target/target_core_fabric_configfs.c
@@ -4,10 +4,10 @@
4 * This file contains generic fabric module configfs infrastructure for 4 * This file contains generic fabric module configfs infrastructure for
5 * TCM v4.x code 5 * TCM v4.x code
6 * 6 *
7 * Copyright (c) 2010 Rising Tide Systems 7 * Copyright (c) 2010,2011 Rising Tide Systems
8 * Copyright (c) 2010 Linux-iSCSI.org 8 * Copyright (c) 2010,2011 Linux-iSCSI.org
9 * 9 *
10 * Copyright (c) 2010 Nicholas A. Bellinger <nab@linux-iscsi.org> 10 * Copyright (c) Nicholas A. Bellinger <nab@linux-iscsi.org>
11* 11*
12 * This program is free software; you can redistribute it and/or modify 12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by 13 * it under the terms of the GNU General Public License as published by
@@ -48,6 +48,7 @@
48#include "target_core_alua.h" 48#include "target_core_alua.h"
49#include "target_core_hba.h" 49#include "target_core_hba.h"
50#include "target_core_pr.h" 50#include "target_core_pr.h"
51#include "target_core_stat.h"
51 52
52#define TF_CIT_SETUP(_name, _item_ops, _group_ops, _attrs) \ 53#define TF_CIT_SETUP(_name, _item_ops, _group_ops, _attrs) \
53static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf) \ 54static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf) \
@@ -241,6 +242,32 @@ TF_CIT_SETUP(tpg_mappedlun, &target_fabric_mappedlun_item_ops, NULL,
241 242
242/* End of tfc_tpg_mappedlun_cit */ 243/* End of tfc_tpg_mappedlun_cit */
243 244
245/* Start of tfc_tpg_mappedlun_port_cit */
246
247static struct config_group *target_core_mappedlun_stat_mkdir(
248 struct config_group *group,
249 const char *name)
250{
251 return ERR_PTR(-ENOSYS);
252}
253
254static void target_core_mappedlun_stat_rmdir(
255 struct config_group *group,
256 struct config_item *item)
257{
258 return;
259}
260
261static struct configfs_group_operations target_fabric_mappedlun_stat_group_ops = {
262 .make_group = target_core_mappedlun_stat_mkdir,
263 .drop_item = target_core_mappedlun_stat_rmdir,
264};
265
266TF_CIT_SETUP(tpg_mappedlun_stat, NULL, &target_fabric_mappedlun_stat_group_ops,
267 NULL);
268
269/* End of tfc_tpg_mappedlun_port_cit */
270
244/* Start of tfc_tpg_nacl_attrib_cit */ 271/* Start of tfc_tpg_nacl_attrib_cit */
245 272
246CONFIGFS_EATTR_OPS(target_fabric_nacl_attrib, se_node_acl, acl_attrib_group); 273CONFIGFS_EATTR_OPS(target_fabric_nacl_attrib, se_node_acl, acl_attrib_group);
@@ -294,6 +321,7 @@ static struct config_group *target_fabric_make_mappedlun(
294 struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; 321 struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
295 struct se_lun_acl *lacl; 322 struct se_lun_acl *lacl;
296 struct config_item *acl_ci; 323 struct config_item *acl_ci;
324 struct config_group *lacl_cg = NULL, *ml_stat_grp = NULL;
297 char *buf; 325 char *buf;
298 unsigned long mapped_lun; 326 unsigned long mapped_lun;
299 int ret = 0; 327 int ret = 0;
@@ -330,15 +358,42 @@ static struct config_group *target_fabric_make_mappedlun(
330 358
331 lacl = core_dev_init_initiator_node_lun_acl(se_tpg, mapped_lun, 359 lacl = core_dev_init_initiator_node_lun_acl(se_tpg, mapped_lun,
332 config_item_name(acl_ci), &ret); 360 config_item_name(acl_ci), &ret);
333 if (!(lacl)) 361 if (!(lacl)) {
362 ret = -EINVAL;
334 goto out; 363 goto out;
364 }
365
366 lacl_cg = &lacl->se_lun_group;
367 lacl_cg->default_groups = kzalloc(sizeof(struct config_group) * 2,
368 GFP_KERNEL);
369 if (!lacl_cg->default_groups) {
370 printk(KERN_ERR "Unable to allocate lacl_cg->default_groups\n");
371 ret = -ENOMEM;
372 goto out;
373 }
335 374
336 config_group_init_type_name(&lacl->se_lun_group, name, 375 config_group_init_type_name(&lacl->se_lun_group, name,
337 &TF_CIT_TMPL(tf)->tfc_tpg_mappedlun_cit); 376 &TF_CIT_TMPL(tf)->tfc_tpg_mappedlun_cit);
377 config_group_init_type_name(&lacl->ml_stat_grps.stat_group,
378 "statistics", &TF_CIT_TMPL(tf)->tfc_tpg_mappedlun_stat_cit);
379 lacl_cg->default_groups[0] = &lacl->ml_stat_grps.stat_group;
380 lacl_cg->default_groups[1] = NULL;
381
382 ml_stat_grp = &ML_STAT_GRPS(lacl)->stat_group;
383 ml_stat_grp->default_groups = kzalloc(sizeof(struct config_group) * 3,
384 GFP_KERNEL);
385 if (!ml_stat_grp->default_groups) {
386 printk(KERN_ERR "Unable to allocate ml_stat_grp->default_groups\n");
387 ret = -ENOMEM;
388 goto out;
389 }
390 target_stat_setup_mappedlun_default_groups(lacl);
338 391
339 kfree(buf); 392 kfree(buf);
340 return &lacl->se_lun_group; 393 return &lacl->se_lun_group;
341out: 394out:
395 if (lacl_cg)
396 kfree(lacl_cg->default_groups);
342 kfree(buf); 397 kfree(buf);
343 return ERR_PTR(ret); 398 return ERR_PTR(ret);
344} 399}
@@ -347,6 +402,28 @@ static void target_fabric_drop_mappedlun(
347 struct config_group *group, 402 struct config_group *group,
348 struct config_item *item) 403 struct config_item *item)
349{ 404{
405 struct se_lun_acl *lacl = container_of(to_config_group(item),
406 struct se_lun_acl, se_lun_group);
407 struct config_item *df_item;
408 struct config_group *lacl_cg = NULL, *ml_stat_grp = NULL;
409 int i;
410
411 ml_stat_grp = &ML_STAT_GRPS(lacl)->stat_group;
412 for (i = 0; ml_stat_grp->default_groups[i]; i++) {
413 df_item = &ml_stat_grp->default_groups[i]->cg_item;
414 ml_stat_grp->default_groups[i] = NULL;
415 config_item_put(df_item);
416 }
417 kfree(ml_stat_grp->default_groups);
418
419 lacl_cg = &lacl->se_lun_group;
420 for (i = 0; lacl_cg->default_groups[i]; i++) {
421 df_item = &lacl_cg->default_groups[i]->cg_item;
422 lacl_cg->default_groups[i] = NULL;
423 config_item_put(df_item);
424 }
425 kfree(lacl_cg->default_groups);
426
350 config_item_put(item); 427 config_item_put(item);
351} 428}
352 429
@@ -376,6 +453,15 @@ TF_CIT_SETUP(tpg_nacl_base, &target_fabric_nacl_base_item_ops,
376 453
377/* End of tfc_tpg_nacl_base_cit */ 454/* End of tfc_tpg_nacl_base_cit */
378 455
456/* Start of tfc_node_fabric_stats_cit */
457/*
458 * This is used as a placeholder for struct se_node_acl->acl_fabric_stat_group
459 * to allow fabrics access to ->acl_fabric_stat_group->default_groups[]
460 */
461TF_CIT_SETUP(tpg_nacl_stat, NULL, NULL, NULL);
462
463/* End of tfc_wwn_fabric_stats_cit */
464
379/* Start of tfc_tpg_nacl_cit */ 465/* Start of tfc_tpg_nacl_cit */
380 466
381static struct config_group *target_fabric_make_nodeacl( 467static struct config_group *target_fabric_make_nodeacl(
@@ -402,7 +488,8 @@ static struct config_group *target_fabric_make_nodeacl(
402 nacl_cg->default_groups[0] = &se_nacl->acl_attrib_group; 488 nacl_cg->default_groups[0] = &se_nacl->acl_attrib_group;
403 nacl_cg->default_groups[1] = &se_nacl->acl_auth_group; 489 nacl_cg->default_groups[1] = &se_nacl->acl_auth_group;
404 nacl_cg->default_groups[2] = &se_nacl->acl_param_group; 490 nacl_cg->default_groups[2] = &se_nacl->acl_param_group;
405 nacl_cg->default_groups[3] = NULL; 491 nacl_cg->default_groups[3] = &se_nacl->acl_fabric_stat_group;
492 nacl_cg->default_groups[4] = NULL;
406 493
407 config_group_init_type_name(&se_nacl->acl_group, name, 494 config_group_init_type_name(&se_nacl->acl_group, name,
408 &TF_CIT_TMPL(tf)->tfc_tpg_nacl_base_cit); 495 &TF_CIT_TMPL(tf)->tfc_tpg_nacl_base_cit);
@@ -412,6 +499,9 @@ static struct config_group *target_fabric_make_nodeacl(
412 &TF_CIT_TMPL(tf)->tfc_tpg_nacl_auth_cit); 499 &TF_CIT_TMPL(tf)->tfc_tpg_nacl_auth_cit);
413 config_group_init_type_name(&se_nacl->acl_param_group, "param", 500 config_group_init_type_name(&se_nacl->acl_param_group, "param",
414 &TF_CIT_TMPL(tf)->tfc_tpg_nacl_param_cit); 501 &TF_CIT_TMPL(tf)->tfc_tpg_nacl_param_cit);
502 config_group_init_type_name(&se_nacl->acl_fabric_stat_group,
503 "fabric_statistics",
504 &TF_CIT_TMPL(tf)->tfc_tpg_nacl_stat_cit);
415 505
416 return &se_nacl->acl_group; 506 return &se_nacl->acl_group;
417} 507}
@@ -758,6 +848,31 @@ TF_CIT_SETUP(tpg_port, &target_fabric_port_item_ops, NULL, target_fabric_port_at
758 848
759/* End of tfc_tpg_port_cit */ 849/* End of tfc_tpg_port_cit */
760 850
851/* Start of tfc_tpg_port_stat_cit */
852
853static struct config_group *target_core_port_stat_mkdir(
854 struct config_group *group,
855 const char *name)
856{
857 return ERR_PTR(-ENOSYS);
858}
859
860static void target_core_port_stat_rmdir(
861 struct config_group *group,
862 struct config_item *item)
863{
864 return;
865}
866
867static struct configfs_group_operations target_fabric_port_stat_group_ops = {
868 .make_group = target_core_port_stat_mkdir,
869 .drop_item = target_core_port_stat_rmdir,
870};
871
872TF_CIT_SETUP(tpg_port_stat, NULL, &target_fabric_port_stat_group_ops, NULL);
873
874/* End of tfc_tpg_port_stat_cit */
875
761/* Start of tfc_tpg_lun_cit */ 876/* Start of tfc_tpg_lun_cit */
762 877
763static struct config_group *target_fabric_make_lun( 878static struct config_group *target_fabric_make_lun(
@@ -768,7 +883,9 @@ static struct config_group *target_fabric_make_lun(
768 struct se_portal_group *se_tpg = container_of(group, 883 struct se_portal_group *se_tpg = container_of(group,
769 struct se_portal_group, tpg_lun_group); 884 struct se_portal_group, tpg_lun_group);
770 struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; 885 struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
886 struct config_group *lun_cg = NULL, *port_stat_grp = NULL;
771 unsigned long unpacked_lun; 887 unsigned long unpacked_lun;
888 int errno;
772 889
773 if (strstr(name, "lun_") != name) { 890 if (strstr(name, "lun_") != name) {
774 printk(KERN_ERR "Unable to locate \'_\" in" 891 printk(KERN_ERR "Unable to locate \'_\" in"
@@ -782,16 +899,64 @@ static struct config_group *target_fabric_make_lun(
782 if (!(lun)) 899 if (!(lun))
783 return ERR_PTR(-EINVAL); 900 return ERR_PTR(-EINVAL);
784 901
902 lun_cg = &lun->lun_group;
903 lun_cg->default_groups = kzalloc(sizeof(struct config_group) * 2,
904 GFP_KERNEL);
905 if (!lun_cg->default_groups) {
906 printk(KERN_ERR "Unable to allocate lun_cg->default_groups\n");
907 return ERR_PTR(-ENOMEM);
908 }
909
785 config_group_init_type_name(&lun->lun_group, name, 910 config_group_init_type_name(&lun->lun_group, name,
786 &TF_CIT_TMPL(tf)->tfc_tpg_port_cit); 911 &TF_CIT_TMPL(tf)->tfc_tpg_port_cit);
912 config_group_init_type_name(&lun->port_stat_grps.stat_group,
913 "statistics", &TF_CIT_TMPL(tf)->tfc_tpg_port_stat_cit);
914 lun_cg->default_groups[0] = &lun->port_stat_grps.stat_group;
915 lun_cg->default_groups[1] = NULL;
916
917 port_stat_grp = &PORT_STAT_GRP(lun)->stat_group;
918 port_stat_grp->default_groups = kzalloc(sizeof(struct config_group) * 3,
919 GFP_KERNEL);
920 if (!port_stat_grp->default_groups) {
921 printk(KERN_ERR "Unable to allocate port_stat_grp->default_groups\n");
922 errno = -ENOMEM;
923 goto out;
924 }
925 target_stat_setup_port_default_groups(lun);
787 926
788 return &lun->lun_group; 927 return &lun->lun_group;
928out:
929 if (lun_cg)
930 kfree(lun_cg->default_groups);
931 return ERR_PTR(errno);
789} 932}
790 933
791static void target_fabric_drop_lun( 934static void target_fabric_drop_lun(
792 struct config_group *group, 935 struct config_group *group,
793 struct config_item *item) 936 struct config_item *item)
794{ 937{
938 struct se_lun *lun = container_of(to_config_group(item),
939 struct se_lun, lun_group);
940 struct config_item *df_item;
941 struct config_group *lun_cg, *port_stat_grp;
942 int i;
943
944 port_stat_grp = &PORT_STAT_GRP(lun)->stat_group;
945 for (i = 0; port_stat_grp->default_groups[i]; i++) {
946 df_item = &port_stat_grp->default_groups[i]->cg_item;
947 port_stat_grp->default_groups[i] = NULL;
948 config_item_put(df_item);
949 }
950 kfree(port_stat_grp->default_groups);
951
952 lun_cg = &lun->lun_group;
953 for (i = 0; lun_cg->default_groups[i]; i++) {
954 df_item = &lun_cg->default_groups[i]->cg_item;
955 lun_cg->default_groups[i] = NULL;
956 config_item_put(df_item);
957 }
958 kfree(lun_cg->default_groups);
959
795 config_item_put(item); 960 config_item_put(item);
796} 961}
797 962
@@ -946,6 +1111,15 @@ TF_CIT_SETUP(tpg, &target_fabric_tpg_item_ops, &target_fabric_tpg_group_ops,
946 1111
947/* End of tfc_tpg_cit */ 1112/* End of tfc_tpg_cit */
948 1113
1114/* Start of tfc_wwn_fabric_stats_cit */
1115/*
1116 * This is used as a placeholder for struct se_wwn->fabric_stat_group
1117 * to allow fabrics access to ->fabric_stat_group->default_groups[]
1118 */
1119TF_CIT_SETUP(wwn_fabric_stats, NULL, NULL, NULL);
1120
1121/* End of tfc_wwn_fabric_stats_cit */
1122
949/* Start of tfc_wwn_cit */ 1123/* Start of tfc_wwn_cit */
950 1124
951static struct config_group *target_fabric_make_wwn( 1125static struct config_group *target_fabric_make_wwn(
@@ -966,8 +1140,17 @@ static struct config_group *target_fabric_make_wwn(
966 return ERR_PTR(-EINVAL); 1140 return ERR_PTR(-EINVAL);
967 1141
968 wwn->wwn_tf = tf; 1142 wwn->wwn_tf = tf;
1143 /*
1144 * Setup default groups from pre-allocated wwn->wwn_default_groups
1145 */
1146 wwn->wwn_group.default_groups = wwn->wwn_default_groups;
1147 wwn->wwn_group.default_groups[0] = &wwn->fabric_stat_group;
1148 wwn->wwn_group.default_groups[1] = NULL;
1149
969 config_group_init_type_name(&wwn->wwn_group, name, 1150 config_group_init_type_name(&wwn->wwn_group, name,
970 &TF_CIT_TMPL(tf)->tfc_tpg_cit); 1151 &TF_CIT_TMPL(tf)->tfc_tpg_cit);
1152 config_group_init_type_name(&wwn->fabric_stat_group, "fabric_statistics",
1153 &TF_CIT_TMPL(tf)->tfc_wwn_fabric_stats_cit);
971 1154
972 return &wwn->wwn_group; 1155 return &wwn->wwn_group;
973} 1156}
@@ -976,6 +1159,18 @@ static void target_fabric_drop_wwn(
976 struct config_group *group, 1159 struct config_group *group,
977 struct config_item *item) 1160 struct config_item *item)
978{ 1161{
1162 struct se_wwn *wwn = container_of(to_config_group(item),
1163 struct se_wwn, wwn_group);
1164 struct config_item *df_item;
1165 struct config_group *cg = &wwn->wwn_group;
1166 int i;
1167
1168 for (i = 0; cg->default_groups[i]; i++) {
1169 df_item = &cg->default_groups[i]->cg_item;
1170 cg->default_groups[i] = NULL;
1171 config_item_put(df_item);
1172 }
1173
979 config_item_put(item); 1174 config_item_put(item);
980} 1175}
981 1176
@@ -1015,9 +1210,11 @@ int target_fabric_setup_cits(struct target_fabric_configfs *tf)
1015{ 1210{
1016 target_fabric_setup_discovery_cit(tf); 1211 target_fabric_setup_discovery_cit(tf);
1017 target_fabric_setup_wwn_cit(tf); 1212 target_fabric_setup_wwn_cit(tf);
1213 target_fabric_setup_wwn_fabric_stats_cit(tf);
1018 target_fabric_setup_tpg_cit(tf); 1214 target_fabric_setup_tpg_cit(tf);
1019 target_fabric_setup_tpg_base_cit(tf); 1215 target_fabric_setup_tpg_base_cit(tf);
1020 target_fabric_setup_tpg_port_cit(tf); 1216 target_fabric_setup_tpg_port_cit(tf);
1217 target_fabric_setup_tpg_port_stat_cit(tf);
1021 target_fabric_setup_tpg_lun_cit(tf); 1218 target_fabric_setup_tpg_lun_cit(tf);
1022 target_fabric_setup_tpg_np_cit(tf); 1219 target_fabric_setup_tpg_np_cit(tf);
1023 target_fabric_setup_tpg_np_base_cit(tf); 1220 target_fabric_setup_tpg_np_base_cit(tf);
@@ -1028,7 +1225,9 @@ int target_fabric_setup_cits(struct target_fabric_configfs *tf)
1028 target_fabric_setup_tpg_nacl_attrib_cit(tf); 1225 target_fabric_setup_tpg_nacl_attrib_cit(tf);
1029 target_fabric_setup_tpg_nacl_auth_cit(tf); 1226 target_fabric_setup_tpg_nacl_auth_cit(tf);
1030 target_fabric_setup_tpg_nacl_param_cit(tf); 1227 target_fabric_setup_tpg_nacl_param_cit(tf);
1228 target_fabric_setup_tpg_nacl_stat_cit(tf);
1031 target_fabric_setup_tpg_mappedlun_cit(tf); 1229 target_fabric_setup_tpg_mappedlun_cit(tf);
1230 target_fabric_setup_tpg_mappedlun_stat_cit(tf);
1032 1231
1033 return 0; 1232 return 0;
1034} 1233}
diff --git a/drivers/target/target_core_stat.c b/drivers/target/target_core_stat.c
new file mode 100644
index 000000000000..5e3a067a7475
--- /dev/null
+++ b/drivers/target/target_core_stat.c
@@ -0,0 +1,1810 @@
1/*******************************************************************************
2 * Filename: target_core_stat.c
3 *
4 * Copyright (c) 2011 Rising Tide Systems
5 * Copyright (c) 2011 Linux-iSCSI.org
6 *
7 * Modern ConfigFS group context specific statistics based on original
8 * target_core_mib.c code
9 *
10 * Copyright (c) 2006-2007 SBE, Inc. All Rights Reserved.
11 *
12 * Nicholas A. Bellinger <nab@linux-iscsi.org>
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 *
28 ******************************************************************************/
29
30#include <linux/kernel.h>
31#include <linux/module.h>
32#include <linux/delay.h>
33#include <linux/timer.h>
34#include <linux/string.h>
35#include <linux/version.h>
36#include <generated/utsrelease.h>
37#include <linux/utsname.h>
38#include <linux/proc_fs.h>
39#include <linux/seq_file.h>
40#include <linux/blkdev.h>
41#include <linux/configfs.h>
42#include <scsi/scsi.h>
43#include <scsi/scsi_device.h>
44#include <scsi/scsi_host.h>
45
46#include <target/target_core_base.h>
47#include <target/target_core_transport.h>
48#include <target/target_core_fabric_ops.h>
49#include <target/target_core_configfs.h>
50#include <target/configfs_macros.h>
51
52#include "target_core_hba.h"
53
54#ifndef INITIAL_JIFFIES
55#define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ))
56#endif
57
58#define NONE "None"
59#define ISPRINT(a) ((a >= ' ') && (a <= '~'))
60
61#define SCSI_LU_INDEX 1
62#define LU_COUNT 1
63
64/*
65 * SCSI Device Table
66 */
67
68CONFIGFS_EATTR_STRUCT(target_stat_scsi_dev, se_dev_stat_grps);
69#define DEV_STAT_SCSI_DEV_ATTR(_name, _mode) \
70static struct target_stat_scsi_dev_attribute \
71 target_stat_scsi_dev_##_name = \
72 __CONFIGFS_EATTR(_name, _mode, \
73 target_stat_scsi_dev_show_attr_##_name, \
74 target_stat_scsi_dev_store_attr_##_name);
75
76#define DEV_STAT_SCSI_DEV_ATTR_RO(_name) \
77static struct target_stat_scsi_dev_attribute \
78 target_stat_scsi_dev_##_name = \
79 __CONFIGFS_EATTR_RO(_name, \
80 target_stat_scsi_dev_show_attr_##_name);
81
82static ssize_t target_stat_scsi_dev_show_attr_inst(
83 struct se_dev_stat_grps *sgrps, char *page)
84{
85 struct se_subsystem_dev *se_subdev = container_of(sgrps,
86 struct se_subsystem_dev, dev_stat_grps);
87 struct se_hba *hba = se_subdev->se_dev_hba;
88 struct se_device *dev = se_subdev->se_dev_ptr;
89
90 if (!dev)
91 return -ENODEV;
92
93 return snprintf(page, PAGE_SIZE, "%u\n", hba->hba_index);
94}
95DEV_STAT_SCSI_DEV_ATTR_RO(inst);
96
97static ssize_t target_stat_scsi_dev_show_attr_indx(
98 struct se_dev_stat_grps *sgrps, char *page)
99{
100 struct se_subsystem_dev *se_subdev = container_of(sgrps,
101 struct se_subsystem_dev, dev_stat_grps);
102 struct se_device *dev = se_subdev->se_dev_ptr;
103
104 if (!dev)
105 return -ENODEV;
106
107 return snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index);
108}
109DEV_STAT_SCSI_DEV_ATTR_RO(indx);
110
111static ssize_t target_stat_scsi_dev_show_attr_role(
112 struct se_dev_stat_grps *sgrps, char *page)
113{
114 struct se_subsystem_dev *se_subdev = container_of(sgrps,
115 struct se_subsystem_dev, dev_stat_grps);
116 struct se_device *dev = se_subdev->se_dev_ptr;
117
118 if (!dev)
119 return -ENODEV;
120
121 return snprintf(page, PAGE_SIZE, "Target\n");
122}
123DEV_STAT_SCSI_DEV_ATTR_RO(role);
124
125static ssize_t target_stat_scsi_dev_show_attr_ports(
126 struct se_dev_stat_grps *sgrps, char *page)
127{
128 struct se_subsystem_dev *se_subdev = container_of(sgrps,
129 struct se_subsystem_dev, dev_stat_grps);
130 struct se_device *dev = se_subdev->se_dev_ptr;
131
132 if (!dev)
133 return -ENODEV;
134
135 return snprintf(page, PAGE_SIZE, "%u\n", dev->dev_port_count);
136}
137DEV_STAT_SCSI_DEV_ATTR_RO(ports);
138
139CONFIGFS_EATTR_OPS(target_stat_scsi_dev, se_dev_stat_grps, scsi_dev_group);
140
141static struct configfs_attribute *target_stat_scsi_dev_attrs[] = {
142 &target_stat_scsi_dev_inst.attr,
143 &target_stat_scsi_dev_indx.attr,
144 &target_stat_scsi_dev_role.attr,
145 &target_stat_scsi_dev_ports.attr,
146 NULL,
147};
148
149static struct configfs_item_operations target_stat_scsi_dev_attrib_ops = {
150 .show_attribute = target_stat_scsi_dev_attr_show,
151 .store_attribute = target_stat_scsi_dev_attr_store,
152};
153
154static struct config_item_type target_stat_scsi_dev_cit = {
155 .ct_item_ops = &target_stat_scsi_dev_attrib_ops,
156 .ct_attrs = target_stat_scsi_dev_attrs,
157 .ct_owner = THIS_MODULE,
158};
159
160/*
161 * SCSI Target Device Table
162 */
163
164CONFIGFS_EATTR_STRUCT(target_stat_scsi_tgt_dev, se_dev_stat_grps);
165#define DEV_STAT_SCSI_TGT_DEV_ATTR(_name, _mode) \
166static struct target_stat_scsi_tgt_dev_attribute \
167 target_stat_scsi_tgt_dev_##_name = \
168 __CONFIGFS_EATTR(_name, _mode, \
169 target_stat_scsi_tgt_dev_show_attr_##_name, \
170 target_stat_scsi_tgt_dev_store_attr_##_name);
171
172#define DEV_STAT_SCSI_TGT_DEV_ATTR_RO(_name) \
173static struct target_stat_scsi_tgt_dev_attribute \
174 target_stat_scsi_tgt_dev_##_name = \
175 __CONFIGFS_EATTR_RO(_name, \
176 target_stat_scsi_tgt_dev_show_attr_##_name);
177
178static ssize_t target_stat_scsi_tgt_dev_show_attr_inst(
179 struct se_dev_stat_grps *sgrps, char *page)
180{
181 struct se_subsystem_dev *se_subdev = container_of(sgrps,
182 struct se_subsystem_dev, dev_stat_grps);
183 struct se_hba *hba = se_subdev->se_dev_hba;
184 struct se_device *dev = se_subdev->se_dev_ptr;
185
186 if (!dev)
187 return -ENODEV;
188
189 return snprintf(page, PAGE_SIZE, "%u\n", hba->hba_index);
190}
191DEV_STAT_SCSI_TGT_DEV_ATTR_RO(inst);
192
193static ssize_t target_stat_scsi_tgt_dev_show_attr_indx(
194 struct se_dev_stat_grps *sgrps, char *page)
195{
196 struct se_subsystem_dev *se_subdev = container_of(sgrps,
197 struct se_subsystem_dev, dev_stat_grps);
198 struct se_device *dev = se_subdev->se_dev_ptr;
199
200 if (!dev)
201 return -ENODEV;
202
203 return snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index);
204}
205DEV_STAT_SCSI_TGT_DEV_ATTR_RO(indx);
206
207static ssize_t target_stat_scsi_tgt_dev_show_attr_num_lus(
208 struct se_dev_stat_grps *sgrps, char *page)
209{
210 struct se_subsystem_dev *se_subdev = container_of(sgrps,
211 struct se_subsystem_dev, dev_stat_grps);
212 struct se_device *dev = se_subdev->se_dev_ptr;
213
214 if (!dev)
215 return -ENODEV;
216
217 return snprintf(page, PAGE_SIZE, "%u\n", LU_COUNT);
218}
219DEV_STAT_SCSI_TGT_DEV_ATTR_RO(num_lus);
220
221static ssize_t target_stat_scsi_tgt_dev_show_attr_status(
222 struct se_dev_stat_grps *sgrps, char *page)
223{
224 struct se_subsystem_dev *se_subdev = container_of(sgrps,
225 struct se_subsystem_dev, dev_stat_grps);
226 struct se_device *dev = se_subdev->se_dev_ptr;
227 char status[16];
228
229 if (!dev)
230 return -ENODEV;
231
232 switch (dev->dev_status) {
233 case TRANSPORT_DEVICE_ACTIVATED:
234 strcpy(status, "activated");
235 break;
236 case TRANSPORT_DEVICE_DEACTIVATED:
237 strcpy(status, "deactivated");
238 break;
239 case TRANSPORT_DEVICE_SHUTDOWN:
240 strcpy(status, "shutdown");
241 break;
242 case TRANSPORT_DEVICE_OFFLINE_ACTIVATED:
243 case TRANSPORT_DEVICE_OFFLINE_DEACTIVATED:
244 strcpy(status, "offline");
245 break;
246 default:
247 sprintf(status, "unknown(%d)", dev->dev_status);
248 break;
249 }
250
251 return snprintf(page, PAGE_SIZE, "%s\n", status);
252}
253DEV_STAT_SCSI_TGT_DEV_ATTR_RO(status);
254
255static ssize_t target_stat_scsi_tgt_dev_show_attr_non_access_lus(
256 struct se_dev_stat_grps *sgrps, char *page)
257{
258 struct se_subsystem_dev *se_subdev = container_of(sgrps,
259 struct se_subsystem_dev, dev_stat_grps);
260 struct se_device *dev = se_subdev->se_dev_ptr;
261 int non_accessible_lus;
262
263 if (!dev)
264 return -ENODEV;
265
266 switch (dev->dev_status) {
267 case TRANSPORT_DEVICE_ACTIVATED:
268 non_accessible_lus = 0;
269 break;
270 case TRANSPORT_DEVICE_DEACTIVATED:
271 case TRANSPORT_DEVICE_SHUTDOWN:
272 case TRANSPORT_DEVICE_OFFLINE_ACTIVATED:
273 case TRANSPORT_DEVICE_OFFLINE_DEACTIVATED:
274 default:
275 non_accessible_lus = 1;
276 break;
277 }
278
279 return snprintf(page, PAGE_SIZE, "%u\n", non_accessible_lus);
280}
281DEV_STAT_SCSI_TGT_DEV_ATTR_RO(non_access_lus);
282
283static ssize_t target_stat_scsi_tgt_dev_show_attr_resets(
284 struct se_dev_stat_grps *sgrps, char *page)
285{
286 struct se_subsystem_dev *se_subdev = container_of(sgrps,
287 struct se_subsystem_dev, dev_stat_grps);
288 struct se_device *dev = se_subdev->se_dev_ptr;
289
290 if (!dev)
291 return -ENODEV;
292
293 return snprintf(page, PAGE_SIZE, "%u\n", dev->num_resets);
294}
295DEV_STAT_SCSI_TGT_DEV_ATTR_RO(resets);
296
297
298CONFIGFS_EATTR_OPS(target_stat_scsi_tgt_dev, se_dev_stat_grps, scsi_tgt_dev_group);
299
300static struct configfs_attribute *target_stat_scsi_tgt_dev_attrs[] = {
301 &target_stat_scsi_tgt_dev_inst.attr,
302 &target_stat_scsi_tgt_dev_indx.attr,
303 &target_stat_scsi_tgt_dev_num_lus.attr,
304 &target_stat_scsi_tgt_dev_status.attr,
305 &target_stat_scsi_tgt_dev_non_access_lus.attr,
306 &target_stat_scsi_tgt_dev_resets.attr,
307 NULL,
308};
309
310static struct configfs_item_operations target_stat_scsi_tgt_dev_attrib_ops = {
311 .show_attribute = target_stat_scsi_tgt_dev_attr_show,
312 .store_attribute = target_stat_scsi_tgt_dev_attr_store,
313};
314
315static struct config_item_type target_stat_scsi_tgt_dev_cit = {
316 .ct_item_ops = &target_stat_scsi_tgt_dev_attrib_ops,
317 .ct_attrs = target_stat_scsi_tgt_dev_attrs,
318 .ct_owner = THIS_MODULE,
319};
320
321/*
322 * SCSI Logical Unit Table
323 */
324
325CONFIGFS_EATTR_STRUCT(target_stat_scsi_lu, se_dev_stat_grps);
326#define DEV_STAT_SCSI_LU_ATTR(_name, _mode) \
327static struct target_stat_scsi_lu_attribute target_stat_scsi_lu_##_name = \
328 __CONFIGFS_EATTR(_name, _mode, \
329 target_stat_scsi_lu_show_attr_##_name, \
330 target_stat_scsi_lu_store_attr_##_name);
331
332#define DEV_STAT_SCSI_LU_ATTR_RO(_name) \
333static struct target_stat_scsi_lu_attribute target_stat_scsi_lu_##_name = \
334 __CONFIGFS_EATTR_RO(_name, \
335 target_stat_scsi_lu_show_attr_##_name);
336
337static ssize_t target_stat_scsi_lu_show_attr_inst(
338 struct se_dev_stat_grps *sgrps, char *page)
339{
340 struct se_subsystem_dev *se_subdev = container_of(sgrps,
341 struct se_subsystem_dev, dev_stat_grps);
342 struct se_hba *hba = se_subdev->se_dev_hba;
343 struct se_device *dev = se_subdev->se_dev_ptr;
344
345 if (!dev)
346 return -ENODEV;
347
348 return snprintf(page, PAGE_SIZE, "%u\n", hba->hba_index);
349}
350DEV_STAT_SCSI_LU_ATTR_RO(inst);
351
352static ssize_t target_stat_scsi_lu_show_attr_dev(
353 struct se_dev_stat_grps *sgrps, char *page)
354{
355 struct se_subsystem_dev *se_subdev = container_of(sgrps,
356 struct se_subsystem_dev, dev_stat_grps);
357 struct se_device *dev = se_subdev->se_dev_ptr;
358
359 if (!dev)
360 return -ENODEV;
361
362 return snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index);
363}
364DEV_STAT_SCSI_LU_ATTR_RO(dev);
365
366static ssize_t target_stat_scsi_lu_show_attr_indx(
367 struct se_dev_stat_grps *sgrps, char *page)
368{
369 struct se_subsystem_dev *se_subdev = container_of(sgrps,
370 struct se_subsystem_dev, dev_stat_grps);
371 struct se_device *dev = se_subdev->se_dev_ptr;
372
373 if (!dev)
374 return -ENODEV;
375
376 return snprintf(page, PAGE_SIZE, "%u\n", SCSI_LU_INDEX);
377}
378DEV_STAT_SCSI_LU_ATTR_RO(indx);
379
380static ssize_t target_stat_scsi_lu_show_attr_lun(
381 struct se_dev_stat_grps *sgrps, char *page)
382{
383 struct se_subsystem_dev *se_subdev = container_of(sgrps,
384 struct se_subsystem_dev, dev_stat_grps);
385 struct se_device *dev = se_subdev->se_dev_ptr;
386
387 if (!dev)
388 return -ENODEV;
389 /* FIXME: scsiLuDefaultLun */
390 return snprintf(page, PAGE_SIZE, "%llu\n", (unsigned long long)0);
391}
392DEV_STAT_SCSI_LU_ATTR_RO(lun);
393
394static ssize_t target_stat_scsi_lu_show_attr_lu_name(
395 struct se_dev_stat_grps *sgrps, char *page)
396{
397 struct se_subsystem_dev *se_subdev = container_of(sgrps,
398 struct se_subsystem_dev, dev_stat_grps);
399 struct se_device *dev = se_subdev->se_dev_ptr;
400
401 if (!dev)
402 return -ENODEV;
403 /* scsiLuWwnName */
404 return snprintf(page, PAGE_SIZE, "%s\n",
405 (strlen(DEV_T10_WWN(dev)->unit_serial)) ?
406 (char *)&DEV_T10_WWN(dev)->unit_serial[0] : "None");
407}
408DEV_STAT_SCSI_LU_ATTR_RO(lu_name);
409
410static ssize_t target_stat_scsi_lu_show_attr_vend(
411 struct se_dev_stat_grps *sgrps, char *page)
412{
413 struct se_subsystem_dev *se_subdev = container_of(sgrps,
414 struct se_subsystem_dev, dev_stat_grps);
415 struct se_device *dev = se_subdev->se_dev_ptr;
416 int j;
417 char str[28];
418
419 if (!dev)
420 return -ENODEV;
421 /* scsiLuVendorId */
422 memcpy(&str[0], (void *)DEV_T10_WWN(dev), 28);
423 for (j = 0; j < 8; j++)
424 str[j] = ISPRINT(DEV_T10_WWN(dev)->vendor[j]) ?
425 DEV_T10_WWN(dev)->vendor[j] : 0x20;
426 str[8] = 0;
427 return snprintf(page, PAGE_SIZE, "%s\n", str);
428}
429DEV_STAT_SCSI_LU_ATTR_RO(vend);
430
431static ssize_t target_stat_scsi_lu_show_attr_prod(
432 struct se_dev_stat_grps *sgrps, char *page)
433{
434 struct se_subsystem_dev *se_subdev = container_of(sgrps,
435 struct se_subsystem_dev, dev_stat_grps);
436 struct se_device *dev = se_subdev->se_dev_ptr;
437 int j;
438 char str[28];
439
440 if (!dev)
441 return -ENODEV;
442
443 /* scsiLuProductId */
444 memcpy(&str[0], (void *)DEV_T10_WWN(dev), 28);
445 for (j = 0; j < 16; j++)
446 str[j] = ISPRINT(DEV_T10_WWN(dev)->model[j]) ?
447 DEV_T10_WWN(dev)->model[j] : 0x20;
448 str[16] = 0;
449 return snprintf(page, PAGE_SIZE, "%s\n", str);
450}
451DEV_STAT_SCSI_LU_ATTR_RO(prod);
452
453static ssize_t target_stat_scsi_lu_show_attr_rev(
454 struct se_dev_stat_grps *sgrps, char *page)
455{
456 struct se_subsystem_dev *se_subdev = container_of(sgrps,
457 struct se_subsystem_dev, dev_stat_grps);
458 struct se_device *dev = se_subdev->se_dev_ptr;
459 int j;
460 char str[28];
461
462 if (!dev)
463 return -ENODEV;
464
465 /* scsiLuRevisionId */
466 memcpy(&str[0], (void *)DEV_T10_WWN(dev), 28);
467 for (j = 0; j < 4; j++)
468 str[j] = ISPRINT(DEV_T10_WWN(dev)->revision[j]) ?
469 DEV_T10_WWN(dev)->revision[j] : 0x20;
470 str[4] = 0;
471 return snprintf(page, PAGE_SIZE, "%s\n", str);
472}
473DEV_STAT_SCSI_LU_ATTR_RO(rev);
474
475static ssize_t target_stat_scsi_lu_show_attr_dev_type(
476 struct se_dev_stat_grps *sgrps, char *page)
477{
478 struct se_subsystem_dev *se_subdev = container_of(sgrps,
479 struct se_subsystem_dev, dev_stat_grps);
480 struct se_device *dev = se_subdev->se_dev_ptr;
481
482 if (!dev)
483 return -ENODEV;
484
485 /* scsiLuPeripheralType */
486 return snprintf(page, PAGE_SIZE, "%u\n",
487 TRANSPORT(dev)->get_device_type(dev));
488}
489DEV_STAT_SCSI_LU_ATTR_RO(dev_type);
490
491static ssize_t target_stat_scsi_lu_show_attr_status(
492 struct se_dev_stat_grps *sgrps, char *page)
493{
494 struct se_subsystem_dev *se_subdev = container_of(sgrps,
495 struct se_subsystem_dev, dev_stat_grps);
496 struct se_device *dev = se_subdev->se_dev_ptr;
497
498 if (!dev)
499 return -ENODEV;
500
501 /* scsiLuStatus */
502 return snprintf(page, PAGE_SIZE, "%s\n",
503 (dev->dev_status == TRANSPORT_DEVICE_ACTIVATED) ?
504 "available" : "notavailable");
505}
506DEV_STAT_SCSI_LU_ATTR_RO(status);
507
508static ssize_t target_stat_scsi_lu_show_attr_state_bit(
509 struct se_dev_stat_grps *sgrps, char *page)
510{
511 struct se_subsystem_dev *se_subdev = container_of(sgrps,
512 struct se_subsystem_dev, dev_stat_grps);
513 struct se_device *dev = se_subdev->se_dev_ptr;
514
515 if (!dev)
516 return -ENODEV;
517
518 /* scsiLuState */
519 return snprintf(page, PAGE_SIZE, "exposed\n");
520}
521DEV_STAT_SCSI_LU_ATTR_RO(state_bit);
522
523static ssize_t target_stat_scsi_lu_show_attr_num_cmds(
524 struct se_dev_stat_grps *sgrps, char *page)
525{
526 struct se_subsystem_dev *se_subdev = container_of(sgrps,
527 struct se_subsystem_dev, dev_stat_grps);
528 struct se_device *dev = se_subdev->se_dev_ptr;
529
530 if (!dev)
531 return -ENODEV;
532
533 /* scsiLuNumCommands */
534 return snprintf(page, PAGE_SIZE, "%llu\n",
535 (unsigned long long)dev->num_cmds);
536}
537DEV_STAT_SCSI_LU_ATTR_RO(num_cmds);
538
539static ssize_t target_stat_scsi_lu_show_attr_read_mbytes(
540 struct se_dev_stat_grps *sgrps, char *page)
541{
542 struct se_subsystem_dev *se_subdev = container_of(sgrps,
543 struct se_subsystem_dev, dev_stat_grps);
544 struct se_device *dev = se_subdev->se_dev_ptr;
545
546 if (!dev)
547 return -ENODEV;
548
549 /* scsiLuReadMegaBytes */
550 return snprintf(page, PAGE_SIZE, "%u\n", (u32)(dev->read_bytes >> 20));
551}
552DEV_STAT_SCSI_LU_ATTR_RO(read_mbytes);
553
554static ssize_t target_stat_scsi_lu_show_attr_write_mbytes(
555 struct se_dev_stat_grps *sgrps, char *page)
556{
557 struct se_subsystem_dev *se_subdev = container_of(sgrps,
558 struct se_subsystem_dev, dev_stat_grps);
559 struct se_device *dev = se_subdev->se_dev_ptr;
560
561 if (!dev)
562 return -ENODEV;
563
564 /* scsiLuWrittenMegaBytes */
565 return snprintf(page, PAGE_SIZE, "%u\n", (u32)(dev->write_bytes >> 20));
566}
567DEV_STAT_SCSI_LU_ATTR_RO(write_mbytes);
568
569static ssize_t target_stat_scsi_lu_show_attr_resets(
570 struct se_dev_stat_grps *sgrps, char *page)
571{
572 struct se_subsystem_dev *se_subdev = container_of(sgrps,
573 struct se_subsystem_dev, dev_stat_grps);
574 struct se_device *dev = se_subdev->se_dev_ptr;
575
576 if (!dev)
577 return -ENODEV;
578
579 /* scsiLuInResets */
580 return snprintf(page, PAGE_SIZE, "%u\n", dev->num_resets);
581}
582DEV_STAT_SCSI_LU_ATTR_RO(resets);
583
584static ssize_t target_stat_scsi_lu_show_attr_full_stat(
585 struct se_dev_stat_grps *sgrps, char *page)
586{
587 struct se_subsystem_dev *se_subdev = container_of(sgrps,
588 struct se_subsystem_dev, dev_stat_grps);
589 struct se_device *dev = se_subdev->se_dev_ptr;
590
591 if (!dev)
592 return -ENODEV;
593
594 /* FIXME: scsiLuOutTaskSetFullStatus */
595 return snprintf(page, PAGE_SIZE, "%u\n", 0);
596}
597DEV_STAT_SCSI_LU_ATTR_RO(full_stat);
598
599static ssize_t target_stat_scsi_lu_show_attr_hs_num_cmds(
600 struct se_dev_stat_grps *sgrps, char *page)
601{
602 struct se_subsystem_dev *se_subdev = container_of(sgrps,
603 struct se_subsystem_dev, dev_stat_grps);
604 struct se_device *dev = se_subdev->se_dev_ptr;
605
606 if (!dev)
607 return -ENODEV;
608
609 /* FIXME: scsiLuHSInCommands */
610 return snprintf(page, PAGE_SIZE, "%u\n", 0);
611}
612DEV_STAT_SCSI_LU_ATTR_RO(hs_num_cmds);
613
614static ssize_t target_stat_scsi_lu_show_attr_creation_time(
615 struct se_dev_stat_grps *sgrps, char *page)
616{
617 struct se_subsystem_dev *se_subdev = container_of(sgrps,
618 struct se_subsystem_dev, dev_stat_grps);
619 struct se_device *dev = se_subdev->se_dev_ptr;
620
621 if (!dev)
622 return -ENODEV;
623
624 /* scsiLuCreationTime */
625 return snprintf(page, PAGE_SIZE, "%u\n", (u32)(((u32)dev->creation_time -
626 INITIAL_JIFFIES) * 100 / HZ));
627}
628DEV_STAT_SCSI_LU_ATTR_RO(creation_time);
629
630CONFIGFS_EATTR_OPS(target_stat_scsi_lu, se_dev_stat_grps, scsi_lu_group);
631
632static struct configfs_attribute *target_stat_scsi_lu_attrs[] = {
633 &target_stat_scsi_lu_inst.attr,
634 &target_stat_scsi_lu_dev.attr,
635 &target_stat_scsi_lu_indx.attr,
636 &target_stat_scsi_lu_lun.attr,
637 &target_stat_scsi_lu_lu_name.attr,
638 &target_stat_scsi_lu_vend.attr,
639 &target_stat_scsi_lu_prod.attr,
640 &target_stat_scsi_lu_rev.attr,
641 &target_stat_scsi_lu_dev_type.attr,
642 &target_stat_scsi_lu_status.attr,
643 &target_stat_scsi_lu_state_bit.attr,
644 &target_stat_scsi_lu_num_cmds.attr,
645 &target_stat_scsi_lu_read_mbytes.attr,
646 &target_stat_scsi_lu_write_mbytes.attr,
647 &target_stat_scsi_lu_resets.attr,
648 &target_stat_scsi_lu_full_stat.attr,
649 &target_stat_scsi_lu_hs_num_cmds.attr,
650 &target_stat_scsi_lu_creation_time.attr,
651 NULL,
652};
653
654static struct configfs_item_operations target_stat_scsi_lu_attrib_ops = {
655 .show_attribute = target_stat_scsi_lu_attr_show,
656 .store_attribute = target_stat_scsi_lu_attr_store,
657};
658
659static struct config_item_type target_stat_scsi_lu_cit = {
660 .ct_item_ops = &target_stat_scsi_lu_attrib_ops,
661 .ct_attrs = target_stat_scsi_lu_attrs,
662 .ct_owner = THIS_MODULE,
663};
664
665/*
666 * Called from target_core_configfs.c:target_core_make_subdev() to setup
667 * the target statistics groups + configfs CITs located in target_core_stat.c
668 */
669void target_stat_setup_dev_default_groups(struct se_subsystem_dev *se_subdev)
670{
671 struct config_group *dev_stat_grp = &DEV_STAT_GRP(se_subdev)->stat_group;
672
673 config_group_init_type_name(&DEV_STAT_GRP(se_subdev)->scsi_dev_group,
674 "scsi_dev", &target_stat_scsi_dev_cit);
675 config_group_init_type_name(&DEV_STAT_GRP(se_subdev)->scsi_tgt_dev_group,
676 "scsi_tgt_dev", &target_stat_scsi_tgt_dev_cit);
677 config_group_init_type_name(&DEV_STAT_GRP(se_subdev)->scsi_lu_group,
678 "scsi_lu", &target_stat_scsi_lu_cit);
679
680 dev_stat_grp->default_groups[0] = &DEV_STAT_GRP(se_subdev)->scsi_dev_group;
681 dev_stat_grp->default_groups[1] = &DEV_STAT_GRP(se_subdev)->scsi_tgt_dev_group;
682 dev_stat_grp->default_groups[2] = &DEV_STAT_GRP(se_subdev)->scsi_lu_group;
683 dev_stat_grp->default_groups[3] = NULL;
684}
685
686/*
687 * SCSI Port Table
688 */
689
690CONFIGFS_EATTR_STRUCT(target_stat_scsi_port, se_port_stat_grps);
691#define DEV_STAT_SCSI_PORT_ATTR(_name, _mode) \
692static struct target_stat_scsi_port_attribute \
693 target_stat_scsi_port_##_name = \
694 __CONFIGFS_EATTR(_name, _mode, \
695 target_stat_scsi_port_show_attr_##_name, \
696 target_stat_scsi_port_store_attr_##_name);
697
698#define DEV_STAT_SCSI_PORT_ATTR_RO(_name) \
699static struct target_stat_scsi_port_attribute \
700 target_stat_scsi_port_##_name = \
701 __CONFIGFS_EATTR_RO(_name, \
702 target_stat_scsi_port_show_attr_##_name);
703
704static ssize_t target_stat_scsi_port_show_attr_inst(
705 struct se_port_stat_grps *pgrps, char *page)
706{
707 struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
708 struct se_port *sep;
709 struct se_device *dev = lun->lun_se_dev;
710 struct se_hba *hba;
711 ssize_t ret;
712
713 spin_lock(&lun->lun_sep_lock);
714 sep = lun->lun_sep;
715 if (!sep) {
716 spin_unlock(&lun->lun_sep_lock);
717 return -ENODEV;
718 }
719 hba = dev->se_hba;
720 ret = snprintf(page, PAGE_SIZE, "%u\n", hba->hba_index);
721 spin_unlock(&lun->lun_sep_lock);
722 return ret;
723}
724DEV_STAT_SCSI_PORT_ATTR_RO(inst);
725
726static ssize_t target_stat_scsi_port_show_attr_dev(
727 struct se_port_stat_grps *pgrps, char *page)
728{
729 struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
730 struct se_port *sep;
731 struct se_device *dev = lun->lun_se_dev;
732 ssize_t ret;
733
734 spin_lock(&lun->lun_sep_lock);
735 sep = lun->lun_sep;
736 if (!sep) {
737 spin_unlock(&lun->lun_sep_lock);
738 return -ENODEV;
739 }
740 ret = snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index);
741 spin_unlock(&lun->lun_sep_lock);
742 return ret;
743}
744DEV_STAT_SCSI_PORT_ATTR_RO(dev);
745
746static ssize_t target_stat_scsi_port_show_attr_indx(
747 struct se_port_stat_grps *pgrps, char *page)
748{
749 struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
750 struct se_port *sep;
751 ssize_t ret;
752
753 spin_lock(&lun->lun_sep_lock);
754 sep = lun->lun_sep;
755 if (!sep) {
756 spin_unlock(&lun->lun_sep_lock);
757 return -ENODEV;
758 }
759 ret = snprintf(page, PAGE_SIZE, "%u\n", sep->sep_index);
760 spin_unlock(&lun->lun_sep_lock);
761 return ret;
762}
763DEV_STAT_SCSI_PORT_ATTR_RO(indx);
764
765static ssize_t target_stat_scsi_port_show_attr_role(
766 struct se_port_stat_grps *pgrps, char *page)
767{
768 struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
769 struct se_device *dev = lun->lun_se_dev;
770 struct se_port *sep;
771 ssize_t ret;
772
773 if (!dev)
774 return -ENODEV;
775
776 spin_lock(&lun->lun_sep_lock);
777 sep = lun->lun_sep;
778 if (!sep) {
779 spin_unlock(&lun->lun_sep_lock);
780 return -ENODEV;
781 }
782 ret = snprintf(page, PAGE_SIZE, "%s%u\n", "Device", dev->dev_index);
783 spin_unlock(&lun->lun_sep_lock);
784 return ret;
785}
786DEV_STAT_SCSI_PORT_ATTR_RO(role);
787
788static ssize_t target_stat_scsi_port_show_attr_busy_count(
789 struct se_port_stat_grps *pgrps, char *page)
790{
791 struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
792 struct se_port *sep;
793 ssize_t ret;
794
795 spin_lock(&lun->lun_sep_lock);
796 sep = lun->lun_sep;
797 if (!sep) {
798 spin_unlock(&lun->lun_sep_lock);
799 return -ENODEV;
800 }
801 /* FIXME: scsiPortBusyStatuses */
802 ret = snprintf(page, PAGE_SIZE, "%u\n", 0);
803 spin_unlock(&lun->lun_sep_lock);
804 return ret;
805}
806DEV_STAT_SCSI_PORT_ATTR_RO(busy_count);
807
808CONFIGFS_EATTR_OPS(target_stat_scsi_port, se_port_stat_grps, scsi_port_group);
809
810static struct configfs_attribute *target_stat_scsi_port_attrs[] = {
811 &target_stat_scsi_port_inst.attr,
812 &target_stat_scsi_port_dev.attr,
813 &target_stat_scsi_port_indx.attr,
814 &target_stat_scsi_port_role.attr,
815 &target_stat_scsi_port_busy_count.attr,
816 NULL,
817};
818
819static struct configfs_item_operations target_stat_scsi_port_attrib_ops = {
820 .show_attribute = target_stat_scsi_port_attr_show,
821 .store_attribute = target_stat_scsi_port_attr_store,
822};
823
824static struct config_item_type target_stat_scsi_port_cit = {
825 .ct_item_ops = &target_stat_scsi_port_attrib_ops,
826 .ct_attrs = target_stat_scsi_port_attrs,
827 .ct_owner = THIS_MODULE,
828};
829
830/*
831 * SCSI Target Port Table
832 */
833CONFIGFS_EATTR_STRUCT(target_stat_scsi_tgt_port, se_port_stat_grps);
834#define DEV_STAT_SCSI_TGT_PORT_ATTR(_name, _mode) \
835static struct target_stat_scsi_tgt_port_attribute \
836 target_stat_scsi_tgt_port_##_name = \
837 __CONFIGFS_EATTR(_name, _mode, \
838 target_stat_scsi_tgt_port_show_attr_##_name, \
839 target_stat_scsi_tgt_port_store_attr_##_name);
840
841#define DEV_STAT_SCSI_TGT_PORT_ATTR_RO(_name) \
842static struct target_stat_scsi_tgt_port_attribute \
843 target_stat_scsi_tgt_port_##_name = \
844 __CONFIGFS_EATTR_RO(_name, \
845 target_stat_scsi_tgt_port_show_attr_##_name);
846
847static ssize_t target_stat_scsi_tgt_port_show_attr_inst(
848 struct se_port_stat_grps *pgrps, char *page)
849{
850 struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
851 struct se_device *dev = lun->lun_se_dev;
852 struct se_port *sep;
853 struct se_hba *hba;
854 ssize_t ret;
855
856 spin_lock(&lun->lun_sep_lock);
857 sep = lun->lun_sep;
858 if (!sep) {
859 spin_unlock(&lun->lun_sep_lock);
860 return -ENODEV;
861 }
862 hba = dev->se_hba;
863 ret = snprintf(page, PAGE_SIZE, "%u\n", hba->hba_index);
864 spin_unlock(&lun->lun_sep_lock);
865 return ret;
866}
867DEV_STAT_SCSI_TGT_PORT_ATTR_RO(inst);
868
869static ssize_t target_stat_scsi_tgt_port_show_attr_dev(
870 struct se_port_stat_grps *pgrps, char *page)
871{
872 struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
873 struct se_device *dev = lun->lun_se_dev;
874 struct se_port *sep;
875 ssize_t ret;
876
877 spin_lock(&lun->lun_sep_lock);
878 sep = lun->lun_sep;
879 if (!sep) {
880 spin_unlock(&lun->lun_sep_lock);
881 return -ENODEV;
882 }
883 ret = snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index);
884 spin_unlock(&lun->lun_sep_lock);
885 return ret;
886}
887DEV_STAT_SCSI_TGT_PORT_ATTR_RO(dev);
888
889static ssize_t target_stat_scsi_tgt_port_show_attr_indx(
890 struct se_port_stat_grps *pgrps, char *page)
891{
892 struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
893 struct se_port *sep;
894 ssize_t ret;
895
896 spin_lock(&lun->lun_sep_lock);
897 sep = lun->lun_sep;
898 if (!sep) {
899 spin_unlock(&lun->lun_sep_lock);
900 return -ENODEV;
901 }
902 ret = snprintf(page, PAGE_SIZE, "%u\n", sep->sep_index);
903 spin_unlock(&lun->lun_sep_lock);
904 return ret;
905}
906DEV_STAT_SCSI_TGT_PORT_ATTR_RO(indx);
907
908static ssize_t target_stat_scsi_tgt_port_show_attr_name(
909 struct se_port_stat_grps *pgrps, char *page)
910{
911 struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
912 struct se_port *sep;
913 struct se_portal_group *tpg;
914 ssize_t ret;
915
916 spin_lock(&lun->lun_sep_lock);
917 sep = lun->lun_sep;
918 if (!sep) {
919 spin_unlock(&lun->lun_sep_lock);
920 return -ENODEV;
921 }
922 tpg = sep->sep_tpg;
923
924 ret = snprintf(page, PAGE_SIZE, "%sPort#%u\n",
925 TPG_TFO(tpg)->get_fabric_name(), sep->sep_index);
926 spin_unlock(&lun->lun_sep_lock);
927 return ret;
928}
929DEV_STAT_SCSI_TGT_PORT_ATTR_RO(name);
930
931static ssize_t target_stat_scsi_tgt_port_show_attr_port_index(
932 struct se_port_stat_grps *pgrps, char *page)
933{
934 struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
935 struct se_port *sep;
936 struct se_portal_group *tpg;
937 ssize_t ret;
938
939 spin_lock(&lun->lun_sep_lock);
940 sep = lun->lun_sep;
941 if (!sep) {
942 spin_unlock(&lun->lun_sep_lock);
943 return -ENODEV;
944 }
945 tpg = sep->sep_tpg;
946
947 ret = snprintf(page, PAGE_SIZE, "%s%s%d\n",
948 TPG_TFO(tpg)->tpg_get_wwn(tpg), "+t+",
949 TPG_TFO(tpg)->tpg_get_tag(tpg));
950 spin_unlock(&lun->lun_sep_lock);
951 return ret;
952}
953DEV_STAT_SCSI_TGT_PORT_ATTR_RO(port_index);
954
955static ssize_t target_stat_scsi_tgt_port_show_attr_in_cmds(
956 struct se_port_stat_grps *pgrps, char *page)
957{
958 struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
959 struct se_port *sep;
960 struct se_portal_group *tpg;
961 ssize_t ret;
962
963 spin_lock(&lun->lun_sep_lock);
964 sep = lun->lun_sep;
965 if (!sep) {
966 spin_unlock(&lun->lun_sep_lock);
967 return -ENODEV;
968 }
969 tpg = sep->sep_tpg;
970
971 ret = snprintf(page, PAGE_SIZE, "%llu\n", sep->sep_stats.cmd_pdus);
972 spin_unlock(&lun->lun_sep_lock);
973 return ret;
974}
975DEV_STAT_SCSI_TGT_PORT_ATTR_RO(in_cmds);
976
977static ssize_t target_stat_scsi_tgt_port_show_attr_write_mbytes(
978 struct se_port_stat_grps *pgrps, char *page)
979{
980 struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
981 struct se_port *sep;
982 struct se_portal_group *tpg;
983 ssize_t ret;
984
985 spin_lock(&lun->lun_sep_lock);
986 sep = lun->lun_sep;
987 if (!sep) {
988 spin_unlock(&lun->lun_sep_lock);
989 return -ENODEV;
990 }
991 tpg = sep->sep_tpg;
992
993 ret = snprintf(page, PAGE_SIZE, "%u\n",
994 (u32)(sep->sep_stats.rx_data_octets >> 20));
995 spin_unlock(&lun->lun_sep_lock);
996 return ret;
997}
998DEV_STAT_SCSI_TGT_PORT_ATTR_RO(write_mbytes);
999
1000static ssize_t target_stat_scsi_tgt_port_show_attr_read_mbytes(
1001 struct se_port_stat_grps *pgrps, char *page)
1002{
1003 struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
1004 struct se_port *sep;
1005 struct se_portal_group *tpg;
1006 ssize_t ret;
1007
1008 spin_lock(&lun->lun_sep_lock);
1009 sep = lun->lun_sep;
1010 if (!sep) {
1011 spin_unlock(&lun->lun_sep_lock);
1012 return -ENODEV;
1013 }
1014 tpg = sep->sep_tpg;
1015
1016 ret = snprintf(page, PAGE_SIZE, "%u\n",
1017 (u32)(sep->sep_stats.tx_data_octets >> 20));
1018 spin_unlock(&lun->lun_sep_lock);
1019 return ret;
1020}
1021DEV_STAT_SCSI_TGT_PORT_ATTR_RO(read_mbytes);
1022
1023static ssize_t target_stat_scsi_tgt_port_show_attr_hs_in_cmds(
1024 struct se_port_stat_grps *pgrps, char *page)
1025{
1026 struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
1027 struct se_port *sep;
1028 struct se_portal_group *tpg;
1029 ssize_t ret;
1030
1031 spin_lock(&lun->lun_sep_lock);
1032 sep = lun->lun_sep;
1033 if (!sep) {
1034 spin_unlock(&lun->lun_sep_lock);
1035 return -ENODEV;
1036 }
1037 tpg = sep->sep_tpg;
1038
1039 /* FIXME: scsiTgtPortHsInCommands */
1040 ret = snprintf(page, PAGE_SIZE, "%u\n", 0);
1041 spin_unlock(&lun->lun_sep_lock);
1042 return ret;
1043}
1044DEV_STAT_SCSI_TGT_PORT_ATTR_RO(hs_in_cmds);
1045
1046CONFIGFS_EATTR_OPS(target_stat_scsi_tgt_port, se_port_stat_grps,
1047 scsi_tgt_port_group);
1048
1049static struct configfs_attribute *target_stat_scsi_tgt_port_attrs[] = {
1050 &target_stat_scsi_tgt_port_inst.attr,
1051 &target_stat_scsi_tgt_port_dev.attr,
1052 &target_stat_scsi_tgt_port_indx.attr,
1053 &target_stat_scsi_tgt_port_name.attr,
1054 &target_stat_scsi_tgt_port_port_index.attr,
1055 &target_stat_scsi_tgt_port_in_cmds.attr,
1056 &target_stat_scsi_tgt_port_write_mbytes.attr,
1057 &target_stat_scsi_tgt_port_read_mbytes.attr,
1058 &target_stat_scsi_tgt_port_hs_in_cmds.attr,
1059 NULL,
1060};
1061
1062static struct configfs_item_operations target_stat_scsi_tgt_port_attrib_ops = {
1063 .show_attribute = target_stat_scsi_tgt_port_attr_show,
1064 .store_attribute = target_stat_scsi_tgt_port_attr_store,
1065};
1066
1067static struct config_item_type target_stat_scsi_tgt_port_cit = {
1068 .ct_item_ops = &target_stat_scsi_tgt_port_attrib_ops,
1069 .ct_attrs = target_stat_scsi_tgt_port_attrs,
1070 .ct_owner = THIS_MODULE,
1071};
1072
1073/*
1074 * SCSI Transport Table
1075o */
1076
1077CONFIGFS_EATTR_STRUCT(target_stat_scsi_transport, se_port_stat_grps);
1078#define DEV_STAT_SCSI_TRANSPORT_ATTR(_name, _mode) \
1079static struct target_stat_scsi_transport_attribute \
1080 target_stat_scsi_transport_##_name = \
1081 __CONFIGFS_EATTR(_name, _mode, \
1082 target_stat_scsi_transport_show_attr_##_name, \
1083 target_stat_scsi_transport_store_attr_##_name);
1084
1085#define DEV_STAT_SCSI_TRANSPORT_ATTR_RO(_name) \
1086static struct target_stat_scsi_transport_attribute \
1087 target_stat_scsi_transport_##_name = \
1088 __CONFIGFS_EATTR_RO(_name, \
1089 target_stat_scsi_transport_show_attr_##_name);
1090
1091static ssize_t target_stat_scsi_transport_show_attr_inst(
1092 struct se_port_stat_grps *pgrps, char *page)
1093{
1094 struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
1095 struct se_device *dev = lun->lun_se_dev;
1096 struct se_port *sep;
1097 struct se_hba *hba;
1098 ssize_t ret;
1099
1100 spin_lock(&lun->lun_sep_lock);
1101 sep = lun->lun_sep;
1102 if (!sep) {
1103 spin_unlock(&lun->lun_sep_lock);
1104 return -ENODEV;
1105 }
1106
1107 hba = dev->se_hba;
1108 ret = snprintf(page, PAGE_SIZE, "%u\n", hba->hba_index);
1109 spin_unlock(&lun->lun_sep_lock);
1110 return ret;
1111}
1112DEV_STAT_SCSI_TRANSPORT_ATTR_RO(inst);
1113
1114static ssize_t target_stat_scsi_transport_show_attr_device(
1115 struct se_port_stat_grps *pgrps, char *page)
1116{
1117 struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
1118 struct se_port *sep;
1119 struct se_portal_group *tpg;
1120 ssize_t ret;
1121
1122 spin_lock(&lun->lun_sep_lock);
1123 sep = lun->lun_sep;
1124 if (!sep) {
1125 spin_unlock(&lun->lun_sep_lock);
1126 return -ENODEV;
1127 }
1128 tpg = sep->sep_tpg;
1129 /* scsiTransportType */
1130 ret = snprintf(page, PAGE_SIZE, "scsiTransport%s\n",
1131 TPG_TFO(tpg)->get_fabric_name());
1132 spin_unlock(&lun->lun_sep_lock);
1133 return ret;
1134}
1135DEV_STAT_SCSI_TRANSPORT_ATTR_RO(device);
1136
1137static ssize_t target_stat_scsi_transport_show_attr_indx(
1138 struct se_port_stat_grps *pgrps, char *page)
1139{
1140 struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
1141 struct se_port *sep;
1142 struct se_portal_group *tpg;
1143 ssize_t ret;
1144
1145 spin_lock(&lun->lun_sep_lock);
1146 sep = lun->lun_sep;
1147 if (!sep) {
1148 spin_unlock(&lun->lun_sep_lock);
1149 return -ENODEV;
1150 }
1151 tpg = sep->sep_tpg;
1152 ret = snprintf(page, PAGE_SIZE, "%u\n",
1153 TPG_TFO(tpg)->tpg_get_inst_index(tpg));
1154 spin_unlock(&lun->lun_sep_lock);
1155 return ret;
1156}
1157DEV_STAT_SCSI_TRANSPORT_ATTR_RO(indx);
1158
1159static ssize_t target_stat_scsi_transport_show_attr_dev_name(
1160 struct se_port_stat_grps *pgrps, char *page)
1161{
1162 struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
1163 struct se_device *dev = lun->lun_se_dev;
1164 struct se_port *sep;
1165 struct se_portal_group *tpg;
1166 struct t10_wwn *wwn;
1167 ssize_t ret;
1168
1169 spin_lock(&lun->lun_sep_lock);
1170 sep = lun->lun_sep;
1171 if (!sep) {
1172 spin_unlock(&lun->lun_sep_lock);
1173 return -ENODEV;
1174 }
1175 tpg = sep->sep_tpg;
1176 wwn = DEV_T10_WWN(dev);
1177 /* scsiTransportDevName */
1178 ret = snprintf(page, PAGE_SIZE, "%s+%s\n",
1179 TPG_TFO(tpg)->tpg_get_wwn(tpg),
1180 (strlen(wwn->unit_serial)) ? wwn->unit_serial :
1181 wwn->vendor);
1182 spin_unlock(&lun->lun_sep_lock);
1183 return ret;
1184}
1185DEV_STAT_SCSI_TRANSPORT_ATTR_RO(dev_name);
1186
1187CONFIGFS_EATTR_OPS(target_stat_scsi_transport, se_port_stat_grps,
1188 scsi_transport_group);
1189
1190static struct configfs_attribute *target_stat_scsi_transport_attrs[] = {
1191 &target_stat_scsi_transport_inst.attr,
1192 &target_stat_scsi_transport_device.attr,
1193 &target_stat_scsi_transport_indx.attr,
1194 &target_stat_scsi_transport_dev_name.attr,
1195 NULL,
1196};
1197
1198static struct configfs_item_operations target_stat_scsi_transport_attrib_ops = {
1199 .show_attribute = target_stat_scsi_transport_attr_show,
1200 .store_attribute = target_stat_scsi_transport_attr_store,
1201};
1202
1203static struct config_item_type target_stat_scsi_transport_cit = {
1204 .ct_item_ops = &target_stat_scsi_transport_attrib_ops,
1205 .ct_attrs = target_stat_scsi_transport_attrs,
1206 .ct_owner = THIS_MODULE,
1207};
1208
1209/*
1210 * Called from target_core_fabric_configfs.c:target_fabric_make_lun() to setup
1211 * the target port statistics groups + configfs CITs located in target_core_stat.c
1212 */
1213void target_stat_setup_port_default_groups(struct se_lun *lun)
1214{
1215 struct config_group *port_stat_grp = &PORT_STAT_GRP(lun)->stat_group;
1216
1217 config_group_init_type_name(&PORT_STAT_GRP(lun)->scsi_port_group,
1218 "scsi_port", &target_stat_scsi_port_cit);
1219 config_group_init_type_name(&PORT_STAT_GRP(lun)->scsi_tgt_port_group,
1220 "scsi_tgt_port", &target_stat_scsi_tgt_port_cit);
1221 config_group_init_type_name(&PORT_STAT_GRP(lun)->scsi_transport_group,
1222 "scsi_transport", &target_stat_scsi_transport_cit);
1223
1224 port_stat_grp->default_groups[0] = &PORT_STAT_GRP(lun)->scsi_port_group;
1225 port_stat_grp->default_groups[1] = &PORT_STAT_GRP(lun)->scsi_tgt_port_group;
1226 port_stat_grp->default_groups[2] = &PORT_STAT_GRP(lun)->scsi_transport_group;
1227 port_stat_grp->default_groups[3] = NULL;
1228}
1229
1230/*
1231 * SCSI Authorized Initiator Table
1232 */
1233
1234CONFIGFS_EATTR_STRUCT(target_stat_scsi_auth_intr, se_ml_stat_grps);
1235#define DEV_STAT_SCSI_AUTH_INTR_ATTR(_name, _mode) \
1236static struct target_stat_scsi_auth_intr_attribute \
1237 target_stat_scsi_auth_intr_##_name = \
1238 __CONFIGFS_EATTR(_name, _mode, \
1239 target_stat_scsi_auth_intr_show_attr_##_name, \
1240 target_stat_scsi_auth_intr_store_attr_##_name);
1241
1242#define DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(_name) \
1243static struct target_stat_scsi_auth_intr_attribute \
1244 target_stat_scsi_auth_intr_##_name = \
1245 __CONFIGFS_EATTR_RO(_name, \
1246 target_stat_scsi_auth_intr_show_attr_##_name);
1247
1248static ssize_t target_stat_scsi_auth_intr_show_attr_inst(
1249 struct se_ml_stat_grps *lgrps, char *page)
1250{
1251 struct se_lun_acl *lacl = container_of(lgrps,
1252 struct se_lun_acl, ml_stat_grps);
1253 struct se_node_acl *nacl = lacl->se_lun_nacl;
1254 struct se_dev_entry *deve;
1255 struct se_portal_group *tpg;
1256 ssize_t ret;
1257
1258 spin_lock_irq(&nacl->device_list_lock);
1259 deve = &nacl->device_list[lacl->mapped_lun];
1260 if (!deve->se_lun || !deve->se_lun_acl) {
1261 spin_unlock_irq(&nacl->device_list_lock);
1262 return -ENODEV;
1263 }
1264 tpg = nacl->se_tpg;
1265 /* scsiInstIndex */
1266 ret = snprintf(page, PAGE_SIZE, "%u\n",
1267 TPG_TFO(tpg)->tpg_get_inst_index(tpg));
1268 spin_unlock_irq(&nacl->device_list_lock);
1269 return ret;
1270}
1271DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(inst);
1272
1273static ssize_t target_stat_scsi_auth_intr_show_attr_dev(
1274 struct se_ml_stat_grps *lgrps, char *page)
1275{
1276 struct se_lun_acl *lacl = container_of(lgrps,
1277 struct se_lun_acl, ml_stat_grps);
1278 struct se_node_acl *nacl = lacl->se_lun_nacl;
1279 struct se_dev_entry *deve;
1280 struct se_lun *lun;
1281 struct se_portal_group *tpg;
1282 ssize_t ret;
1283
1284 spin_lock_irq(&nacl->device_list_lock);
1285 deve = &nacl->device_list[lacl->mapped_lun];
1286 if (!deve->se_lun || !deve->se_lun_acl) {
1287 spin_unlock_irq(&nacl->device_list_lock);
1288 return -ENODEV;
1289 }
1290 tpg = nacl->se_tpg;
1291 lun = deve->se_lun;
1292 /* scsiDeviceIndex */
1293 ret = snprintf(page, PAGE_SIZE, "%u\n", lun->lun_se_dev->dev_index);
1294 spin_unlock_irq(&nacl->device_list_lock);
1295 return ret;
1296}
1297DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(dev);
1298
1299static ssize_t target_stat_scsi_auth_intr_show_attr_port(
1300 struct se_ml_stat_grps *lgrps, char *page)
1301{
1302 struct se_lun_acl *lacl = container_of(lgrps,
1303 struct se_lun_acl, ml_stat_grps);
1304 struct se_node_acl *nacl = lacl->se_lun_nacl;
1305 struct se_dev_entry *deve;
1306 struct se_portal_group *tpg;
1307 ssize_t ret;
1308
1309 spin_lock_irq(&nacl->device_list_lock);
1310 deve = &nacl->device_list[lacl->mapped_lun];
1311 if (!deve->se_lun || !deve->se_lun_acl) {
1312 spin_unlock_irq(&nacl->device_list_lock);
1313 return -ENODEV;
1314 }
1315 tpg = nacl->se_tpg;
1316 /* scsiAuthIntrTgtPortIndex */
1317 ret = snprintf(page, PAGE_SIZE, "%u\n", TPG_TFO(tpg)->tpg_get_tag(tpg));
1318 spin_unlock_irq(&nacl->device_list_lock);
1319 return ret;
1320}
1321DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(port);
1322
1323static ssize_t target_stat_scsi_auth_intr_show_attr_indx(
1324 struct se_ml_stat_grps *lgrps, char *page)
1325{
1326 struct se_lun_acl *lacl = container_of(lgrps,
1327 struct se_lun_acl, ml_stat_grps);
1328 struct se_node_acl *nacl = lacl->se_lun_nacl;
1329 struct se_dev_entry *deve;
1330 ssize_t ret;
1331
1332 spin_lock_irq(&nacl->device_list_lock);
1333 deve = &nacl->device_list[lacl->mapped_lun];
1334 if (!deve->se_lun || !deve->se_lun_acl) {
1335 spin_unlock_irq(&nacl->device_list_lock);
1336 return -ENODEV;
1337 }
1338 /* scsiAuthIntrIndex */
1339 ret = snprintf(page, PAGE_SIZE, "%u\n", nacl->acl_index);
1340 spin_unlock_irq(&nacl->device_list_lock);
1341 return ret;
1342}
1343DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(indx);
1344
1345static ssize_t target_stat_scsi_auth_intr_show_attr_dev_or_port(
1346 struct se_ml_stat_grps *lgrps, char *page)
1347{
1348 struct se_lun_acl *lacl = container_of(lgrps,
1349 struct se_lun_acl, ml_stat_grps);
1350 struct se_node_acl *nacl = lacl->se_lun_nacl;
1351 struct se_dev_entry *deve;
1352 ssize_t ret;
1353
1354 spin_lock_irq(&nacl->device_list_lock);
1355 deve = &nacl->device_list[lacl->mapped_lun];
1356 if (!deve->se_lun || !deve->se_lun_acl) {
1357 spin_unlock_irq(&nacl->device_list_lock);
1358 return -ENODEV;
1359 }
1360 /* scsiAuthIntrDevOrPort */
1361 ret = snprintf(page, PAGE_SIZE, "%u\n", 1);
1362 spin_unlock_irq(&nacl->device_list_lock);
1363 return ret;
1364}
1365DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(dev_or_port);
1366
1367static ssize_t target_stat_scsi_auth_intr_show_attr_intr_name(
1368 struct se_ml_stat_grps *lgrps, char *page)
1369{
1370 struct se_lun_acl *lacl = container_of(lgrps,
1371 struct se_lun_acl, ml_stat_grps);
1372 struct se_node_acl *nacl = lacl->se_lun_nacl;
1373 struct se_dev_entry *deve;
1374 ssize_t ret;
1375
1376 spin_lock_irq(&nacl->device_list_lock);
1377 deve = &nacl->device_list[lacl->mapped_lun];
1378 if (!deve->se_lun || !deve->se_lun_acl) {
1379 spin_unlock_irq(&nacl->device_list_lock);
1380 return -ENODEV;
1381 }
1382 /* scsiAuthIntrName */
1383 ret = snprintf(page, PAGE_SIZE, "%s\n", nacl->initiatorname);
1384 spin_unlock_irq(&nacl->device_list_lock);
1385 return ret;
1386}
1387DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(intr_name);
1388
1389static ssize_t target_stat_scsi_auth_intr_show_attr_map_indx(
1390 struct se_ml_stat_grps *lgrps, char *page)
1391{
1392 struct se_lun_acl *lacl = container_of(lgrps,
1393 struct se_lun_acl, ml_stat_grps);
1394 struct se_node_acl *nacl = lacl->se_lun_nacl;
1395 struct se_dev_entry *deve;
1396 ssize_t ret;
1397
1398 spin_lock_irq(&nacl->device_list_lock);
1399 deve = &nacl->device_list[lacl->mapped_lun];
1400 if (!deve->se_lun || !deve->se_lun_acl) {
1401 spin_unlock_irq(&nacl->device_list_lock);
1402 return -ENODEV;
1403 }
1404 /* FIXME: scsiAuthIntrLunMapIndex */
1405 ret = snprintf(page, PAGE_SIZE, "%u\n", 0);
1406 spin_unlock_irq(&nacl->device_list_lock);
1407 return ret;
1408}
1409DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(map_indx);
1410
1411static ssize_t target_stat_scsi_auth_intr_show_attr_att_count(
1412 struct se_ml_stat_grps *lgrps, char *page)
1413{
1414 struct se_lun_acl *lacl = container_of(lgrps,
1415 struct se_lun_acl, ml_stat_grps);
1416 struct se_node_acl *nacl = lacl->se_lun_nacl;
1417 struct se_dev_entry *deve;
1418 ssize_t ret;
1419
1420 spin_lock_irq(&nacl->device_list_lock);
1421 deve = &nacl->device_list[lacl->mapped_lun];
1422 if (!deve->se_lun || !deve->se_lun_acl) {
1423 spin_unlock_irq(&nacl->device_list_lock);
1424 return -ENODEV;
1425 }
1426 /* scsiAuthIntrAttachedTimes */
1427 ret = snprintf(page, PAGE_SIZE, "%u\n", deve->attach_count);
1428 spin_unlock_irq(&nacl->device_list_lock);
1429 return ret;
1430}
1431DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(att_count);
1432
1433static ssize_t target_stat_scsi_auth_intr_show_attr_num_cmds(
1434 struct se_ml_stat_grps *lgrps, char *page)
1435{
1436 struct se_lun_acl *lacl = container_of(lgrps,
1437 struct se_lun_acl, ml_stat_grps);
1438 struct se_node_acl *nacl = lacl->se_lun_nacl;
1439 struct se_dev_entry *deve;
1440 ssize_t ret;
1441
1442 spin_lock_irq(&nacl->device_list_lock);
1443 deve = &nacl->device_list[lacl->mapped_lun];
1444 if (!deve->se_lun || !deve->se_lun_acl) {
1445 spin_unlock_irq(&nacl->device_list_lock);
1446 return -ENODEV;
1447 }
1448 /* scsiAuthIntrOutCommands */
1449 ret = snprintf(page, PAGE_SIZE, "%u\n", deve->total_cmds);
1450 spin_unlock_irq(&nacl->device_list_lock);
1451 return ret;
1452}
1453DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(num_cmds);
1454
1455static ssize_t target_stat_scsi_auth_intr_show_attr_read_mbytes(
1456 struct se_ml_stat_grps *lgrps, char *page)
1457{
1458 struct se_lun_acl *lacl = container_of(lgrps,
1459 struct se_lun_acl, ml_stat_grps);
1460 struct se_node_acl *nacl = lacl->se_lun_nacl;
1461 struct se_dev_entry *deve;
1462 ssize_t ret;
1463
1464 spin_lock_irq(&nacl->device_list_lock);
1465 deve = &nacl->device_list[lacl->mapped_lun];
1466 if (!deve->se_lun || !deve->se_lun_acl) {
1467 spin_unlock_irq(&nacl->device_list_lock);
1468 return -ENODEV;
1469 }
1470 /* scsiAuthIntrReadMegaBytes */
1471 ret = snprintf(page, PAGE_SIZE, "%u\n", (u32)(deve->read_bytes >> 20));
1472 spin_unlock_irq(&nacl->device_list_lock);
1473 return ret;
1474}
1475DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(read_mbytes);
1476
1477static ssize_t target_stat_scsi_auth_intr_show_attr_write_mbytes(
1478 struct se_ml_stat_grps *lgrps, char *page)
1479{
1480 struct se_lun_acl *lacl = container_of(lgrps,
1481 struct se_lun_acl, ml_stat_grps);
1482 struct se_node_acl *nacl = lacl->se_lun_nacl;
1483 struct se_dev_entry *deve;
1484 ssize_t ret;
1485
1486 spin_lock_irq(&nacl->device_list_lock);
1487 deve = &nacl->device_list[lacl->mapped_lun];
1488 if (!deve->se_lun || !deve->se_lun_acl) {
1489 spin_unlock_irq(&nacl->device_list_lock);
1490 return -ENODEV;
1491 }
1492 /* scsiAuthIntrWrittenMegaBytes */
1493 ret = snprintf(page, PAGE_SIZE, "%u\n", (u32)(deve->write_bytes >> 20));
1494 spin_unlock_irq(&nacl->device_list_lock);
1495 return ret;
1496}
1497DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(write_mbytes);
1498
1499static ssize_t target_stat_scsi_auth_intr_show_attr_hs_num_cmds(
1500 struct se_ml_stat_grps *lgrps, char *page)
1501{
1502 struct se_lun_acl *lacl = container_of(lgrps,
1503 struct se_lun_acl, ml_stat_grps);
1504 struct se_node_acl *nacl = lacl->se_lun_nacl;
1505 struct se_dev_entry *deve;
1506 ssize_t ret;
1507
1508 spin_lock_irq(&nacl->device_list_lock);
1509 deve = &nacl->device_list[lacl->mapped_lun];
1510 if (!deve->se_lun || !deve->se_lun_acl) {
1511 spin_unlock_irq(&nacl->device_list_lock);
1512 return -ENODEV;
1513 }
1514 /* FIXME: scsiAuthIntrHSOutCommands */
1515 ret = snprintf(page, PAGE_SIZE, "%u\n", 0);
1516 spin_unlock_irq(&nacl->device_list_lock);
1517 return ret;
1518}
1519DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(hs_num_cmds);
1520
1521static ssize_t target_stat_scsi_auth_intr_show_attr_creation_time(
1522 struct se_ml_stat_grps *lgrps, char *page)
1523{
1524 struct se_lun_acl *lacl = container_of(lgrps,
1525 struct se_lun_acl, ml_stat_grps);
1526 struct se_node_acl *nacl = lacl->se_lun_nacl;
1527 struct se_dev_entry *deve;
1528 ssize_t ret;
1529
1530 spin_lock_irq(&nacl->device_list_lock);
1531 deve = &nacl->device_list[lacl->mapped_lun];
1532 if (!deve->se_lun || !deve->se_lun_acl) {
1533 spin_unlock_irq(&nacl->device_list_lock);
1534 return -ENODEV;
1535 }
1536 /* scsiAuthIntrLastCreation */
1537 ret = snprintf(page, PAGE_SIZE, "%u\n", (u32)(((u32)deve->creation_time -
1538 INITIAL_JIFFIES) * 100 / HZ));
1539 spin_unlock_irq(&nacl->device_list_lock);
1540 return ret;
1541}
1542DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(creation_time);
1543
1544static ssize_t target_stat_scsi_auth_intr_show_attr_row_status(
1545 struct se_ml_stat_grps *lgrps, char *page)
1546{
1547 struct se_lun_acl *lacl = container_of(lgrps,
1548 struct se_lun_acl, ml_stat_grps);
1549 struct se_node_acl *nacl = lacl->se_lun_nacl;
1550 struct se_dev_entry *deve;
1551 ssize_t ret;
1552
1553 spin_lock_irq(&nacl->device_list_lock);
1554 deve = &nacl->device_list[lacl->mapped_lun];
1555 if (!deve->se_lun || !deve->se_lun_acl) {
1556 spin_unlock_irq(&nacl->device_list_lock);
1557 return -ENODEV;
1558 }
1559 /* FIXME: scsiAuthIntrRowStatus */
1560 ret = snprintf(page, PAGE_SIZE, "Ready\n");
1561 spin_unlock_irq(&nacl->device_list_lock);
1562 return ret;
1563}
1564DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(row_status);
1565
1566CONFIGFS_EATTR_OPS(target_stat_scsi_auth_intr, se_ml_stat_grps,
1567 scsi_auth_intr_group);
1568
1569static struct configfs_attribute *target_stat_scsi_auth_intr_attrs[] = {
1570 &target_stat_scsi_auth_intr_inst.attr,
1571 &target_stat_scsi_auth_intr_dev.attr,
1572 &target_stat_scsi_auth_intr_port.attr,
1573 &target_stat_scsi_auth_intr_indx.attr,
1574 &target_stat_scsi_auth_intr_dev_or_port.attr,
1575 &target_stat_scsi_auth_intr_intr_name.attr,
1576 &target_stat_scsi_auth_intr_map_indx.attr,
1577 &target_stat_scsi_auth_intr_att_count.attr,
1578 &target_stat_scsi_auth_intr_num_cmds.attr,
1579 &target_stat_scsi_auth_intr_read_mbytes.attr,
1580 &target_stat_scsi_auth_intr_write_mbytes.attr,
1581 &target_stat_scsi_auth_intr_hs_num_cmds.attr,
1582 &target_stat_scsi_auth_intr_creation_time.attr,
1583 &target_stat_scsi_auth_intr_row_status.attr,
1584 NULL,
1585};
1586
1587static struct configfs_item_operations target_stat_scsi_auth_intr_attrib_ops = {
1588 .show_attribute = target_stat_scsi_auth_intr_attr_show,
1589 .store_attribute = target_stat_scsi_auth_intr_attr_store,
1590};
1591
1592static struct config_item_type target_stat_scsi_auth_intr_cit = {
1593 .ct_item_ops = &target_stat_scsi_auth_intr_attrib_ops,
1594 .ct_attrs = target_stat_scsi_auth_intr_attrs,
1595 .ct_owner = THIS_MODULE,
1596};
1597
1598/*
1599 * SCSI Attached Initiator Port Table
1600 */
1601
1602CONFIGFS_EATTR_STRUCT(target_stat_scsi_att_intr_port, se_ml_stat_grps);
1603#define DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR(_name, _mode) \
1604static struct target_stat_scsi_att_intr_port_attribute \
1605 target_stat_scsi_att_intr_port_##_name = \
1606 __CONFIGFS_EATTR(_name, _mode, \
1607 target_stat_scsi_att_intr_port_show_attr_##_name, \
1608 target_stat_scsi_att_intr_port_store_attr_##_name);
1609
1610#define DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(_name) \
1611static struct target_stat_scsi_att_intr_port_attribute \
1612 target_stat_scsi_att_intr_port_##_name = \
1613 __CONFIGFS_EATTR_RO(_name, \
1614 target_stat_scsi_att_intr_port_show_attr_##_name);
1615
1616static ssize_t target_stat_scsi_att_intr_port_show_attr_inst(
1617 struct se_ml_stat_grps *lgrps, char *page)
1618{
1619 struct se_lun_acl *lacl = container_of(lgrps,
1620 struct se_lun_acl, ml_stat_grps);
1621 struct se_node_acl *nacl = lacl->se_lun_nacl;
1622 struct se_dev_entry *deve;
1623 struct se_portal_group *tpg;
1624 ssize_t ret;
1625
1626 spin_lock_irq(&nacl->device_list_lock);
1627 deve = &nacl->device_list[lacl->mapped_lun];
1628 if (!deve->se_lun || !deve->se_lun_acl) {
1629 spin_unlock_irq(&nacl->device_list_lock);
1630 return -ENODEV;
1631 }
1632 tpg = nacl->se_tpg;
1633 /* scsiInstIndex */
1634 ret = snprintf(page, PAGE_SIZE, "%u\n",
1635 TPG_TFO(tpg)->tpg_get_inst_index(tpg));
1636 spin_unlock_irq(&nacl->device_list_lock);
1637 return ret;
1638}
1639DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(inst);
1640
1641static ssize_t target_stat_scsi_att_intr_port_show_attr_dev(
1642 struct se_ml_stat_grps *lgrps, char *page)
1643{
1644 struct se_lun_acl *lacl = container_of(lgrps,
1645 struct se_lun_acl, ml_stat_grps);
1646 struct se_node_acl *nacl = lacl->se_lun_nacl;
1647 struct se_dev_entry *deve;
1648 struct se_lun *lun;
1649 struct se_portal_group *tpg;
1650 ssize_t ret;
1651
1652 spin_lock_irq(&nacl->device_list_lock);
1653 deve = &nacl->device_list[lacl->mapped_lun];
1654 if (!deve->se_lun || !deve->se_lun_acl) {
1655 spin_unlock_irq(&nacl->device_list_lock);
1656 return -ENODEV;
1657 }
1658 tpg = nacl->se_tpg;
1659 lun = deve->se_lun;
1660 /* scsiDeviceIndex */
1661 ret = snprintf(page, PAGE_SIZE, "%u\n", lun->lun_se_dev->dev_index);
1662 spin_unlock_irq(&nacl->device_list_lock);
1663 return ret;
1664}
1665DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(dev);
1666
1667static ssize_t target_stat_scsi_att_intr_port_show_attr_port(
1668 struct se_ml_stat_grps *lgrps, char *page)
1669{
1670 struct se_lun_acl *lacl = container_of(lgrps,
1671 struct se_lun_acl, ml_stat_grps);
1672 struct se_node_acl *nacl = lacl->se_lun_nacl;
1673 struct se_dev_entry *deve;
1674 struct se_portal_group *tpg;
1675 ssize_t ret;
1676
1677 spin_lock_irq(&nacl->device_list_lock);
1678 deve = &nacl->device_list[lacl->mapped_lun];
1679 if (!deve->se_lun || !deve->se_lun_acl) {
1680 spin_unlock_irq(&nacl->device_list_lock);
1681 return -ENODEV;
1682 }
1683 tpg = nacl->se_tpg;
1684 /* scsiPortIndex */
1685 ret = snprintf(page, PAGE_SIZE, "%u\n", TPG_TFO(tpg)->tpg_get_tag(tpg));
1686 spin_unlock_irq(&nacl->device_list_lock);
1687 return ret;
1688}
1689DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(port);
1690
1691static ssize_t target_stat_scsi_att_intr_port_show_attr_indx(
1692 struct se_ml_stat_grps *lgrps, char *page)
1693{
1694 struct se_lun_acl *lacl = container_of(lgrps,
1695 struct se_lun_acl, ml_stat_grps);
1696 struct se_node_acl *nacl = lacl->se_lun_nacl;
1697 struct se_session *se_sess;
1698 struct se_portal_group *tpg;
1699 ssize_t ret;
1700
1701 spin_lock_irq(&nacl->nacl_sess_lock);
1702 se_sess = nacl->nacl_sess;
1703 if (!se_sess) {
1704 spin_unlock_irq(&nacl->nacl_sess_lock);
1705 return -ENODEV;
1706 }
1707
1708 tpg = nacl->se_tpg;
1709 /* scsiAttIntrPortIndex */
1710 ret = snprintf(page, PAGE_SIZE, "%u\n",
1711 TPG_TFO(tpg)->sess_get_index(se_sess));
1712 spin_unlock_irq(&nacl->nacl_sess_lock);
1713 return ret;
1714}
1715DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(indx);
1716
1717static ssize_t target_stat_scsi_att_intr_port_show_attr_port_auth_indx(
1718 struct se_ml_stat_grps *lgrps, char *page)
1719{
1720 struct se_lun_acl *lacl = container_of(lgrps,
1721 struct se_lun_acl, ml_stat_grps);
1722 struct se_node_acl *nacl = lacl->se_lun_nacl;
1723 struct se_dev_entry *deve;
1724 ssize_t ret;
1725
1726 spin_lock_irq(&nacl->device_list_lock);
1727 deve = &nacl->device_list[lacl->mapped_lun];
1728 if (!deve->se_lun || !deve->se_lun_acl) {
1729 spin_unlock_irq(&nacl->device_list_lock);
1730 return -ENODEV;
1731 }
1732 /* scsiAttIntrPortAuthIntrIdx */
1733 ret = snprintf(page, PAGE_SIZE, "%u\n", nacl->acl_index);
1734 spin_unlock_irq(&nacl->device_list_lock);
1735 return ret;
1736}
1737DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(port_auth_indx);
1738
1739static ssize_t target_stat_scsi_att_intr_port_show_attr_port_ident(
1740 struct se_ml_stat_grps *lgrps, char *page)
1741{
1742 struct se_lun_acl *lacl = container_of(lgrps,
1743 struct se_lun_acl, ml_stat_grps);
1744 struct se_node_acl *nacl = lacl->se_lun_nacl;
1745 struct se_session *se_sess;
1746 struct se_portal_group *tpg;
1747 ssize_t ret;
1748 unsigned char buf[64];
1749
1750 spin_lock_irq(&nacl->nacl_sess_lock);
1751 se_sess = nacl->nacl_sess;
1752 if (!se_sess) {
1753 spin_unlock_irq(&nacl->nacl_sess_lock);
1754 return -ENODEV;
1755 }
1756
1757 tpg = nacl->se_tpg;
1758 /* scsiAttIntrPortName+scsiAttIntrPortIdentifier */
1759 memset(buf, 0, 64);
1760 if (TPG_TFO(tpg)->sess_get_initiator_sid != NULL)
1761 TPG_TFO(tpg)->sess_get_initiator_sid(se_sess,
1762 (unsigned char *)&buf[0], 64);
1763
1764 ret = snprintf(page, PAGE_SIZE, "%s+i+%s\n", nacl->initiatorname, buf);
1765 spin_unlock_irq(&nacl->nacl_sess_lock);
1766 return ret;
1767}
1768DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(port_ident);
1769
1770CONFIGFS_EATTR_OPS(target_stat_scsi_att_intr_port, se_ml_stat_grps,
1771 scsi_att_intr_port_group);
1772
1773static struct configfs_attribute *target_stat_scsi_ath_intr_port_attrs[] = {
1774 &target_stat_scsi_att_intr_port_inst.attr,
1775 &target_stat_scsi_att_intr_port_dev.attr,
1776 &target_stat_scsi_att_intr_port_port.attr,
1777 &target_stat_scsi_att_intr_port_indx.attr,
1778 &target_stat_scsi_att_intr_port_port_auth_indx.attr,
1779 &target_stat_scsi_att_intr_port_port_ident.attr,
1780 NULL,
1781};
1782
1783static struct configfs_item_operations target_stat_scsi_att_intr_port_attrib_ops = {
1784 .show_attribute = target_stat_scsi_att_intr_port_attr_show,
1785 .store_attribute = target_stat_scsi_att_intr_port_attr_store,
1786};
1787
1788static struct config_item_type target_stat_scsi_att_intr_port_cit = {
1789 .ct_item_ops = &target_stat_scsi_att_intr_port_attrib_ops,
1790 .ct_attrs = target_stat_scsi_ath_intr_port_attrs,
1791 .ct_owner = THIS_MODULE,
1792};
1793
1794/*
1795 * Called from target_core_fabric_configfs.c:target_fabric_make_mappedlun() to setup
1796 * the target MappedLUN statistics groups + configfs CITs located in target_core_stat.c
1797 */
1798void target_stat_setup_mappedlun_default_groups(struct se_lun_acl *lacl)
1799{
1800 struct config_group *ml_stat_grp = &ML_STAT_GRPS(lacl)->stat_group;
1801
1802 config_group_init_type_name(&ML_STAT_GRPS(lacl)->scsi_auth_intr_group,
1803 "scsi_auth_intr", &target_stat_scsi_auth_intr_cit);
1804 config_group_init_type_name(&ML_STAT_GRPS(lacl)->scsi_att_intr_port_group,
1805 "scsi_att_intr_port", &target_stat_scsi_att_intr_port_cit);
1806
1807 ml_stat_grp->default_groups[0] = &ML_STAT_GRPS(lacl)->scsi_auth_intr_group;
1808 ml_stat_grp->default_groups[1] = &ML_STAT_GRPS(lacl)->scsi_att_intr_port_group;
1809 ml_stat_grp->default_groups[2] = NULL;
1810}
diff --git a/drivers/target/target_core_stat.h b/drivers/target/target_core_stat.h
new file mode 100644
index 000000000000..86c252f9ea47
--- /dev/null
+++ b/drivers/target/target_core_stat.h
@@ -0,0 +1,8 @@
1#ifndef TARGET_CORE_STAT_H
2#define TARGET_CORE_STAT_H
3
4extern void target_stat_setup_dev_default_groups(struct se_subsystem_dev *);
5extern void target_stat_setup_port_default_groups(struct se_lun *);
6extern void target_stat_setup_mappedlun_default_groups(struct se_lun_acl *);
7
8#endif /*** TARGET_CORE_STAT_H ***/