Commit 12d233842987d9972957419e427987b94f7bd7b4

Authored by Nicholas Bellinger
Committed by James Bottomley
1 parent 15fb48cc40

[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>

Showing 7 changed files with 2127 additions and 18 deletions Side-by-side Diff

drivers/target/Makefile
... ... @@ -12,7 +12,8 @@
12 12 target_core_transport.o \
13 13 target_core_cdb.o \
14 14 target_core_ua.o \
15   - target_core_rd.o
  15 + target_core_rd.o \
  16 + target_core_stat.o
16 17  
17 18 obj-$(CONFIG_TARGET_CORE) += target_core_mod.o
18 19  
drivers/target/target_core_configfs.c
... ... @@ -3,8 +3,8 @@
3 3 *
4 4 * This file contains ConfigFS logic for the Generic Target Engine project.
5 5 *
6   - * Copyright (c) 2008-2010 Rising Tide Systems
7   - * Copyright (c) 2008-2010 Linux-iSCSI.org
  6 + * Copyright (c) 2008-2011 Rising Tide Systems
  7 + * Copyright (c) 2008-2011 Linux-iSCSI.org
8 8 *
9 9 * Nicholas A. Bellinger <nab@kernel.org>
10 10 *
... ... @@ -50,6 +50,7 @@
50 50 #include "target_core_hba.h"
51 51 #include "target_core_pr.h"
52 52 #include "target_core_rd.h"
  53 +#include "target_core_stat.h"
53 54  
54 55 static struct list_head g_tf_list;
55 56 static struct mutex g_tf_lock;
... ... @@ -2709,6 +2710,34 @@
2709 2710  
2710 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 +
  2715 +static struct config_group *target_core_stat_mkdir(
  2716 + struct config_group *group,
  2717 + const char *name)
  2718 +{
  2719 + return ERR_PTR(-ENOSYS);
  2720 +}
  2721 +
  2722 +static void target_core_stat_rmdir(
  2723 + struct config_group *group,
  2724 + struct config_item *item)
  2725 +{
  2726 + return;
  2727 +}
  2728 +
  2729 +static 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 +
  2734 +static 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 2741 /* Start functions for struct config_item_type target_core_hba_cit */
2713 2742  
2714 2743 static struct config_group *target_core_make_subdev(
2715 2744  
... ... @@ -2721,10 +2750,12 @@
2721 2750 struct config_item *hba_ci = &group->cg_item;
2722 2751 struct se_hba *hba = item_to_hba(hba_ci);
2723 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))
2726   - return NULL;
2727   -
  2756 + ret = mutex_lock_interruptible(&hba->hba_access_mutex);
  2757 + if (ret)
  2758 + return ERR_PTR(ret);
2728 2759 /*
2729 2760 * Locate the struct se_subsystem_api from parent's struct se_hba.
2730 2761 */
... ... @@ -2754,7 +2785,7 @@
2754 2785 se_dev->se_dev_hba = hba;
2755 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 2789 GFP_KERNEL);
2759 2790 if (!(dev_cg->default_groups))
2760 2791 goto out;
2761 2792  
2762 2793  
... ... @@ -2786,13 +2817,17 @@
2786 2817 &target_core_dev_wwn_cit);
2787 2818 config_group_init_type_name(&se_dev->t10_alua.alua_tg_pt_gps_group,
2788 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 2823 dev_cg->default_groups[0] = &se_dev->se_dev_attrib.da_group;
2790 2824 dev_cg->default_groups[1] = &se_dev->se_dev_pr_group;
2791 2825 dev_cg->default_groups[2] = &se_dev->t10_wwn.t10_wwn_group;
2792 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 2832 tg_pt_gp = core_alua_allocate_tg_pt_gp(se_dev, "default_tg_pt_gp", 1);
2798 2833 if (!(tg_pt_gp))
... ... @@ -2812,6 +2847,17 @@
2812 2847 tg_pt_gp_cg->default_groups[0] = &tg_pt_gp->tg_pt_gp_group;
2813 2848 tg_pt_gp_cg->default_groups[1] = NULL;
2814 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 2862 printk(KERN_INFO "Target_Core_ConfigFS: Allocated struct se_subsystem_dev:"
2817 2863 " %p se_dev_su_ptr: %p\n", se_dev, se_dev->se_dev_su_ptr);
... ... @@ -2823,6 +2869,8 @@
2823 2869 core_alua_free_tg_pt_gp(T10_ALUA(se_dev)->default_tg_pt_gp);
2824 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 2874 if (tg_pt_gp_cg)
2827 2875 kfree(tg_pt_gp_cg->default_groups);
2828 2876 if (dev_cg)
... ... @@ -2832,7 +2880,7 @@
2832 2880 kfree(se_dev);
2833 2881 unlock:
2834 2882 mutex_unlock(&hba->hba_access_mutex);
2835   - return NULL;
  2883 + return ERR_PTR(errno);
2836 2884 }
2837 2885  
2838 2886 static void target_core_drop_subdev(
... ... @@ -2844,7 +2892,7 @@
2844 2892 struct se_hba *hba;
2845 2893 struct se_subsystem_api *t;
2846 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 2896 int i;
2849 2897  
2850 2898 hba = item_to_hba(&se_dev->se_dev_hba->hba_group.cg_item);
... ... @@ -2855,6 +2903,14 @@
2855 2903 spin_lock(&se_global->g_device_lock);
2856 2904 list_del(&se_dev->g_se_dev_list);
2857 2905 spin_unlock(&se_global->g_device_lock);
  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);
2858 2914  
2859 2915 tg_pt_gp_cg = &T10_ALUA(se_dev)->alua_tg_pt_gps_group;
2860 2916 for (i = 0; tg_pt_gp_cg->default_groups[i]; i++) {
drivers/target/target_core_fabric_configfs.c
... ... @@ -4,10 +4,10 @@
4 4 * This file contains generic fabric module configfs infrastructure for
5 5 * TCM v4.x code
6 6 *
7   - * Copyright (c) 2010 Rising Tide Systems
8   - * Copyright (c) 2010 Linux-iSCSI.org
  7 + * Copyright (c) 2010,2011 Rising Tide Systems
  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 12 * This program is free software; you can redistribute it and/or modify
13 13 * it under the terms of the GNU General Public License as published by
... ... @@ -48,6 +48,7 @@
48 48 #include "target_core_alua.h"
49 49 #include "target_core_hba.h"
50 50 #include "target_core_pr.h"
  51 +#include "target_core_stat.h"
51 52  
52 53 #define TF_CIT_SETUP(_name, _item_ops, _group_ops, _attrs) \
53 54 static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf) \
... ... @@ -241,6 +242,32 @@
241 242  
242 243 /* End of tfc_tpg_mappedlun_cit */
243 244  
  245 +/* Start of tfc_tpg_mappedlun_port_cit */
  246 +
  247 +static 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 +
  254 +static void target_core_mappedlun_stat_rmdir(
  255 + struct config_group *group,
  256 + struct config_item *item)
  257 +{
  258 + return;
  259 +}
  260 +
  261 +static 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 +
  266 +TF_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 271 /* Start of tfc_tpg_nacl_attrib_cit */
245 272  
246 273 CONFIGFS_EATTR_OPS(target_fabric_nacl_attrib, se_node_acl, acl_attrib_group);
... ... @@ -294,6 +321,7 @@
294 321 struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
295 322 struct se_lun_acl *lacl;
296 323 struct config_item *acl_ci;
  324 + struct config_group *lacl_cg = NULL, *ml_stat_grp = NULL;
297 325 char *buf;
298 326 unsigned long mapped_lun;
299 327 int ret = 0;
300 328  
301 329  
302 330  
303 331  
304 332  
... ... @@ -330,15 +358,42 @@
330 358  
331 359 lacl = core_dev_init_initiator_node_lun_acl(se_tpg, mapped_lun,
332 360 config_item_name(acl_ci), &ret);
333   - if (!(lacl))
  361 + if (!(lacl)) {
  362 + ret = -EINVAL;
334 363 goto out;
  364 + }
335 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 + }
  374 +
336 375 config_group_init_type_name(&lacl->se_lun_group, name,
337 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;
338 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);
  391 +
339 392 kfree(buf);
340 393 return &lacl->se_lun_group;
341 394 out:
  395 + if (lacl_cg)
  396 + kfree(lacl_cg->default_groups);
342 397 kfree(buf);
343 398 return ERR_PTR(ret);
344 399 }
... ... @@ -347,6 +402,28 @@
347 402 struct config_group *group,
348 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 427 config_item_put(item);
351 428 }
352 429  
... ... @@ -376,6 +453,15 @@
376 453  
377 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 + */
  461 +TF_CIT_SETUP(tpg_nacl_stat, NULL, NULL, NULL);
  462 +
  463 +/* End of tfc_wwn_fabric_stats_cit */
  464 +
379 465 /* Start of tfc_tpg_nacl_cit */
380 466  
381 467 static struct config_group *target_fabric_make_nodeacl(
... ... @@ -402,7 +488,8 @@
402 488 nacl_cg->default_groups[0] = &se_nacl->acl_attrib_group;
403 489 nacl_cg->default_groups[1] = &se_nacl->acl_auth_group;
404 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 494 config_group_init_type_name(&se_nacl->acl_group, name,
408 495 &TF_CIT_TMPL(tf)->tfc_tpg_nacl_base_cit);
... ... @@ -412,6 +499,9 @@
412 499 &TF_CIT_TMPL(tf)->tfc_tpg_nacl_auth_cit);
413 500 config_group_init_type_name(&se_nacl->acl_param_group, "param",
414 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 506 return &se_nacl->acl_group;
417 507 }
... ... @@ -758,6 +848,31 @@
758 848  
759 849 /* End of tfc_tpg_port_cit */
760 850  
  851 +/* Start of tfc_tpg_port_stat_cit */
  852 +
  853 +static 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 +
  860 +static void target_core_port_stat_rmdir(
  861 + struct config_group *group,
  862 + struct config_item *item)
  863 +{
  864 + return;
  865 +}
  866 +
  867 +static 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 +
  872 +TF_CIT_SETUP(tpg_port_stat, NULL, &target_fabric_port_stat_group_ops, NULL);
  873 +
  874 +/* End of tfc_tpg_port_stat_cit */
  875 +
761 876 /* Start of tfc_tpg_lun_cit */
762 877  
763 878 static struct config_group *target_fabric_make_lun(
764 879  
... ... @@ -768,7 +883,9 @@
768 883 struct se_portal_group *se_tpg = container_of(group,
769 884 struct se_portal_group, tpg_lun_group);
770 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 887 unsigned long unpacked_lun;
  888 + int errno;
772 889  
773 890 if (strstr(name, "lun_") != name) {
774 891 printk(KERN_ERR "Unable to locate \'_\" in"
775 892  
776 893  
777 894  
778 895  
... ... @@ -782,16 +899,64 @@
782 899 if (!(lun))
783 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 910 config_group_init_type_name(&lun->lun_group, name,
786 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;
787 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);
  926 +
788 927 return &lun->lun_group;
  928 +out:
  929 + if (lun_cg)
  930 + kfree(lun_cg->default_groups);
  931 + return ERR_PTR(errno);
789 932 }
790 933  
791 934 static void target_fabric_drop_lun(
792 935 struct config_group *group,
793 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 960 config_item_put(item);
796 961 }
797 962  
... ... @@ -946,6 +1111,15 @@
946 1111  
947 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 + */
  1119 +TF_CIT_SETUP(wwn_fabric_stats, NULL, NULL, NULL);
  1120 +
  1121 +/* End of tfc_wwn_fabric_stats_cit */
  1122 +
949 1123 /* Start of tfc_wwn_cit */
950 1124  
951 1125 static struct config_group *target_fabric_make_wwn(
952 1126  
... ... @@ -966,8 +1140,17 @@
966 1140 return ERR_PTR(-EINVAL);
967 1141  
968 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 1150 config_group_init_type_name(&wwn->wwn_group, name,
970 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 1155 return &wwn->wwn_group;
973 1156 }
... ... @@ -976,6 +1159,18 @@
976 1159 struct config_group *group,
977 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 1174 config_item_put(item);
980 1175 }
981 1176  
982 1177  
... ... @@ -1015,9 +1210,11 @@
1015 1210 {
1016 1211 target_fabric_setup_discovery_cit(tf);
1017 1212 target_fabric_setup_wwn_cit(tf);
  1213 + target_fabric_setup_wwn_fabric_stats_cit(tf);
1018 1214 target_fabric_setup_tpg_cit(tf);
1019 1215 target_fabric_setup_tpg_base_cit(tf);
1020 1216 target_fabric_setup_tpg_port_cit(tf);
  1217 + target_fabric_setup_tpg_port_stat_cit(tf);
1021 1218 target_fabric_setup_tpg_lun_cit(tf);
1022 1219 target_fabric_setup_tpg_np_cit(tf);
1023 1220 target_fabric_setup_tpg_np_base_cit(tf);
1024 1221  
... ... @@ -1028,7 +1225,9 @@
1028 1225 target_fabric_setup_tpg_nacl_attrib_cit(tf);
1029 1226 target_fabric_setup_tpg_nacl_auth_cit(tf);
1030 1227 target_fabric_setup_tpg_nacl_param_cit(tf);
  1228 + target_fabric_setup_tpg_nacl_stat_cit(tf);
1031 1229 target_fabric_setup_tpg_mappedlun_cit(tf);
  1230 + target_fabric_setup_tpg_mappedlun_stat_cit(tf);
1032 1231  
1033 1232 return 0;
1034 1233 }
drivers/target/target_core_stat.c
Changes suppressed. Click to show
  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 +
  68 +CONFIGFS_EATTR_STRUCT(target_stat_scsi_dev, se_dev_stat_grps);
  69 +#define DEV_STAT_SCSI_DEV_ATTR(_name, _mode) \
  70 +static 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) \
  77 +static 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 +
  82 +static 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 +}
  95 +DEV_STAT_SCSI_DEV_ATTR_RO(inst);
  96 +
  97 +static 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 +}
  109 +DEV_STAT_SCSI_DEV_ATTR_RO(indx);
  110 +
  111 +static 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 +}
  123 +DEV_STAT_SCSI_DEV_ATTR_RO(role);
  124 +
  125 +static 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 +}
  137 +DEV_STAT_SCSI_DEV_ATTR_RO(ports);
  138 +
  139 +CONFIGFS_EATTR_OPS(target_stat_scsi_dev, se_dev_stat_grps, scsi_dev_group);
  140 +
  141 +static 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 +
  149 +static 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 +
  154 +static 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 +
  164 +CONFIGFS_EATTR_STRUCT(target_stat_scsi_tgt_dev, se_dev_stat_grps);
  165 +#define DEV_STAT_SCSI_TGT_DEV_ATTR(_name, _mode) \
  166 +static 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) \
  173 +static 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 +
  178 +static 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 +}
  191 +DEV_STAT_SCSI_TGT_DEV_ATTR_RO(inst);
  192 +
  193 +static 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 +}
  205 +DEV_STAT_SCSI_TGT_DEV_ATTR_RO(indx);
  206 +
  207 +static 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 +}
  219 +DEV_STAT_SCSI_TGT_DEV_ATTR_RO(num_lus);
  220 +
  221 +static 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 +}
  253 +DEV_STAT_SCSI_TGT_DEV_ATTR_RO(status);
  254 +
  255 +static 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 +}
  281 +DEV_STAT_SCSI_TGT_DEV_ATTR_RO(non_access_lus);
  282 +
  283 +static 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 +}
  295 +DEV_STAT_SCSI_TGT_DEV_ATTR_RO(resets);
  296 +
  297 +
  298 +CONFIGFS_EATTR_OPS(target_stat_scsi_tgt_dev, se_dev_stat_grps, scsi_tgt_dev_group);
  299 +
  300 +static 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 +
  310 +static 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 +
  315 +static 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 +
  325 +CONFIGFS_EATTR_STRUCT(target_stat_scsi_lu, se_dev_stat_grps);
  326 +#define DEV_STAT_SCSI_LU_ATTR(_name, _mode) \
  327 +static 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) \
  333 +static 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 +
  337 +static 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 +}
  350 +DEV_STAT_SCSI_LU_ATTR_RO(inst);
  351 +
  352 +static 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 +}
  364 +DEV_STAT_SCSI_LU_ATTR_RO(dev);
  365 +
  366 +static 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 +}
  378 +DEV_STAT_SCSI_LU_ATTR_RO(indx);
  379 +
  380 +static 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 +}
  392 +DEV_STAT_SCSI_LU_ATTR_RO(lun);
  393 +
  394 +static 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 +}
  408 +DEV_STAT_SCSI_LU_ATTR_RO(lu_name);
  409 +
  410 +static 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 +}
  429 +DEV_STAT_SCSI_LU_ATTR_RO(vend);
  430 +
  431 +static 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 +}
  451 +DEV_STAT_SCSI_LU_ATTR_RO(prod);
  452 +
  453 +static 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 +}
  473 +DEV_STAT_SCSI_LU_ATTR_RO(rev);
  474 +
  475 +static 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 +}
  489 +DEV_STAT_SCSI_LU_ATTR_RO(dev_type);
  490 +
  491 +static 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 +}
  506 +DEV_STAT_SCSI_LU_ATTR_RO(status);
  507 +
  508 +static 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 +}
  521 +DEV_STAT_SCSI_LU_ATTR_RO(state_bit);
  522 +
  523 +static 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 +}
  537 +DEV_STAT_SCSI_LU_ATTR_RO(num_cmds);
  538 +
  539 +static 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 +}
  552 +DEV_STAT_SCSI_LU_ATTR_RO(read_mbytes);
  553 +
  554 +static 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 +}
  567 +DEV_STAT_SCSI_LU_ATTR_RO(write_mbytes);
  568 +
  569 +static 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 +}
  582 +DEV_STAT_SCSI_LU_ATTR_RO(resets);
  583 +
  584 +static 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 +}
  597 +DEV_STAT_SCSI_LU_ATTR_RO(full_stat);
  598 +
  599 +static 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 +}
  612 +DEV_STAT_SCSI_LU_ATTR_RO(hs_num_cmds);
  613 +
  614 +static 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 +}
  628 +DEV_STAT_SCSI_LU_ATTR_RO(creation_time);
  629 +
  630 +CONFIGFS_EATTR_OPS(target_stat_scsi_lu, se_dev_stat_grps, scsi_lu_group);
  631 +
  632 +static 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 +
  654 +static 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 +
  659 +static 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 + */
  669 +void 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 +
  690 +CONFIGFS_EATTR_STRUCT(target_stat_scsi_port, se_port_stat_grps);
  691 +#define DEV_STAT_SCSI_PORT_ATTR(_name, _mode) \
  692 +static 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) \
  699 +static 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 +
  704 +static 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 +}
  724 +DEV_STAT_SCSI_PORT_ATTR_RO(inst);
  725 +
  726 +static 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 +}
  744 +DEV_STAT_SCSI_PORT_ATTR_RO(dev);
  745 +
  746 +static 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 +}
  763 +DEV_STAT_SCSI_PORT_ATTR_RO(indx);
  764 +
  765 +static 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 +}
  786 +DEV_STAT_SCSI_PORT_ATTR_RO(role);
  787 +
  788 +static 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 +}
  806 +DEV_STAT_SCSI_PORT_ATTR_RO(busy_count);
  807 +
  808 +CONFIGFS_EATTR_OPS(target_stat_scsi_port, se_port_stat_grps, scsi_port_group);
  809 +
  810 +static 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 +
  819 +static 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 +
  824 +static 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 + */
  833 +CONFIGFS_EATTR_STRUCT(target_stat_scsi_tgt_port, se_port_stat_grps);
  834 +#define DEV_STAT_SCSI_TGT_PORT_ATTR(_name, _mode) \
  835 +static 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) \
  842 +static 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 +
  847 +static 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 +}
  867 +DEV_STAT_SCSI_TGT_PORT_ATTR_RO(inst);
  868 +
  869 +static 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 +}
  887 +DEV_STAT_SCSI_TGT_PORT_ATTR_RO(dev);
  888 +
  889 +static 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 +}
  906 +DEV_STAT_SCSI_TGT_PORT_ATTR_RO(indx);
  907 +
  908 +static 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 +}
  929 +DEV_STAT_SCSI_TGT_PORT_ATTR_RO(name);
  930 +
  931 +static 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 +}
  953 +DEV_STAT_SCSI_TGT_PORT_ATTR_RO(port_index);
  954 +
  955 +static 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 +}
  975 +DEV_STAT_SCSI_TGT_PORT_ATTR_RO(in_cmds);
  976 +
  977 +static 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 +}
  998 +DEV_STAT_SCSI_TGT_PORT_ATTR_RO(write_mbytes);
  999 +
  1000 +static 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 +}
  1021 +DEV_STAT_SCSI_TGT_PORT_ATTR_RO(read_mbytes);
  1022 +
  1023 +static 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 +}
  1044 +DEV_STAT_SCSI_TGT_PORT_ATTR_RO(hs_in_cmds);
  1045 +
  1046 +CONFIGFS_EATTR_OPS(target_stat_scsi_tgt_port, se_port_stat_grps,
  1047 + scsi_tgt_port_group);
  1048 +
  1049 +static 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 +
  1062 +static 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 +
  1067 +static 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
  1075 +o */
  1076 +
  1077 +CONFIGFS_EATTR_STRUCT(target_stat_scsi_transport, se_port_stat_grps);
  1078 +#define DEV_STAT_SCSI_TRANSPORT_ATTR(_name, _mode) \
  1079 +static 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) \
  1086 +static 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 +
  1091 +static 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 +}
  1112 +DEV_STAT_SCSI_TRANSPORT_ATTR_RO(inst);
  1113 +
  1114 +static 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 +}
  1135 +DEV_STAT_SCSI_TRANSPORT_ATTR_RO(device);
  1136 +
  1137 +static 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 +}
  1157 +DEV_STAT_SCSI_TRANSPORT_ATTR_RO(indx);
  1158 +
  1159 +static 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 +}
  1185 +DEV_STAT_SCSI_TRANSPORT_ATTR_RO(dev_name);
  1186 +
  1187 +CONFIGFS_EATTR_OPS(target_stat_scsi_transport, se_port_stat_grps,
  1188 + scsi_transport_group);
  1189 +
  1190 +static 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 +
  1198 +static 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 +
  1203 +static 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 + */
  1213 +void 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 +
  1234 +CONFIGFS_EATTR_STRUCT(target_stat_scsi_auth_intr, se_ml_stat_grps);
  1235 +#define DEV_STAT_SCSI_AUTH_INTR_ATTR(_name, _mode) \
  1236 +static 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) \
  1243 +static 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 +
  1248 +static 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 +}
  1271 +DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(inst);
  1272 +
  1273 +static 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 +}
  1297 +DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(dev);
  1298 +
  1299 +static 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 +}
  1321 +DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(port);
  1322 +
  1323 +static 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 +}
  1343 +DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(indx);
  1344 +
  1345 +static 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 +}
  1365 +DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(dev_or_port);
  1366 +
  1367 +static 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 +}
  1387 +DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(intr_name);
  1388 +
  1389 +static 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 +}
  1409 +DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(map_indx);
  1410 +
  1411 +static 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 +}
  1431 +DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(att_count);
  1432 +
  1433 +static 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 +}
  1453 +DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(num_cmds);
  1454 +
  1455 +static 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 +}
  1475 +DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(read_mbytes);
  1476 +
  1477 +static 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 +}
  1497 +DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(write_mbytes);
  1498 +
  1499 +static 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 +}
  1519 +DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(hs_num_cmds);
  1520 +
  1521 +static 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 +}
  1542 +DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(creation_time);
  1543 +
  1544 +static 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 +}
  1564 +DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(row_status);
  1565 +
  1566 +CONFIGFS_EATTR_OPS(target_stat_scsi_auth_intr, se_ml_stat_grps,
  1567 + scsi_auth_intr_group);
  1568 +
  1569 +static 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 +
  1587 +static 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 +
  1592 +static 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 +
  1602 +CONFIGFS_EATTR_STRUCT(target_stat_scsi_att_intr_port, se_ml_stat_grps);
  1603 +#define DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR(_name, _mode) \
  1604 +static 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) \
  1611 +static 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 +
  1616 +static 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 +}
  1639 +DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(inst);
  1640 +
  1641 +static 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 +}
  1665 +DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(dev);
  1666 +
  1667 +static 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 +}
  1689 +DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(port);
  1690 +
  1691 +static 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 +}
  1715 +DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(indx);
  1716 +
  1717 +static 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 +}
  1737 +DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(port_auth_indx);
  1738 +
  1739 +static 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 +}
  1768 +DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(port_ident);
  1769 +
  1770 +CONFIGFS_EATTR_OPS(target_stat_scsi_att_intr_port, se_ml_stat_grps,
  1771 + scsi_att_intr_port_group);
  1772 +
  1773 +static 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 +
  1783 +static 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 +
  1788 +static 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 + */
  1798 +void 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 +}
drivers/target/target_core_stat.h
  1 +#ifndef TARGET_CORE_STAT_H
  2 +#define TARGET_CORE_STAT_H
  3 +
  4 +extern void target_stat_setup_dev_default_groups(struct se_subsystem_dev *);
  5 +extern void target_stat_setup_port_default_groups(struct se_lun *);
  6 +extern void target_stat_setup_mappedlun_default_groups(struct se_lun_acl *);
  7 +
  8 +#endif /*** TARGET_CORE_STAT_H ***/
include/target/target_core_base.h
... ... @@ -601,7 +601,8 @@
601 601 struct config_group acl_attrib_group;
602 602 struct config_group acl_auth_group;
603 603 struct config_group acl_param_group;
604   - struct config_group *acl_default_groups[4];
  604 + struct config_group acl_fabric_stat_group;
  605 + struct config_group *acl_default_groups[5];
605 606 struct list_head acl_list;
606 607 struct list_head acl_sess_list;
607 608 } ____cacheline_aligned;
... ... @@ -622,6 +623,12 @@
622 623 struct se_transform_info;
623 624 struct scatterlist;
624 625  
  626 +struct se_ml_stat_grps {
  627 + struct config_group stat_group;
  628 + struct config_group scsi_auth_intr_group;
  629 + struct config_group scsi_att_intr_port_group;
  630 +};
  631 +
625 632 struct se_lun_acl {
626 633 char initiatorname[TRANSPORT_IQN_LEN];
627 634 u32 mapped_lun;
628 635  
... ... @@ -629,8 +636,11 @@
629 636 struct se_lun *se_lun;
630 637 struct list_head lacl_list;
631 638 struct config_group se_lun_group;
  639 + struct se_ml_stat_grps ml_stat_grps;
632 640 } ____cacheline_aligned;
633 641  
  642 +#define ML_STAT_GRPS(lacl) (&(lacl)->ml_stat_grps)
  643 +
634 644 struct se_dev_entry {
635 645 bool def_pr_registered;
636 646 /* See transport_lunflags_table */
... ... @@ -693,6 +703,13 @@
693 703 struct config_group da_group;
694 704 } ____cacheline_aligned;
695 705  
  706 +struct se_dev_stat_grps {
  707 + struct config_group stat_group;
  708 + struct config_group scsi_dev_group;
  709 + struct config_group scsi_tgt_dev_group;
  710 + struct config_group scsi_lu_group;
  711 +};
  712 +
696 713 struct se_subsystem_dev {
697 714 /* Used for struct se_subsystem_dev-->se_dev_alias, must be less than PAGE_SIZE */
698 715 #define SE_DEV_ALIAS_LEN 512
699 716  
... ... @@ -716,11 +733,14 @@
716 733 struct config_group se_dev_group;
717 734 /* For T10 Reservations */
718 735 struct config_group se_dev_pr_group;
  736 + /* For target_core_stat.c groups */
  737 + struct se_dev_stat_grps dev_stat_grps;
719 738 } ____cacheline_aligned;
720 739  
721 740 #define T10_ALUA(su_dev) (&(su_dev)->t10_alua)
722 741 #define T10_RES(su_dev) (&(su_dev)->t10_reservation)
723 742 #define T10_PR_OPS(su_dev) (&(su_dev)->t10_reservation.pr_ops)
  743 +#define DEV_STAT_GRP(dev) (&(dev)->dev_stat_grps)
724 744  
725 745 struct se_device {
726 746 /* Set to 1 if thread is NOT sleeping on thread_sem */
... ... @@ -834,6 +854,13 @@
834 854  
835 855 #define SE_HBA(dev) ((dev)->se_hba)
836 856  
  857 +struct se_port_stat_grps {
  858 + struct config_group stat_group;
  859 + struct config_group scsi_port_group;
  860 + struct config_group scsi_tgt_port_group;
  861 + struct config_group scsi_transport_group;
  862 +};
  863 +
837 864 struct se_lun {
838 865 /* See transport_lun_status_table */
839 866 enum transport_lun_status_table lun_status;
840 867  
841 868  
... ... @@ -848,11 +875,13 @@
848 875 struct list_head lun_cmd_list;
849 876 struct list_head lun_acl_list;
850 877 struct se_device *lun_se_dev;
  878 + struct se_port *lun_sep;
851 879 struct config_group lun_group;
852   - struct se_port *lun_sep;
  880 + struct se_port_stat_grps port_stat_grps;
853 881 } ____cacheline_aligned;
854 882  
855 883 #define SE_LUN(cmd) ((cmd)->se_lun)
  884 +#define PORT_STAT_GRP(lun) (&(lun)->port_stat_grps)
856 885  
857 886 struct scsi_port_stats {
858 887 u64 cmd_pdus;
... ... @@ -924,6 +953,8 @@
924 953 struct se_wwn {
925 954 struct target_fabric_configfs *wwn_tf;
926 955 struct config_group wwn_group;
  956 + struct config_group *wwn_default_groups[2];
  957 + struct config_group fabric_stat_group;
927 958 } ____cacheline_aligned;
928 959  
929 960 struct se_global {
include/target/target_core_configfs.h
... ... @@ -14,10 +14,12 @@
14 14 struct target_fabric_configfs_template {
15 15 struct config_item_type tfc_discovery_cit;
16 16 struct config_item_type tfc_wwn_cit;
  17 + struct config_item_type tfc_wwn_fabric_stats_cit;
17 18 struct config_item_type tfc_tpg_cit;
18 19 struct config_item_type tfc_tpg_base_cit;
19 20 struct config_item_type tfc_tpg_lun_cit;
20 21 struct config_item_type tfc_tpg_port_cit;
  22 + struct config_item_type tfc_tpg_port_stat_cit;
21 23 struct config_item_type tfc_tpg_np_cit;
22 24 struct config_item_type tfc_tpg_np_base_cit;
23 25 struct config_item_type tfc_tpg_attrib_cit;
24 26  
... ... @@ -27,7 +29,9 @@
27 29 struct config_item_type tfc_tpg_nacl_attrib_cit;
28 30 struct config_item_type tfc_tpg_nacl_auth_cit;
29 31 struct config_item_type tfc_tpg_nacl_param_cit;
  32 + struct config_item_type tfc_tpg_nacl_stat_cit;
30 33 struct config_item_type tfc_tpg_mappedlun_cit;
  34 + struct config_item_type tfc_tpg_mappedlun_stat_cit;
31 35 };
32 36  
33 37 struct target_fabric_configfs {