aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorThomas Huth <thuth@redhat.com>2016-11-15 14:02:51 +0100
committerAlexey Kardashevskiy <aik@ozlabs.ru>2016-11-24 23:24:23 +1100
commit264553932ba3cee4b7472838daaecfaaa61c91da (patch)
tree0181e5cedf18fe482f0905509601b5ffb61f0459 /lib
parenteee0d12dc541dd345d7931976e352ea5a6494155 (diff)
downloadSLOF-264553932ba3cee4b7472838daaecfaaa61c91da.zip
SLOF-264553932ba3cee4b7472838daaecfaaa61c91da.tar.gz
SLOF-264553932ba3cee4b7472838daaecfaaa61c91da.tar.bz2
virtio: Implement block write support
Refactor the virtio-block code a little bit to provide block write access, too. Write access to the first 34 sectors is not allowed, though, to avoid that the user / client program accidentially destroys the partition table. Signed-off-by: Thomas Huth <thuth@redhat.com> Reviewed-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Diffstat (limited to 'lib')
-rw-r--r--lib/libvirtio/virtio-blk.c27
-rw-r--r--lib/libvirtio/virtio-blk.h3
-rw-r--r--lib/libvirtio/virtio.code11
-rw-r--r--lib/libvirtio/virtio.in1
4 files changed, 28 insertions, 14 deletions
diff --git a/lib/libvirtio/virtio-blk.c b/lib/libvirtio/virtio-blk.c
index 07ec104..cdfdd10 100644
--- a/lib/libvirtio/virtio-blk.c
+++ b/lib/libvirtio/virtio-blk.c
@@ -112,15 +112,17 @@ static void fill_blk_hdr(struct virtio_blk_req *blkhdr, bool is_modern,
}
/**
- * Read blocks
+ * Read / write blocks
* @param reg pointer to "reg" property
* @param buf pointer to destination buffer
- * @param blocknum block number of the first block that should be read
- * @param cnt amount of blocks that should be read
- * @return number of blocks that have been read successfully
+ * @param blocknum block number of the first block that should be transfered
+ * @param cnt amount of blocks that should be transfered
+ * @param type VIRTIO_BLK_T_OUT for write, VIRTIO_BLK_T_IN for read transfers
+ * @return number of blocks that have been transfered successfully
*/
int
-virtioblk_read(struct virtio_device *dev, char *buf, uint64_t blocknum, long cnt)
+virtioblk_transfer(struct virtio_device *dev, char *buf, uint64_t blocknum,
+ long cnt, unsigned int type)
{
struct vring_desc *desc;
int id;
@@ -136,15 +138,15 @@ virtioblk_read(struct virtio_device *dev, char *buf, uint64_t blocknum, long cnt
uint16_t last_used_idx, avail_idx;
int blk_size = DEFAULT_SECTOR_SIZE;
- //printf("virtioblk_read: dev=%p buf=%p blocknum=%li count=%li\n",
- // dev, buf, blocknum, cnt);
+ //printf("virtioblk_transfer: dev=%p buf=%p blocknum=%lli cnt=%li type=%i\n",
+ // dev, buf, blocknum, cnt, type);
/* Check whether request is within disk capacity */
capacity = virtio_get_config(dev,
offset_of(struct virtio_blk_cfg, capacity),
sizeof(capacity));
if (blocknum + cnt - 1 > capacity) {
- puts("virtioblk_read: Access beyond end of device!");
+ puts("virtioblk_transfer: Access beyond end of device!");
return 0;
}
@@ -152,7 +154,7 @@ virtioblk_read(struct virtio_device *dev, char *buf, uint64_t blocknum, long cnt
offset_of(struct virtio_blk_cfg, blk_size),
sizeof(blk_size));
if (blk_size % DEFAULT_SECTOR_SIZE) {
- fprintf(stderr, "virtio-blk: Unaligned sector read %d\n", blk_size);
+ fprintf(stderr, "virtio-blk: Unaligned sector size %d\n", blk_size);
return 0;
}
@@ -167,7 +169,7 @@ virtioblk_read(struct virtio_device *dev, char *buf, uint64_t blocknum, long cnt
current_used_idx = &vq_used->idx;
/* Set up header */
- fill_blk_hdr(&blkhdr, dev->is_modern, VIRTIO_BLK_T_IN | VIRTIO_BLK_T_BARRIER,
+ fill_blk_hdr(&blkhdr, dev->is_modern, type | VIRTIO_BLK_T_BARRIER,
1, blocknum * blk_size / DEFAULT_SECTOR_SIZE);
/* Determine descriptor index */
@@ -182,7 +184,7 @@ virtioblk_read(struct virtio_device *dev, char *buf, uint64_t blocknum, long cnt
/* Set up virtqueue descriptor for data */
desc = &vq_desc[(id + 1) % vq_size];
virtio_fill_desc(desc, dev->is_modern, (uint64_t)buf, cnt * blk_size,
- VRING_DESC_F_NEXT | VRING_DESC_F_WRITE,
+ VRING_DESC_F_NEXT | ((type & 1) ? 0 : VRING_DESC_F_WRITE),
(id + 2) % vq_size);
/* Set up virtqueue descriptor for status */
@@ -209,7 +211,8 @@ virtioblk_read(struct virtio_device *dev, char *buf, uint64_t blocknum, long cnt
if (status == 0)
return cnt;
- printf("virtioblk_read failed! status = %i\n", status);
+ printf("virtioblk_transfer failed! type=%i, status = %i\n",
+ type, status);
return 0;
}
diff --git a/lib/libvirtio/virtio-blk.h b/lib/libvirtio/virtio-blk.h
index 2e7b592..21f0adc 100644
--- a/lib/libvirtio/virtio-blk.h
+++ b/lib/libvirtio/virtio-blk.h
@@ -55,6 +55,7 @@ struct virtio_blk_req {
extern int virtioblk_init(struct virtio_device *dev);
extern void virtioblk_shutdown(struct virtio_device *dev);
-extern int virtioblk_read(struct virtio_device *dev, char *buf, uint64_t blocknum, long cnt);
+extern int virtioblk_transfer(struct virtio_device *dev, char *buf,
+ uint64_t blocknum, long cnt, unsigned int type);
#endif /* _VIRTIO_BLK_H */
diff --git a/lib/libvirtio/virtio.code b/lib/libvirtio/virtio.code
index 971a3cf..b8262ad 100644
--- a/lib/libvirtio/virtio.code
+++ b/lib/libvirtio/virtio.code
@@ -70,7 +70,16 @@ PRIM(virtio_X2d_blk_X2d_read)
long cnt = TOS.n; POP;
long blkno = TOS.n; POP;
void *buf = TOS.a;
- TOS.n = virtioblk_read(dev, buf, blkno, cnt);
+ TOS.n = virtioblk_transfer(dev, buf, blkno, cnt, VIRTIO_BLK_T_IN);
+MIRP
+
+// : virtio-blk-write ( buf blkno cnt dev -- #written )
+PRIM(virtio_X2d_blk_X2d_write)
+ void *dev = TOS.a; POP;
+ long cnt = TOS.n; POP;
+ long blkno = TOS.n; POP;
+ void *buf = TOS.a;
+ TOS.n = virtioblk_transfer(dev, buf, blkno, cnt, VIRTIO_BLK_T_OUT);
MIRP
/******** virtio-fs ********/
diff --git a/lib/libvirtio/virtio.in b/lib/libvirtio/virtio.in
index d2b1641..41a9cd0 100644
--- a/lib/libvirtio/virtio.in
+++ b/lib/libvirtio/virtio.in
@@ -20,6 +20,7 @@ cod(virtio-set-qaddr)
cod(virtio-blk-init)
cod(virtio-blk-shutdown)
cod(virtio-blk-read)
+cod(virtio-blk-write)
cod(virtio-scsi-init)
cod(virtio-scsi-shutdown)