--- /n/fossil/sys/src/cmd/fossil/cache.c Tue Apr 3 18:36:49 2012 +++ /sys/src/cmd/fossil/cache.c Sun Feb 13 09:57:10 2022 @@ -718,13 +718,14 @@ qlock(&fl->lk); addr = fl->last; + nwrap = 0; +NotFound: b = cacheLocal(c, PartLabel, addr/n, OReadOnly); if(b == nil){ fprint(2, "%s: cacheAllocBlock: xxx %r\n", argv0); qunlock(&fl->lk); return nil; } - nwrap = 0; for(;;){ if(++addr >= fl->end){ addr = 0; @@ -768,7 +769,12 @@ fprint(2, "%s: cacheAllocBlock: xxx3 %r\n", argv0); return nil; } -assert(b->iostate == BioLabel || b->iostate == BioClean); + if(!(b->iostate == BioLabel || b->iostate == BioClean)){ + if(0)fprint(2, "%s: cacheAllocBlock addr %ud iostate %s label %L\n", + argv0, addr, bioStr(b->iostate), &lab); + blockPut(b); + goto NotFound; + } fl->last = addr; lab.type = type; lab.tag = tag; @@ -1563,7 +1569,18 @@ l.state |= BsClosed; l.epochClose = p->epoch; if(l.epochClose == l.epoch){ - qlock(&c->fl->lk); + /* lock ordering: trying for c->fl->lk while holding b->lk can deadlock */ + if(!canqlock(&c->fl->lk)){ + blockPut(b); + qlock(&c->fl->lk); + b = cacheLocalData(c, p->addr, p->type, p->tag, OOverWrite, 0); + if(b == nil){ + fprint(2, "%s: warning: lost block at end of doRemoveLink\n", + argv0); + qunlock(&c->fl->lk); + return; + } + } if(l.epoch == c->fl->epochLow) c->fl->nused--; blockSetLabel(b, &l, 0);