15e96a66cSDavid du Colombier /* 25e96a66cSDavid du Colombier * Archiver. In charge of sending blocks to Venti. 35e96a66cSDavid du Colombier */ 45e96a66cSDavid du Colombier 55e96a66cSDavid du Colombier #include "stdinc.h" 65e96a66cSDavid du Colombier #include "dat.h" 75e96a66cSDavid du Colombier #include "fns.h" 85e96a66cSDavid du Colombier #include "error.h" 95e96a66cSDavid du Colombier 105e96a66cSDavid du Colombier #include "9.h" /* for consPrint */ 115e96a66cSDavid du Colombier 125e96a66cSDavid du Colombier #define DEBUG 0 135e96a66cSDavid du Colombier 145e96a66cSDavid du Colombier static void archThread(void*); 155e96a66cSDavid du Colombier 165e96a66cSDavid du Colombier struct Arch 175e96a66cSDavid du Colombier { 185e96a66cSDavid du Colombier int ref; 195e96a66cSDavid du Colombier uint blockSize; 205e96a66cSDavid du Colombier uint diskSize; 215e96a66cSDavid du Colombier Cache *c; 225e96a66cSDavid du Colombier Fs *fs; 235e96a66cSDavid du Colombier VtSession *z; 245e96a66cSDavid du Colombier 255e96a66cSDavid du Colombier VtLock *lk; 265e96a66cSDavid du Colombier VtRendez *starve; 275e96a66cSDavid du Colombier VtRendez *die; 285e96a66cSDavid du Colombier }; 295e96a66cSDavid du Colombier 305e96a66cSDavid du Colombier Arch * 315e96a66cSDavid du Colombier archInit(Cache *c, Disk *disk, Fs *fs, VtSession *z) 325e96a66cSDavid du Colombier { 335e96a66cSDavid du Colombier Arch *a; 345e96a66cSDavid du Colombier 355e96a66cSDavid du Colombier a = vtMemAllocZ(sizeof(Arch)); 365e96a66cSDavid du Colombier 375e96a66cSDavid du Colombier a->c = c; 385e96a66cSDavid du Colombier a->z = z; 395e96a66cSDavid du Colombier a->fs = fs; 405e96a66cSDavid du Colombier a->blockSize = diskBlockSize(disk); 415e96a66cSDavid du Colombier a->lk = vtLockAlloc(); 425e96a66cSDavid du Colombier a->starve = vtRendezAlloc(a->lk); 435e96a66cSDavid du Colombier 445e96a66cSDavid du Colombier a->ref = 2; 455e96a66cSDavid du Colombier vtThread(archThread, a); 465e96a66cSDavid du Colombier 475e96a66cSDavid du Colombier return a; 485e96a66cSDavid du Colombier } 495e96a66cSDavid du Colombier 505e96a66cSDavid du Colombier void 515e96a66cSDavid du Colombier archFree(Arch *a) 525e96a66cSDavid du Colombier { 535e96a66cSDavid du Colombier /* kill slave */ 545e96a66cSDavid du Colombier vtLock(a->lk); 555e96a66cSDavid du Colombier a->die = vtRendezAlloc(a->lk); 565e96a66cSDavid du Colombier vtWakeup(a->starve); 575e96a66cSDavid du Colombier while(a->ref > 1) 585e96a66cSDavid du Colombier vtSleep(a->die); 595e96a66cSDavid du Colombier vtUnlock(a->lk); 605e96a66cSDavid du Colombier vtRendezFree(a->starve); 615e96a66cSDavid du Colombier vtRendezFree(a->die); 625e96a66cSDavid du Colombier vtLockFree(a->lk); 635e96a66cSDavid du Colombier vtMemFree(a); 645e96a66cSDavid du Colombier } 655e96a66cSDavid du Colombier 665e96a66cSDavid du Colombier static int 675e96a66cSDavid du Colombier ventiSend(Arch *a, Block *b, uchar *data) 685e96a66cSDavid du Colombier { 695e96a66cSDavid du Colombier uint n; 705e96a66cSDavid du Colombier uchar score[VtScoreSize]; 715e96a66cSDavid du Colombier 725e96a66cSDavid du Colombier if(DEBUG > 1) 735e96a66cSDavid du Colombier fprint(2, "ventiSend: sending %#ux %L to venti\n", b->addr, &b->l); 745e96a66cSDavid du Colombier n = vtZeroTruncate(vtType[b->l.type], data, a->blockSize); 755e96a66cSDavid du Colombier if(DEBUG > 1) 765e96a66cSDavid du Colombier fprint(2, "ventiSend: truncate %d to %d\n", a->blockSize, n); 775e96a66cSDavid du Colombier if(!vtWrite(a->z, score, vtType[b->l.type], data, n)){ 785e96a66cSDavid du Colombier fprint(2, "ventiSend: vtWrite block %#ux failed: %R\n", b->addr); 795e96a66cSDavid du Colombier return 0; 805e96a66cSDavid du Colombier } 815e96a66cSDavid du Colombier if(!vtSha1Check(score, data, n)){ 825e96a66cSDavid du Colombier uchar score2[VtScoreSize]; 835e96a66cSDavid du Colombier vtSha1(score2, data, n); 845e96a66cSDavid du Colombier fprint(2, "ventiSend: vtWrite block %#ux failed vtSha1Check %V %V\n", 855e96a66cSDavid du Colombier b->addr, score, score2); 865e96a66cSDavid du Colombier return 0; 875e96a66cSDavid du Colombier } 885e96a66cSDavid du Colombier if(!vtSync(a->z)) 895e96a66cSDavid du Colombier return 0; 905e96a66cSDavid du Colombier return 1; 915e96a66cSDavid du Colombier } 925e96a66cSDavid du Colombier 935e96a66cSDavid du Colombier /* 945e96a66cSDavid du Colombier * parameters for recursion; there are so many, 955e96a66cSDavid du Colombier * and some only change occasionally. this is 965e96a66cSDavid du Colombier * easier than spelling things out at each call. 975e96a66cSDavid du Colombier */ 985e96a66cSDavid du Colombier typedef struct Param Param; 995e96a66cSDavid du Colombier struct Param 1005e96a66cSDavid du Colombier { 1015e96a66cSDavid du Colombier /* these never change */ 1025e96a66cSDavid du Colombier uint snapEpoch; /* epoch for snapshot being archived */ 1035e96a66cSDavid du Colombier uint blockSize; 1045e96a66cSDavid du Colombier Cache *c; 1055e96a66cSDavid du Colombier Arch *a; 1065e96a66cSDavid du Colombier 1075e96a66cSDavid du Colombier /* changes on every call */ 1085e96a66cSDavid du Colombier uint depth; 1095e96a66cSDavid du Colombier 1105e96a66cSDavid du Colombier /* statistics */ 1115e96a66cSDavid du Colombier uint nfixed; 1125e96a66cSDavid du Colombier uint nsend; 1135e96a66cSDavid du Colombier uint nvisit; 1145e96a66cSDavid du Colombier uint nfailsend; 1155e96a66cSDavid du Colombier uint maxdepth; 1165e96a66cSDavid du Colombier uint nreclaim; 1175e96a66cSDavid du Colombier uint nfake; 1185e96a66cSDavid du Colombier uint nreal; 1195e96a66cSDavid du Colombier 1205e96a66cSDavid du Colombier /* these occasionally change (must save old values and put back) */ 1215e96a66cSDavid du Colombier uint dsize; 1225e96a66cSDavid du Colombier uint psize; 1235e96a66cSDavid du Colombier 1245e96a66cSDavid du Colombier /* return value; avoids using stack space */ 1255e96a66cSDavid du Colombier Label l; 1265e96a66cSDavid du Colombier uchar score[VtScoreSize]; 1275e96a66cSDavid du Colombier }; 1285e96a66cSDavid du Colombier 1295e96a66cSDavid du Colombier static void 1305e96a66cSDavid du Colombier shaBlock(uchar score[VtScoreSize], Block *b, uchar *data, uint bsize) 1315e96a66cSDavid du Colombier { 1325e96a66cSDavid du Colombier vtSha1(score, data, vtZeroTruncate(vtType[b->l.type], data, bsize)); 1335e96a66cSDavid du Colombier } 1345e96a66cSDavid du Colombier 1355e96a66cSDavid du Colombier static uint 1365e96a66cSDavid du Colombier etype(Entry *e) 1375e96a66cSDavid du Colombier { 1385e96a66cSDavid du Colombier uint t; 1395e96a66cSDavid du Colombier 1405e96a66cSDavid du Colombier if(e->flags&VtEntryDir) 1415e96a66cSDavid du Colombier t = BtDir; 1425e96a66cSDavid du Colombier else 1435e96a66cSDavid du Colombier t = BtData; 1445e96a66cSDavid du Colombier return t+e->depth; 1455e96a66cSDavid du Colombier } 1465e96a66cSDavid du Colombier 1475e96a66cSDavid du Colombier static uchar* 1485e96a66cSDavid du Colombier copyBlock(Block *b, u32int blockSize) 1495e96a66cSDavid du Colombier { 1505e96a66cSDavid du Colombier uchar *data; 1515e96a66cSDavid du Colombier 1525e96a66cSDavid du Colombier data = vtMemAlloc(blockSize); 1535e96a66cSDavid du Colombier if(data == nil) 1545e96a66cSDavid du Colombier return nil; 1555e96a66cSDavid du Colombier memmove(data, b->data, blockSize); 1565e96a66cSDavid du Colombier return data; 1575e96a66cSDavid du Colombier } 1585e96a66cSDavid du Colombier 1595e96a66cSDavid du Colombier /* 1605e96a66cSDavid du Colombier * Walk over the block tree, archiving it to Venti. 1615e96a66cSDavid du Colombier * 1625e96a66cSDavid du Colombier * We don't archive the snapshots. Instead we zero the 1635e96a66cSDavid du Colombier * entries in a temporary copy and archive that. 1645e96a66cSDavid du Colombier * 1655e96a66cSDavid du Colombier * Return value is: 1665e96a66cSDavid du Colombier * 1675e96a66cSDavid du Colombier * ArchFailure some error occurred 1685e96a66cSDavid du Colombier * ArchSuccess block and all children archived 1695e96a66cSDavid du Colombier * ArchFaked success, but block or children got copied 1705e96a66cSDavid du Colombier */ 1715e96a66cSDavid du Colombier enum 1725e96a66cSDavid du Colombier { 1735e96a66cSDavid du Colombier ArchFailure, 1745e96a66cSDavid du Colombier ArchSuccess, 1755e96a66cSDavid du Colombier ArchFaked, 1765e96a66cSDavid du Colombier }; 1775e96a66cSDavid du Colombier static int 1785e96a66cSDavid du Colombier archWalk(Param *p, u32int addr, uchar type, u32int tag) 1795e96a66cSDavid du Colombier { 1805e96a66cSDavid du Colombier int ret, i, x, psize, dsize; 1815e96a66cSDavid du Colombier uchar *data, score[VtScoreSize]; 1825e96a66cSDavid du Colombier Block *b; 1835e96a66cSDavid du Colombier Label l; 1845e96a66cSDavid du Colombier Entry *e; 1855e96a66cSDavid du Colombier WalkPtr w; 1865e96a66cSDavid du Colombier 1875e96a66cSDavid du Colombier p->nvisit++; 1885e96a66cSDavid du Colombier 1895e96a66cSDavid du Colombier b = cacheLocalData(p->c, addr, type, tag, OReadWrite,0); 1905e96a66cSDavid du Colombier if(b == nil){ 1915e96a66cSDavid du Colombier fprint(2, "archive(%ud, %#ux): cannot find block: %R\n", p->snapEpoch, addr); 1925e96a66cSDavid du Colombier if(strcmp(vtGetError(), ELabelMismatch) == 0){ 1935e96a66cSDavid du Colombier /* might as well plod on so we write _something_ to Venti */ 1945e96a66cSDavid du Colombier memmove(p->score, vtZeroScore, VtScoreSize); 1955e96a66cSDavid du Colombier return ArchFaked; 1965e96a66cSDavid du Colombier } 1975e96a66cSDavid du Colombier return ArchFailure; 1985e96a66cSDavid du Colombier } 1995e96a66cSDavid du Colombier 2005e96a66cSDavid du Colombier if(DEBUG) fprint(2, "%*sarchive(%ud, %#ux): block label %L\n", 2015e96a66cSDavid du Colombier p->depth*2, "", p->snapEpoch, b->addr, &b->l); 2025e96a66cSDavid du Colombier p->depth++; 2035e96a66cSDavid du Colombier if(p->depth > p->maxdepth) 2045e96a66cSDavid du Colombier p->maxdepth = p->depth; 2055e96a66cSDavid du Colombier 2065e96a66cSDavid du Colombier data = b->data; 2075e96a66cSDavid du Colombier if((b->l.state&BsVenti) == 0){ 2085e96a66cSDavid du Colombier initWalk(&w, b, b->l.type==BtDir ? p->dsize : p->psize); 2095e96a66cSDavid du Colombier for(i=0; nextWalk(&w, score, &type, &tag, &e); i++){ 2105e96a66cSDavid du Colombier if(e){ 2115e96a66cSDavid du Colombier if(!(e->flags&VtEntryActive)) 2125e96a66cSDavid du Colombier continue; 213*fe853e23SDavid du Colombier if((e->snap && !e->archive) 214*fe853e23SDavid du Colombier || (e->flags&VtEntryNoArchive)){ 215*fe853e23SDavid du Colombier if(0) fprint(2, "snap; faking %#ux\n", b->addr); 2165e96a66cSDavid du Colombier if(data == b->data){ 2175e96a66cSDavid du Colombier data = copyBlock(b, p->blockSize); 2185e96a66cSDavid du Colombier if(data == nil){ 2195e96a66cSDavid du Colombier ret = ArchFailure; 2205e96a66cSDavid du Colombier goto Out; 2215e96a66cSDavid du Colombier } 2225e96a66cSDavid du Colombier w.data = data; 2235e96a66cSDavid du Colombier } 2245e96a66cSDavid du Colombier memmove(e->score, vtZeroScore, VtScoreSize); 2255e96a66cSDavid du Colombier e->depth = 0; 2265e96a66cSDavid du Colombier e->size = 0; 2275e96a66cSDavid du Colombier e->tag = 0; 2285e96a66cSDavid du Colombier e->flags &= ~VtEntryLocal; 2295e96a66cSDavid du Colombier entryPack(e, data, w.n-1); 2305e96a66cSDavid du Colombier continue; 2315e96a66cSDavid du Colombier } 2325e96a66cSDavid du Colombier } 2335e96a66cSDavid du Colombier addr = globalToLocal(score); 2345e96a66cSDavid du Colombier if(addr == NilBlock) 2355e96a66cSDavid du Colombier continue; 2365e96a66cSDavid du Colombier dsize = p->dsize; 2375e96a66cSDavid du Colombier psize = p->psize; 2385e96a66cSDavid du Colombier if(e){ 2395e96a66cSDavid du Colombier p->dsize= e->dsize; 2405e96a66cSDavid du Colombier p->psize = e->psize; 2415e96a66cSDavid du Colombier } 2425e96a66cSDavid du Colombier vtUnlock(b->lk); 2435e96a66cSDavid du Colombier x = archWalk(p, addr, type, tag); 2445e96a66cSDavid du Colombier vtLock(b->lk); 2455e96a66cSDavid du Colombier if(e){ 2465e96a66cSDavid du Colombier p->dsize = dsize; 2475e96a66cSDavid du Colombier p->psize = psize; 2485e96a66cSDavid du Colombier } 2495e96a66cSDavid du Colombier while(b->iostate != BioClean && b->iostate != BioDirty) 2505e96a66cSDavid du Colombier vtSleep(b->ioready); 2515e96a66cSDavid du Colombier switch(x){ 2525e96a66cSDavid du Colombier case ArchFailure: 2535e96a66cSDavid du Colombier fprint(2, "archWalk %#ux failed; ptr is in %#ux offset %d\n", 2545e96a66cSDavid du Colombier addr, b->addr, i); 2555e96a66cSDavid du Colombier ret = ArchFailure; 2565e96a66cSDavid du Colombier goto Out; 2575e96a66cSDavid du Colombier case ArchFaked: 258*fe853e23SDavid du Colombier /* 259*fe853e23SDavid du Colombier * When we're writing the entry for an archive directory 260*fe853e23SDavid du Colombier * (like /archive/2003/1215) then even if we've faked 261*fe853e23SDavid du Colombier * any data, record the score unconditionally. 262*fe853e23SDavid du Colombier * This way, we will always record the Venti score here. 263*fe853e23SDavid du Colombier * Otherwise, temporary data or corrupted file system 264*fe853e23SDavid du Colombier * would cause us to keep holding onto the on-disk 265*fe853e23SDavid du Colombier * copy of the archive. 266*fe853e23SDavid du Colombier */ 267*fe853e23SDavid du Colombier if(e==nil || !e->archive) 2685e96a66cSDavid du Colombier if(data == b->data){ 269*fe853e23SDavid du Colombier if(0) fprint(2, "faked %#ux, faking %#ux (%V)\n", addr, b->addr, p->score); 2705e96a66cSDavid du Colombier data = copyBlock(b, p->blockSize); 2715e96a66cSDavid du Colombier if(data == nil){ 2725e96a66cSDavid du Colombier ret = ArchFailure; 2735e96a66cSDavid du Colombier goto Out; 2745e96a66cSDavid du Colombier } 2755e96a66cSDavid du Colombier w.data = data; 2765e96a66cSDavid du Colombier } 2775e96a66cSDavid du Colombier /* fall through */ 2785e96a66cSDavid du Colombier if(0) fprint(2, "falling\n"); 2795e96a66cSDavid du Colombier case ArchSuccess: 2805e96a66cSDavid du Colombier if(e){ 2815e96a66cSDavid du Colombier memmove(e->score, p->score, VtScoreSize); 2825e96a66cSDavid du Colombier e->flags &= ~VtEntryLocal; 2835e96a66cSDavid du Colombier entryPack(e, data, w.n-1); 2845e96a66cSDavid du Colombier }else 2855e96a66cSDavid du Colombier memmove(data+(w.n-1)*VtScoreSize, p->score, VtScoreSize); 2865e96a66cSDavid du Colombier if(data == b->data){ 2875e96a66cSDavid du Colombier blockDirty(b); 2885e96a66cSDavid du Colombier if(!(b->l.state & BsCopied)) 2895e96a66cSDavid du Colombier blockRemoveLink(b, addr, p->l.type, p->l.tag); 2905e96a66cSDavid du Colombier } 2915e96a66cSDavid du Colombier break; 2925e96a66cSDavid du Colombier } 2935e96a66cSDavid du Colombier } 2945e96a66cSDavid du Colombier 2955e96a66cSDavid du Colombier if(!ventiSend(p->a, b, data)){ 2965e96a66cSDavid du Colombier p->nfailsend++; 2975e96a66cSDavid du Colombier ret = ArchFailure; 2985e96a66cSDavid du Colombier goto Out; 2995e96a66cSDavid du Colombier } 3005e96a66cSDavid du Colombier p->nsend++; 3015e96a66cSDavid du Colombier if(data != b->data) 3025e96a66cSDavid du Colombier p->nfake++; 3035e96a66cSDavid du Colombier if(data == b->data){ /* not faking it, so update state */ 3045e96a66cSDavid du Colombier p->nreal++; 3055e96a66cSDavid du Colombier l = b->l; 3065e96a66cSDavid du Colombier l.state |= BsVenti; 3075e96a66cSDavid du Colombier if(!blockSetLabel(b, &l)){ 3085e96a66cSDavid du Colombier ret = ArchFailure; 3095e96a66cSDavid du Colombier goto Out; 3105e96a66cSDavid du Colombier } 3115e96a66cSDavid du Colombier } 3125e96a66cSDavid du Colombier } 3135e96a66cSDavid du Colombier 3145e96a66cSDavid du Colombier shaBlock(p->score, b, data, p->blockSize); 3155e96a66cSDavid du Colombier if(0) fprint(2, "ventisend %V %p %p %p\n", p->score, data, b->data, w.data); 3165e96a66cSDavid du Colombier ret = data!=b->data ? ArchFaked : ArchSuccess; 3175e96a66cSDavid du Colombier p->l = b->l; 3185e96a66cSDavid du Colombier Out: 3195e96a66cSDavid du Colombier if(data != b->data) 3205e96a66cSDavid du Colombier vtMemFree(data); 3215e96a66cSDavid du Colombier p->depth--; 3225e96a66cSDavid du Colombier blockPut(b); 3235e96a66cSDavid du Colombier return ret; 3245e96a66cSDavid du Colombier } 3255e96a66cSDavid du Colombier 3265e96a66cSDavid du Colombier static void 3275e96a66cSDavid du Colombier archThread(void *v) 3285e96a66cSDavid du Colombier { 3295e96a66cSDavid du Colombier Arch *a = v; 3305e96a66cSDavid du Colombier Block *b; 3315e96a66cSDavid du Colombier Param p; 3325e96a66cSDavid du Colombier Super super; 3335e96a66cSDavid du Colombier int ret; 3345e96a66cSDavid du Colombier u32int addr; 3355e96a66cSDavid du Colombier uchar rbuf[VtRootSize]; 3365e96a66cSDavid du Colombier VtRoot root; 3375e96a66cSDavid du Colombier 3385e96a66cSDavid du Colombier vtThreadSetName("arch"); 3395e96a66cSDavid du Colombier 3405e96a66cSDavid du Colombier for(;;){ 3415e96a66cSDavid du Colombier /* look for work */ 3425e96a66cSDavid du Colombier vtLock(a->fs->elk); 3435e96a66cSDavid du Colombier b = superGet(a->c, &super); 3445e96a66cSDavid du Colombier if(b == nil){ 3455e96a66cSDavid du Colombier vtUnlock(a->fs->elk); 3465e96a66cSDavid du Colombier fprint(2, "archThread: superGet: %R"); 3475e96a66cSDavid du Colombier sleep(60*1000); 3485e96a66cSDavid du Colombier continue; 3495e96a66cSDavid du Colombier } 3505e96a66cSDavid du Colombier addr = super.next; 3515e96a66cSDavid du Colombier if(addr != NilBlock && super.current == NilBlock){ 3525e96a66cSDavid du Colombier super.current = addr; 3535e96a66cSDavid du Colombier super.next = NilBlock; 3545e96a66cSDavid du Colombier superPack(&super, b->data); 3555e96a66cSDavid du Colombier blockDirty(b); 3565e96a66cSDavid du Colombier }else 3575e96a66cSDavid du Colombier addr = super.current; 3585e96a66cSDavid du Colombier blockPut(b); 3595e96a66cSDavid du Colombier vtUnlock(a->fs->elk); 3605e96a66cSDavid du Colombier 3615e96a66cSDavid du Colombier if(addr == NilBlock){ 3625e96a66cSDavid du Colombier /* wait for work */ 3635e96a66cSDavid du Colombier vtLock(a->lk); 3645e96a66cSDavid du Colombier vtSleep(a->starve); 3655e96a66cSDavid du Colombier if(a->die != nil) 3665e96a66cSDavid du Colombier goto Done; 3675e96a66cSDavid du Colombier vtUnlock(a->lk); 3685e96a66cSDavid du Colombier continue; 3695e96a66cSDavid du Colombier } 3705e96a66cSDavid du Colombier 3715e96a66cSDavid du Colombier sleep(10*1000); /* window of opportunity to provoke races */ 3725e96a66cSDavid du Colombier 3735e96a66cSDavid du Colombier /* do work */ 3745e96a66cSDavid du Colombier memset(&p, 0, sizeof p); 3755e96a66cSDavid du Colombier p.blockSize = a->blockSize; 3765e96a66cSDavid du Colombier p.dsize = 3*VtEntrySize; /* root has three Entries */ 3775e96a66cSDavid du Colombier p.c = a->c; 3785e96a66cSDavid du Colombier p.a = a; 3795e96a66cSDavid du Colombier 3805e96a66cSDavid du Colombier ret = archWalk(&p, addr, BtDir, RootTag); 3815e96a66cSDavid du Colombier switch(ret){ 3825e96a66cSDavid du Colombier default: 3835e96a66cSDavid du Colombier abort(); 3845e96a66cSDavid du Colombier case ArchFailure: 3855e96a66cSDavid du Colombier fprint(2, "archiveBlock %#ux: %R\n", addr); 3865e96a66cSDavid du Colombier sleep(60*1000); 3875e96a66cSDavid du Colombier continue; 3885e96a66cSDavid du Colombier case ArchSuccess: 3895e96a66cSDavid du Colombier case ArchFaked: 3905e96a66cSDavid du Colombier break; 3915e96a66cSDavid du Colombier } 3925e96a66cSDavid du Colombier 3935e96a66cSDavid du Colombier if(0) fprint(2, "archiveSnapshot 0x%#ux: maxdepth %ud nfixed %ud" 3945e96a66cSDavid du Colombier " send %ud nfailsend %ud nvisit %ud" 3955e96a66cSDavid du Colombier " nreclaim %ud nfake %ud nreal %ud\n", 3965e96a66cSDavid du Colombier addr, p.maxdepth, p.nfixed, 3975e96a66cSDavid du Colombier p.nsend, p.nfailsend, p.nvisit, 3985e96a66cSDavid du Colombier p.nreclaim, p.nfake, p.nreal); 3995e96a66cSDavid du Colombier if(0) fprint(2, "archiveBlock %V (%ud)\n", p.score, p.blockSize); 4005e96a66cSDavid du Colombier 4015e96a66cSDavid du Colombier /* tie up vac root */ 4025e96a66cSDavid du Colombier memset(&root, 0, sizeof root); 4035e96a66cSDavid du Colombier root.version = VtRootVersion; 40434e04225SDavid du Colombier strecpy(root.type, root.type+sizeof root.type, "vac"); 4055e96a66cSDavid du Colombier strecpy(root.name, root.name+sizeof root.name, "fossil"); 4065e96a66cSDavid du Colombier memmove(root.score, p.score, VtScoreSize); 4075e96a66cSDavid du Colombier memmove(root.prev, super.last, VtScoreSize); 4085e96a66cSDavid du Colombier root.blockSize = a->blockSize; 4095e96a66cSDavid du Colombier vtRootPack(&root, rbuf); 4105e96a66cSDavid du Colombier if(!vtWrite(a->z, p.score, VtRootType, rbuf, VtRootSize) 4115e96a66cSDavid du Colombier || !vtSha1Check(p.score, rbuf, VtRootSize)){ 4125e96a66cSDavid du Colombier fprint(2, "vtWriteBlock %#ux: %R\n", addr); 4135e96a66cSDavid du Colombier sleep(60*1000); 4145e96a66cSDavid du Colombier continue; 4155e96a66cSDavid du Colombier } 4165e96a66cSDavid du Colombier 4175e96a66cSDavid du Colombier /* record success */ 4185e96a66cSDavid du Colombier vtLock(a->fs->elk); 4195e96a66cSDavid du Colombier b = superGet(a->c, &super); 4205e96a66cSDavid du Colombier if(b == nil){ 4215e96a66cSDavid du Colombier vtUnlock(a->fs->elk); 4225e96a66cSDavid du Colombier fprint(2, "archThread: superGet: %R"); 4235e96a66cSDavid du Colombier sleep(60*1000); 4245e96a66cSDavid du Colombier continue; 4255e96a66cSDavid du Colombier } 4265e96a66cSDavid du Colombier super.current = NilBlock; 4275e96a66cSDavid du Colombier memmove(super.last, p.score, VtScoreSize); 4285e96a66cSDavid du Colombier superPack(&super, b->data); 4295e96a66cSDavid du Colombier blockDirty(b); 4305e96a66cSDavid du Colombier blockPut(b); 4315e96a66cSDavid du Colombier vtUnlock(a->fs->elk); 4325e96a66cSDavid du Colombier 4335e96a66cSDavid du Colombier consPrint("archive vac:%V\n", p.score); 4345e96a66cSDavid du Colombier } 4355e96a66cSDavid du Colombier 4365e96a66cSDavid du Colombier Done: 4375e96a66cSDavid du Colombier a->ref--; 4385e96a66cSDavid du Colombier vtWakeup(a->die); 4395e96a66cSDavid du Colombier vtUnlock(a->lk); 4405e96a66cSDavid du Colombier } 4415e96a66cSDavid du Colombier 4425e96a66cSDavid du Colombier void 4435e96a66cSDavid du Colombier archKick(Arch *a) 4445e96a66cSDavid du Colombier { 4455e96a66cSDavid du Colombier if(a == nil){ 4465e96a66cSDavid du Colombier fprint(2, "warning: archKick nil\n"); 4475e96a66cSDavid du Colombier return; 4485e96a66cSDavid du Colombier } 4495e96a66cSDavid du Colombier vtLock(a->lk); 4505e96a66cSDavid du Colombier vtWakeup(a->starve); 4515e96a66cSDavid du Colombier vtUnlock(a->lk); 4525e96a66cSDavid du Colombier } 453