James
can you give me the status of the below patch ?
Is there anything missing from my side or is the patch still in review by you ?
Cheers Swen
On Friday 09 November 2007 14:07, Swen Schillig wrote:
> Updated the statistics patch to cover the issues pointed out by Heiko.
>
> James, could you please apply.
>
> Thanks
> Swen
>
> ---
> From: Swen Schillig <[EMAIL PROTECTED]>
>
> add some statistics provided by the zFCP adapter to the sysfs
>
> The new zFCP adapter statistics provide a variety of information
> about the virtual adapter (subchannel). In order to collect this information
> the zFCP driver is extended on one side to query the adapter and
> on the other side summarize certain values which can then be fetched on
> demand.
> This information is made available via files(attributes) in the sysfs
> filesystem.
>
> The information provided by the new zFCP adapter statistics can be fetched
> by reading from the following files in the sysfs filesystem
>
> /sys/class/scsi_host/host<n>/seconds_active
> /sys/class/scsi_host/host<n>/requests
> /sys/class/scsi_host/host<n>/megabytes
> /sys/class/scsi_host/host<n>/utilization
>
> These are the statistics on a virtual adapter (subchannel) level.
> In addition latency information is provided on a SCSI device level (LUN) which
> can be found at the following location
>
> /sys/class/scsi_device/<H:C:T:L>/device/cmd_latency
> /sys/class/scsi_device/<H:C:T:L>/device/read_latency
> /sys/class/scsi_device/<H:C:T:L>/device/write_latency
>
>
> The information provided is raw and not modified or interpreted by any means.
> No interpretation or modification of the values is done by the zFCP driver.
> The individual values are summed up during normal operation of the virtual
> adapter.
> An overrun of the variables is neither detected nor treated. The conclusion
> is that
> the file has to be read twice to make a meaningful statement, because only
> the differences of the values
> between the two reads can be used.
>
> The statistics make use of the SCSI mid-layer interface to provide its data
> to the user.
> In detail two hooks from the scsi_host_template are used to integrate
> the zFCP statistics.
>
> struct scsi_host_template {
> ...
> .shost_attrs = zfcp_a_stats_attrs,
> .sdev_attrs = zfcp_sysfs_sdev_attrs,
> ...
> };
>
>
> Signed-off-by: Swen Schillig <[EMAIL PROTECTED]>
> Signed-off-by: Christof Schmitt <[EMAIL PROTECTED]>
> Signed-off-by: Michael Loehr <[EMAIL PROTECTED]>
>
> ---
> drivers/s390/scsi/zfcp_aux.c | 2
> drivers/s390/scsi/zfcp_def.h | 14 +++
> drivers/s390/scsi/zfcp_fsf.c | 39 ++++++++++
> drivers/s390/scsi/zfcp_fsf.h | 29 +++++++-
> drivers/s390/scsi/zfcp_scsi.c | 149
> ++++++++++++++++++++++++++++++++++++++++++
> 5 files changed, 230 insertions(+), 3 deletions(-)
>
> Index: scsi-misc/drivers/s390/scsi/zfcp_def.h
> ===================================================================
> --- scsi-misc.orig/drivers/s390/scsi/zfcp_def.h
> +++ scsi-misc/drivers/s390/scsi/zfcp_def.h
> @@ -869,6 +869,18 @@ struct zfcp_erp_action {
> struct timer_list timer;
> };
>
> +struct latency_cont {
> + u32 channel;
> + u32 fabric;
> + u32 counter;
> +};
> +
> +struct zfcp_latencies {
> + struct latency_cont read;
> + struct latency_cont write;
> + struct latency_cont cmd;
> + spinlock_t lock;
> +};
>
> struct zfcp_adapter {
> struct list_head list; /* list of adapters */
> @@ -884,6 +896,7 @@ struct zfcp_adapter {
> u32 adapter_features; /* FCP channel features */
> u32 connection_features; /* host connection
> features */
> u32 hardware_version; /* of FCP channel */
> + u16 timer_ticks; /* time int for a tick */
> struct Scsi_Host *scsi_host; /* Pointer to mid-layer */
> struct list_head port_list_head; /* remote port list */
> struct list_head port_remove_lh; /* head of ports to be
> @@ -983,6 +996,7 @@ struct zfcp_unit {
> struct scsi_device *device; /* scsi device struct pointer
> */
> struct zfcp_erp_action erp_action; /* pending error recovery */
> atomic_t erp_counter;
> + struct zfcp_latencies latencies;
> };
>
> /* FSF request */
> Index: scsi-misc/drivers/s390/scsi/zfcp_fsf.c
> ===================================================================
> --- scsi-misc.orig/drivers/s390/scsi/zfcp_fsf.c
> +++ scsi-misc/drivers/s390/scsi/zfcp_fsf.c
> @@ -2079,6 +2079,7 @@ zfcp_fsf_exchange_config_evaluate(struct
> fc_host_supported_classes(shost) =
> FC_COS_CLASS2 | FC_COS_CLASS3;
> adapter->hydra_version = bottom->adapter_type;
> + adapter->timer_ticks = bottom->timer_interval;
> if (fc_host_permanent_port_name(shost) == -1)
> fc_host_permanent_port_name(shost) =
> fc_host_port_name(shost);
> @@ -3823,6 +3824,36 @@ zfcp_fsf_send_fcp_command_task_managemen
> return fsf_req;
> }
>
> +static void zfcp_fsf_req_latency(struct zfcp_fsf_req *fsf_req)
> +{
> + struct fsf_qual_latency_info *lat_inf;
> + struct zfcp_unit *unit;
> + unsigned long flags;
> +
> + lat_inf = &fsf_req->qtcb->prefix.prot_status_qual.latency_info;
> + unit = fsf_req->unit;
> +
> + spin_lock_irqsave(&unit->latencies.lock, flags);
> + switch (fsf_req->qtcb->bottom.io.data_direction) {
> + case FSF_DATADIR_READ:
> + unit->latencies.read.channel += lat_inf->channel_lat;
> + unit->latencies.read.fabric += lat_inf->fabric_lat;
> + unit->latencies.read.counter++;
> + break;
> + case FSF_DATADIR_WRITE:
> + unit->latencies.write.channel += lat_inf->channel_lat;
> + unit->latencies.write.fabric += lat_inf->fabric_lat;
> + unit->latencies.write.counter++;
> + break;
> + case FSF_DATADIR_CMND:
> + unit->latencies.cmd.channel += lat_inf->channel_lat;
> + unit->latencies.cmd.fabric += lat_inf->fabric_lat;
> + unit->latencies.cmd.counter++;
> + break;
> + }
> + spin_unlock_irqrestore(&unit->latencies.lock, flags);
> +}
> +
> /*
> * function: zfcp_fsf_send_fcp_command_handler
> *
> @@ -4036,9 +4067,17 @@ zfcp_fsf_send_fcp_command_handler(struct
> break;
>
> case FSF_GOOD:
> + if (fsf_req->adapter->adapter_features &
> + FSF_FEATURE_MEASUREMENT_DATA)
> + zfcp_fsf_req_latency(fsf_req);
> break;
>
> case FSF_FCP_RSP_AVAILABLE:
> + if ((fsf_req->qtcb->prefix.prot_status &
> + FSF_PROT_FSF_STATUS_PRESENTED) &&
> + (fsf_req->adapter->adapter_features &
> + FSF_FEATURE_MEASUREMENT_DATA))
> + zfcp_fsf_req_latency(fsf_req);
> break;
>
> default:
> Index: scsi-misc/drivers/s390/scsi/zfcp_fsf.h
> ===================================================================
> --- scsi-misc.orig/drivers/s390/scsi/zfcp_fsf.h
> +++ scsi-misc/drivers/s390/scsi/zfcp_fsf.h
> @@ -213,6 +213,7 @@
> #define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010
> #define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020
> #define FSF_FEATURE_UPDATE_ALERT 0x00000100
> +#define FSF_FEATURE_MEASUREMENT_DATA 0x00000200
>
> /* host connection features */
> #define FSF_FEATURE_NPIV_MODE 0x00000001
> @@ -322,11 +323,18 @@ struct fsf_link_down_info {
> u8 vendor_specific_code;
> } __attribute__ ((packed));
>
> +struct fsf_qual_latency_info {
> + u32 channel_lat;
> + u32 fabric_lat;
> + u8 res1[8];
> +} __attribute__ ((packed));
> +
> union fsf_prot_status_qual {
> u64 doubleword[FSF_PROT_STATUS_QUAL_SIZE / sizeof(u64)];
> struct fsf_qual_version_error version_error;
> struct fsf_qual_sequence_error sequence_error;
> struct fsf_link_down_info link_down_info;
> + struct fsf_qual_latency_info latency_info;
> } __attribute__ ((packed));
>
> struct fsf_qtcb_prefix {
> @@ -340,6 +348,15 @@ struct fsf_qtcb_prefix {
> u8 res1[20];
> } __attribute__ ((packed));
>
> +struct fsf_statistics_info {
> + u64 input_req;
> + u64 output_req;
> + u64 control_req;
> + u64 input_mb;
> + u64 output_mb;
> + u64 seconds_act;
> +} __attribute__ ((packed));
> +
> union fsf_status_qual {
> u8 byte[FSF_STATUS_QUALIFIER_SIZE];
> u16 halfword[FSF_STATUS_QUALIFIER_SIZE / sizeof (u16)];
> @@ -427,7 +444,9 @@ struct fsf_qtcb_bottom_config {
> u32 fc_link_speed;
> u32 adapter_type;
> u32 peer_d_id;
> - u8 res2[12];
> + u8 res1[2];
> + u16 timer_interval;
> + u8 res2[8];
> u32 s_id;
> struct fsf_nport_serv_param nport_serv_param;
> u8 reserved_nport_serv_param[16];
> @@ -436,7 +455,8 @@ struct fsf_qtcb_bottom_config {
> u32 hardware_version;
> u8 serial_number[32];
> struct fsf_nport_serv_param plogi_payload;
> - u8 res4[160];
> + struct fsf_statistics_info stat_info;
> + u8 res4[112];
> } __attribute__ ((packed));
>
> struct fsf_qtcb_bottom_port {
> @@ -469,7 +489,10 @@ struct fsf_qtcb_bottom_port {
> u64 control_requests;
> u64 input_mb; /* where 1 MByte == 1.000.000 Bytes */
> u64 output_mb; /* where 1 MByte == 1.000.000 Bytes */
> - u8 res2[256];
> + u8 cp_util;
> + u8 cb_util;
> + u8 a_util;
> + u8 res2[253];
> } __attribute__ ((packed));
>
> union fsf_qtcb_bottom {
> Index: scsi-misc/drivers/s390/scsi/zfcp_scsi.c
> ===================================================================
> --- scsi-misc.orig/drivers/s390/scsi/zfcp_scsi.c
> +++ scsi-misc/drivers/s390/scsi/zfcp_scsi.c
> @@ -39,6 +39,7 @@ static struct zfcp_unit *zfcp_unit_looku
> unsigned int, unsigned int);
>
> static struct device_attribute *zfcp_sysfs_sdev_attrs[];
> +static struct class_device_attribute *zfcp_a_stats_attrs[];
>
> struct zfcp_data zfcp_data = {
> .scsi_host_template = {
> @@ -59,6 +60,7 @@ struct zfcp_data zfcp_data = {
> .use_clustering = 1,
> .sdev_attrs = zfcp_sysfs_sdev_attrs,
> .max_sectors = ZFCP_MAX_SECTORS,
> + .shost_attrs = zfcp_a_stats_attrs,
> },
> .driver_version = ZFCP_VERSION,
> };
> @@ -803,6 +805,35 @@ struct fc_function_template zfcp_transpo
> .disable_target_scan = 1,
> };
>
> +#define ZFCP_DEFINE_LATENCY_ATTR(_name) \
> +static ssize_t
> \
> +zfcp_sysfs_unit_##_name##_latency_show(struct device *dev, \
> + struct device_attribute *attr, \
> + char *buf) { \
> + struct scsi_device *sdev = to_scsi_device(dev); \
> + struct zfcp_unit *unit = sdev->hostdata; \
> + struct zfcp_latencies *lat = &unit->latencies; \
> + struct zfcp_adapter *adapter = unit->port->adapter; \
> + int retval; \
> + unsigned long flags; \
> + \
> + \
> + spin_lock_irqsave(&lat->lock, flags); \
> + retval = sprintf(buf, "%u %u %u\n", \
> + lat->_name.fabric * adapter->timer_ticks / 1000, \
> + lat->_name.channel * adapter->timer_ticks / 1000,\
> + lat->_name.counter); \
> + spin_unlock_irqrestore(&lat->lock, flags); \
> + \
> + return retval; \
> +} \
> +static DEVICE_ATTR(_name##_latency, S_IRUGO, \
> + zfcp_sysfs_unit_##_name##_latency_show, NULL);
> +
> +ZFCP_DEFINE_LATENCY_ATTR(read);
> +ZFCP_DEFINE_LATENCY_ATTR(write);
> +ZFCP_DEFINE_LATENCY_ATTR(cmd);
> +
> /**
> * ZFCP_DEFINE_SCSI_ATTR
> * @_name: name of show attribute
> @@ -833,6 +864,124 @@ static struct device_attribute *zfcp_sys
> &dev_attr_fcp_lun,
> &dev_attr_wwpn,
> &dev_attr_hba_id,
> + &dev_attr_read_latency,
> + &dev_attr_write_latency,
> + &dev_attr_cmd_latency,
> + NULL
> +};
> +
> +
> +static ssize_t
> +zfcp_sysfs_adapter_utilization_show(struct class_device *cdev, char *buf)
> +{
> + struct Scsi_Host *scsi_host = class_to_shost(cdev);
> + struct zfcp_adapter *adapter = (struct zfcp_adapter *)
> + scsi_host->hostdata[0];
> + struct fsf_qtcb_bottom_port *qtcb_port;
> + int retval;
> +
> + if (!(adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA))
> + return -EOPNOTSUPP;
> +
> + qtcb_port = kzalloc(sizeof(struct fsf_qtcb_bottom_port), GFP_KERNEL);
> + if (!qtcb_port)
> + return -ENOMEM;
> +
> + retval = zfcp_fsf_exchange_port_data_sync(adapter, qtcb_port);
> + if (!retval)
> + retval = sprintf(buf, "%u %u %u\n", qtcb_port->cp_util,
> + qtcb_port->cb_util, qtcb_port->a_util);
> + kfree(qtcb_port);
> + return retval;
> +}
> +
> +static
> +CLASS_DEVICE_ATTR(utilization, S_IRUGO, zfcp_sysfs_adapter_utilization_show,
> + NULL);
> +
> +static int
> +zfcp_sysfs_adapter_ex_config(struct class_device *cdev,
> + struct fsf_qtcb_bottom_config **qtcb_config)
> +{
> + struct Scsi_Host *scsi_host = class_to_shost(cdev);
> + struct zfcp_adapter *adapter = (struct zfcp_adapter *)
> + scsi_host->hostdata[0];
> +
> + if (!(adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA))
> + return -EOPNOTSUPP;
> +
> + *qtcb_config = kzalloc(sizeof(struct fsf_qtcb_bottom_config),
> + GFP_KERNEL);
> + if (!*qtcb_config)
> + return -ENOMEM;
> +
> + return zfcp_fsf_exchange_config_data_sync(adapter, *qtcb_config);
> +}
> +
> +static ssize_t
> +zfcp_sysfs_adapter_request_show(struct class_device *cdev, char *buf)
> +{
> + struct fsf_qtcb_bottom_config *qtcb_config;
> + int retval;
> +
> + retval = zfcp_sysfs_adapter_ex_config(cdev, &qtcb_config);
> +
> + if (!retval) {
> + retval = sprintf(buf, "%lu %lu %lu\n",
> + qtcb_config->stat_info.input_req,
> + qtcb_config->stat_info.output_req,
> + qtcb_config->stat_info.control_req);
> + kfree(qtcb_config);
> + }
> + return retval;
> +}
> +
> +static CLASS_DEVICE_ATTR(requests, S_IRUGO, zfcp_sysfs_adapter_request_show,
> +NULL);
> +
> +static ssize_t
> +zfcp_sysfs_adapter_mb_show(struct class_device *cdev, char *buf)
> +{
> + struct fsf_qtcb_bottom_config *qtcb_config;
> + int retval;
> +
> + retval = zfcp_sysfs_adapter_ex_config(cdev, &qtcb_config);
> +
> + if (!retval) {
> + retval = sprintf(buf, "%lu %lu\n",
> + qtcb_config->stat_info.input_mb,
> + qtcb_config->stat_info.output_mb);
> + kfree(qtcb_config);
> + }
> + return retval;
> +}
> +
> +static CLASS_DEVICE_ATTR(megabytes, S_IRUGO, zfcp_sysfs_adapter_mb_show,
> NULL);
> +
> +static ssize_t
> +zfcp_sysfs_adapter_seconds_active_show(struct class_device *cdev, char *buf)
> +{
> + struct fsf_qtcb_bottom_config *qtcb_config;
> + int retval;
> +
> + retval = zfcp_sysfs_adapter_ex_config(cdev, &qtcb_config);
> + if (!retval) {
> + retval = sprintf(buf, "%lu\n",
> + qtcb_config->stat_info.seconds_act);
> + kfree(qtcb_config);
> + }
> + return retval;
> +}
> +
> +static CLASS_DEVICE_ATTR(seconds_active, S_IRUGO,
> + zfcp_sysfs_adapter_seconds_active_show, NULL);
> +
> +
> +static struct class_device_attribute *zfcp_a_stats_attrs[] = {
> + &class_device_attr_utilization,
> + &class_device_attr_requests,
> + &class_device_attr_megabytes,
> + &class_device_attr_seconds_active,
> NULL
> };
>
> Index: scsi-misc/drivers/s390/scsi/zfcp_aux.c
> ===================================================================
> --- scsi-misc.orig/drivers/s390/scsi/zfcp_aux.c
> +++ scsi-misc/drivers/s390/scsi/zfcp_aux.c
> @@ -847,6 +847,8 @@ zfcp_unit_enqueue(struct zfcp_port *port
> /* mark unit unusable as long as sysfs registration is not complete */
> atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status);
>
> + spin_lock_init(&unit->latencies.lock);
> +
> if (device_register(&unit->sysfs_device)) {
> kfree(unit);
> return NULL;
>
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html