blktrace: pass zfcp driver data
Stefan Raspl [Thu, 16 Oct 2008 06:23:39 +0000 (08:23 +0200)]
This patch writes the channel and fabric latencies in nanoseconds per
request via blktrace for later analysis. The utilization of the inbound
and outbound adapter queue is also reported.

Signed-off-by: Stefan Raspl <raspl@linux.vnet.ibm.com>
Signed-off-by: Martin Peschke <mp3@de.ibm.com>
Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>

drivers/s390/scsi/zfcp_def.h
drivers/s390/scsi/zfcp_fsf.c
drivers/s390/scsi/zfcp_fsf.h
drivers/s390/scsi/zfcp_qdio.c

index 8a13071..9ce4c75 100644 (file)
@@ -583,6 +583,8 @@ struct zfcp_fsf_req {
        unsigned long long     issued;         /* request sent time (STCK) */
        struct zfcp_unit       *unit;
        void                    (*handler)(struct zfcp_fsf_req *);
+       u16                     qdio_outb_usage;/* usage of outbound queue */
+       u16                     qdio_inb_usage; /* usage of inbound queue */
 };
 
 /* driver data */
index 739356a..5ae1d49 100644 (file)
@@ -6,6 +6,7 @@
  * Copyright IBM Corporation 2002, 2008
  */
 
+#include <linux/blktrace_api.h>
 #include "zfcp_ext.h"
 
 static void zfcp_fsf_request_timeout_handler(unsigned long data)
@@ -777,6 +778,7 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *req)
        list_add_tail(&req->list, &adapter->req_list[idx]);
        spin_unlock(&adapter->req_list_lock);
 
+       req->qdio_outb_usage = atomic_read(&req_q->count);
        req->issued = get_clock();
        if (zfcp_qdio_send(req)) {
                /* Queues are down..... */
@@ -2082,6 +2084,36 @@ static void zfcp_fsf_req_latency(struct zfcp_fsf_req *req)
        spin_unlock_irqrestore(&unit->latencies.lock, flags);
 }
 
+#ifdef CONFIG_BLK_DEV_IO_TRACE
+static void zfcp_fsf_trace_latency(struct zfcp_fsf_req *fsf_req)
+{
+       struct fsf_qual_latency_info *lat_inf;
+       struct scsi_cmnd *scsi_cmnd = (struct scsi_cmnd *)fsf_req->data;
+       struct request *req = scsi_cmnd->request;
+       struct zfcp_blk_drv_data trace;
+       int ticks = fsf_req->adapter->timer_ticks;
+
+       trace.flags = 0;
+       trace.magic = ZFCP_BLK_DRV_DATA_MAGIC;
+       if (fsf_req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA) {
+               trace.flags |= ZFCP_BLK_LAT_VALID;
+               lat_inf = &fsf_req->qtcb->prefix.prot_status_qual.latency_info;
+               trace.channel_lat = lat_inf->channel_lat * ticks;
+               trace.fabric_lat = lat_inf->fabric_lat * ticks;
+       }
+       if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)
+               trace.flags |= ZFCP_BLK_REQ_ERROR;
+       trace.inb_usage = fsf_req->qdio_inb_usage;
+       trace.outb_usage = fsf_req->qdio_outb_usage;
+
+       blk_add_driver_data(req->q, req, &trace, sizeof(trace));
+}
+#else
+static inline void zfcp_fsf_trace_latency(struct zfcp_fsf_req *fsf_req)
+{
+}
+#endif
+
 static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req)
 {
        struct scsi_cmnd *scpnt = req->data;
@@ -2114,6 +2146,8 @@ static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req)
        if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA)
                zfcp_fsf_req_latency(req);
 
+       zfcp_fsf_trace_latency(req);
+
        if (unlikely(fcp_rsp_iu->validity.bits.fcp_rsp_len_valid)) {
                if (fcp_rsp_info[3] == RSP_CODE_GOOD)
                        set_host_byte(scpnt, DID_OK);
index fd3a887..fa2a317 100644 (file)
@@ -439,4 +439,16 @@ struct fsf_qtcb {
        u8 log[FSF_QTCB_LOG_SIZE];
 } __attribute__ ((packed));
 
+struct zfcp_blk_drv_data {
+#define ZFCP_BLK_DRV_DATA_MAGIC                        0x1
+       u32 magic;
+#define ZFCP_BLK_LAT_VALID                     0x1
+#define ZFCP_BLK_REQ_ERROR                     0x2
+       u16 flags;
+       u8 inb_usage;
+       u8 outb_usage;
+       u64 channel_lat;
+       u64 fabric_lat;
+} __attribute__ ((packed));
+
 #endif                         /* FSF_H */
index 3e05080..664752f 100644 (file)
@@ -115,6 +115,7 @@ static void zfcp_qdio_reqid_check(struct zfcp_adapter *adapter,
        spin_unlock_irqrestore(&adapter->req_list_lock, flags);
 
        fsf_req->sbal_response = sbal_idx;
+       fsf_req->qdio_inb_usage = atomic_read(&adapter->resp_q.count);
        zfcp_fsf_req_complete(fsf_req);
 }