]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
kvm tools: Use pread() and pwrite() in disk-image.c
authorPekka Enberg <penberg@kernel.org>
Fri, 8 Apr 2011 11:53:26 +0000 (14:53 +0300)
committerPekka Enberg <penberg@kernel.org>
Fri, 8 Apr 2011 11:53:26 +0000 (14:53 +0300)
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>
tools/kvm/disk-image.c
tools/kvm/include/kvm/read-write.h
tools/kvm/read-write.c

index 9a830270c68370f4185fba404d6688ce6508b714..80999c13d505b9dd7b8beb48cc6ec3f749128807 100644 (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;
index a49394b021ff86e66651d238bc78248e4e437b1c..069326b2a40dd4be8dbb3932f9ed559c934b23c3 100644 (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 */
index 46b147d3b8b6e9d046bd02b87c7411222d0695b7..398918b5fe9948c60977e300e24659ef39361f67 100644 (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;
+}