]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
kvm: Implement virtio block device write support
authorPekka Enberg <penberg@kernel.org>
Sat, 8 Jan 2011 12:28:59 +0000 (14:28 +0200)
committerPekka Enberg <penberg@kernel.org>
Sat, 8 Jan 2011 12:28:59 +0000 (14:28 +0200)
This patch implement virtio block device write support. The writes are not
persistent because we map the disk image with MAP_PRIVATE.

Signed-off-by: Pekka Enberg <penberg@kernel.org>
tools/kvm/blk-virtio.c
tools/kvm/disk-image.c
tools/kvm/include/kvm/disk-image.h

index 1e26ca5d85bbd285dadc8c8360a8dee2b8253093..13e6d90a66bf31a3f7966b937dd9620dcfa815ae 100644 (file)
@@ -119,10 +119,9 @@ static bool blk_virtio_read(struct kvm *self, struct virt_queue *queue)
        struct virtio_blk_outhdr *req;
        struct vring_desc *desc;
        uint16_t desc_ndx;
-       uint32_t dst_len;
+       uint32_t block_len;
        uint8_t *status;
-       void *dst;
-       int err;
+       void *block;
 
        desc_ndx                = queue->vring.avail->ring[queue->last_avail_idx++ % queue->vring.num];
 
@@ -141,8 +140,8 @@ static bool blk_virtio_read(struct kvm *self, struct virt_queue *queue)
        desc                    = &queue->vring.desc[desc->next];
        assert(!(desc->flags & VRING_DESC_F_INDIRECT));
 
-       dst                     = guest_flat_to_host(self, desc->addr);
-       dst_len                 = desc->len;
+       block                   = guest_flat_to_host(self, desc->addr);
+       block_len               = desc->len;
 
        /* status */
        desc                    = &queue->vring.desc[desc->next];
@@ -150,16 +149,31 @@ static bool blk_virtio_read(struct kvm *self, struct virt_queue *queue)
 
        status                  = guest_flat_to_host(self, desc->addr);
 
-       if (req->type == VIRTIO_BLK_T_IN) {
-               err = disk_image__read_sector(self->disk_image, req->sector, dst, dst_len);
+       switch (req->type) {
+       case VIRTIO_BLK_T_IN: {
+               int err;
 
+               err             = disk_image__read_sector(self->disk_image, req->sector, block, block_len);
                if (err)
                        *status                 = VIRTIO_BLK_S_IOERR;
                else
                        *status                 = VIRTIO_BLK_S_OK;
-       } else {
+               break;
+       }
+       case VIRTIO_BLK_T_OUT: {
+               int err;
+
+               err             = disk_image__write_sector(self->disk_image, req->sector, block, block_len);
+               if (err)
+                       *status                 = VIRTIO_BLK_S_IOERR;
+               else
+                       *status                 = VIRTIO_BLK_S_OK;
+               break;
+       }
+       default:
                warning("request type %d", req->type);
                *status                 = VIRTIO_BLK_S_IOERR;
+               break;
        }
 
        used_elem               = &queue->vring.used->ring[queue->vring.used->idx++ % queue->vring.num];
index a6d1e964810a5cb0d9b5c4fb565929b3b526f543..fd2d96898b829976649f239ef6c2b1f64a7af82f 100644 (file)
@@ -46,7 +46,7 @@ struct disk_image *disk_image__open(const char *filename)
 
        self->size      = st.st_size;
 
-       self->mmap      = mmap(NULL, self->size, PROT_READ, MAP_PRIVATE, self->fd, 0);
+       self->mmap      = mmap(NULL, self->size, PROT_READ|PROT_WRITE, MAP_PRIVATE, self->fd, 0);
        if (self->mmap == MAP_FAILED)
                goto failed_close_fd;
 
@@ -85,3 +85,15 @@ int disk_image__read_sector(struct disk_image *self, uint64_t sector, void *dst,
 
        return 0;
 }
+
+int disk_image__write_sector(struct disk_image *self, uint64_t sector, void *src, uint32_t src_len)
+{
+       uint64_t offset = sector << SECTOR_SHIFT;
+
+       if (offset + src_len > self->size)
+               return -1;
+
+       memcpy(self->mmap + offset, src, src_len);
+
+       return 0;
+}
index 6cba338d4fba9616baf3705a91f298f2b84fdd3d..c6413ca51ffa46d06ce97cddefe8c154aa9e0ef3 100644 (file)
@@ -12,5 +12,6 @@ struct disk_image {
 struct disk_image *disk_image__open(const char *filename);
 void disk_image__close(struct disk_image *self);
 int disk_image__read_sector(struct disk_image *self, uint64_t sector, void *dst, uint32_t dst_len);
+int disk_image__write_sector(struct disk_image *self, uint64_t sector, void *src, uint32_t src_len);
 
 #endif /* KVM__DISK_IMAGE_H */