aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/venti/srv/syncarena.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/venti/srv/syncarena.c')
-rw-r--r--src/cmd/venti/srv/syncarena.c174
1 files changed, 174 insertions, 0 deletions
diff --git a/src/cmd/venti/srv/syncarena.c b/src/cmd/venti/srv/syncarena.c
new file mode 100644
index 00000000..d11ca4f3
--- /dev/null
+++ b/src/cmd/venti/srv/syncarena.c
@@ -0,0 +1,174 @@
+#include "stdinc.h"
+#include "dat.h"
+#include "fns.h"
+
+static int writeclumphead(Arena *arena, u64int aa, Clump *cl);
+static int writeclumpmagic(Arena *arena, u64int aa, u32int 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, u64int start, u32int n, int zok, int fix)
+{
+ ZBlock *lump;
+ Clump cl;
+ ClumpInfo ci;
+ static ClumpInfo zci = { .type = -1 };
+ u8int score[VtScoreSize];
+ u64int uncsize, used, aa;
+ u32int clump, clumps, cclumps, magic;
+ int err, flush, broken;
+ AState as;
+
+ 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, "can't write corrected clump free magic: %r");
+ 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;
+ err |= SyncDataErr;
+ }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;
+ if(start && (err&SyncHeader)){
+ trace(TraceProc, "syncarena setdcachestate");
+ as.arena = arena;
+ as.aa = start+arena->memstats.used;
+ as.stats = arena->memstats;
+ setdcachestate(&as);
+ }
+
+ return err;
+}
+
+static int
+writeclumphead(Arena *arena, u64int 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, u64int aa, u32int magic)
+{
+ u8int buf[U32Size];
+
+ packmagic(magic, buf);
+ return writearena(arena, aa, buf, U32Size) == U32Size;
+}