From: Steven Smith Date: Thu, 28 May 2009 10:54:19 +0000 (+0100) Subject: patch blk-latency-stats X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=1279dd7dc1d951e8ae48aadd99b8ade088708ec0;p=people%2Fssmith%2Fnc2-2.6.27.bak%2F.git patch blk-latency-stats --- diff --git a/drivers/xen/blkback/blkback.c b/drivers/xen/blkback/blkback.c index 1305cc86..7408056c 100644 --- a/drivers/xen/blkback/blkback.c +++ b/drivers/xen/blkback/blkback.c @@ -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; diff --git a/drivers/xen/blkback/common.h b/drivers/xen/blkback/common.h index 039363f6..0671b165 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 5ded579e..50abb4a1 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 dffea16a..d58531eb 100644 --- a/drivers/xen/blktap/blktap.c +++ b/drivers/xen/blktap/blktap.c @@ -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; diff --git a/drivers/xen/blktap/blktap.h b/drivers/xen/blktap/blktap.h index e9e22069..07a4f1ec 100644 --- a/drivers/xen/blktap/blktap.h +++ b/drivers/xen/blktap/blktap.h @@ -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]; diff --git a/drivers/xen/blktap/common.h b/drivers/xen/blktap/common.h index d12a99ce..a258e0b9 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 4ae2fe14..083a57dc 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 };