ref: 50750b43f50b2a70aa61e36e38c0339613bff915
parent: 8b220ec643c364d751d90644d8a45ee135276aff
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Thu Aug 13 06:41:12 EDT 2015
hjfs: fix deadlocks buffers which still have requests queued on them are not free! we cannot chanedev() a buffer while it has still requests queued on it and we canot just queue our request (having different address) on the buffer while there are other requests before it, otherwise we would create artificial block dependency that can cause deadlock.
--- a/sys/src/cmd/hjfs/buf.c
+++ b/sys/src/cmd/hjfs/buf.c
@@ -54,16 +54,28 @@
BufReq *r;
r = emalloc(sizeof(*r));
- memcpy(r, &req, sizeof(*r));
+ *r = req;
r->next = nil;
if(*first == nil)
- *first = *last = r;
- else{+ *first = r;
+ else
(*last)->next = r;
- *last = r;
- }
+ *last = r;
}
+static BufReq
+undelayreq(BufReq **first, BufReq **last)
+{+ BufReq r;
+
+ r = **first;
+ free(*first);
+ *first = r.next;
+ if(r.next == nil)
+ *last = nil;
+ return r;
+}
+
static void
work(Dev *d, Buf *b)
{@@ -81,7 +93,7 @@
{Buf *c, *l;
- assert(!b->busy);
+again:
if(req.d == b->d && req.off == b->off){markbusy(b);
send(req.resp, &b);
@@ -90,19 +102,30 @@
l = &req.d->buf[req.off & BUFHASH];
for(c = l->dnext; c != l; c = c->dnext)
if(c->off == req.off){- if(c->busy){+ if(c->busy)
delayreq(req, &c->next, &c->last);
- return;
+ else{+ markbusy(c);
+ send(req.resp, &c);
}
- markbusy(c);
- send(req.resp, &c);
- return;
+ if(b->next == nil)
+ return;
+ req = undelayreq(&b->next, &b->last);
+ goto again;
}
+ if(b->next != nil){+ givebuf(undelayreq(&b->next, &b->last), b);
+ b = bfree.fnext;
+ }
+ if(b == &bfree){+ delayreq(req, &freereq, &freereqlast);
+ return;
+ }
markbusy(b);
- if(b->op & BDELWRI){+ if(b->d != nil && b->op & BDELWRI){+ delayreq(req, &b->next, &b->last);
b->op &= ~BDELWRI;
b->op |= BWRITE;
- delayreq(req, &b->next, &b->last);
b->resp = putb;
work(b->d, b);
return;
@@ -120,30 +143,10 @@
static void
handleget(BufReq req)
{- Buf *b;
-
- b = bfree.fnext;
- if(b == &bfree){- delayreq(req, &freereq, &freereqlast);
- return;
- }
- givebuf(req, b);
+ givebuf(req, bfree.fnext);
}
static void
-undelayreq(Buf *b, BufReq **first, BufReq **last)
-{- BufReq *r;
-
- r = *first;
- *first = r->next;
- if(*last == r)
- *last = nil;
- givebuf(*r, b);
- free(r);
-}
-
-static void
handleput(Buf *b)
{ if(b->op & BWRIM){@@ -161,9 +164,9 @@
b->op &= ~BWRITE;
markfree(b);
if(b->next != nil)
- undelayreq(b, &b->next, &b->last);
+ givebuf(undelayreq(&b->next, &b->last), b);
else if(freereq != nil)
- undelayreq(b, &freereq, &freereqlast);
+ givebuf(undelayreq(&freereq, &freereqlast), b);
}
static void
--
⑨