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 <penberg@kernel.org>
This commit is contained in:
Pekka Enberg
2011-04-08 14:53:26 +03:00
committed by Will Deacon
parent c067c5c17f
commit 6b7deb024d
3 changed files with 83 additions and 8 deletions
+2 -8
View File
@@ -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;
+6
View File
@@ -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 */
+75
View File
@@ -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;
}