--- hw/dataplane/iosched.h | 78 ++++++++++++++++++++++++++++++++++++++++++++++++ hw/virtio-blk.c | 5 ++++ 2 files changed, 83 insertions(+) create mode 100644 hw/dataplane/iosched.h diff --git a/hw/dataplane/iosched.h b/hw/dataplane/iosched.h new file mode 100644 index 0000000..12ebccc --- /dev/null +++ b/hw/dataplane/iosched.h @@ -0,0 +1,78 @@ +#ifndef IOSCHED_H +#define IOSCHED_H + +#include "hw/dataplane/ioq.h" + +typedef struct { + unsigned long iocbs; + unsigned long merges; + unsigned long sched_calls; +} IOSched; + +static int iocb_cmp(const void *a, const void *b) +{ + const struct iocb *iocb_a = a; + const struct iocb *iocb_b = b; + + /* + * Note that we can't simply subtract req2->sector from req1->sector + * here as that could overflow the return value. + */ + if (iocb_a->u.c.offset > iocb_b->u.c.offset) { + return 1; + } else if (iocb_a->u.c.offset < iocb_b->u.c.offset) { + return -1; + } else { + return 0; + } +} + +static size_t iocb_nbytes(struct iocb *iocb) +{ + struct iovec *iov = iocb->u.c.buf; + size_t nbytes = 0; + size_t i; + for (i = 0; i < iocb->u.c.nbytes; i++) { + nbytes += iov->iov_len; + iov++; + } + return nbytes; +} + +static void iosched_init(IOSched *iosched) +{ + memset(iosched, 0, sizeof *iosched); +} + +static void iosched_print_stats(IOSched *iosched) +{ + fprintf(stderr, "iocbs = %lu merges = %lu sched_calls = %lu\n", + iosched->iocbs, iosched->merges, iosched->sched_calls); + memset(iosched, 0, sizeof *iosched); +} + +static void iosched(IOSched *iosched, struct iocb *unsorted[], unsigned int count) +{ + struct iocb *sorted[count]; + struct iocb *last; + unsigned int i; + + if ((++iosched->sched_calls % 1000) == 0) { + iosched_print_stats(iosched); + } + + memcpy(sorted, unsorted, sizeof sorted); + qsort(sorted, count, sizeof sorted[0], iocb_cmp); + + iosched->iocbs += count; + last = sorted[0]; + for (i = 1; i < count; i++) { + if (last->aio_lio_opcode == sorted[i]->aio_lio_opcode && + last->u.c.offset + iocb_nbytes(last) == sorted[i]->u.c.offset) { + iosched->merges++; + } + last = sorted[i]; + } +} + +#endif /* IOSCHED_H */ diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index f67fdb7..75cb0f2 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -22,6 +22,7 @@ #include "hw/dataplane/event-poll.h" #include "hw/dataplane/vring.h" #include "hw/dataplane/ioq.h" +#include "hw/dataplane/iosched.h" #include "kvm.h" enum { @@ -57,6 +58,7 @@ typedef struct { EventHandler notify_handler; /* virtqueue notify handler */ IOQueue ioqueue; /* Linux AIO queue (should really be per dataplane thread) */ + IOSched iosched; /* I/O scheduler */ VirtIOBlockRequest requests[REQ_MAX]; /* pool of requests, managed by the queue */ } VirtIOBlock; @@ -249,6 +251,8 @@ static bool handle_notify(EventHandler *handler) } } + iosched(&s->iosched, s->ioqueue.queue, s->ioqueue.queue_idx); + /* Submit requests, if any */ int rc = ioq_submit(&s->ioqueue); if (unlikely(rc < 0)) { @@ -289,6 +293,7 @@ static void data_plane_start(VirtIOBlock *s) { int i; + iosched_init(&s->iosched); vring_setup(&s->vring, &s->vdev, 0); /* Set up guest notifier (irq) */ -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html