/* * Some of this logic is duplicated in hdisk.c */ Packet* readlump(u8int *score, int type, u32int size, int *cached) { Lump *u; Packet *p; IAddr ia; u32int n; trace(TraceLump, "readlump enter"); /* qlock(&stats.lock); stats.lumpreads++; qunlock(&stats.lock); */ if(scorecmp(score, zeroscore) == 0) return packetalloc(); u = lookuplump(score, type); if(u->data != nil){ trace(TraceLump, "readlump lookuplump hit"); if(cached) *cached = 1; n = packetsize(u->data); if(n > size){ seterr(EOk, "read too small: asked for %d need at least %d", size, n); putlump(u); return nil; } p = packetdup(u->data, 0, n); putlump(u); return p; } if(cached) *cached = 0; if(lookupscore(score, type, &ia) < 0){ /* ZZZ place to check for someone trying to guess scores */ seterr(EOk, "no block with score %V/%d exists", score, type); putlump(u); return nil; } if(ia.size > size){ seterr(EOk, "read too small 1: asked for %d need at least %d", size, ia.size); putlump(u); return nil; } trace(TraceLump, "readlump readilump"); p = readilump(u, &ia, score); putlump(u); trace(TraceLump, "readlump exit"); return p; }
/* * save away a lump, and return it's score. * doesn't store duplicates, but checks that the data is really the same. */ int writelump(Packet *p, u8int *score, int type, u32int creator, uint ms) { Lump *u; int ok; /* qlock(&stats.lock); stats.lumpwrites++; qunlock(&stats.lock); */ packetsha1(p, score); if(packetsize(p) == 0 || writestodevnull==1){ packetfree(p); return 0; } u = lookuplump(score, type); if(u->data != nil){ ok = 0; if(packetcmp(p, u->data) != 0){ uchar nscore[VtScoreSize]; packetsha1(u->data, nscore); if(scorecmp(u->score, score) != 0) seterr(EStrange, "lookuplump returned bad score %V not %V", u->score, score); else if(scorecmp(u->score, nscore) != 0) seterr(EStrange, "lookuplump returned bad data %V not %V", nscore, u->score); else seterr(EStrange, "score collision %V", score); ok = -1; } packetfree(p); putlump(u); return ok; } if(writestodevnull==2){ packetfree(p); return 0; } if(queuewrites) return queuewrite(u, p, creator, ms); ok = writeqlump(u, p, creator, ms); putlump(u); return ok; }
static void queueproc(void *vq) { LumpQueue *q; Lump *u; Packet *p; int creator; uint ms; threadsetname("queueproc"); q = vq; for(;;){ qlock(&q->lock); while(q->w == q->r){ trace(TraceProc, "queueproc sleep empty"); rsleep(&q->empty); } u = q->q[q->r].u; p = q->q[q->r].p; creator = q->q[q->r].creator; ms = q->q[q->r].ms; q->r = (q->r + 1) & (MaxLumpQ - 1); trace(TraceProc, "queueproc wakeup flush"); rwakeupall(&q->flush); trace(TraceProc, "queueproc wakeup full"); rwakeup(&q->full); qunlock(&q->lock); trace(TraceProc, "queueproc writelump %V", u->score); if(writeqlump(u, p, creator, ms) < 0) fprint(2, "failed to write lump for %V: %r", u->score); trace(TraceProc, "queueproc wrotelump %V", u->score); putlump(u); } }
static void debugread(HConnect *c, u8int *score) { int type; Lump *u; IAddr ia; IEntry ie; int i; Arena *arena; u64int aa; ZBlock *zb; Clump cl; vlong off; u8int sc[VtScoreSize]; if(scorecmp(score, zeroscore) == 0){ hprint(&c->hout, "zero score\n"); return; } hprint(&c->hout, "<h2>index search %V</h2><pre>\n", score); if(icachelookup(score, -1, &ia) < 0) hprint(&c->hout, " icache: not found\n"); else hprint(&c->hout, " icache: addr=%#llx size=%d type=%d blocks=%d\n", ia.addr, ia.size, ia.type, ia.blocks); if(loadientry(mainindex, score, -1, &ie) < 0) hprint(&c->hout, " idisk: not found\n"); else hprint(&c->hout, " idisk: addr=%#llx size=%d type=%d blocks=%d\n", ie.ia.addr, ie.ia.size, ie.ia.type, ie.ia.blocks); hprint(&c->hout, "</pre><h2>lookup %V</h2>\n", score); hprint(&c->hout, "<pre>\n"); for(type=0; type < VtMaxType; type++){ hprint(&c->hout, "%V type %d:", score, type); u = lookuplump(score, type); if(u->data != nil) hprint(&c->hout, " +cache"); else hprint(&c->hout, " -cache"); putlump(u); if(lookupscore(score, type, &ia) < 0){ hprint(&c->hout, " -lookup\n"); continue; } hprint(&c->hout, "\n lookupscore: addr=%#llx size=%d blocks=%d\n", ia.addr, ia.size, ia.blocks); arena = amapitoa(mainindex, ia.addr, &aa); if(arena == nil){ hprint(&c->hout, " amapitoa failed: %r\n"); continue; } hprint(&c->hout, " amapitoa: aa=%#llx arena=" "<a href=\"/disk?disk=%s&type=a&arena=%s&score=%V\">%s</a>\n", aa, arena->part->name, arena->name, score, arena->name); zb = loadclump(arena, aa, ia.blocks, &cl, sc, 1); if(zb == nil){ hprint(&c->hout, " loadclump failed: %r\n"); continue; } hprint(&c->hout, " loadclump: uncsize=%d type=%d score=%V\n", cl.info.uncsize, cl.info.type, sc); if(ia.size != cl.info.uncsize || ia.type != cl.info.type || scorecmp(score, sc) != 0){ hprint(&c->hout, " clump info mismatch\n"); continue; } } if(hargstr(c, "brute", "")[0] == 'y'){ hprint(&c->hout, "</pre>\n"); hprint(&c->hout, "<h2>brute force arena search %V</h2>\n", score); hprint(&c->hout, "<pre>\n"); for(i=0; i<mainindex->narenas; i++){ arena = mainindex->arenas[i]; hprint(&c->hout, "%s...\n", arena->name); hflush(&c->hout); off = findintoc(nil, arena, score); if(off >= 0) hprint(&c->hout, "%s %#llx (%#llx)\n", arena->name, off, mainindex->amap[i].start + off); } } hprint(&c->hout, "</pre>\n"); }