void zeropart(Part *part, int blocksize) { ZBlock *b; uint64_t addr; int w; fprint(2, "clearing %s\n", part->name); b = alloczblock(MaxIoSize, 1, blocksize); w = 0; for(addr = PartBlank; addr + MaxIoSize <= part->size; addr += MaxIoSize){ if(writepart(part, addr, b->data, MaxIoSize) < 0) sysfatal("can't initialize %s, writing block %d failed: %r", part->name, w); w++; } for(; addr + blocksize <= part->size; addr += blocksize) if(writepart(part, addr, b->data, blocksize) < 0) sysfatal("can't initialize %s: %r", part->name); if(flushpart(part) < 0) sysfatal("can't flush writes to %s: %r", part->name); freezblock(b); }
int wbisect(ISect *is) { ZBlock *b; b = alloczblock(HeadSize, 1, 0); if(b == nil){ /* ZZZ set error? */ return -1; } if(packisect(is, b->data) < 0){ seterr(ECorrupt, "can't make index section header: %r"); freezblock(b); return -1; } if(writepart(is->part, PartBlank, b->data, HeadSize) < 0 || flushpart(is->part) < 0){ seterr(EAdmin, "can't write index section header: %r"); freezblock(b); return -1; } freezblock(b); return 0; }
int wbarenahead(Arena *arena) { ZBlock *b; ArenaHead head; int bad; namecp(head.name, arena->name); head.version = arena->version; head.size = arena->size + 2 * arena->blocksize; head.blocksize = arena->blocksize; head.clumpmagic = arena->clumpmagic; b = alloczblock(arena->blocksize, 1, arena->part->blocksize); if(b == nil){ logerr(EAdmin, "can't write arena header: %r"); /* ZZZ add error message? */ return -1; } /* * this writepart is okay because it only happens * during initialization. */ bad = packarenahead(&head, b->data)<0 || writepart(arena->part, arena->base - arena->blocksize, b->data, arena->blocksize)<0 || flushpart(arena->part)<0; freezblock(b); if(bad) return -1; return 0; }
int writebloom(Bloom *b) { wbbloomhead(b); if(writepart(b->part, 0, b->data, b->size) < 0) return -1; if(flushpart(b->part) < 0) return -1; return 0; }
static void pageout(void) { if(buflen==0 || !fix || memcmp(buf, sbuf, buflen) == 0){ buflen = 0; return; } if(writepart(part, bufoffset, buf, buflen) < 0) print("disk write failed at %#llux+%#ux (%,lld+%,d)\n", bufoffset, buflen, bufoffset, buflen); buflen = 0; }
/* * sort from bucket b of ib into the output file to */ static uint32_t sortiebuck(IEBucks *ib, int b) { uint32_t n; n = readiebuck(ib, b); if(n == TWID32) return TWID32; qsort(ib->buf, n, IEntrySize, ientrycmp); if(writepart(ib->part, ib->off, ib->buf, n*IEntrySize) < 0){ seterr(EOk, "can't write sorted bucket: %r"); return TWID32; } ib->off += n * IEntrySize; return n; }
Arena* newarena(Part *part, uint32_t vers, char *name, uint64_t base, uint64_t size, uint32_t blocksize) { int bsize; Arena *arena; if(nameok(name) < 0){ seterr(EOk, "illegal arena name", name); return nil; } arena = MKZ(Arena); arena->part = part; arena->version = vers; if(vers == ArenaVersion4) arena->clumpmagic = _ClumpMagic; else{ do arena->clumpmagic = fastrand(); while(arena->clumpmagic==_ClumpMagic || arena->clumpmagic==0); } arena->blocksize = blocksize; arena->clumpmax = arena->blocksize / ClumpInfoSize; arena->base = base + blocksize; arena->size = size - 2 * blocksize; namecp(arena->name, name); bsize = sizeof zero; if(bsize > arena->blocksize) bsize = arena->blocksize; if(wbarena(arena)<0 || wbarenahead(arena)<0 || writepart(arena->part, arena->base, zero, bsize)<0){ freearena(arena); return nil; } return arena; }
/* * write out a single bucket */ static int flushiebuck(IEBucks *ib, int b, int reset) { uint32_t n; if(ib->bucks[b].used == 0) return 0; n = ib->bucks[b].used; U32PUT(&ib->bucks[b].buf[n], ib->bucks[b].head); n += U32Size; USED(n); if(writepart(ib->part, (uint64_t)ib->chunks * ib->size, ib->bucks[b].buf, ib->size) < 0){ seterr(EOk, "can't write sorting bucket to file: %r"); xabort(); return -1; } ib->bucks[b].head = ib->chunks++; ib->bucks[b].total += ib->bucks[b].used; if(reset) ib->bucks[b].used = 0; return 0; }
int wbindex(Index *ix) { Fmt f; ZBlock *b; int i; if(ix->nsects == 0){ seterr(EOk, "no sections in index %s", ix->name); return -1; } b = alloczblock(ix->tabsize, 1, ix->blocksize); if(b == nil){ seterr(EOk, "can't write index configuration: out of memory"); return -1; } fmtzbinit(&f, b); if(outputindex(&f, ix) < 0){ seterr(EOk, "can't make index configuration: table storage too small %d", ix->tabsize); freezblock(b); return -1; } for(i = 0; i < ix->nsects; i++){ if(writepart(ix->sects[i]->part, ix->sects[i]->tabbase, b->data, ix->tabsize) < 0 || flushpart(ix->sects[i]->part) < 0){ seterr(EOk, "can't write index: %r"); freezblock(b); return -1; } } freezblock(b); for(i = 0; i < ix->nsects; i++) if(wbisect(ix->sects[i]) < 0) return -1; return 0; }
static int icachewritesect(Index *ix, ISect *is, u8int *buf) { int err, i, werr, h, bsize, t; u32int lo, hi; u64int addr, naddr; uint nbuf, off; DBlock *b; IBucket ib; IEntry *ie, *iedirty, **l, *chunk; lo = is->start * ix->div; if(TWID32/ix->div < is->stop) hi = TWID32; else hi = is->stop * ix->div - 1; trace(TraceProc, "icachewritesect enter %ud %ud %llud", lo, hi, iwrite.as.aa); iedirty = icachedirty(lo, hi, iwrite.as.aa); iedirty = iesort(iedirty); bsize = 1 << is->blocklog; err = 0; while(iedirty){ disksched(); while((t = icachesleeptime) == SleepForever){ sleep(1000); disksched(); } if(t < minicachesleeptime) t = minicachesleeptime; if(t > 0) sleep(t); trace(TraceProc, "icachewritesect nextchunk"); chunk = nextchunk(ix, is, &iedirty, &addr, &nbuf); trace(TraceProc, "icachewritesect readpart 0x%llux+0x%ux", addr, nbuf); if(readpart(is->part, addr, buf, nbuf) < 0){ fprint(2, "%s: part %s addr 0x%llux: icachewritesect " "readpart: %r\n", argv0, is->part->name, addr); err = -1; continue; } trace(TraceProc, "icachewritesect updatebuf"); addstat(StatIsectReadBytes, nbuf); addstat(StatIsectRead, 1); for(l=&chunk; (ie=*l)!=nil; l=&ie->nextdirty){ again: naddr = ie2diskaddr(ix, is, ie); off = naddr - addr; if(off+bsize > nbuf){ fprint(2, "%s: whoops! addr=0x%llux nbuf=%ud " "addr+nbuf=0x%llux naddr=0x%llux\n", argv0, addr, nbuf, addr+nbuf, naddr); assert(off+bsize <= nbuf); } unpackibucket(&ib, buf+off, is->bucketmagic); if(okibucket(&ib, is) < 0){ fprint(2, "%s: bad bucket XXX\n", argv0); goto skipit; } trace(TraceProc, "icachewritesect add %V at 0x%llux", ie->score, naddr); h = bucklook(ie->score, ie->ia.type, ib.data, ib.n); if(h & 1){ h ^= 1; packientry(ie, &ib.data[h]); }else if(ib.n < is->buckmax){ memmove(&ib.data[h + IEntrySize], &ib.data[h], ib.n*IEntrySize - h); ib.n++; packientry(ie, &ib.data[h]); }else{ fprint(2, "%s: bucket overflow XXX\n", argv0); skipit: err = -1; *l = ie->nextdirty; ie = *l; if(ie) goto again; else break; } packibucket(&ib, buf+off, is->bucketmagic); } diskaccess(1); trace(TraceProc, "icachewritesect writepart", addr, nbuf); werr = 0; if(writepart(is->part, addr, buf, nbuf) < 0 || flushpart(is->part) < 0) werr = -1; for(i=0; i<nbuf; i+=bsize){ if((b = _getdblock(is->part, addr+i, ORDWR, 0)) != nil){ memmove(b->data, buf+i, bsize); putdblock(b); } } if(werr < 0){ fprint(2, "%s: part %s addr 0x%llux: icachewritesect " "writepart: %r\n", argv0, is->part->name, addr); err = -1; continue; } addstat(StatIsectWriteBytes, nbuf); addstat(StatIsectWrite, 1); icacheclean(chunk); } trace(TraceProc, "icachewritesect done"); return err; }