mirror of
https://github.com/clearlinux/kvmtool.git
synced 2026-08-22 05:28:30 +00:00
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:
committed by
Will Deacon
parent
c067c5c17f
commit
6b7deb024d
+2
-8
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user