shithub: riscv

Download patch

ref: 5542062dc8e0b6486a9e9e0b8993645b42eb9e5a
parent: b7a778917dd9f6f07f63897dedcc31b6ab0c8383
author: aiju <devnull@localhost>
date: Thu Jun 15 03:41:26 EDT 2017

vmx: fix virtio bugs

--- a/sys/src/cmd/vmx/virtio.c
+++ b/sys/src/cmd/vmx/virtio.c
@@ -208,7 +208,7 @@
 		if(m > n - rc) m = n - rc;
 		memmove(v, (u8int*)c->p + p, m);
 		p += m, rc += m;
-		v = (u8int*)v + p;
+		v = (u8int*)v + m;
 		b->rptr += m;
 	}
 }
@@ -238,11 +238,33 @@
 		if(m > n - rc) m = n - rc;
 		memmove((u8int*)c->p + p, v, m);
 		p += m, rc += m;
-		v = (u8int*)v + p;
+		v = (u8int*)v + m;
 		b->wptr += m;
 	}
 }
 
+ulong
+vioqrem(VIOBuf *b, int wr)
+{
+	VIOBuf *c;
+	u32int p;
+	ulong rc;
+	
+	p = wr ? b->wptr : b->rptr;
+	for(c = b;; c = c->next){
+		if(c == nil) return 0;
+		if(((c->flags & BUFWR) != 0) == wr){
+			if(p < c->len) break;
+			p -= c->len;
+		}
+	}
+	rc = c->len - p;
+	for(c = c->next; c != nil; c = c->next)
+		if(((c->flags & BUFWR) != 0) == wr)
+			rc += c->len;
+	return rc;
+}
+
 static void
 vioqaddrset(VIOQueue *q, u64int addr)
 {
@@ -448,14 +470,14 @@
 		}	
 		rc = write(v->net.writefd, txbuf, len);
 		vioputbuf(vb);
-		if(rc < len){
-			vmerror("write(vionetwproc): incomplete write");
-			continue;
-		}
 		if(rc < 0){
 			vmerror("write(vionetwproc): %r");
 			continue;
 		}
+		if(rc < len){
+			vmerror("write(vionetwproc): incomplete write");
+			continue;
+		}
 	}
 }
 
@@ -585,9 +607,9 @@
 	VIOBuf *b;
 	u8int cmd[16];
 	u8int ack;
-	char buf[512];
+	char buf[8192];
 	uvlong addr;
-	int rc;
+	int rc, n, m;
 	
 	threadsetname("vioblkproc");
 	v = vp;
@@ -603,21 +625,40 @@
 		addr = GET64(cmd, 8);
 		switch(GET32(cmd, 0)){
 		case 0:
-			if(addr >> 55 != 0) rc = 0;
-			else rc = pread(v->blk.fd, buf, 512, addr << 9);
-			if(rc < 0) vmerror("pread(vioblkproc): %r");
-			if(rc < 512){
-				memset(buf, 0, 512);
+			n = vioqrem(b, 1) - 1;
+			if(n < 0 || addr * 512 + n > v->blk.size * 512){
 				ack = 1;
+				break;
 			}
-			vioqwrite(b, buf, 512);
+			seek(v->blk.fd, addr << 9, 0);
+			for(; n > 0; n -= rc){
+				rc = sizeof(buf);
+				if(n < rc) rc = n;
+				rc = read(v->blk.fd, buf, rc);
+				if(rc < 0) vmerror("read(vioblkproc): %r");
+				if(rc <= 0){
+					ack = 1;
+					break;
+				}
+				vioqwrite(b, buf, rc);
+			}
 			break;
 		case 1:
-			if(vioqread(b, buf, 512) < 512) rc = 0;
-			else if(addr >> 55 != 0) rc = 0;
-			else rc = pwrite(v->blk.fd, buf, 512, addr << 9);
-			if(rc < 0) vmerror("pwrite(vioblkproc): %r");
-			if(rc < 512) ack = 1;
+			n = vioqrem(b, 0);
+			if(addr * 512 + n > v->blk.size * 512){
+				ack = 1;
+				break;
+			}
+			seek(v->blk.fd, addr << 9, 0);
+			for(; n > 0; n -= rc){
+				m = vioqread(b, buf, sizeof(buf));
+				rc = write(v->blk.fd, buf, m);
+				if(rc < 0) vmerror("write(vioblkproc): %r");
+				if(rc < m){
+					ack = 1;
+					break;
+				}
+			}
 			break;
 		default:
 		nope:
@@ -641,6 +682,6 @@
 	d->io = vioblkio;
 	d->blk.fd = fd;
 	d->blk.size = seek(fd, 0, 2) >> 9;
-	proccreate(vioblkproc, d, 8192);
+	proccreate(vioblkproc, d, 16384);
 	return 0;
 }