When _cacheLocal loads the label of a block from the disk and not its contents (if called with mode = OOverWrite), mark the cache entry iostate as BioLabel. It used to be marked BioClean, which causes problems when doRemoveLink calls cacheLocalData with OOverWrite and then leaves the data invalid, where it can be found by a concurrent archThread and written to venti. Reference: /n/sources/patch/applied/fossil-archive-corruption Date: Thu Mar 22 17:26:04 CET 2012 Signed-off-by: miller@hamnavoe.com --- /sys/src/cmd/fossil/cache.c Thu Mar 22 17:25:54 2012 +++ /sys/src/cmd/fossil/cache.c Thu Mar 22 17:25:50 2012 @@ -561,12 +561,13 @@ switch(b->iostate){ default: abort(); - case BioEmpty: case BioLabel: if(mode == OOverWrite){ - blockSetIOState(b, BioClean); + /* leave iostate as BioLabel because data hasn't been read */ return b; } + /* fall through */ + case BioEmpty: diskRead(c->disk, b); vtSleep(b->ioready); break; @@ -1098,7 +1099,7 @@ if(b->iostate == BioDirty) return 1; - assert(b->iostate == BioClean); + assert(b->iostate == BioClean || b->iostate == BioLabel); vtLock(c->dirtylk); vtLock(c->lk);