diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2011-03-14 07:06:11 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2011-03-23 12:36:50 -0400 |
commit | 12d233842987d9972957419e427987b94f7bd7b4 (patch) | |
tree | b3d08872b37f08aac3a9ec66e3fef49fbedb0f19 /drivers/target | |
parent | 15fb48cc40be170423fe8ddd17666aa6175315e3 (diff) |
[SCSI] target: add initial statistics
This patch adds a target_core_mib.c statistics conversion for
backend context struct se_subsystem_dev + struct se_device config_group
based statistics in target_core_device.c using CONFIGFS_EATTR()
based struct config_item_types from target_core_stat.c code.
The conversion from backend /proc/scsi_target/mib/ context output to configfs
default groups+attributes include scsi_dev, scsi_lu, and scsi_tgt_dev output
from within individual:
/sys/kernel/config/target/core/$HBA/DEV/
The legacy procfs output now appear as individual configfs attributes under:
*) $HBA/$DEV/statistics/scsi_dev:
|-- indx
|-- inst
|-- ports
`-- role
*) $HBA/$DEV/statistics/scsi_lu:
|-- creation_time
|-- dev
|-- dev_type
|-- full_stat
|-- hs_num_cmds
|-- indx
|-- inst
|-- lu_name
|-- lun
|-- num_cmds
|-- prod
|-- read_mbytes
|-- resets
|-- rev
|-- state_bit
|-- status
|-- vend
`-- write_mbytes
*) $HBA/$DEV/statistics/scsi_tgt_dev:
|-- indx
|-- inst
|-- non_access_lus
|-- num_lus
|-- resets
`-- status
The conversion from backend /proc/scsi_target/mib/ context output to configfs
default groups+attributes include scsi_port, scsi_tgt_port and scsi_transport
output from within individual:
/sys/kernel/config/target/fabric/$WWN/tpgt_$TPGT/lun/lun_$LUN_ID/statistics/
The legacy procfs output now appear as individual configfs attributes under:
*) fabric/$WWN/tpgt_$TPGT/lun/lun_$LUN_ID/statistics/scsi_port
|-- busy_count
|-- dev
|-- indx
|-- inst
`-- role
*) fabric/$WWN/tpgt_$TPGT/lun/lun_$LUN_ID/statistics/scsi_tgt_port
|-- dev
|-- hs_in_cmds
|-- in_cmds
|-- indx
|-- inst
|-- name
|-- port_index
|-- read_mbytes
`-- write_mbytes
*) fabric/$WWN/tpgt_$TPGT/lun/lun_$LUN_ID/statistics/scsi_transport
|-- dev_name
|-- device
|-- indx
`-- inst
The conversion from backend /proc/scsi_target/mib/ context output to configfs
default groups+attributes include scsi_att_intr_port and scsi_auth_intr output
from within individual:
/sys/kernel/config/target/fabric/$WWN/tpgt_$TPGT/acls/$INITIATOR_WWN/lun_$LUN_ID/statistics/
The legacy procfs output now appear as individual configfs attributes under:
*) acls/$INITIATOR_WWN/lun_$LUN_ID/statistics/scsi_att_intr_port
|-- dev
|-- indx
|-- inst
|-- port
|-- port_auth_indx
`-- port_ident
*) acls/$INITIATOR_WWN/lun_$LUN_ID/statistics/scsi_auth_intr
|-- att_count
|-- creation_time
|-- dev
|-- dev_or_port
|-- hs_num_cmds
|-- indx
|-- inst
|-- intr_name
|-- map_indx
|-- num_cmds
|-- port
|-- read_mbytes
|-- row_status
`-- write_mbytes
Also, this includes adding struct target_fabric_configfs_template->
tfc_wwn_fabric_stats_cit and ->tfc_tpg_nacl_stat_cit respectively for
use during target_core_fabric_configfs.c:target_fabric_setup_cits()
Signed-off-by: Nicholas A. Bellinger <nab@linux-iscsi.org>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/target')
-rw-r--r-- | drivers/target/Makefile | 3 | ||||
-rw-r--r-- | drivers/target/target_core_configfs.c | 76 | ||||
-rw-r--r-- | drivers/target/target_core_fabric_configfs.c | 209 | ||||
-rw-r--r-- | drivers/target/target_core_stat.c | 1810 | ||||
-rw-r--r-- | drivers/target/target_core_stat.h | 8 |
5 files changed, 2090 insertions, 16 deletions
diff --git a/drivers/target/Makefile b/drivers/target/Makefile index 050ee6569b2b..4f3cb788f06a 100644 --- a/drivers/target/Makefile +++ b/drivers/target/Makefile | |||
@@ -12,7 +12,8 @@ target_core_mod-y := target_core_configfs.o \ | |||
12 | target_core_transport.o \ | 12 | target_core_transport.o \ |
13 | target_core_cdb.o \ | 13 | target_core_cdb.o \ |
14 | target_core_ua.o \ | 14 | target_core_ua.o \ |
15 | target_core_rd.o | 15 | target_core_rd.o \ |
16 | target_core_stat.o | ||
16 | 17 | ||
17 | obj-$(CONFIG_TARGET_CORE) += target_core_mod.o | 18 | obj-$(CONFIG_TARGET_CORE) += target_core_mod.o |
18 | 19 | ||
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index a38fec4acceb..a5f44a6e6e1d 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c | |||
@@ -3,8 +3,8 @@ | |||
3 | * | 3 | * |
4 | * This file contains ConfigFS logic for the Generic Target Engine project. | 4 | * This file contains ConfigFS logic for the Generic Target Engine project. |
5 | * | 5 | * |
6 | * Copyright (c) 2008-2010 Rising Tide Systems | 6 | * Copyright (c) 2008-2011 Rising Tide Systems |
7 | * Copyright (c) 2008-2010 Linux-iSCSI.org | 7 | * Copyright (c) 2008-2011 Linux-iSCSI.org |
8 | * | 8 | * |
9 | * Nicholas A. Bellinger <nab@kernel.org> | 9 | * Nicholas A. Bellinger <nab@kernel.org> |
10 | * | 10 | * |
@@ -50,6 +50,7 @@ | |||
50 | #include "target_core_hba.h" | 50 | #include "target_core_hba.h" |
51 | #include "target_core_pr.h" | 51 | #include "target_core_pr.h" |
52 | #include "target_core_rd.h" | 52 | #include "target_core_rd.h" |
53 | #include "target_core_stat.h" | ||
53 | 54 | ||
54 | static struct list_head g_tf_list; | 55 | static struct list_head g_tf_list; |
55 | static struct mutex g_tf_lock; | 56 | static struct mutex g_tf_lock; |
@@ -2709,6 +2710,34 @@ static struct config_item_type target_core_alua_cit = { | |||
2709 | 2710 | ||
2710 | /* End functions for struct config_item_type target_core_alua_cit */ | 2711 | /* End functions for struct config_item_type target_core_alua_cit */ |
2711 | 2712 | ||
2713 | /* Start functions for struct config_item_type target_core_stat_cit */ | ||
2714 | |||
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 | /* Start functions for struct config_item_type target_core_hba_cit */ | 2741 | /* Start functions for struct config_item_type target_core_hba_cit */ |
2713 | 2742 | ||
2714 | static struct config_group *target_core_make_subdev( | 2743 | static struct config_group *target_core_make_subdev( |
@@ -2721,10 +2750,12 @@ static struct config_group *target_core_make_subdev( | |||
2721 | struct config_item *hba_ci = &group->cg_item; | 2750 | struct config_item *hba_ci = &group->cg_item; |
2722 | struct se_hba *hba = item_to_hba(hba_ci); | 2751 | struct se_hba *hba = item_to_hba(hba_ci); |
2723 | struct config_group *dev_cg = NULL, *tg_pt_gp_cg = NULL; | 2752 | struct config_group *dev_cg = NULL, *tg_pt_gp_cg = NULL; |
2753 | struct config_group *dev_stat_grp = NULL; | ||
2754 | int errno = -ENOMEM, ret; | ||
2724 | 2755 | ||
2725 | if (mutex_lock_interruptible(&hba->hba_access_mutex)) | 2756 | ret = mutex_lock_interruptible(&hba->hba_access_mutex); |
2726 | return NULL; | 2757 | if (ret) |
2727 | 2758 | return ERR_PTR(ret); | |
2728 | /* | 2759 | /* |
2729 | * Locate the struct se_subsystem_api from parent's struct se_hba. | 2760 | * Locate the struct se_subsystem_api from parent's struct se_hba. |
2730 | */ | 2761 | */ |
@@ -2754,7 +2785,7 @@ static struct config_group *target_core_make_subdev( | |||
2754 | se_dev->se_dev_hba = hba; | 2785 | se_dev->se_dev_hba = hba; |
2755 | dev_cg = &se_dev->se_dev_group; | 2786 | dev_cg = &se_dev->se_dev_group; |
2756 | 2787 | ||
2757 | dev_cg->default_groups = kzalloc(sizeof(struct config_group) * 6, | 2788 | dev_cg->default_groups = kzalloc(sizeof(struct config_group) * 7, |
2758 | GFP_KERNEL); | 2789 | GFP_KERNEL); |
2759 | if (!(dev_cg->default_groups)) | 2790 | if (!(dev_cg->default_groups)) |
2760 | goto out; | 2791 | goto out; |
@@ -2786,13 +2817,17 @@ static struct config_group *target_core_make_subdev( | |||
2786 | &target_core_dev_wwn_cit); | 2817 | &target_core_dev_wwn_cit); |
2787 | config_group_init_type_name(&se_dev->t10_alua.alua_tg_pt_gps_group, | 2818 | config_group_init_type_name(&se_dev->t10_alua.alua_tg_pt_gps_group, |
2788 | "alua", &target_core_alua_tg_pt_gps_cit); | 2819 | "alua", &target_core_alua_tg_pt_gps_cit); |
2820 | config_group_init_type_name(&se_dev->dev_stat_grps.stat_group, | ||
2821 | "statistics", &target_core_stat_cit); | ||
2822 | |||
2789 | dev_cg->default_groups[0] = &se_dev->se_dev_attrib.da_group; | 2823 | dev_cg->default_groups[0] = &se_dev->se_dev_attrib.da_group; |
2790 | dev_cg->default_groups[1] = &se_dev->se_dev_pr_group; | 2824 | dev_cg->default_groups[1] = &se_dev->se_dev_pr_group; |
2791 | dev_cg->default_groups[2] = &se_dev->t10_wwn.t10_wwn_group; | 2825 | dev_cg->default_groups[2] = &se_dev->t10_wwn.t10_wwn_group; |
2792 | dev_cg->default_groups[3] = &se_dev->t10_alua.alua_tg_pt_gps_group; | 2826 | dev_cg->default_groups[3] = &se_dev->t10_alua.alua_tg_pt_gps_group; |
2793 | dev_cg->default_groups[4] = NULL; | 2827 | dev_cg->default_groups[4] = &se_dev->dev_stat_grps.stat_group; |
2828 | dev_cg->default_groups[5] = NULL; | ||
2794 | /* | 2829 | /* |
2795 | * Add core/$HBA/$DEV/alua/tg_pt_gps/default_tg_pt_gp | 2830 | * Add core/$HBA/$DEV/alua/default_tg_pt_gp |
2796 | */ | 2831 | */ |
2797 | tg_pt_gp = core_alua_allocate_tg_pt_gp(se_dev, "default_tg_pt_gp", 1); | 2832 | tg_pt_gp = core_alua_allocate_tg_pt_gp(se_dev, "default_tg_pt_gp", 1); |
2798 | if (!(tg_pt_gp)) | 2833 | if (!(tg_pt_gp)) |
@@ -2812,6 +2847,17 @@ static struct config_group *target_core_make_subdev( | |||
2812 | tg_pt_gp_cg->default_groups[0] = &tg_pt_gp->tg_pt_gp_group; | 2847 | tg_pt_gp_cg->default_groups[0] = &tg_pt_gp->tg_pt_gp_group; |
2813 | tg_pt_gp_cg->default_groups[1] = NULL; | 2848 | tg_pt_gp_cg->default_groups[1] = NULL; |
2814 | T10_ALUA(se_dev)->default_tg_pt_gp = tg_pt_gp; | 2849 | T10_ALUA(se_dev)->default_tg_pt_gp = tg_pt_gp; |
2850 | /* | ||
2851 | * Add core/$HBA/$DEV/statistics/ default groups | ||
2852 | */ | ||
2853 | dev_stat_grp = &DEV_STAT_GRP(se_dev)->stat_group; | ||
2854 | dev_stat_grp->default_groups = kzalloc(sizeof(struct config_group) * 4, | ||
2855 | GFP_KERNEL); | ||
2856 | if (!dev_stat_grp->default_groups) { | ||
2857 | printk(KERN_ERR "Unable to allocate dev_stat_grp->default_groups\n"); | ||
2858 | goto out; | ||
2859 | } | ||
2860 | target_stat_setup_dev_default_groups(se_dev); | ||
2815 | 2861 | ||
2816 | printk(KERN_INFO "Target_Core_ConfigFS: Allocated struct se_subsystem_dev:" | 2862 | printk(KERN_INFO "Target_Core_ConfigFS: Allocated struct se_subsystem_dev:" |
2817 | " %p se_dev_su_ptr: %p\n", se_dev, se_dev->se_dev_su_ptr); | 2863 | " %p se_dev_su_ptr: %p\n", se_dev, se_dev->se_dev_su_ptr); |
@@ -2823,6 +2869,8 @@ out: | |||
2823 | core_alua_free_tg_pt_gp(T10_ALUA(se_dev)->default_tg_pt_gp); | 2869 | core_alua_free_tg_pt_gp(T10_ALUA(se_dev)->default_tg_pt_gp); |
2824 | T10_ALUA(se_dev)->default_tg_pt_gp = NULL; | 2870 | T10_ALUA(se_dev)->default_tg_pt_gp = NULL; |
2825 | } | 2871 | } |
2872 | if (dev_stat_grp) | ||
2873 | kfree(dev_stat_grp->default_groups); | ||
2826 | if (tg_pt_gp_cg) | 2874 | if (tg_pt_gp_cg) |
2827 | kfree(tg_pt_gp_cg->default_groups); | 2875 | kfree(tg_pt_gp_cg->default_groups); |
2828 | if (dev_cg) | 2876 | if (dev_cg) |
@@ -2832,7 +2880,7 @@ out: | |||
2832 | kfree(se_dev); | 2880 | kfree(se_dev); |
2833 | unlock: | 2881 | unlock: |
2834 | mutex_unlock(&hba->hba_access_mutex); | 2882 | mutex_unlock(&hba->hba_access_mutex); |
2835 | return NULL; | 2883 | return ERR_PTR(errno); |
2836 | } | 2884 | } |
2837 | 2885 | ||
2838 | static void target_core_drop_subdev( | 2886 | static void target_core_drop_subdev( |
@@ -2844,7 +2892,7 @@ static void target_core_drop_subdev( | |||
2844 | struct se_hba *hba; | 2892 | struct se_hba *hba; |
2845 | struct se_subsystem_api *t; | 2893 | struct se_subsystem_api *t; |
2846 | struct config_item *df_item; | 2894 | struct config_item *df_item; |
2847 | struct config_group *dev_cg, *tg_pt_gp_cg; | 2895 | struct config_group *dev_cg, *tg_pt_gp_cg, *dev_stat_grp; |
2848 | int i; | 2896 | int i; |
2849 | 2897 | ||
2850 | hba = item_to_hba(&se_dev->se_dev_hba->hba_group.cg_item); | 2898 | hba = item_to_hba(&se_dev->se_dev_hba->hba_group.cg_item); |
@@ -2856,6 +2904,14 @@ static void target_core_drop_subdev( | |||
2856 | list_del(&se_dev->g_se_dev_list); | 2904 | list_del(&se_dev->g_se_dev_list); |
2857 | spin_unlock(&se_global->g_device_lock); | 2905 | spin_unlock(&se_global->g_device_lock); |
2858 | 2906 | ||
2907 | dev_stat_grp = &DEV_STAT_GRP(se_dev)->stat_group; | ||
2908 | for (i = 0; dev_stat_grp->default_groups[i]; i++) { | ||
2909 | df_item = &dev_stat_grp->default_groups[i]->cg_item; | ||
2910 | dev_stat_grp->default_groups[i] = NULL; | ||
2911 | config_item_put(df_item); | ||
2912 | } | ||
2913 | kfree(dev_stat_grp->default_groups); | ||
2914 | |||
2859 | tg_pt_gp_cg = &T10_ALUA(se_dev)->alua_tg_pt_gps_group; | 2915 | tg_pt_gp_cg = &T10_ALUA(se_dev)->alua_tg_pt_gps_group; |
2860 | for (i = 0; tg_pt_gp_cg->default_groups[i]; i++) { | 2916 | for (i = 0; tg_pt_gp_cg->default_groups[i]; i++) { |
2861 | df_item = &tg_pt_gp_cg->default_groups[i]->cg_item; | 2917 | df_item = &tg_pt_gp_cg->default_groups[i]->cg_item; |
diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index b65d1c8e7740..07ab5a3bb8e8 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c | |||
@@ -4,10 +4,10 @@ | |||
4 | * This file contains generic fabric module configfs infrastructure for | 4 | * This file contains generic fabric module configfs infrastructure for |
5 | * TCM v4.x code | 5 | * TCM v4.x code |
6 | * | 6 | * |
7 | * Copyright (c) 2010 Rising Tide Systems | 7 | * Copyright (c) 2010,2011 Rising Tide Systems |
8 | * Copyright (c) 2010 Linux-iSCSI.org | 8 | * Copyright (c) 2010,2011 Linux-iSCSI.org |
9 | * | 9 | * |
10 | * Copyright (c) 2010 Nicholas A. Bellinger <nab@linux-iscsi.org> | 10 | * Copyright (c) Nicholas A. Bellinger <nab@linux-iscsi.org> |
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
13 | * it under the terms of the GNU General Public License as published by | 13 | * it under the terms of the GNU General Public License as published by |
@@ -48,6 +48,7 @@ | |||
48 | #include "target_core_alua.h" | 48 | #include "target_core_alua.h" |
49 | #include "target_core_hba.h" | 49 | #include "target_core_hba.h" |
50 | #include "target_core_pr.h" | 50 | #include "target_core_pr.h" |
51 | #include "target_core_stat.h" | ||
51 | 52 | ||
52 | #define TF_CIT_SETUP(_name, _item_ops, _group_ops, _attrs) \ | 53 | #define TF_CIT_SETUP(_name, _item_ops, _group_ops, _attrs) \ |
53 | static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf) \ | 54 | static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf) \ |
@@ -241,6 +242,32 @@ TF_CIT_SETUP(tpg_mappedlun, &target_fabric_mappedlun_item_ops, NULL, | |||
241 | 242 | ||
242 | /* End of tfc_tpg_mappedlun_cit */ | 243 | /* End of tfc_tpg_mappedlun_cit */ |
243 | 244 | ||
245 | /* Start of tfc_tpg_mappedlun_port_cit */ | ||
246 | |||
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 | /* Start of tfc_tpg_nacl_attrib_cit */ | 271 | /* Start of tfc_tpg_nacl_attrib_cit */ |
245 | 272 | ||
246 | CONFIGFS_EATTR_OPS(target_fabric_nacl_attrib, se_node_acl, acl_attrib_group); | 273 | CONFIGFS_EATTR_OPS(target_fabric_nacl_attrib, se_node_acl, acl_attrib_group); |
@@ -294,6 +321,7 @@ static struct config_group *target_fabric_make_mappedlun( | |||
294 | struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; | 321 | struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; |
295 | struct se_lun_acl *lacl; | 322 | struct se_lun_acl *lacl; |
296 | struct config_item *acl_ci; | 323 | struct config_item *acl_ci; |
324 | struct config_group *lacl_cg = NULL, *ml_stat_grp = NULL; | ||
297 | char *buf; | 325 | char *buf; |
298 | unsigned long mapped_lun; | 326 | unsigned long mapped_lun; |
299 | int ret = 0; | 327 | int ret = 0; |
@@ -330,15 +358,42 @@ static struct config_group *target_fabric_make_mappedlun( | |||
330 | 358 | ||
331 | lacl = core_dev_init_initiator_node_lun_acl(se_tpg, mapped_lun, | 359 | lacl = core_dev_init_initiator_node_lun_acl(se_tpg, mapped_lun, |
332 | config_item_name(acl_ci), &ret); | 360 | config_item_name(acl_ci), &ret); |
333 | if (!(lacl)) | 361 | if (!(lacl)) { |
362 | ret = -EINVAL; | ||
334 | goto out; | 363 | goto out; |
364 | } | ||
365 | |||
366 | lacl_cg = &lacl->se_lun_group; | ||
367 | lacl_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, | ||
368 | GFP_KERNEL); | ||
369 | if (!lacl_cg->default_groups) { | ||
370 | printk(KERN_ERR "Unable to allocate lacl_cg->default_groups\n"); | ||
371 | ret = -ENOMEM; | ||
372 | goto out; | ||
373 | } | ||
335 | 374 | ||
336 | config_group_init_type_name(&lacl->se_lun_group, name, | 375 | config_group_init_type_name(&lacl->se_lun_group, name, |
337 | &TF_CIT_TMPL(tf)->tfc_tpg_mappedlun_cit); | 376 | &TF_CIT_TMPL(tf)->tfc_tpg_mappedlun_cit); |
377 | config_group_init_type_name(&lacl->ml_stat_grps.stat_group, | ||
378 | "statistics", &TF_CIT_TMPL(tf)->tfc_tpg_mappedlun_stat_cit); | ||
379 | lacl_cg->default_groups[0] = &lacl->ml_stat_grps.stat_group; | ||
380 | lacl_cg->default_groups[1] = NULL; | ||
381 | |||
382 | ml_stat_grp = &ML_STAT_GRPS(lacl)->stat_group; | ||
383 | ml_stat_grp->default_groups = kzalloc(sizeof(struct config_group) * 3, | ||
384 | GFP_KERNEL); | ||
385 | if (!ml_stat_grp->default_groups) { | ||
386 | printk(KERN_ERR "Unable to allocate ml_stat_grp->default_groups\n"); | ||
387 | ret = -ENOMEM; | ||
388 | goto out; | ||
389 | } | ||
390 | target_stat_setup_mappedlun_default_groups(lacl); | ||
338 | 391 | ||
339 | kfree(buf); | 392 | kfree(buf); |
340 | return &lacl->se_lun_group; | 393 | return &lacl->se_lun_group; |
341 | out: | 394 | out: |
395 | if (lacl_cg) | ||
396 | kfree(lacl_cg->default_groups); | ||
342 | kfree(buf); | 397 | kfree(buf); |
343 | return ERR_PTR(ret); | 398 | return ERR_PTR(ret); |
344 | } | 399 | } |
@@ -347,6 +402,28 @@ static void target_fabric_drop_mappedlun( | |||
347 | struct config_group *group, | 402 | struct config_group *group, |
348 | struct config_item *item) | 403 | struct config_item *item) |
349 | { | 404 | { |
405 | struct se_lun_acl *lacl = container_of(to_config_group(item), | ||
406 | struct se_lun_acl, se_lun_group); | ||
407 | struct config_item *df_item; | ||
408 | struct config_group *lacl_cg = NULL, *ml_stat_grp = NULL; | ||
409 | int i; | ||
410 | |||
411 | ml_stat_grp = &ML_STAT_GRPS(lacl)->stat_group; | ||
412 | for (i = 0; ml_stat_grp->default_groups[i]; i++) { | ||
413 | df_item = &ml_stat_grp->default_groups[i]->cg_item; | ||
414 | ml_stat_grp->default_groups[i] = NULL; | ||
415 | config_item_put(df_item); | ||
416 | } | ||
417 | kfree(ml_stat_grp->default_groups); | ||
418 | |||
419 | lacl_cg = &lacl->se_lun_group; | ||
420 | for (i = 0; lacl_cg->default_groups[i]; i++) { | ||
421 | df_item = &lacl_cg->default_groups[i]->cg_item; | ||
422 | lacl_cg->default_groups[i] = NULL; | ||
423 | config_item_put(df_item); | ||
424 | } | ||
425 | kfree(lacl_cg->default_groups); | ||
426 | |||
350 | config_item_put(item); | 427 | config_item_put(item); |
351 | } | 428 | } |
352 | 429 | ||
@@ -376,6 +453,15 @@ TF_CIT_SETUP(tpg_nacl_base, &target_fabric_nacl_base_item_ops, | |||
376 | 453 | ||
377 | /* End of tfc_tpg_nacl_base_cit */ | 454 | /* End of tfc_tpg_nacl_base_cit */ |
378 | 455 | ||
456 | /* Start of tfc_node_fabric_stats_cit */ | ||
457 | /* | ||
458 | * This is used as a placeholder for struct se_node_acl->acl_fabric_stat_group | ||
459 | * to allow fabrics access to ->acl_fabric_stat_group->default_groups[] | ||
460 | */ | ||
461 | TF_CIT_SETUP(tpg_nacl_stat, NULL, NULL, NULL); | ||
462 | |||
463 | /* End of tfc_wwn_fabric_stats_cit */ | ||
464 | |||
379 | /* Start of tfc_tpg_nacl_cit */ | 465 | /* Start of tfc_tpg_nacl_cit */ |
380 | 466 | ||
381 | static struct config_group *target_fabric_make_nodeacl( | 467 | static struct config_group *target_fabric_make_nodeacl( |
@@ -402,7 +488,8 @@ static struct config_group *target_fabric_make_nodeacl( | |||
402 | nacl_cg->default_groups[0] = &se_nacl->acl_attrib_group; | 488 | nacl_cg->default_groups[0] = &se_nacl->acl_attrib_group; |
403 | nacl_cg->default_groups[1] = &se_nacl->acl_auth_group; | 489 | nacl_cg->default_groups[1] = &se_nacl->acl_auth_group; |
404 | nacl_cg->default_groups[2] = &se_nacl->acl_param_group; | 490 | nacl_cg->default_groups[2] = &se_nacl->acl_param_group; |
405 | nacl_cg->default_groups[3] = NULL; | 491 | nacl_cg->default_groups[3] = &se_nacl->acl_fabric_stat_group; |
492 | nacl_cg->default_groups[4] = NULL; | ||
406 | 493 | ||
407 | config_group_init_type_name(&se_nacl->acl_group, name, | 494 | config_group_init_type_name(&se_nacl->acl_group, name, |
408 | &TF_CIT_TMPL(tf)->tfc_tpg_nacl_base_cit); | 495 | &TF_CIT_TMPL(tf)->tfc_tpg_nacl_base_cit); |
@@ -412,6 +499,9 @@ static struct config_group *target_fabric_make_nodeacl( | |||
412 | &TF_CIT_TMPL(tf)->tfc_tpg_nacl_auth_cit); | 499 | &TF_CIT_TMPL(tf)->tfc_tpg_nacl_auth_cit); |
413 | config_group_init_type_name(&se_nacl->acl_param_group, "param", | 500 | config_group_init_type_name(&se_nacl->acl_param_group, "param", |
414 | &TF_CIT_TMPL(tf)->tfc_tpg_nacl_param_cit); | 501 | &TF_CIT_TMPL(tf)->tfc_tpg_nacl_param_cit); |
502 | config_group_init_type_name(&se_nacl->acl_fabric_stat_group, | ||
503 | "fabric_statistics", | ||
504 | &TF_CIT_TMPL(tf)->tfc_tpg_nacl_stat_cit); | ||
415 | 505 | ||
416 | return &se_nacl->acl_group; | 506 | return &se_nacl->acl_group; |
417 | } | 507 | } |
@@ -758,6 +848,31 @@ TF_CIT_SETUP(tpg_port, &target_fabric_port_item_ops, NULL, target_fabric_port_at | |||
758 | 848 | ||
759 | /* End of tfc_tpg_port_cit */ | 849 | /* End of tfc_tpg_port_cit */ |
760 | 850 | ||
851 | /* Start of tfc_tpg_port_stat_cit */ | ||
852 | |||
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 | /* Start of tfc_tpg_lun_cit */ | 876 | /* Start of tfc_tpg_lun_cit */ |
762 | 877 | ||
763 | static struct config_group *target_fabric_make_lun( | 878 | static struct config_group *target_fabric_make_lun( |
@@ -768,7 +883,9 @@ static struct config_group *target_fabric_make_lun( | |||
768 | struct se_portal_group *se_tpg = container_of(group, | 883 | struct se_portal_group *se_tpg = container_of(group, |
769 | struct se_portal_group, tpg_lun_group); | 884 | struct se_portal_group, tpg_lun_group); |
770 | struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; | 885 | struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; |
886 | struct config_group *lun_cg = NULL, *port_stat_grp = NULL; | ||
771 | unsigned long unpacked_lun; | 887 | unsigned long unpacked_lun; |
888 | int errno; | ||
772 | 889 | ||
773 | if (strstr(name, "lun_") != name) { | 890 | if (strstr(name, "lun_") != name) { |
774 | printk(KERN_ERR "Unable to locate \'_\" in" | 891 | printk(KERN_ERR "Unable to locate \'_\" in" |
@@ -782,16 +899,64 @@ static struct config_group *target_fabric_make_lun( | |||
782 | if (!(lun)) | 899 | if (!(lun)) |
783 | return ERR_PTR(-EINVAL); | 900 | return ERR_PTR(-EINVAL); |
784 | 901 | ||
902 | lun_cg = &lun->lun_group; | ||
903 | lun_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, | ||
904 | GFP_KERNEL); | ||
905 | if (!lun_cg->default_groups) { | ||
906 | printk(KERN_ERR "Unable to allocate lun_cg->default_groups\n"); | ||
907 | return ERR_PTR(-ENOMEM); | ||
908 | } | ||
909 | |||
785 | config_group_init_type_name(&lun->lun_group, name, | 910 | config_group_init_type_name(&lun->lun_group, name, |
786 | &TF_CIT_TMPL(tf)->tfc_tpg_port_cit); | 911 | &TF_CIT_TMPL(tf)->tfc_tpg_port_cit); |
912 | config_group_init_type_name(&lun->port_stat_grps.stat_group, | ||
913 | "statistics", &TF_CIT_TMPL(tf)->tfc_tpg_port_stat_cit); | ||
914 | lun_cg->default_groups[0] = &lun->port_stat_grps.stat_group; | ||
915 | lun_cg->default_groups[1] = NULL; | ||
916 | |||
917 | port_stat_grp = &PORT_STAT_GRP(lun)->stat_group; | ||
918 | port_stat_grp->default_groups = kzalloc(sizeof(struct config_group) * 3, | ||
919 | GFP_KERNEL); | ||
920 | if (!port_stat_grp->default_groups) { | ||
921 | printk(KERN_ERR "Unable to allocate port_stat_grp->default_groups\n"); | ||
922 | errno = -ENOMEM; | ||
923 | goto out; | ||
924 | } | ||
925 | target_stat_setup_port_default_groups(lun); | ||
787 | 926 | ||
788 | return &lun->lun_group; | 927 | return &lun->lun_group; |
928 | out: | ||
929 | if (lun_cg) | ||
930 | kfree(lun_cg->default_groups); | ||
931 | return ERR_PTR(errno); | ||
789 | } | 932 | } |
790 | 933 | ||
791 | static void target_fabric_drop_lun( | 934 | static void target_fabric_drop_lun( |
792 | struct config_group *group, | 935 | struct config_group *group, |
793 | struct config_item *item) | 936 | struct config_item *item) |
794 | { | 937 | { |
938 | struct se_lun *lun = container_of(to_config_group(item), | ||
939 | struct se_lun, lun_group); | ||
940 | struct config_item *df_item; | ||
941 | struct config_group *lun_cg, *port_stat_grp; | ||
942 | int i; | ||
943 | |||
944 | port_stat_grp = &PORT_STAT_GRP(lun)->stat_group; | ||
945 | for (i = 0; port_stat_grp->default_groups[i]; i++) { | ||
946 | df_item = &port_stat_grp->default_groups[i]->cg_item; | ||
947 | port_stat_grp->default_groups[i] = NULL; | ||
948 | config_item_put(df_item); | ||
949 | } | ||
950 | kfree(port_stat_grp->default_groups); | ||
951 | |||
952 | lun_cg = &lun->lun_group; | ||
953 | for (i = 0; lun_cg->default_groups[i]; i++) { | ||
954 | df_item = &lun_cg->default_groups[i]->cg_item; | ||
955 | lun_cg->default_groups[i] = NULL; | ||
956 | config_item_put(df_item); | ||
957 | } | ||
958 | kfree(lun_cg->default_groups); | ||
959 | |||
795 | config_item_put(item); | 960 | config_item_put(item); |
796 | } | 961 | } |
797 | 962 | ||
@@ -946,6 +1111,15 @@ TF_CIT_SETUP(tpg, &target_fabric_tpg_item_ops, &target_fabric_tpg_group_ops, | |||
946 | 1111 | ||
947 | /* End of tfc_tpg_cit */ | 1112 | /* End of tfc_tpg_cit */ |
948 | 1113 | ||
1114 | /* Start of tfc_wwn_fabric_stats_cit */ | ||
1115 | /* | ||
1116 | * This is used as a placeholder for struct se_wwn->fabric_stat_group | ||
1117 | * to allow fabrics access to ->fabric_stat_group->default_groups[] | ||
1118 | */ | ||
1119 | TF_CIT_SETUP(wwn_fabric_stats, NULL, NULL, NULL); | ||
1120 | |||
1121 | /* End of tfc_wwn_fabric_stats_cit */ | ||
1122 | |||
949 | /* Start of tfc_wwn_cit */ | 1123 | /* Start of tfc_wwn_cit */ |
950 | 1124 | ||
951 | static struct config_group *target_fabric_make_wwn( | 1125 | static struct config_group *target_fabric_make_wwn( |
@@ -966,8 +1140,17 @@ static struct config_group *target_fabric_make_wwn( | |||
966 | return ERR_PTR(-EINVAL); | 1140 | return ERR_PTR(-EINVAL); |
967 | 1141 | ||
968 | wwn->wwn_tf = tf; | 1142 | wwn->wwn_tf = tf; |
1143 | /* | ||
1144 | * Setup default groups from pre-allocated wwn->wwn_default_groups | ||
1145 | */ | ||
1146 | wwn->wwn_group.default_groups = wwn->wwn_default_groups; | ||
1147 | wwn->wwn_group.default_groups[0] = &wwn->fabric_stat_group; | ||
1148 | wwn->wwn_group.default_groups[1] = NULL; | ||
1149 | |||
969 | config_group_init_type_name(&wwn->wwn_group, name, | 1150 | config_group_init_type_name(&wwn->wwn_group, name, |
970 | &TF_CIT_TMPL(tf)->tfc_tpg_cit); | 1151 | &TF_CIT_TMPL(tf)->tfc_tpg_cit); |
1152 | config_group_init_type_name(&wwn->fabric_stat_group, "fabric_statistics", | ||
1153 | &TF_CIT_TMPL(tf)->tfc_wwn_fabric_stats_cit); | ||
971 | 1154 | ||
972 | return &wwn->wwn_group; | 1155 | return &wwn->wwn_group; |
973 | } | 1156 | } |
@@ -976,6 +1159,18 @@ static void target_fabric_drop_wwn( | |||
976 | struct config_group *group, | 1159 | struct config_group *group, |
977 | struct config_item *item) | 1160 | struct config_item *item) |
978 | { | 1161 | { |
1162 | struct se_wwn *wwn = container_of(to_config_group(item), | ||
1163 | struct se_wwn, wwn_group); | ||
1164 | struct config_item *df_item; | ||
1165 | struct config_group *cg = &wwn->wwn_group; | ||
1166 | int i; | ||
1167 | |||
1168 | for (i = 0; cg->default_groups[i]; i++) { | ||
1169 | df_item = &cg->default_groups[i]->cg_item; | ||
1170 | cg->default_groups[i] = NULL; | ||
1171 | config_item_put(df_item); | ||
1172 | } | ||
1173 | |||
979 | config_item_put(item); | 1174 | config_item_put(item); |
980 | } | 1175 | } |
981 | 1176 | ||
@@ -1015,9 +1210,11 @@ int target_fabric_setup_cits(struct target_fabric_configfs *tf) | |||
1015 | { | 1210 | { |
1016 | target_fabric_setup_discovery_cit(tf); | 1211 | target_fabric_setup_discovery_cit(tf); |
1017 | target_fabric_setup_wwn_cit(tf); | 1212 | target_fabric_setup_wwn_cit(tf); |
1213 | target_fabric_setup_wwn_fabric_stats_cit(tf); | ||
1018 | target_fabric_setup_tpg_cit(tf); | 1214 | target_fabric_setup_tpg_cit(tf); |
1019 | target_fabric_setup_tpg_base_cit(tf); | 1215 | target_fabric_setup_tpg_base_cit(tf); |
1020 | target_fabric_setup_tpg_port_cit(tf); | 1216 | target_fabric_setup_tpg_port_cit(tf); |
1217 | target_fabric_setup_tpg_port_stat_cit(tf); | ||
1021 | target_fabric_setup_tpg_lun_cit(tf); | 1218 | target_fabric_setup_tpg_lun_cit(tf); |
1022 | target_fabric_setup_tpg_np_cit(tf); | 1219 | target_fabric_setup_tpg_np_cit(tf); |
1023 | target_fabric_setup_tpg_np_base_cit(tf); | 1220 | target_fabric_setup_tpg_np_base_cit(tf); |
@@ -1028,7 +1225,9 @@ int target_fabric_setup_cits(struct target_fabric_configfs *tf) | |||
1028 | target_fabric_setup_tpg_nacl_attrib_cit(tf); | 1225 | target_fabric_setup_tpg_nacl_attrib_cit(tf); |
1029 | target_fabric_setup_tpg_nacl_auth_cit(tf); | 1226 | target_fabric_setup_tpg_nacl_auth_cit(tf); |
1030 | target_fabric_setup_tpg_nacl_param_cit(tf); | 1227 | target_fabric_setup_tpg_nacl_param_cit(tf); |
1228 | target_fabric_setup_tpg_nacl_stat_cit(tf); | ||
1031 | target_fabric_setup_tpg_mappedlun_cit(tf); | 1229 | target_fabric_setup_tpg_mappedlun_cit(tf); |
1230 | target_fabric_setup_tpg_mappedlun_stat_cit(tf); | ||
1032 | 1231 | ||
1033 | return 0; | 1232 | return 0; |
1034 | } | 1233 | } |
diff --git a/drivers/target/target_core_stat.c b/drivers/target/target_core_stat.c new file mode 100644 index 000000000000..5e3a067a7475 --- /dev/null +++ b/drivers/target/target_core_stat.c | |||
@@ -0,0 +1,1810 @@ | |||
1 | /******************************************************************************* | ||
2 | * Filename: target_core_stat.c | ||
3 | * | ||
4 | * Copyright (c) 2011 Rising Tide Systems | ||
5 | * Copyright (c) 2011 Linux-iSCSI.org | ||
6 | * | ||
7 | * Modern ConfigFS group context specific statistics based on original | ||
8 | * target_core_mib.c code | ||
9 | * | ||
10 | * Copyright (c) 2006-2007 SBE, Inc. All Rights Reserved. | ||
11 | * | ||
12 | * Nicholas A. Bellinger <nab@linux-iscsi.org> | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by | ||
16 | * the Free Software Foundation; either version 2 of the License, or | ||
17 | * (at your option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
27 | * | ||
28 | ******************************************************************************/ | ||
29 | |||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/timer.h> | ||
34 | #include <linux/string.h> | ||
35 | #include <linux/version.h> | ||
36 | #include <generated/utsrelease.h> | ||
37 | #include <linux/utsname.h> | ||
38 | #include <linux/proc_fs.h> | ||
39 | #include <linux/seq_file.h> | ||
40 | #include <linux/blkdev.h> | ||
41 | #include <linux/configfs.h> | ||
42 | #include <scsi/scsi.h> | ||
43 | #include <scsi/scsi_device.h> | ||
44 | #include <scsi/scsi_host.h> | ||
45 | |||
46 | #include <target/target_core_base.h> | ||
47 | #include <target/target_core_transport.h> | ||
48 | #include <target/target_core_fabric_ops.h> | ||
49 | #include <target/target_core_configfs.h> | ||
50 | #include <target/configfs_macros.h> | ||
51 | |||
52 | #include "target_core_hba.h" | ||
53 | |||
54 | #ifndef INITIAL_JIFFIES | ||
55 | #define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ)) | ||
56 | #endif | ||
57 | |||
58 | #define NONE "None" | ||
59 | #define ISPRINT(a) ((a >= ' ') && (a <= '~')) | ||
60 | |||
61 | #define SCSI_LU_INDEX 1 | ||
62 | #define LU_COUNT 1 | ||
63 | |||
64 | /* | ||
65 | * SCSI Device Table | ||
66 | */ | ||
67 | |||
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 | } | ||
diff --git a/drivers/target/target_core_stat.h b/drivers/target/target_core_stat.h new file mode 100644 index 000000000000..86c252f9ea47 --- /dev/null +++ b/drivers/target/target_core_stat.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef TARGET_CORE_STAT_H | ||
2 | #define TARGET_CORE_STAT_H | ||
3 | |||
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 ***/ | ||