From: Pekka Enberg Date: Fri, 8 Apr 2011 11:53:26 +0000 (+0300) Subject: kvm tools: Use pread() and pwrite() in disk-image.c X-Git-Tag: next-20110824~3^2~480 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=df3663f30d9b85f6a7692783c569b9b8415cdf56;p=karo-tx-linux.git 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 --- 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; +}