]> xenbits.xensource.com Git - people/ssmith/nc2-2.6.27.bak/.git/commitdiff
patch blk-latency-stats
authorSteven Smith <ssmith@weybridge.uk.xensource.com>
Thu, 28 May 2009 10:54:19 +0000 (11:54 +0100)
committerSteven Smith <ssmith@weybridge.uk.xensource.com>
Thu, 28 May 2009 10:54:19 +0000 (11:54 +0100)
drivers/xen/blkback/blkback.c
drivers/xen/blkback/common.h
drivers/xen/blkback/xenbus.c
drivers/xen/blktap/backdev.c
drivers/xen/blktap/blktap.c
drivers/xen/blktap/blktap.h
drivers/xen/blktap/common.h
drivers/xen/blktap/xenbus.c

index 1305cc86273e4f0ff3eee218bd8193e42ef9de77..7408056c274bc1e245639737934df43a7eb4aa81 100644 (file)
@@ -77,6 +77,7 @@ typedef struct {
        atomic_t       pendcnt;
        unsigned short operation;
        int            status;
+       struct timeval time;
        struct list_head free_list;
 } pending_req_t;
 
@@ -185,6 +186,44 @@ static void fast_flush_area(pending_req_t *req)
        BUG_ON(ret);
 }
 
+static inline s64 timeval_to_us(struct timeval *tv)
+{
+       return ((s64)tv->tv_sec * USEC_PER_SEC) + tv->tv_usec;
+}
+
+static inline void collect_statistics(pending_req_t *req)
+{
+       blkif_t *blkif;
+       struct timeval now;
+       s64 interval, *max, *sum, *cnt;
+
+       blkif = req->blkif;
+       do_gettimeofday(&now);
+       interval = timeval_to_us(&now) - timeval_to_us(&req->time);
+
+       switch (req->operation) {
+       case BLKIF_OP_READ:
+               cnt = &blkif->st_rd_cnt;
+               sum = &blkif->st_rd_sum_usecs;
+               max = &blkif->st_rd_max_usecs;
+               break;
+       case BLKIF_OP_WRITE:
+       case BLKIF_OP_WRITE_BARRIER:
+               cnt = &blkif->st_wr_cnt;
+               sum = &blkif->st_wr_sum_usecs;
+               max = &blkif->st_wr_max_usecs;
+               break;
+       default:
+               return;
+       }
+
+       if (interval > *max)
+               *max = interval;
+
+       *sum += interval;
+       *cnt += 1;
+}
+
 /******************************************************************
  * QUEUE MANAGEMENT FUNCTIONS
  */
@@ -324,6 +363,7 @@ static void __end_block_io_op(pending_req_t *pending_req, int error)
                blkif_t *blkif = pending_req->blkif;
 
                fast_flush_area(pending_req);
+               collect_statistics(pending_req);
                make_response(pending_req->blkif, pending_req->id,
                              pending_req->operation, pending_req->status);
                blkif_put(pending_req->blkif);
@@ -489,6 +529,7 @@ static void dispatch_rw_block_io(blkif_t *blkif,
        pending_req->operation = req->operation;
        pending_req->status    = BLKIF_RSP_OKAY;
        pending_req->nr_pages  = nseg;
+       do_gettimeofday(&pending_req->time);
 
        for (i = 0; i < nseg; i++) {
                uint32_t flags;
index 039363f60dddc2ee5754d2c865083a99740d47f3..0671b1651b9aff435860e733c707dfe95394b9b6 100644 (file)
@@ -104,6 +104,12 @@ typedef struct blkif_st {
        int                 st_br_req;
        int                 st_rd_sect;
        int                 st_wr_sect;
+       s64                 st_rd_cnt;
+       s64                 st_rd_sum_usecs;
+       s64                 st_rd_max_usecs;
+       s64                 st_wr_cnt;
+       s64                 st_wr_sum_usecs;
+       s64                 st_wr_max_usecs;
 
        wait_queue_head_t waiting_to_free;
 
index 5ded579e15d433a30e4d104e6e34110e80594729..50abb4a196348ce6f9797ff065c625d86b2bec91 100644 (file)
@@ -138,12 +138,51 @@ static void update_blkif_status(blkif_t *blkif)
        }                                                               \
        static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
 
+#define VBD_SHOW_AVG(name, _cnt, _sum, _max)                           \
+       static ssize_t show_##name(struct device *_dev,                 \
+                                  struct device_attribute *attr,       \
+                                  char *buf)                           \
+       {                                                               \
+               int ret = -ENODEV;                                      \
+               s64 cnt, sum, max;                                      \
+               struct backend_info *be;                                \
+               struct xenbus_device *dev = to_xenbus_device(_dev);     \
+                                                                       \
+               down(&blkback_dev_sem);                                 \
+               be = dev->dev.driver_data;                              \
+               if (be) {                                               \
+                       cnt = _cnt;                                     \
+                       sum = _sum;                                     \
+                       max = _max;                                     \
+                                                                       \
+                       if (cnt)                                        \
+                               do_div(sum, cnt);                       \
+                       ret = sprintf(buf, "requests: %lld, "           \
+                                     "avg usecs: %llu, "               \
+                                     "max usecs: %llu\n",              \
+                                     cnt, sum, max);                   \
+                                                                       \
+                       (_sum) = 0;                                     \
+                       (_cnt) = 0;                                     \
+                       (_max) = 0;                                     \
+               }                                                       \
+               up(&blkback_dev_sem);                                   \
+                                                                       \
+               return ret;                                             \
+       }                                                               \
+       static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
+
+
 VBD_SHOW(oo_req,  "%d\n", be->blkif->st_oo_req);
 VBD_SHOW(rd_req,  "%d\n", be->blkif->st_rd_req);
 VBD_SHOW(wr_req,  "%d\n", be->blkif->st_wr_req);
 VBD_SHOW(br_req,  "%d\n", be->blkif->st_br_req);
 VBD_SHOW(rd_sect, "%d\n", be->blkif->st_rd_sect);
 VBD_SHOW(wr_sect, "%d\n", be->blkif->st_wr_sect);
+VBD_SHOW_AVG(rd_usecs, be->blkif->st_rd_cnt,
+            be->blkif->st_rd_sum_usecs, be->blkif->st_rd_max_usecs);
+VBD_SHOW_AVG(wr_usecs, be->blkif->st_wr_cnt,
+            be->blkif->st_wr_sum_usecs, be->blkif->st_wr_max_usecs);
 
 static struct attribute *vbdstat_attrs[] = {
        &dev_attr_oo_req.attr,
@@ -152,6 +191,8 @@ static struct attribute *vbdstat_attrs[] = {
        &dev_attr_br_req.attr,
        &dev_attr_rd_sect.attr,
        &dev_attr_wr_sect.attr,
+       &dev_attr_rd_usecs.attr,
+       &dev_attr_wr_usecs.attr,
        NULL
 };
 
index 1bdcfded095277ed4739b810df5d55a28861342f..b18ecd394cd8f5d3594f34eadd6d03582c7398b7 100644 (file)
@@ -393,6 +393,7 @@ process_backdev_request(struct tap_blkif *uinfo, struct backdev_info *info)
        pending_req->operation = blkif_req.operation;
        pending_req->status    = BLKIF_RSP_OKAY;
        pending_req->nr_pages  = blkif_req.nr_segments;
+       do_gettimeofday(&pending_req->time);
 
        /*record [mmap_idx,pending_idx] to [usr_idx] mapping*/
        uinfo->idx_map[usr_idx] = MAKE_ID(mmap_idx, pending_idx);
index dffea16a005deb08f6c9902ff8c4a41b7f831b44..d58531eb94a7cdf3b8a26bbb14535e67e99e5cd7 100644 (file)
@@ -855,6 +855,42 @@ static void fast_flush_area(pending_req_t *req, int pending_idx, int usr_idx,
                               req->nr_pages << PAGE_SHIFT, NULL);
 }
 
+static inline s64 timeval_to_us(struct timeval *tv)
+{
+       return ((s64)tv->tv_sec * USEC_PER_SEC) + tv->tv_usec;
+}
+
+static inline void collect_statistics(blkif_t *blkif, pending_req_t *req)
+{
+       struct timeval now;
+       s64 interval, *max, *sum, *cnt;
+
+       do_gettimeofday(&now);
+       interval = timeval_to_us(&now) - timeval_to_us(&req->time);
+
+       switch (req->operation) {
+       case BLKIF_OP_READ:
+               cnt = &blkif->st_rd_cnt;
+               sum = &blkif->st_rd_sum_usecs;
+               max = &blkif->st_rd_max_usecs;
+               break;
+       case BLKIF_OP_WRITE:
+       case BLKIF_OP_WRITE_BARRIER:
+               cnt = &blkif->st_wr_cnt;
+               sum = &blkif->st_wr_sum_usecs;
+               max = &blkif->st_wr_max_usecs;
+               break;
+       default:
+               return;
+       }
+
+       if (interval > *max)
+               *max = interval;
+
+       *sum += interval;
+       *cnt += 1;
+}
+
 /******************************************************************
  * SCHEDULER FUNCTIONS
  */
@@ -997,6 +1033,7 @@ static int blktap_read_ufe_ring(tap_blkif_t *info)
                                       ID_TO_IDX(info->idx_map[usr_idx])));
 
                pending_req = &pending_reqs[mmap_idx][pending_idx];
+               collect_statistics(blkif, pending_req);
 
                if (pending_req->inuse == 2)
                        backdev_finish_req(info, usr_idx, &res, pending_req);
@@ -1189,6 +1226,8 @@ static void dispatch_rw_block_io(blkif_t *blkif,
        pending_req->operation = operation;
        pending_req->status    = BLKIF_RSP_OKAY;
        pending_req->nr_pages  = nseg;
+       do_gettimeofday(&pending_req->time);
+
        op = 0;
        for (i = 0; i < nseg; i++) {
                unsigned long uvaddr;
index e9e220691dcd59d8abb30604d147c2fa2b154c82..07a4f1ece6da4db2458450eab202c1cd468e951a 100644 (file)
@@ -77,6 +77,7 @@ typedef struct pending_req {
        int            status;
        struct list_head free_list;
        int            inuse;
+       struct timeval time;
 } pending_req_t;
 
 extern pending_req_t *pending_reqs[MAX_PENDING_REQS];
index d12a99cef4eb3f28619344b1f85d02e2968f88b9..a258e0b99180ca8ef2503720541bb6f69dd2d057 100644 (file)
@@ -81,6 +81,12 @@ typedef struct blkif_st {
        int                 st_oo_req;
        int                 st_rd_sect;
        int                 st_wr_sect;
+       s64                 st_rd_cnt;
+       s64                 st_rd_sum_usecs;
+       s64                 st_rd_max_usecs;
+       s64                 st_wr_cnt;
+       s64                 st_wr_sum_usecs;
+       s64                 st_wr_max_usecs;
 
        wait_queue_head_t waiting_to_free;
 
index 4ae2fe144afbf808875bdfed91cf3935e2103021..083a57dca99848f8a94c001c8f9fb3bbe44bf0b3 100644 (file)
@@ -201,11 +201,49 @@ static int blktap_name(blkif_t *blkif, char *buf)
        }                                                               \
        static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
 
+#define VBD_SHOW_AVG(name, _cnt, _sum, _max)                           \
+       static ssize_t show_##name(struct device *_dev,                 \
+                                  struct device_attribute *attr,       \
+                                  char *buf)                           \
+       {                                                               \
+               int ret = -ENODEV;                                      \
+               s64 cnt, sum, max;                                      \
+               struct backend_info *be;                                \
+               struct xenbus_device *dev = to_xenbus_device(_dev);     \
+                                                                       \
+               down(&blktap_dev_sem);                                  \
+               be = dev->dev.driver_data;                              \
+               if (be) {                                               \
+                       cnt = _cnt;                                     \
+                       sum = _sum;                                     \
+                       max = _max;                                     \
+                                                                       \
+                       if (cnt)                                        \
+                               do_div(sum, cnt);                       \
+                       ret = sprintf(buf, "requests: %lld, "           \
+                                     "avg usecs: %llu, "               \
+                                     "max usecs: %llu\n",              \
+                                     cnt, sum, max);                   \
+                                                                       \
+                       (_sum) = 0;                                     \
+                       (_cnt) = 0;                                     \
+                       (_max) = 0;                                     \
+               }                                                       \
+               up(&blktap_dev_sem);                                    \
+                                                                       \
+               return ret;                                             \
+       }                                                               \
+       static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
+
 VBD_SHOW(oo_req,  "%d\n", be->blkif->st_oo_req);
 VBD_SHOW(rd_req,  "%d\n", be->blkif->st_rd_req);
 VBD_SHOW(wr_req,  "%d\n", be->blkif->st_wr_req);
 VBD_SHOW(rd_sect, "%d\n", be->blkif->st_rd_sect);
 VBD_SHOW(wr_sect, "%d\n", be->blkif->st_wr_sect);
+VBD_SHOW_AVG(rd_usecs, be->blkif->st_rd_cnt,
+            be->blkif->st_rd_sum_usecs, be->blkif->st_rd_max_usecs);
+VBD_SHOW_AVG(wr_usecs, be->blkif->st_wr_cnt,
+            be->blkif->st_wr_sum_usecs, be->blkif->st_wr_max_usecs);
 
 static struct attribute *tapstat_attrs[] = {
        &dev_attr_oo_req.attr,
@@ -213,6 +251,8 @@ static struct attribute *tapstat_attrs[] = {
        &dev_attr_wr_req.attr,
        &dev_attr_rd_sect.attr,
        &dev_attr_wr_sect.attr,
+       &dev_attr_rd_usecs.attr,
+       &dev_attr_wr_usecs.attr,
        NULL
 };