From df3663f30d9b85f6a7692783c569b9b8415cdf56 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Fri, 8 Apr 2011 14:53:26 +0300 Subject: [PATCH] kvm tools: Use pread() and pwrite() in disk-image.c This patch convert lseek() + read()/write() pairs with pread()/pwrite(). The performance of running the following command dd if=/dev/vda of=/dev/null in the guest does not show significant performance differences but should be a net win because of the reduction in system calls. Signed-off-by: Pekka Enberg --- tools/kvm/disk-image.c | 10 +--- tools/kvm/include/kvm/read-write.h | 6 +++ tools/kvm/read-write.c | 75 ++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 8 deletions(-) diff --git a/tools/kvm/disk-image.c b/tools/kvm/disk-image.c index 9a830270c683..80999c13d505 100644 --- a/tools/kvm/disk-image.c +++ b/tools/kvm/disk-image.c @@ -35,10 +35,7 @@ static int raw_image__read_sector(struct disk_image *self, uint64_t sector, void if (offset + dst_len > self->size) return -1; - if (lseek(self->fd, offset, SEEK_SET) < 0) - return -1; - - if (read_in_full(self->fd, dst, dst_len) < 0) + if (pread_in_full(self->fd, dst, dst_len, offset) < 0) return -1; return 0; @@ -51,10 +48,7 @@ static int raw_image__write_sector(struct disk_image *self, uint64_t sector, voi if (offset + src_len > self->size) return -1; - if (lseek(self->fd, offset, SEEK_SET) < 0) - return -1; - - if (write_in_full(self->fd, src, src_len) < 0) + if (pwrite_in_full(self->fd, src, src_len, offset) < 0) return -1; return 0; diff --git a/tools/kvm/include/kvm/read-write.h b/tools/kvm/include/kvm/read-write.h index a49394b021ff..069326b2a40d 100644 --- a/tools/kvm/include/kvm/read-write.h +++ b/tools/kvm/include/kvm/read-write.h @@ -10,4 +10,10 @@ ssize_t xwrite(int fd, const void *buf, size_t count); ssize_t read_in_full(int fd, void *buf, size_t count); ssize_t write_in_full(int fd, const void *buf, size_t count); +ssize_t xpread(int fd, void *buf, size_t count, off_t offset); +ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset); + +ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset); +ssize_t pwrite_in_full(int fd, const void *buf, size_t count, off_t offset); + #endif /* KVM_READ_WRITE_H */ diff --git a/tools/kvm/read-write.c b/tools/kvm/read-write.c index 46b147d3b8b6..398918b5fe99 100644 --- a/tools/kvm/read-write.c +++ b/tools/kvm/read-write.c @@ -77,3 +77,78 @@ ssize_t write_in_full(int fd, const void *buf, size_t count) return total; } + +/* Same as pread(2) except that this function never returns EAGAIN or EINTR. */ +ssize_t xpread(int fd, void *buf, size_t count, off_t offset) +{ + ssize_t nr; + +restart: + nr = pread(fd, buf, count, offset); + if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR))) + goto restart; + + return nr; +} + +/* Same as pwrite(2) except that this function never returns EAGAIN or EINTR. */ +ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset) +{ + ssize_t nr; + +restart: + nr = pwrite(fd, buf, count, offset); + if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR))) + goto restart; + + return nr; +} + +ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset) +{ + ssize_t total = 0; + char *p = buf; + + while (count > 0) { + ssize_t nr; + + nr = xpread(fd, p, count, offset); + if (nr <= 0) { + if (total > 0) + return total; + + return -1; + } + + count -= nr; + total += nr; + p += nr; + offset += nr; + } + + return total; +} + +ssize_t pwrite_in_full(int fd, const void *buf, size_t count, off_t offset) +{ + const char *p = buf; + ssize_t total = 0; + + while (count > 0) { + ssize_t nr; + + nr = xpwrite(fd, p, count, offset); + if (nr < 0) + return -1; + if (nr == 0) { + errno = ENOSPC; + return -1; + } + count -= nr; + total += nr; + p += nr; + offset += nr; + } + + return total; +} -- 2.39.5