Signed-off-by: Sasha Levin <levinsasha928@xxxxxxxxx> --- tools/kvm/disk/core.c | 48 ++++++---------------------------- tools/kvm/disk/qcow.c | 47 +++++++++++++++++++++++++++++++-- tools/kvm/disk/raw.c | 50 +++++++++++++++++++++--------------- tools/kvm/include/kvm/disk-image.h | 26 +++++++----------- 4 files changed, 91 insertions(+), 80 deletions(-) diff --git a/tools/kvm/disk/core.c b/tools/kvm/disk/core.c index a914fef7..38aa99b 100644 --- a/tools/kvm/disk/core.c +++ b/tools/kvm/disk/core.c @@ -134,36 +134,19 @@ void disk_image__close_all(struct disk_image **disks, int count) ssize_t disk_image__read(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount) { ssize_t total = 0; - ssize_t nr; if (debug_iodelay) msleep(debug_iodelay); - if (disk->ops.read_sector_iov) { - /* - * Try mulitple buffer based operation first - */ - total = disk->ops.read_sector_iov(disk, sector, iov, iovcount); + if (disk->ops.read_sector) { + total = disk->ops.read_sector(disk, sector, iov, iovcount); if (total < 0) { pr_info("disk_image__read error: total=%ld\n", (long)total); return -1; } - } else if (disk->ops.read_sector) { - /* - * Fallback to single buffer based operation - */ - while (iovcount--) { - nr = disk->ops.read_sector(disk, sector, iov->iov_base, iov->iov_len); - if (nr != (ssize_t)iov->iov_len) { - pr_info("disk_image__read error: nr = %ld iov_len=%ld\n", (long)nr, (long)iov->iov_len); - return -1; - } - sector += iov->iov_len >> SECTOR_SHIFT; - iov++; - total += nr; - } - } else + } else { die("No disk image operation for read\n"); + } return total; } @@ -175,37 +158,22 @@ ssize_t disk_image__read(struct disk_image *disk, u64 sector, const struct iovec ssize_t disk_image__write(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount) { ssize_t total = 0; - ssize_t nr; if (debug_iodelay) msleep(debug_iodelay); - if (disk->ops.write_sector_iov) { + if (disk->ops.write_sector) { /* * Try writev based operation first */ - total = disk->ops.write_sector_iov(disk, sector, iov, iovcount); + total = disk->ops.write_sector(disk, sector, iov, iovcount); if (total < 0) { pr_info("disk_image__write error: total=%ld\n", (long)total); return -1; } - } else if (disk->ops.write_sector) { - /* - * Fallback to single buffer based operation - */ - while (iovcount--) { - nr = disk->ops.write_sector(disk, sector, iov->iov_base, iov->iov_len); - if (nr != (ssize_t)iov->iov_len) { - pr_info("disk_image__write error: nr=%ld iov_len=%ld\n", (long)nr, (long)iov->iov_len); - return -1; - } - - sector += iov->iov_len >> SECTOR_SHIFT; - iov++; - total += nr; - } - } else + } else { die("No disk image operation for read\n"); + } return total; } diff --git a/tools/kvm/disk/qcow.c b/tools/kvm/disk/qcow.c index bdf6bd8..288782e 100644 --- a/tools/kvm/disk/qcow.c +++ b/tools/kvm/disk/qcow.c @@ -452,7 +452,7 @@ out_error: return -1; } -static ssize_t qcow_read_sector(struct disk_image *disk, u64 sector, +static ssize_t qcow_read_sector_single(struct disk_image *disk, u64 sector, void *dst, u32 dst_len) { struct qcow *q = disk->priv; @@ -488,6 +488,26 @@ static ssize_t qcow_read_sector(struct disk_image *disk, u64 sector, return dst_len; } +static ssize_t qcow_read_sector(struct disk_image *disk, u64 sector, + const struct iovec *iov, int iovcount) +{ + ssize_t nr, total = 0; + + while (iovcount--) { + nr = qcow_read_sector_single(disk, sector, iov->iov_base, iov->iov_len); + if (nr != (ssize_t)iov->iov_len) { + pr_info("qcow_read_sector error: nr=%ld iov_len=%ld\n", (long)nr, (long)iov->iov_len); + return -1; + } + + sector += iov->iov_len >> SECTOR_SHIFT; + iov++; + total += nr; + } + + return total; +} + static inline u64 file_size(int fd) { struct stat st; @@ -867,7 +887,7 @@ error: return -1; } -static ssize_t qcow_write_sector(struct disk_image *disk, u64 sector, void *src, u32 src_len) +static ssize_t qcow_write_sector_single(struct disk_image *disk, u64 sector, void *src, u32 src_len) { struct qcow *q = disk->priv; struct qcow_header *header = q->header; @@ -896,7 +916,28 @@ static ssize_t qcow_write_sector(struct disk_image *disk, u64 sector, void *src, return nr_written; } -static ssize_t qcow_nowrite_sector(struct disk_image *disk, u64 sector, void *src, u32 src_len) +static ssize_t qcow_write_sector(struct disk_image *disk, u64 sector, + const struct iovec *iov, int iovcount) +{ + ssize_t nr, total = 0; + + while (iovcount--) { + nr = qcow_write_sector_single(disk, sector, iov->iov_base, iov->iov_len); + if (nr != (ssize_t)iov->iov_len) { + pr_info("qcow_write_sector error: nr=%ld iov_len=%ld\n", (long)nr, (long)iov->iov_len); + return -1; + } + + sector += iov->iov_len >> SECTOR_SHIFT; + iov++; + total += nr; + } + + return total; +} + +static ssize_t qcow_nowrite_sector(struct disk_image *disk, u64 sector, + const struct iovec *iov, int iovcount) { /* I/O error */ pr_info("%s: no write support\n", __func__); diff --git a/tools/kvm/disk/raw.c b/tools/kvm/disk/raw.c index 66c52be..1c6a985 100644 --- a/tools/kvm/disk/raw.c +++ b/tools/kvm/disk/raw.c @@ -1,41 +1,49 @@ #include "kvm/disk-image.h" -ssize_t raw_image__read_sector_iov(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount) +ssize_t raw_image__read_sector(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount) { u64 offset = sector << SECTOR_SHIFT; return preadv_in_full(disk->fd, iov, iovcount, offset); } -ssize_t raw_image__write_sector_iov(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount) +ssize_t raw_image__write_sector(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount) { u64 offset = sector << SECTOR_SHIFT; return pwritev_in_full(disk->fd, iov, iovcount, offset); } -ssize_t raw_image__read_sector(struct disk_image *disk, u64 sector, void *dst, u32 dst_len) +ssize_t raw_image__read_sector_mmap(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount) { u64 offset = sector << SECTOR_SHIFT; + ssize_t nr, total = 0; - if (offset + dst_len > disk->size) - return -1; + while (iovcount--) { + memcpy(iov->iov_base, disk->priv + offset, iov->iov_len); - memcpy(dst, disk->priv + offset, dst_len); + sector += iov->iov_len >> SECTOR_SHIFT; + iov++; + total += nr; + } - return dst_len; + return total; } -ssize_t raw_image__write_sector(struct disk_image *disk, u64 sector, void *src, u32 src_len) +ssize_t raw_image__write_sector_mmap(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount) { u64 offset = sector << SECTOR_SHIFT; + ssize_t nr, total = 0; - if (offset + src_len > disk->size) - return -1; + while (iovcount--) { + memcpy(disk->priv + offset, iov->iov_base, iov->iov_len); - memcpy(disk->priv + offset, src, src_len); + sector += iov->iov_len >> SECTOR_SHIFT; + iov++; + total += nr; + } - return src_len; + return total; } int raw_image__close(struct disk_image *disk) @@ -51,17 +59,17 @@ int raw_image__close(struct disk_image *disk) /* * multiple buffer based disk image operations */ -static struct disk_image_operations raw_image_iov_ops = { - .read_sector_iov = raw_image__read_sector_iov, - .write_sector_iov = raw_image__write_sector_iov, +static struct disk_image_operations raw_image_regular_ops = { + .read_sector = raw_image__read_sector, + .write_sector = raw_image__write_sector, }; /* - * single buffer based disk image operations + * mmap() based disk image operations */ -static struct disk_image_operations raw_image_ops = { - .read_sector = raw_image__read_sector, - .write_sector = raw_image__write_sector, +static struct disk_image_operations raw_image_mmap_ops = { + .read_sector = raw_image__read_sector_mmap, + .write_sector = raw_image__write_sector_mmap, .close = raw_image__close, }; @@ -73,10 +81,10 @@ struct disk_image *raw_image__probe(int fd, struct stat *st, bool readonly) * Use mmap's MAP_PRIVATE to implement non-persistent write * FIXME: This does not work on 32-bit host. */ - return disk_image__new(fd, st->st_size, &raw_image_ops, DISK_IMAGE_MMAP); + return disk_image__new(fd, st->st_size, &raw_image_mmap_ops, DISK_IMAGE_MMAP); else /* * Use read/write instead of mmap */ - return disk_image__new(fd, st->st_size, &raw_image_iov_ops, DISK_IMAGE_REGULAR); + return disk_image__new(fd, st->st_size, &raw_image_regular_ops, DISK_IMAGE_REGULAR); } diff --git a/tools/kvm/include/kvm/disk-image.h b/tools/kvm/include/kvm/disk-image.h index bb97cdf..5087b9e 100644 --- a/tools/kvm/include/kvm/disk-image.h +++ b/tools/kvm/include/kvm/disk-image.h @@ -31,18 +31,8 @@ enum { struct disk_image; struct disk_image_operations { - /* - * The following two are used for reading or writing with a single buffer. - * The implentation can use readv/writev or memcpy. - */ - ssize_t (*read_sector)(struct disk_image *disk, u64 sector, void *dst, u32 dst_len); - ssize_t (*write_sector)(struct disk_image *disk, u64 sector, void *src, u32 src_len); - /* - * The following two are used for reading or writing with multiple buffers. - * The implentation can use readv/writev or memcpy. - */ - ssize_t (*read_sector_iov)(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount); - ssize_t (*write_sector_iov)(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount); + ssize_t (*read_sector)(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount); + ssize_t (*write_sector)(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount); int (*flush)(struct disk_image *disk); int (*close)(struct disk_image *disk); }; @@ -67,10 +57,14 @@ ssize_t disk_image__get_serial(struct disk_image *disk, void *buffer, ssize_t *l struct disk_image *raw_image__probe(int fd, struct stat *st, bool readonly); struct disk_image *blkdev__probe(const char *filename, struct stat *st); -ssize_t raw_image__read_sector_iov(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount); -ssize_t raw_image__write_sector_iov(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount); -ssize_t raw_image__read_sector(struct disk_image *disk, u64 sector, void *dst, u32 dst_len); -ssize_t raw_image__write_sector(struct disk_image *disk, u64 sector, void *src, u32 src_len); +ssize_t raw_image__read_sector(struct disk_image *disk, u64 sector, + const struct iovec *iov, int iovcount); +ssize_t raw_image__write_sector(struct disk_image *disk, u64 sector, + const struct iovec *iov, int iovcount); +ssize_t raw_image__read_sector_mmap(struct disk_image *disk, u64 sector, + const struct iovec *iov, int iovcount); +ssize_t raw_image__write_sector_mmap(struct disk_image *disk, u64 sector, + const struct iovec *iov, int iovcount); int raw_image__close(struct disk_image *disk); #endif /* KVM__DISK_IMAGE_H */ -- 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