syncarena.c (4816B)
1 #include "stdinc.h" 2 #include "dat.h" 3 #include "fns.h" 4 5 static int writeclumphead(Arena *arena, u64int aa, Clump *cl); 6 static int writeclumpmagic(Arena *arena, u64int aa, u32int magic); 7 8 int 9 clumpinfocmp(ClumpInfo *c, ClumpInfo *d) 10 { 11 return c->type != d->type 12 || c->size != d->size 13 || c->uncsize != d->uncsize 14 || scorecmp(c->score, d->score)!=0; 15 } 16 17 /* 18 * synchronize the clump info directory with 19 * with the clumps actually stored in the arena. 20 * the directory should be at least as up to date 21 * as the arena's trailer. 22 * 23 * checks/updates at most n clumps. 24 * 25 * returns 0 if ok, flags if error occurred 26 */ 27 int 28 syncarena(Arena *arena, u32int n, int zok, int fix) 29 { 30 ZBlock *lump; 31 Clump cl; 32 ClumpInfo ci; 33 static ClumpInfo zci = { .type = -1 }; 34 u8int score[VtScoreSize]; 35 u64int uncsize, used, aa; 36 u32int clump, clumps, cclumps, magic; 37 int err, flush, broken; 38 39 used = arena->memstats.used; 40 clumps = arena->memstats.clumps; 41 cclumps = arena->memstats.cclumps; 42 uncsize = arena->memstats.uncsize; 43 trace(TraceProc, "syncarena start"); 44 flush = 0; 45 err = 0; 46 for(; n; n--){ 47 aa = arena->memstats.used; 48 clump = arena->memstats.clumps; 49 magic = clumpmagic(arena, aa); 50 if(magic == ClumpFreeMagic) 51 break; 52 if(magic != arena->clumpmagic){ 53 fprint(2, "%s: illegal clump magic number=%#8.8ux at clump=%d\n", arena->name, magic, clump); 54 /* err |= SyncDataErr; */ 55 if(fix && writeclumpmagic(arena, aa, ClumpFreeMagic) < 0){ 56 fprint(2, "%s: can't write corrected clump free magic: %r", arena->name); 57 err |= SyncFixErr; 58 } 59 break; 60 } 61 62 broken = 0; 63 lump = loadclump(arena, aa, 0, &cl, score, 0); 64 if(lump == nil){ 65 fprint(2, "%s: clump=%d failed to read correctly: %r\n", arena->name, clump); 66 break; 67 }else if(cl.info.type != VtCorruptType){ 68 scoremem(score, lump->data, cl.info.uncsize); 69 if(scorecmp(cl.info.score, score) != 0){ 70 /* ignore partially written block */ 71 if(cl.encoding == ClumpENone) 72 break; 73 fprint(2, "%s: clump=%d has mismatched score\n", arena->name, clump); 74 err |= SyncDataErr; 75 broken = 1; 76 }else if(vttypevalid(cl.info.type) < 0){ 77 fprint(2, "%s: clump=%d has invalid type %d", arena->name, clump, cl.info.type); 78 err |= SyncDataErr; 79 broken = 1; 80 } 81 if(broken && fix){ 82 cl.info.type = VtCorruptType; 83 if(writeclumphead(arena, aa, &cl) < 0){ 84 fprint(2, "%s: can't write corrected clump header: %r", arena->name); 85 err |= SyncFixErr; 86 } 87 } 88 } 89 freezblock(lump); 90 arena->memstats.used += ClumpSize + cl.info.size; 91 92 arena->memstats.clumps++; 93 if(!broken && readclumpinfo(arena, clump, &ci)<0){ 94 fprint(2, "%s: arena directory read failed\n", arena->name); 95 broken = 1; 96 }else if(!broken && clumpinfocmp(&ci, &cl.info)!=0){ 97 if(clumpinfocmp(&ci, &zci) == 0){ 98 err |= SyncCIZero; 99 if(!zok) 100 fprint(2, "%s: unwritten clump info for clump=%d\n", arena->name, clump); 101 }else{ 102 err |= SyncCIErr; 103 fprint(2, "%s: bad clump info for clump=%d\n", arena->name, clump); 104 fprint(2, "\texpected score=%V type=%d size=%d uncsize=%d\n", 105 cl.info.score, cl.info.type, cl.info.size, cl.info.uncsize); 106 fprint(2, "\tfound score=%V type=%d size=%d uncsize=%d\n", 107 ci.score, ci.type, ci.size, ci.uncsize); 108 } 109 broken = 1; 110 } 111 if(broken && fix){ 112 flush = 1; 113 ci = cl.info; 114 if(writeclumpinfo(arena, clump, &ci) < 0){ 115 fprint(2, "%s: can't write correct clump directory: %r\n", arena->name); 116 err |= SyncFixErr; 117 } 118 } 119 trace(TraceProc, "syncarena unindexed clump %V %d", cl.info.score, arena->memstats.clumps); 120 121 arena->memstats.uncsize += cl.info.uncsize; 122 if(cl.info.size < cl.info.uncsize) 123 arena->memstats.cclumps++; 124 } 125 126 if(flush){ 127 trace(TraceProc, "syncarena flush"); 128 arena->wtime = now(); 129 if(arena->ctime == 0 && arena->memstats.clumps) 130 arena->ctime = arena->wtime; 131 flushdcache(); 132 } 133 134 if(used != arena->memstats.used 135 || clumps != arena->memstats.clumps 136 || cclumps != arena->memstats.cclumps 137 || uncsize != arena->memstats.uncsize){ 138 err |= SyncHeader; 139 fprint(2, "arena %s: fix=%d flush=%d %lld->%lld %ud->%ud %ud->%ud %lld->%lld\n", 140 arena->name, 141 fix, 142 flush, 143 used, arena->memstats.used, 144 clumps, arena->memstats.clumps, 145 cclumps, arena->memstats.cclumps, 146 uncsize, arena->memstats.uncsize); 147 } 148 149 return err; 150 } 151 152 static int 153 writeclumphead(Arena *arena, u64int aa, Clump *cl) 154 { 155 ZBlock *zb; 156 int bad; 157 158 zb = alloczblock(ClumpSize, 0, arena->blocksize); 159 if(zb == nil) 160 return -1; 161 bad = packclump(cl, zb->data, arena->clumpmagic)<0 162 || writearena(arena, aa, zb->data, ClumpSize) != ClumpSize; 163 freezblock(zb); 164 return bad ? -1 : 0; 165 } 166 167 static int 168 writeclumpmagic(Arena *arena, u64int aa, u32int magic) 169 { 170 u8int buf[U32Size]; 171 172 packmagic(magic, buf); 173 return writearena(arena, aa, buf, U32Size) == U32Size; 174 }