From 24363419f70c97bb5f5016afef2c28458a3d0805 Mon Sep 17 00:00:00 2001 From: t_jeang Date: Tue, 6 Jan 2009 12:06:01 +0000 Subject: [PATCH] imported patch blk-latency-stats --- drivers/xen/blkback/blkback.c | 41 +++++++++++++++++++++++++++++++++++ drivers/xen/blkback/common.h | 6 +++++ drivers/xen/blkback/xenbus.c | 41 +++++++++++++++++++++++++++++++++++ drivers/xen/blktap/backdev.c | 1 + drivers/xen/blktap/blktap.c | 39 +++++++++++++++++++++++++++++++++ drivers/xen/blktap/blktap.h | 1 + drivers/xen/blktap/common.h | 6 +++++ drivers/xen/blktap/xenbus.c | 40 ++++++++++++++++++++++++++++++++++ 8 files changed, 175 insertions(+) diff --git a/drivers/xen/blkback/blkback.c b/drivers/xen/blkback/blkback.c index dbb4cd81..970afe20 100644 --- a/drivers/xen/blkback/blkback.c +++ b/drivers/xen/blkback/blkback.c @@ -76,6 +76,7 @@ typedef struct { atomic_t pendcnt; unsigned short operation; int status; + struct timeval time; struct list_head free_list; } pending_req_t; @@ -184,6 +185,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 */ @@ -323,6 +362,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); @@ -491,6 +531,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; diff --git a/drivers/xen/blkback/common.h b/drivers/xen/blkback/common.h index 793abaa0..bd4e1548 100644 --- a/drivers/xen/blkback/common.h +++ b/drivers/xen/blkback/common.h @@ -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; diff --git a/drivers/xen/blkback/xenbus.c b/drivers/xen/blkback/xenbus.c index 57598aae..775f723d 100644 --- a/drivers/xen/blkback/xenbus.c +++ b/drivers/xen/blkback/xenbus.c @@ -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 }; diff --git a/drivers/xen/blktap/backdev.c b/drivers/xen/blktap/backdev.c index 1bdcfded..b18ecd39 100644 --- a/drivers/xen/blktap/backdev.c +++ b/drivers/xen/blktap/backdev.c @@ -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); diff --git a/drivers/xen/blktap/blktap.c b/drivers/xen/blktap/blktap.c index f27c02f7..3729c160 100644 --- a/drivers/xen/blktap/blktap.c +++ b/drivers/xen/blktap/blktap.c @@ -856,6 +856,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 */ @@ -998,6 +1034,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); @@ -1175,6 +1212,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; diff --git a/drivers/xen/blktap/blktap.h b/drivers/xen/blktap/blktap.h index 1cf4e72c..1793305a 100644 --- a/drivers/xen/blktap/blktap.h +++ b/drivers/xen/blktap/blktap.h @@ -76,6 +76,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]; diff --git a/drivers/xen/blktap/common.h b/drivers/xen/blktap/common.h index 134e50cd..f204369e 100644 --- a/drivers/xen/blktap/common.h +++ b/drivers/xen/blktap/common.h @@ -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; diff --git a/drivers/xen/blktap/xenbus.c b/drivers/xen/blktap/xenbus.c index 9bf32164..63d1a00f 100644 --- a/drivers/xen/blktap/xenbus.c +++ b/drivers/xen/blktap/xenbus.c @@ -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 }; -- 2.39.5