This patch hooks AIO support into virtio-blk, allowing for faster IO. Signed-off-by: Sasha Levin <levinsasha928@xxxxxxxxx> --- tools/kvm/disk/core.c | 35 +++++++++++++++++++++++++++++++++-- tools/kvm/disk/qcow.c | 4 ++++ tools/kvm/disk/raw.c | 20 ++++++++++++++++---- tools/kvm/include/kvm/disk-image.h | 3 +++ tools/kvm/virtio/blk.c | 11 +++++------ 5 files changed, 61 insertions(+), 12 deletions(-) diff --git a/tools/kvm/disk/core.c b/tools/kvm/disk/core.c index a5e6713..e221d37 100644 --- a/tools/kvm/disk/core.c +++ b/tools/kvm/disk/core.c @@ -1,8 +1,30 @@ #include "kvm/disk-image.h" #include "kvm/qcow.h" +#include "kvm/virtio-blk.h" + +#include <sys/eventfd.h> +#include <sys/poll.h> + +#define AIO_MAX 32 int debug_iodelay; +static void *disk_image__thread(void *param) +{ + struct disk_image *disk = param; + u64 dummy; + + while (read(disk->evt, &dummy, sizeof(dummy)) > 0) { + struct io_event event; + struct timespec notime = {0}; + + while (io_getevents(disk->ctx, 1, 1, &event, ¬ime) > 0) + disk->disk_req_cb(event.data, event.res); + } + + return NULL; +} + struct disk_image *disk_image__new(int fd, u64 size, struct disk_image_operations *ops, int use_mmap) { struct disk_image *disk; @@ -26,6 +48,14 @@ struct disk_image *disk_image__new(int fd, u64 size, struct disk_image_operation } } + if (disk) { + pthread_t thread; + + disk->evt = eventfd(0, 0); + io_setup(AIO_MAX, &disk->ctx); + if (pthread_create(&thread, NULL, disk_image__thread, disk) != 0) + die("Failed starting IO thread"); + } return disk; } @@ -87,6 +117,7 @@ struct disk_image **disk_image__open_all(const char **filenames, bool *readonly, goto error; } } + return disks; error: for (i = 0; i < count; i++) @@ -151,7 +182,7 @@ ssize_t disk_image__read(struct disk_image *disk, u64 sector, const struct iovec /* Do nothing */ } - if (disk->disk_req_cb) + if (!disk->async && disk->disk_req_cb) disk->disk_req_cb(param, total); return total; @@ -183,7 +214,7 @@ ssize_t disk_image__write(struct disk_image *disk, u64 sector, const struct iove /* Do nothing */ } - if (disk->disk_req_cb) + if (!disk->async && disk->disk_req_cb) disk->disk_req_cb(param, total); return total; diff --git a/tools/kvm/disk/qcow.c b/tools/kvm/disk/qcow.c index f9598de..87385df 100644 --- a/tools/kvm/disk/qcow.c +++ b/tools/kvm/disk/qcow.c @@ -1145,6 +1145,8 @@ static struct disk_image *qcow2_probe(int fd, bool readonly) if (!disk_image) goto free_refcount_table; + + disk_image->async = 1; disk_image->priv = q; return disk_image; @@ -1276,6 +1278,8 @@ static struct disk_image *qcow1_probe(int fd, bool readonly) if (!disk_image) goto free_l1_table; + + disk_image->async = 1; disk_image->priv = q; return disk_image; diff --git a/tools/kvm/disk/raw.c b/tools/kvm/disk/raw.c index 51e8318..d3b432d 100644 --- a/tools/kvm/disk/raw.c +++ b/tools/kvm/disk/raw.c @@ -1,19 +1,25 @@ #include "kvm/disk-image.h" +#include <libaio.h> + ssize_t raw_image__read_sector(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount, void *param) { + struct iocb iocb; u64 offset = sector << SECTOR_SHIFT; - return preadv_in_full(disk->fd, iov, iovcount, offset); + return aio_preadv(disk->ctx, &iocb, disk->fd, iov, iovcount, offset, + disk->evt, param); } ssize_t raw_image__write_sector(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount, void *param) { + struct iocb iocb; u64 offset = sector << SECTOR_SHIFT; - return pwritev_in_full(disk->fd, iov, iovcount, offset); + return aio_pwritev(disk->ctx, &iocb, disk->fd, iov, iovcount, offset, + disk->evt, param); } ssize_t raw_image__read_sector_mmap(struct disk_image *disk, u64 sector, const struct iovec *iov, @@ -83,6 +89,7 @@ struct disk_image_operations ro_ops_nowrite = { struct disk_image *raw_image__probe(int fd, struct stat *st, bool readonly) { + struct disk_image *disk; if (readonly) { /* @@ -94,8 +101,10 @@ struct disk_image *raw_image__probe(int fd, struct stat *st, bool readonly) disk = disk_image__new(fd, st->st_size, &ro_ops, DISK_IMAGE_MMAP); if (disk == NULL) { ro_ops = raw_image_regular_ops; - ro_ops.write_sector = NULL; + disk = disk_image__new(fd, st->st_size, &ro_ops_nowrite, DISK_IMAGE_REGULAR); + if (disk) + disk->async = 1; } return disk; @@ -103,6 +112,9 @@ struct disk_image *raw_image__probe(int fd, struct stat *st, bool readonly) /* * Use read/write instead of mmap */ - return disk_image__new(fd, st->st_size, &raw_image_regular_ops, DISK_IMAGE_REGULAR); + disk = disk_image__new(fd, st->st_size, &raw_image_regular_ops, DISK_IMAGE_REGULAR); + if (disk) + disk->async = 1; + return disk; } } diff --git a/tools/kvm/include/kvm/disk-image.h b/tools/kvm/include/kvm/disk-image.h index 632e54d..0b1457d 100644 --- a/tools/kvm/include/kvm/disk-image.h +++ b/tools/kvm/include/kvm/disk-image.h @@ -46,6 +46,9 @@ struct disk_image { void *priv; void *disk_req_cb_param; void (*disk_req_cb)(void *param, long len); + bool async; + int evt; + io_context_t ctx; }; struct disk_image *disk_image__open(const char *filename, bool readonly); diff --git a/tools/kvm/virtio/blk.c b/tools/kvm/virtio/blk.c index 5969d27..69c1e59 100644 --- a/tools/kvm/virtio/blk.c +++ b/tools/kvm/virtio/blk.c @@ -2,7 +2,6 @@ #include "kvm/virtio-pci-dev.h" #include "kvm/disk-image.h" -#include "kvm/virtio.h" #include "kvm/mutex.h" #include "kvm/util.h" #include "kvm/kvm.h" @@ -11,23 +10,23 @@ #include "kvm/ioeventfd.h" #include "kvm/guest_compat.h" #include "kvm/virtio-pci.h" +#include "kvm/virtio.h" #include <linux/virtio_ring.h> #include <linux/virtio_blk.h> - #include <linux/kernel.h> #include <linux/list.h> #include <linux/types.h> #include <pthread.h> #define VIRTIO_BLK_MAX_DEV 4 -#define NUM_VIRT_QUEUES 1 -#define VIRTIO_BLK_QUEUE_SIZE 128 /* * the header and status consume too entries */ #define DISK_SEG_MAX (VIRTIO_BLK_QUEUE_SIZE - 2) +#define VIRTIO_BLK_QUEUE_SIZE 128 +#define NUM_VIRT_QUEUES 1 struct blk_dev_req { struct list_head list; @@ -86,8 +85,8 @@ void virtio_blk_complete(void *param, long len) u8 *status; /* status */ - status = req->iov[req->out + req->in - 1].iov_base; - *status = (len < 0) ? VIRTIO_BLK_S_IOERR : VIRTIO_BLK_S_OK; + status = req->iov[req->out + req->in - 1].iov_base; + *status = (len < 0) ? VIRTIO_BLK_S_IOERR : VIRTIO_BLK_S_OK; mutex_lock(&bdev->mutex); virt_queue__set_used_elem(req->vq, req->head, len); -- 1.7.7.1 -- 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