Blame


1 6f4d00ee 2013-09-23 0intro /*
2 6f4d00ee 2013-09-23 0intro * Archiver. In charge of sending blocks to Venti.
3 6f4d00ee 2013-09-23 0intro */
4 6f4d00ee 2013-09-23 0intro
5 6f4d00ee 2013-09-23 0intro #include "stdinc.h"
6 6f4d00ee 2013-09-23 0intro #include "dat.h"
7 6f4d00ee 2013-09-23 0intro #include "fns.h"
8 6f4d00ee 2013-09-23 0intro #include "error.h"
9 6f4d00ee 2013-09-23 0intro
10 6f4d00ee 2013-09-23 0intro #include "9.h" /* for consPrint */
11 6f4d00ee 2013-09-23 0intro
12 6f4d00ee 2013-09-23 0intro #define DEBUG 0
13 6f4d00ee 2013-09-23 0intro
14 6f4d00ee 2013-09-23 0intro static void archThread(void*);
15 6f4d00ee 2013-09-23 0intro
16 6f4d00ee 2013-09-23 0intro struct Arch
17 6f4d00ee 2013-09-23 0intro {
18 6f4d00ee 2013-09-23 0intro int ref;
19 6f4d00ee 2013-09-23 0intro uint blockSize;
20 6f4d00ee 2013-09-23 0intro uint diskSize;
21 6f4d00ee 2013-09-23 0intro Cache *c;
22 6f4d00ee 2013-09-23 0intro Fs *fs;
23 4b576658 2013-09-23 0intro VtConn *z;
24 6f4d00ee 2013-09-23 0intro
25 4b576658 2013-09-23 0intro QLock lk;
26 4b576658 2013-09-23 0intro Rendez starve;
27 4b576658 2013-09-23 0intro Rendez die;
28 6f4d00ee 2013-09-23 0intro };
29 6f4d00ee 2013-09-23 0intro
30 6f4d00ee 2013-09-23 0intro Arch *
31 4b576658 2013-09-23 0intro archInit(Cache *c, Disk *disk, Fs *fs, VtConn *z)
32 6f4d00ee 2013-09-23 0intro {
33 6f4d00ee 2013-09-23 0intro Arch *a;
34 6f4d00ee 2013-09-23 0intro
35 4b576658 2013-09-23 0intro a = vtmallocz(sizeof(Arch));
36 6f4d00ee 2013-09-23 0intro
37 6f4d00ee 2013-09-23 0intro a->c = c;
38 6f4d00ee 2013-09-23 0intro a->z = z;
39 6f4d00ee 2013-09-23 0intro a->fs = fs;
40 6f4d00ee 2013-09-23 0intro a->blockSize = diskBlockSize(disk);
41 4b576658 2013-09-23 0intro a->starve.l = &a->lk;
42 6f4d00ee 2013-09-23 0intro
43 6f4d00ee 2013-09-23 0intro a->ref = 2;
44 4b576658 2013-09-23 0intro proccreate(archThread, a, STACK);
45 6f4d00ee 2013-09-23 0intro
46 6f4d00ee 2013-09-23 0intro return a;
47 6f4d00ee 2013-09-23 0intro }
48 6f4d00ee 2013-09-23 0intro
49 6f4d00ee 2013-09-23 0intro void
50 6f4d00ee 2013-09-23 0intro archFree(Arch *a)
51 6f4d00ee 2013-09-23 0intro {
52 6f4d00ee 2013-09-23 0intro /* kill slave */
53 4b576658 2013-09-23 0intro qlock(&a->lk);
54 4b576658 2013-09-23 0intro a->die.l = &a->lk;
55 4b576658 2013-09-23 0intro rwakeup(&a->starve);
56 6f4d00ee 2013-09-23 0intro while(a->ref > 1)
57 4b576658 2013-09-23 0intro rsleep(&a->die);
58 4b576658 2013-09-23 0intro qunlock(&a->lk);
59 4b576658 2013-09-23 0intro vtfree(a);
60 6f4d00ee 2013-09-23 0intro }
61 6f4d00ee 2013-09-23 0intro
62 6f4d00ee 2013-09-23 0intro static int
63 6f4d00ee 2013-09-23 0intro ventiSend(Arch *a, Block *b, uchar *data)
64 6f4d00ee 2013-09-23 0intro {
65 6f4d00ee 2013-09-23 0intro uint n;
66 6f4d00ee 2013-09-23 0intro uchar score[VtScoreSize];
67 6f4d00ee 2013-09-23 0intro
68 6f4d00ee 2013-09-23 0intro if(DEBUG > 1)
69 6f4d00ee 2013-09-23 0intro fprint(2, "ventiSend: sending %#ux %L to venti\n", b->addr, &b->l);
70 4b576658 2013-09-23 0intro n = vtzerotruncate(vtType[b->l.type], data, a->blockSize);
71 6f4d00ee 2013-09-23 0intro if(DEBUG > 1)
72 6f4d00ee 2013-09-23 0intro fprint(2, "ventiSend: truncate %d to %d\n", a->blockSize, n);
73 4b576658 2013-09-23 0intro if(vtwrite(a->z, score, vtType[b->l.type], data, n) < 0){
74 4b576658 2013-09-23 0intro fprint(2, "ventiSend: vtwrite block %#ux failed: %r\n", b->addr);
75 6f4d00ee 2013-09-23 0intro return 0;
76 6f4d00ee 2013-09-23 0intro }
77 4b576658 2013-09-23 0intro if(vtsha1check(score, data, n) < 0){
78 6f4d00ee 2013-09-23 0intro uchar score2[VtScoreSize];
79 4b576658 2013-09-23 0intro vtsha1(score2, data, n);
80 4b576658 2013-09-23 0intro fprint(2, "ventiSend: vtwrite block %#ux failed vtsha1check %V %V\n",
81 6f4d00ee 2013-09-23 0intro b->addr, score, score2);
82 6f4d00ee 2013-09-23 0intro return 0;
83 6f4d00ee 2013-09-23 0intro }
84 4b576658 2013-09-23 0intro if(vtsync(a->z) < 0)
85 6f4d00ee 2013-09-23 0intro return 0;
86 6f4d00ee 2013-09-23 0intro return 1;
87 6f4d00ee 2013-09-23 0intro }
88 6f4d00ee 2013-09-23 0intro
89 6f4d00ee 2013-09-23 0intro /*
90 6f4d00ee 2013-09-23 0intro * parameters for recursion; there are so many,
91 6f4d00ee 2013-09-23 0intro * and some only change occasionally. this is
92 6f4d00ee 2013-09-23 0intro * easier than spelling things out at each call.
93 6f4d00ee 2013-09-23 0intro */
94 6f4d00ee 2013-09-23 0intro typedef struct Param Param;
95 6f4d00ee 2013-09-23 0intro struct Param
96 6f4d00ee 2013-09-23 0intro {
97 6f4d00ee 2013-09-23 0intro /* these never change */
98 6f4d00ee 2013-09-23 0intro uint snapEpoch; /* epoch for snapshot being archived */
99 6f4d00ee 2013-09-23 0intro uint blockSize;
100 6f4d00ee 2013-09-23 0intro Cache *c;
101 6f4d00ee 2013-09-23 0intro Arch *a;
102 6f4d00ee 2013-09-23 0intro
103 6f4d00ee 2013-09-23 0intro /* changes on every call */
104 6f4d00ee 2013-09-23 0intro uint depth;
105 6f4d00ee 2013-09-23 0intro
106 6f4d00ee 2013-09-23 0intro /* statistics */
107 6f4d00ee 2013-09-23 0intro uint nfixed;
108 6f4d00ee 2013-09-23 0intro uint nsend;
109 6f4d00ee 2013-09-23 0intro uint nvisit;
110 6f4d00ee 2013-09-23 0intro uint nfailsend;
111 6f4d00ee 2013-09-23 0intro uint maxdepth;
112 6f4d00ee 2013-09-23 0intro uint nreclaim;
113 6f4d00ee 2013-09-23 0intro uint nfake;
114 6f4d00ee 2013-09-23 0intro uint nreal;
115 6f4d00ee 2013-09-23 0intro
116 6f4d00ee 2013-09-23 0intro /* these occasionally change (must save old values and put back) */
117 6f4d00ee 2013-09-23 0intro uint dsize;
118 6f4d00ee 2013-09-23 0intro uint psize;
119 6f4d00ee 2013-09-23 0intro
120 6f4d00ee 2013-09-23 0intro /* return value; avoids using stack space */
121 6f4d00ee 2013-09-23 0intro Label l;
122 6f4d00ee 2013-09-23 0intro uchar score[VtScoreSize];
123 6f4d00ee 2013-09-23 0intro };
124 6f4d00ee 2013-09-23 0intro
125 6f4d00ee 2013-09-23 0intro static void
126 6f4d00ee 2013-09-23 0intro shaBlock(uchar score[VtScoreSize], Block *b, uchar *data, uint bsize)
127 6f4d00ee 2013-09-23 0intro {
128 4b576658 2013-09-23 0intro vtsha1(score, data, vtzerotruncate(vtType[b->l.type], data, bsize));
129 6f4d00ee 2013-09-23 0intro }
130 6f4d00ee 2013-09-23 0intro
131 6f4d00ee 2013-09-23 0intro static uchar*
132 6f4d00ee 2013-09-23 0intro copyBlock(Block *b, u32int blockSize)
133 6f4d00ee 2013-09-23 0intro {
134 6f4d00ee 2013-09-23 0intro uchar *data;
135 6f4d00ee 2013-09-23 0intro
136 4b576658 2013-09-23 0intro data = vtmalloc(blockSize);
137 6f4d00ee 2013-09-23 0intro if(data == nil)
138 6f4d00ee 2013-09-23 0intro return nil;
139 6f4d00ee 2013-09-23 0intro memmove(data, b->data, blockSize);
140 6f4d00ee 2013-09-23 0intro return data;
141 6f4d00ee 2013-09-23 0intro }
142 6f4d00ee 2013-09-23 0intro
143 6f4d00ee 2013-09-23 0intro /*
144 6f4d00ee 2013-09-23 0intro * Walk over the block tree, archiving it to Venti.
145 6f4d00ee 2013-09-23 0intro *
146 6f4d00ee 2013-09-23 0intro * We don't archive the snapshots. Instead we zero the
147 6f4d00ee 2013-09-23 0intro * entries in a temporary copy of the block and archive that.
148 6f4d00ee 2013-09-23 0intro *
149 6f4d00ee 2013-09-23 0intro * Return value is:
150 6f4d00ee 2013-09-23 0intro *
151 6f4d00ee 2013-09-23 0intro * ArchFailure some error occurred
152 6f4d00ee 2013-09-23 0intro * ArchSuccess block and all children archived
153 6f4d00ee 2013-09-23 0intro * ArchFaked success, but block or children got copied
154 6f4d00ee 2013-09-23 0intro */
155 6f4d00ee 2013-09-23 0intro enum
156 6f4d00ee 2013-09-23 0intro {
157 6f4d00ee 2013-09-23 0intro ArchFailure,
158 6f4d00ee 2013-09-23 0intro ArchSuccess,
159 6f4d00ee 2013-09-23 0intro ArchFaked,
160 6f4d00ee 2013-09-23 0intro };
161 6f4d00ee 2013-09-23 0intro static int
162 6f4d00ee 2013-09-23 0intro archWalk(Param *p, u32int addr, uchar type, u32int tag)
163 6f4d00ee 2013-09-23 0intro {
164 6f4d00ee 2013-09-23 0intro int ret, i, x, psize, dsize;
165 6f4d00ee 2013-09-23 0intro uchar *data, score[VtScoreSize];
166 6f4d00ee 2013-09-23 0intro Block *b;
167 6f4d00ee 2013-09-23 0intro Label l;
168 6f4d00ee 2013-09-23 0intro Entry *e;
169 6f4d00ee 2013-09-23 0intro WalkPtr w;
170 4b576658 2013-09-23 0intro char err[ERRMAX];
171 6f4d00ee 2013-09-23 0intro
172 6f4d00ee 2013-09-23 0intro p->nvisit++;
173 6f4d00ee 2013-09-23 0intro
174 6f4d00ee 2013-09-23 0intro b = cacheLocalData(p->c, addr, type, tag, OReadWrite,0);
175 6f4d00ee 2013-09-23 0intro if(b == nil){
176 4b576658 2013-09-23 0intro fprint(2, "archive(%ud, %#ux): cannot find block: %r\n", p->snapEpoch, addr);
177 4b576658 2013-09-23 0intro rerrstr(err, sizeof err);
178 4b576658 2013-09-23 0intro if(strcmp(err, ELabelMismatch) == 0){
179 6f4d00ee 2013-09-23 0intro /* might as well plod on so we write _something_ to Venti */
180 4b576658 2013-09-23 0intro memmove(p->score, vtzeroscore, VtScoreSize);
181 6f4d00ee 2013-09-23 0intro return ArchFaked;
182 6f4d00ee 2013-09-23 0intro }
183 6f4d00ee 2013-09-23 0intro return ArchFailure;
184 6f4d00ee 2013-09-23 0intro }
185 6f4d00ee 2013-09-23 0intro
186 6f4d00ee 2013-09-23 0intro if(DEBUG) fprint(2, "%*sarchive(%ud, %#ux): block label %L\n",
187 6f4d00ee 2013-09-23 0intro p->depth*2, "", p->snapEpoch, b->addr, &b->l);
188 6f4d00ee 2013-09-23 0intro p->depth++;
189 6f4d00ee 2013-09-23 0intro if(p->depth > p->maxdepth)
190 6f4d00ee 2013-09-23 0intro p->maxdepth = p->depth;
191 6f4d00ee 2013-09-23 0intro
192 6f4d00ee 2013-09-23 0intro data = b->data;
193 6f4d00ee 2013-09-23 0intro if((b->l.state&BsVenti) == 0){
194 6f4d00ee 2013-09-23 0intro initWalk(&w, b, b->l.type==BtDir ? p->dsize : p->psize);
195 6f4d00ee 2013-09-23 0intro for(i=0; nextWalk(&w, score, &type, &tag, &e); i++){
196 6f4d00ee 2013-09-23 0intro if(e){
197 6f4d00ee 2013-09-23 0intro if(!(e->flags&VtEntryActive))
198 6f4d00ee 2013-09-23 0intro continue;
199 6f4d00ee 2013-09-23 0intro if((e->snap && !e->archive)
200 6f4d00ee 2013-09-23 0intro || (e->flags&VtEntryNoArchive)){
201 6f4d00ee 2013-09-23 0intro if(0) fprint(2, "snap; faking %#ux\n", b->addr);
202 6f4d00ee 2013-09-23 0intro if(data == b->data){
203 6f4d00ee 2013-09-23 0intro data = copyBlock(b, p->blockSize);
204 6f4d00ee 2013-09-23 0intro if(data == nil){
205 6f4d00ee 2013-09-23 0intro ret = ArchFailure;
206 6f4d00ee 2013-09-23 0intro goto Out;
207 6f4d00ee 2013-09-23 0intro }
208 6f4d00ee 2013-09-23 0intro w.data = data;
209 6f4d00ee 2013-09-23 0intro }
210 4b576658 2013-09-23 0intro memmove(e->score, vtzeroscore, VtScoreSize);
211 6f4d00ee 2013-09-23 0intro e->depth = 0;
212 6f4d00ee 2013-09-23 0intro e->size = 0;
213 6f4d00ee 2013-09-23 0intro e->tag = 0;
214 6f4d00ee 2013-09-23 0intro e->flags &= ~VtEntryLocal;
215 6f4d00ee 2013-09-23 0intro entryPack(e, data, w.n-1);
216 6f4d00ee 2013-09-23 0intro continue;
217 6f4d00ee 2013-09-23 0intro }
218 6f4d00ee 2013-09-23 0intro }
219 6f4d00ee 2013-09-23 0intro addr = globalToLocal(score);
220 6f4d00ee 2013-09-23 0intro if(addr == NilBlock)
221 6f4d00ee 2013-09-23 0intro continue;
222 6f4d00ee 2013-09-23 0intro dsize = p->dsize;
223 6f4d00ee 2013-09-23 0intro psize = p->psize;
224 6f4d00ee 2013-09-23 0intro if(e){
225 6f4d00ee 2013-09-23 0intro p->dsize= e->dsize;
226 6f4d00ee 2013-09-23 0intro p->psize = e->psize;
227 6f4d00ee 2013-09-23 0intro }
228 4b576658 2013-09-23 0intro qunlock(&b->lk);
229 6f4d00ee 2013-09-23 0intro x = archWalk(p, addr, type, tag);
230 4b576658 2013-09-23 0intro qlock(&b->lk);
231 6f4d00ee 2013-09-23 0intro if(e){
232 6f4d00ee 2013-09-23 0intro p->dsize = dsize;
233 6f4d00ee 2013-09-23 0intro p->psize = psize;
234 6f4d00ee 2013-09-23 0intro }
235 6f4d00ee 2013-09-23 0intro while(b->iostate != BioClean && b->iostate != BioDirty)
236 4b576658 2013-09-23 0intro rsleep(&b->ioready);
237 6f4d00ee 2013-09-23 0intro switch(x){
238 6f4d00ee 2013-09-23 0intro case ArchFailure:
239 6f4d00ee 2013-09-23 0intro fprint(2, "archWalk %#ux failed; ptr is in %#ux offset %d\n",
240 6f4d00ee 2013-09-23 0intro addr, b->addr, i);
241 6f4d00ee 2013-09-23 0intro ret = ArchFailure;
242 6f4d00ee 2013-09-23 0intro goto Out;
243 6f4d00ee 2013-09-23 0intro case ArchFaked:
244 6f4d00ee 2013-09-23 0intro /*
245 6f4d00ee 2013-09-23 0intro * When we're writing the entry for an archive directory
246 6f4d00ee 2013-09-23 0intro * (like /archive/2003/1215) then even if we've faked
247 6f4d00ee 2013-09-23 0intro * any data, record the score unconditionally.
248 6f4d00ee 2013-09-23 0intro * This way, we will always record the Venti score here.
249 6f4d00ee 2013-09-23 0intro * Otherwise, temporary data or corrupted file system
250 6f4d00ee 2013-09-23 0intro * would cause us to keep holding onto the on-disk
251 6f4d00ee 2013-09-23 0intro * copy of the archive.
252 6f4d00ee 2013-09-23 0intro */
253 6f4d00ee 2013-09-23 0intro if(e==nil || !e->archive)
254 6f4d00ee 2013-09-23 0intro if(data == b->data){
255 6f4d00ee 2013-09-23 0intro if(0) fprint(2, "faked %#ux, faking %#ux (%V)\n", addr, b->addr, p->score);
256 6f4d00ee 2013-09-23 0intro data = copyBlock(b, p->blockSize);
257 6f4d00ee 2013-09-23 0intro if(data == nil){
258 6f4d00ee 2013-09-23 0intro ret = ArchFailure;
259 6f4d00ee 2013-09-23 0intro goto Out;
260 6f4d00ee 2013-09-23 0intro }
261 6f4d00ee 2013-09-23 0intro w.data = data;
262 6f4d00ee 2013-09-23 0intro }
263 6f4d00ee 2013-09-23 0intro /* fall through */
264 6f4d00ee 2013-09-23 0intro if(0) fprint(2, "falling\n");
265 6f4d00ee 2013-09-23 0intro case ArchSuccess:
266 6f4d00ee 2013-09-23 0intro if(e){
267 6f4d00ee 2013-09-23 0intro memmove(e->score, p->score, VtScoreSize);
268 6f4d00ee 2013-09-23 0intro e->flags &= ~VtEntryLocal;
269 6f4d00ee 2013-09-23 0intro entryPack(e, data, w.n-1);
270 6f4d00ee 2013-09-23 0intro }else
271 6f4d00ee 2013-09-23 0intro memmove(data+(w.n-1)*VtScoreSize, p->score, VtScoreSize);
272 6f4d00ee 2013-09-23 0intro if(data == b->data){
273 6f4d00ee 2013-09-23 0intro blockDirty(b);
274 6f4d00ee 2013-09-23 0intro /*
275 6f4d00ee 2013-09-23 0intro * If b is in the active tree, then we need to note that we've
276 fa325e9b 2020-01-10 cross * just removed addr from the active tree (replacing it with the
277 6f4d00ee 2013-09-23 0intro * copy we just stored to Venti). If addr is in other snapshots,
278 6f4d00ee 2013-09-23 0intro * this will close addr but not free it, since it has a non-empty
279 6f4d00ee 2013-09-23 0intro * epoch range.
280 6f4d00ee 2013-09-23 0intro *
281 6f4d00ee 2013-09-23 0intro * If b is in the active tree but has been copied (this can happen
282 6f4d00ee 2013-09-23 0intro * if we get killed at just the right moment), then we will
283 fa325e9b 2020-01-10 cross * mistakenly leak its kids.
284 6f4d00ee 2013-09-23 0intro *
285 6f4d00ee 2013-09-23 0intro * The children of an archive directory (e.g., /archive/2004/0604)
286 6f4d00ee 2013-09-23 0intro * are not treated as in the active tree.
287 6f4d00ee 2013-09-23 0intro */
288 6f4d00ee 2013-09-23 0intro if((b->l.state&BsCopied)==0 && (e==nil || e->snap==0))
289 6f4d00ee 2013-09-23 0intro blockRemoveLink(b, addr, p->l.type, p->l.tag, 0);
290 6f4d00ee 2013-09-23 0intro }
291 6f4d00ee 2013-09-23 0intro break;
292 6f4d00ee 2013-09-23 0intro }
293 6f4d00ee 2013-09-23 0intro }
294 6f4d00ee 2013-09-23 0intro
295 6f4d00ee 2013-09-23 0intro if(!ventiSend(p->a, b, data)){
296 6f4d00ee 2013-09-23 0intro p->nfailsend++;
297 6f4d00ee 2013-09-23 0intro ret = ArchFailure;
298 6f4d00ee 2013-09-23 0intro goto Out;
299 6f4d00ee 2013-09-23 0intro }
300 6f4d00ee 2013-09-23 0intro p->nsend++;
301 6f4d00ee 2013-09-23 0intro if(data != b->data)
302 6f4d00ee 2013-09-23 0intro p->nfake++;
303 6f4d00ee 2013-09-23 0intro if(data == b->data){ /* not faking it, so update state */
304 6f4d00ee 2013-09-23 0intro p->nreal++;
305 6f4d00ee 2013-09-23 0intro l = b->l;
306 6f4d00ee 2013-09-23 0intro l.state |= BsVenti;
307 6f4d00ee 2013-09-23 0intro if(!blockSetLabel(b, &l, 0)){
308 6f4d00ee 2013-09-23 0intro ret = ArchFailure;
309 6f4d00ee 2013-09-23 0intro goto Out;
310 6f4d00ee 2013-09-23 0intro }
311 6f4d00ee 2013-09-23 0intro }
312 6f4d00ee 2013-09-23 0intro }
313 6f4d00ee 2013-09-23 0intro
314 6f4d00ee 2013-09-23 0intro shaBlock(p->score, b, data, p->blockSize);
315 6f4d00ee 2013-09-23 0intro if(0) fprint(2, "ventisend %V %p %p %p\n", p->score, data, b->data, w.data);
316 6f4d00ee 2013-09-23 0intro ret = data!=b->data ? ArchFaked : ArchSuccess;
317 6f4d00ee 2013-09-23 0intro p->l = b->l;
318 6f4d00ee 2013-09-23 0intro Out:
319 6f4d00ee 2013-09-23 0intro if(data != b->data)
320 4b576658 2013-09-23 0intro vtfree(data);
321 6f4d00ee 2013-09-23 0intro p->depth--;
322 6f4d00ee 2013-09-23 0intro blockPut(b);
323 6f4d00ee 2013-09-23 0intro return ret;
324 6f4d00ee 2013-09-23 0intro }
325 6f4d00ee 2013-09-23 0intro
326 6f4d00ee 2013-09-23 0intro static void
327 6f4d00ee 2013-09-23 0intro archThread(void *v)
328 6f4d00ee 2013-09-23 0intro {
329 6f4d00ee 2013-09-23 0intro Arch *a = v;
330 6f4d00ee 2013-09-23 0intro Block *b;
331 6f4d00ee 2013-09-23 0intro Param p;
332 6f4d00ee 2013-09-23 0intro Super super;
333 6f4d00ee 2013-09-23 0intro int ret;
334 6f4d00ee 2013-09-23 0intro u32int addr;
335 6f4d00ee 2013-09-23 0intro uchar rbuf[VtRootSize];
336 6f4d00ee 2013-09-23 0intro VtRoot root;
337 6f4d00ee 2013-09-23 0intro
338 4b576658 2013-09-23 0intro threadsetname("arch");
339 6f4d00ee 2013-09-23 0intro
340 6f4d00ee 2013-09-23 0intro for(;;){
341 6f4d00ee 2013-09-23 0intro /* look for work */
342 4b576658 2013-09-23 0intro wlock(&a->fs->elk);
343 6f4d00ee 2013-09-23 0intro b = superGet(a->c, &super);
344 6f4d00ee 2013-09-23 0intro if(b == nil){
345 4b576658 2013-09-23 0intro wunlock(&a->fs->elk);
346 4b576658 2013-09-23 0intro fprint(2, "archThread: superGet: %r\n");
347 6f4d00ee 2013-09-23 0intro sleep(60*1000);
348 6f4d00ee 2013-09-23 0intro continue;
349 6f4d00ee 2013-09-23 0intro }
350 6f4d00ee 2013-09-23 0intro addr = super.next;
351 6f4d00ee 2013-09-23 0intro if(addr != NilBlock && super.current == NilBlock){
352 6f4d00ee 2013-09-23 0intro super.current = addr;
353 6f4d00ee 2013-09-23 0intro super.next = NilBlock;
354 6f4d00ee 2013-09-23 0intro superPack(&super, b->data);
355 6f4d00ee 2013-09-23 0intro blockDirty(b);
356 6f4d00ee 2013-09-23 0intro }else
357 6f4d00ee 2013-09-23 0intro addr = super.current;
358 6f4d00ee 2013-09-23 0intro blockPut(b);
359 4b576658 2013-09-23 0intro wunlock(&a->fs->elk);
360 6f4d00ee 2013-09-23 0intro
361 6f4d00ee 2013-09-23 0intro if(addr == NilBlock){
362 6f4d00ee 2013-09-23 0intro /* wait for work */
363 4b576658 2013-09-23 0intro qlock(&a->lk);
364 4b576658 2013-09-23 0intro rsleep(&a->starve);
365 4b576658 2013-09-23 0intro if(a->die.l != nil)
366 6f4d00ee 2013-09-23 0intro goto Done;
367 4b576658 2013-09-23 0intro qunlock(&a->lk);
368 6f4d00ee 2013-09-23 0intro continue;
369 6f4d00ee 2013-09-23 0intro }
370 6f4d00ee 2013-09-23 0intro
371 6f4d00ee 2013-09-23 0intro sleep(10*1000); /* window of opportunity to provoke races */
372 6f4d00ee 2013-09-23 0intro
373 6f4d00ee 2013-09-23 0intro /* do work */
374 6f4d00ee 2013-09-23 0intro memset(&p, 0, sizeof p);
375 6f4d00ee 2013-09-23 0intro p.blockSize = a->blockSize;
376 6f4d00ee 2013-09-23 0intro p.dsize = 3*VtEntrySize; /* root has three Entries */
377 6f4d00ee 2013-09-23 0intro p.c = a->c;
378 6f4d00ee 2013-09-23 0intro p.a = a;
379 6f4d00ee 2013-09-23 0intro
380 6f4d00ee 2013-09-23 0intro ret = archWalk(&p, addr, BtDir, RootTag);
381 6f4d00ee 2013-09-23 0intro switch(ret){
382 6f4d00ee 2013-09-23 0intro default:
383 6f4d00ee 2013-09-23 0intro abort();
384 6f4d00ee 2013-09-23 0intro case ArchFailure:
385 4b576658 2013-09-23 0intro fprint(2, "archiveBlock %#ux: %r\n", addr);
386 6f4d00ee 2013-09-23 0intro sleep(60*1000);
387 6f4d00ee 2013-09-23 0intro continue;
388 6f4d00ee 2013-09-23 0intro case ArchSuccess:
389 6f4d00ee 2013-09-23 0intro case ArchFaked:
390 6f4d00ee 2013-09-23 0intro break;
391 6f4d00ee 2013-09-23 0intro }
392 6f4d00ee 2013-09-23 0intro
393 6f4d00ee 2013-09-23 0intro if(0) fprint(2, "archiveSnapshot 0x%#ux: maxdepth %ud nfixed %ud"
394 6f4d00ee 2013-09-23 0intro " send %ud nfailsend %ud nvisit %ud"
395 6f4d00ee 2013-09-23 0intro " nreclaim %ud nfake %ud nreal %ud\n",
396 6f4d00ee 2013-09-23 0intro addr, p.maxdepth, p.nfixed,
397 6f4d00ee 2013-09-23 0intro p.nsend, p.nfailsend, p.nvisit,
398 6f4d00ee 2013-09-23 0intro p.nreclaim, p.nfake, p.nreal);
399 6f4d00ee 2013-09-23 0intro if(0) fprint(2, "archiveBlock %V (%ud)\n", p.score, p.blockSize);
400 6f4d00ee 2013-09-23 0intro
401 6f4d00ee 2013-09-23 0intro /* tie up vac root */
402 6f4d00ee 2013-09-23 0intro memset(&root, 0, sizeof root);
403 6f4d00ee 2013-09-23 0intro strecpy(root.type, root.type+sizeof root.type, "vac");
404 6f4d00ee 2013-09-23 0intro strecpy(root.name, root.name+sizeof root.name, "fossil");
405 6f4d00ee 2013-09-23 0intro memmove(root.score, p.score, VtScoreSize);
406 6f4d00ee 2013-09-23 0intro memmove(root.prev, super.last, VtScoreSize);
407 4b576658 2013-09-23 0intro root.blocksize = a->blockSize;
408 4b576658 2013-09-23 0intro vtrootpack(&root, rbuf);
409 4b576658 2013-09-23 0intro if(vtwrite(a->z, p.score, VtRootType, rbuf, VtRootSize) < 0
410 4b576658 2013-09-23 0intro || vtsha1check(p.score, rbuf, VtRootSize) < 0){
411 4b576658 2013-09-23 0intro fprint(2, "vtWriteBlock %#ux: %r\n", addr);
412 6f4d00ee 2013-09-23 0intro sleep(60*1000);
413 6f4d00ee 2013-09-23 0intro continue;
414 6f4d00ee 2013-09-23 0intro }
415 6f4d00ee 2013-09-23 0intro
416 6f4d00ee 2013-09-23 0intro /* record success */
417 4b576658 2013-09-23 0intro wlock(&a->fs->elk);
418 6f4d00ee 2013-09-23 0intro b = superGet(a->c, &super);
419 6f4d00ee 2013-09-23 0intro if(b == nil){
420 4b576658 2013-09-23 0intro wunlock(&a->fs->elk);
421 4b576658 2013-09-23 0intro fprint(2, "archThread: superGet: %r\n");
422 6f4d00ee 2013-09-23 0intro sleep(60*1000);
423 6f4d00ee 2013-09-23 0intro continue;
424 6f4d00ee 2013-09-23 0intro }
425 6f4d00ee 2013-09-23 0intro super.current = NilBlock;
426 6f4d00ee 2013-09-23 0intro memmove(super.last, p.score, VtScoreSize);
427 6f4d00ee 2013-09-23 0intro superPack(&super, b->data);
428 6f4d00ee 2013-09-23 0intro blockDirty(b);
429 6f4d00ee 2013-09-23 0intro blockPut(b);
430 4b576658 2013-09-23 0intro wunlock(&a->fs->elk);
431 6f4d00ee 2013-09-23 0intro
432 6f4d00ee 2013-09-23 0intro consPrint("archive vac:%V\n", p.score);
433 6f4d00ee 2013-09-23 0intro }
434 6f4d00ee 2013-09-23 0intro
435 6f4d00ee 2013-09-23 0intro Done:
436 6f4d00ee 2013-09-23 0intro a->ref--;
437 4b576658 2013-09-23 0intro rwakeup(&a->die);
438 4b576658 2013-09-23 0intro qunlock(&a->lk);
439 6f4d00ee 2013-09-23 0intro }
440 6f4d00ee 2013-09-23 0intro
441 6f4d00ee 2013-09-23 0intro void
442 6f4d00ee 2013-09-23 0intro archKick(Arch *a)
443 6f4d00ee 2013-09-23 0intro {
444 6f4d00ee 2013-09-23 0intro if(a == nil){
445 6f4d00ee 2013-09-23 0intro fprint(2, "warning: archKick nil\n");
446 6f4d00ee 2013-09-23 0intro return;
447 6f4d00ee 2013-09-23 0intro }
448 4b576658 2013-09-23 0intro qlock(&a->lk);
449 4b576658 2013-09-23 0intro rwakeup(&a->starve);
450 4b576658 2013-09-23 0intro qunlock(&a->lk);
451 6f4d00ee 2013-09-23 0intro }