123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- /*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
- #include "stdinc.h"
- #include "dat.h"
- #include "fns.h"
- static int writeclumphead(Arena *arena, uint64_t aa, Clump *cl);
- static int writeclumpmagic(Arena *arena, uint64_t aa, uint32_t magic);
- int
- clumpinfocmp(ClumpInfo *c, ClumpInfo *d)
- {
- return c->type != d->type
- || c->size != d->size
- || c->uncsize != d->uncsize
- || scorecmp(c->score, d->score)!=0;
- }
- /*
- * synchronize the clump info directory with
- * with the clumps actually stored in the arena.
- * the directory should be at least as up to date
- * as the arena's trailer.
- *
- * checks/updates at most n clumps.
- *
- * returns 0 if ok, flags if error occurred
- */
- int
- syncarena(Arena *arena, uint32_t n, int zok, int fix)
- {
- ZBlock *lump;
- Clump cl;
- ClumpInfo ci;
- static ClumpInfo zci = { .type = -1 };
- uint8_t score[VtScoreSize];
- uint64_t uncsize, used, aa;
- uint32_t clump, clumps, cclumps, magic;
- int err, flush, broken;
- used = arena->memstats.used;
- clumps = arena->memstats.clumps;
- cclumps = arena->memstats.cclumps;
- uncsize = arena->memstats.uncsize;
- trace(TraceProc, "syncarena start");
- flush = 0;
- err = 0;
- for(; n; n--){
- aa = arena->memstats.used;
- clump = arena->memstats.clumps;
- magic = clumpmagic(arena, aa);
- if(magic == ClumpFreeMagic)
- break;
- if(magic != arena->clumpmagic){
- fprint(2, "%s: illegal clump magic number=%#8.8ux at clump=%d\n", arena->name, magic, clump);
- /* err |= SyncDataErr; */
- if(fix && writeclumpmagic(arena, aa, ClumpFreeMagic) < 0){
- fprint(2, "%s: can't write corrected clump free magic: %r", arena->name);
- err |= SyncFixErr;
- }
- break;
- }
- broken = 0;
- lump = loadclump(arena, aa, 0, &cl, score, 0);
- if(lump == nil){
- fprint(2, "%s: clump=%d failed to read correctly: %r\n", arena->name, clump);
- break;
- }else if(cl.info.type != VtCorruptType){
- scoremem(score, lump->data, cl.info.uncsize);
- if(scorecmp(cl.info.score, score) != 0){
- /* ignore partially written block */
- if(cl.encoding == ClumpENone)
- break;
- fprint(2, "%s: clump=%d has mismatched score\n", arena->name, clump);
- err |= SyncDataErr;
- broken = 1;
- }else if(vttypevalid(cl.info.type) < 0){
- fprint(2, "%s: clump=%d has invalid type %d", arena->name, clump, cl.info.type);
- err |= SyncDataErr;
- broken = 1;
- }
- if(broken && fix){
- cl.info.type = VtCorruptType;
- if(writeclumphead(arena, aa, &cl) < 0){
- fprint(2, "%s: can't write corrected clump header: %r", arena->name);
- err |= SyncFixErr;
- }
- }
- }
- freezblock(lump);
- arena->memstats.used += ClumpSize + cl.info.size;
- arena->memstats.clumps++;
- if(!broken && readclumpinfo(arena, clump, &ci)<0){
- fprint(2, "%s: arena directory read failed\n", arena->name);
- broken = 1;
- }else if(!broken && clumpinfocmp(&ci, &cl.info)!=0){
- if(clumpinfocmp(&ci, &zci) == 0){
- err |= SyncCIZero;
- if(!zok)
- fprint(2, "%s: unwritten clump info for clump=%d\n", arena->name, clump);
- }else{
- err |= SyncCIErr;
- fprint(2, "%s: bad clump info for clump=%d\n", arena->name, clump);
- fprint(2, "\texpected score=%V type=%d size=%d uncsize=%d\n",
- cl.info.score, cl.info.type, cl.info.size, cl.info.uncsize);
- fprint(2, "\tfound score=%V type=%d size=%d uncsize=%d\n",
- ci.score, ci.type, ci.size, ci.uncsize);
- }
- broken = 1;
- }
- if(broken && fix){
- flush = 1;
- ci = cl.info;
- if(writeclumpinfo(arena, clump, &ci) < 0){
- fprint(2, "%s: can't write correct clump directory: %r\n", arena->name);
- err |= SyncFixErr;
- }
- }
- trace(TraceProc, "syncarena unindexed clump %V %d", cl.info.score, arena->memstats.clumps);
- arena->memstats.uncsize += cl.info.uncsize;
- if(cl.info.size < cl.info.uncsize)
- arena->memstats.cclumps++;
- }
- if(flush){
- trace(TraceProc, "syncarena flush");
- arena->wtime = now();
- if(arena->ctime == 0 && arena->memstats.clumps)
- arena->ctime = arena->wtime;
- flushdcache();
- }
- if(used != arena->memstats.used
- || clumps != arena->memstats.clumps
- || cclumps != arena->memstats.cclumps
- || uncsize != arena->memstats.uncsize){
- err |= SyncHeader;
- fprint(2, "arena %s: fix=%d flush=%d %lld->%lld %ud->%ud %ud->%ud %lld->%lld\n",
- arena->name,
- fix,
- flush,
- used, arena->memstats.used,
- clumps, arena->memstats.clumps,
- cclumps, arena->memstats.cclumps,
- uncsize, arena->memstats.uncsize);
- }
- return err;
- }
- static int
- writeclumphead(Arena *arena, uint64_t aa, Clump *cl)
- {
- ZBlock *zb;
- int bad;
- zb = alloczblock(ClumpSize, 0, arena->blocksize);
- if(zb == nil)
- return -1;
- bad = packclump(cl, zb->data, arena->clumpmagic)<0
- || writearena(arena, aa, zb->data, ClumpSize) != ClumpSize;
- freezblock(zb);
- return bad ? -1 : 0;
- }
- static int
- writeclumpmagic(Arena *arena, uint64_t aa, uint32_t magic)
- {
- uint8_t buf[U32Size];
- packmagic(magic, buf);
- return writearena(arena, aa, buf, U32Size) == U32Size;
- }
|