atomic_t pendcnt;
unsigned short operation;
int status;
+ struct timeval time;
struct list_head free_list;
} pending_req_t;
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
*/
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);
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;
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;
} \
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,
&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
};
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);
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
*/
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);
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;
int status;
struct list_head free_list;
int inuse;
+ struct timeval time;
} pending_req_t;
extern pending_req_t *pending_reqs[MAX_PENDING_REQS];
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;
} \
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,
&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
};