]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/venti/srv/syncarena.c
Import sources from 2011-03-30 iso image - lib
[plan9front.git] / sys / src / cmd / venti / srv / syncarena.c
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 }