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

Reply via email to