shithub: riscv

Download patch

ref: 8c4bb53bdcae806bb13dbe26df51a848ff563d36
parent: f43df64325efb80fc48a85009df016477238b21b
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Tue Aug 11 13:56:06 EDT 2015

hjfs: fix abort() in givebuf()

it is possible for another getbuf() on buffer b to come in
before undelayreq() calls givebuf() on a buffer again. then
givebuf() would find b already busy and abort().

instead, we now handle what getbuf() did in givebuf() and
consider the Buf* argument to givebuf() as a hint only for
the case when we have to actually flush/read a block from
disk.

--- a/sys/src/cmd/hjfs/buf.c
+++ b/sys/src/cmd/hjfs/buf.c
@@ -81,11 +81,24 @@
 {
 	Buf *c, *l;
 
-	markbusy(b);
+	assert(!b->busy);
 	if(req.d == b->d && req.off == b->off){
+		markbusy(b);
 		send(req.resp, &b);
 		return;
 	}
+	l = &req.d->buf[req.off & BUFHASH];
+	for(c = l->dnext; c != l; c = c->dnext)
+		if(c->off == req.off){
+			if(c->busy){
+				delayreq(req, &c->next, &c->last);
+				return;
+			}
+			markbusy(c);
+			send(req.resp, &c);
+			return;
+		}
+	markbusy(b);
 	if(b->op & BDELWRI){
 		b->op &= ~BDELWRI;
 		b->op |= BWRITE;
@@ -94,10 +107,6 @@
 		work(b->d, b);
 		return;
 	}
-	l = &req.d->buf[req.off & BUFHASH];
-	for(c = l->dnext; c != l; c = c->dnext)
-		if(c->off == req.off)
-			abort();
 	changedev(b, req.d, req.off);
 	b->op &= ~(BWRITE|BDELWRI|BWRIM);
 	if(req.nodata)
@@ -109,6 +118,19 @@
 }
 
 static void
+handleget(BufReq req)
+{
+	Buf *b;
+	
+	b = bfree.fnext;
+	if(b == &bfree){
+		delayreq(req, &freereq, &freereqlast);
+		return;
+	}
+	givebuf(req, b);
+}
+
+static void
 undelayreq(Buf *b, BufReq **first, BufReq **last)
 {
 	BufReq *r;
@@ -119,31 +141,6 @@
 		*last = nil;
 	givebuf(*r, b);
 	free(r);
-}
-
-static void
-handleget(BufReq req)
-{
-	Buf *b, *l;
-	Dev *d;
-	
-	d = req.d;
-	l = &d->buf[req.off & BUFHASH];
-	for(b = l->dnext; b != l; b = b->dnext)
-		if(b->off == req.off){
-			if(b->busy){
-				delayreq(req, &b->next, &b->last);
-				return;
-			}
-			givebuf(req, b);
-			return;
-		}
-	if(bfree.fnext == &bfree){
-		delayreq(req, &freereq, &freereqlast);
-		return;
-	}
-	b = bfree.fnext;
-	givebuf(req, b);
 }
 
 static void