ref: 8db68ca3d6ed8120aef097e365b88e545c4cce6c
parent: 807264bdf7762d6450fd820a1815d90e1ccf357d
author: 9ferno <[email protected]>
date: Wed Oct 26 05:28:43 EDT 2022
attempt to fix the deadlock between putwrite() and dowrite()
--- a/9p.c
+++ b/9p.c
@@ -1303,7 +1303,6 @@
if(buf == nil)
return -1;
-
howmuch = min(Blocksize-lastblksize, wbufsize);
if(chatty9p > 1)
dprint("fill lastblksize %llud howmuch %llud\n",
--- a/all.h
+++ b/all.h
@@ -76,7 +76,7 @@
u8 *xiobuf; /* "real" buffer pointer */
Content *io; /* cast'able to contents */
};
- u32 dirties; /* number of dirty blocks yet to be written by the writer */
+ u64 dirties; /* number of dirty blocks yet to be written by the writer */
u8 tofree; /* free this Iobuf after the dirty blocks are written to the disk */
};
--- a/writer.c
+++ b/writer.c
@@ -92,13 +92,14 @@
have wlock()'ed the Iobuf too */
if(drts.head != nil){
b = pluck(drts.head);
- rwakeup(&drts.isfull);
+ if(drts.n == npendingwrites-1)
+ rwakeup(&drts.isfull);
+ if(chatty9p > 4 && b!=nil){
+ dprint("getwrite done b->blkno %llud\n", b->blkno);
+ stats();
+ }
}else
b = nil;
- if(chatty9p > 4 && b!=nil){
- dprint("getwrite done b->blkno %llud\n", b->blkno);
- stats();
- }
qunlock(&drts.lck);
return b;
}
@@ -109,17 +110,31 @@
{
Wbuf *w;
+ /*
+ copying contents to w before.
+ This avoids rsleep'ing while holding a wlock() on the Iobuf.
+ rsleep'ing while holding the wlock() causes a deadlock()
+ with dowrite() when it tries to decrement dirties by holding
+ a wlock() on the Iobuf.
+ */
+ w = emalloc9p(sizeof(Wbuf));
+ w->blkno = b->blkno;
+ w->payload = allocmemunit();
+ memcpy(w->payload, b->xiobuf, Rawblocksize);
+ b->dirties++;
+ w->iobuf = b;
+ if(chkwunlock(b) == 0){
+ showbuf(b);
+ panic("putwrite chkwunlock(p) == 0 called by %#p\n", getcallerpc(&b));
+ }
+
qlock(&drts.lck);
if(chatty9p > 4){
dprint("putwrite start p->blkno %llud\n", b->blkno);
stats();
}
- if(drts.n > npendingwrites)
+ if(drts.n == npendingwrites)
rsleep(&drts.isfull);
- w = emalloc9p(sizeof(Wbuf));
- w->blkno = b->blkno;
- w->payload = allocmemunit();
- memcpy(w->payload, b->xiobuf, Rawblocksize);
if(drts.head == nil){
drts.head = drts.tail = w;
}else{
@@ -130,12 +145,6 @@
drts.n++;
if(drts.n == 1)
rwakeup(&drts.isempty);
- b->dirties++;
- w->iobuf = b;
- if(chkwunlock(b) == 0){
- showbuf(b);
- panic("putwrite chkwunlock(p) == 0 called by %#p\n", getcallerpc(&b));
- }
if(chatty9p > 4 && b!=nil){
dprint("putwrite done b->blkno %llud\n", b->blkno);
stats();