diff mbox

[v2,3/4] virtio: Implement block write support

Message ID 1479214972-19153-4-git-send-email-thuth@redhat.com
State Accepted
Headers show

Commit Message

Thomas Huth Nov. 15, 2016, 1:02 p.m. UTC
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>
---
 board-qemu/slof/virtio-block.fs | 13 +++++++++++++
 lib/libvirtio/virtio-blk.c      | 27 +++++++++++++++------------
 lib/libvirtio/virtio-blk.h      |  3 ++-
 lib/libvirtio/virtio.code       | 11 ++++++++++-
 lib/libvirtio/virtio.in         |  1 +
 5 files changed, 41 insertions(+), 14 deletions(-)

Comments

Nikunj A Dadhania Nov. 16, 2016, 7:50 a.m. UTC | #1
Thomas Huth <thuth@redhat.com> writes:

> 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>

Regards,
Nikunj
diff mbox

Patch

diff --git a/board-qemu/slof/virtio-block.fs b/board-qemu/slof/virtio-block.fs
index bc9013e..b3065b2 100644
--- a/board-qemu/slof/virtio-block.fs
+++ b/board-qemu/slof/virtio-block.fs
@@ -49,6 +49,15 @@  virtio-setup-vd VALUE virtiodev
    virtiodev virtio-blk-read
 ;
 
+: write-blocks  ( addr block# #blocks -- #written )
+    \ Do not allow writes to the partition table (GPT is in first 34 sectors)
+    over 22 < IF
+        ." virtio-blk ERROR: Write access to partition table is not allowed." cr
+        3drop 0 EXIT
+    THEN
+    virtiodev virtio-blk-write
+;
+
 \ Standard node "open" function
 : open  ( -- okay? )
    open 0= IF false EXIT THEN
@@ -79,6 +88,10 @@  virtio-setup-vd VALUE virtiodev
    s" read" deblocker @ $call-method
 ;
 
+: write ( addr len -- actual )
+    s" write" deblocker @ $call-method
+;
+
 \ Set disk alias if none is set yet
 : (set-alias)
    s" disk" get-next-alias ?dup IF
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)