Blob


1 #include "stdinc.h"
2 #include "dat.h"
3 #include "fns.h"
5 static int writeclumphead(Arena *arena, u64int aa, Clump *cl);
6 static int writeclumpmagic(Arena *arena, u64int aa, u32int magic);
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 }
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;
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 }
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;
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);
109 broken = 1;
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;
119 trace(TraceProc, "syncarena unindexed clump %V %d", cl.info.score, arena->memstats.clumps);
121 arena->memstats.uncsize += cl.info.uncsize;
122 if(cl.info.size < cl.info.uncsize)
123 arena->memstats.cclumps++;
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();
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);
149 return err;
152 static int
153 writeclumphead(Arena *arena, u64int aa, Clump *cl)
155 ZBlock *zb;
156 int bad;
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;
167 static int
168 writeclumpmagic(Arena *arena, u64int aa, u32int magic)
170 u8int buf[U32Size];
172 packmagic(magic, buf);
173 return writearena(arena, aa, buf, U32Size) == U32Size;