2 28b49df3 2006-07-18 devnull * Mirror one arena partition onto another.
3 28b49df3 2006-07-18 devnull * Be careful to copy only new data.
6 28b49df3 2006-07-18 devnull #include "stdinc.h"
7 28b49df3 2006-07-18 devnull #include "dat.h"
8 28b49df3 2006-07-18 devnull #include "fns.h"
10 28b49df3 2006-07-18 devnull Channel *writechan;
12 28b49df3 2006-07-18 devnull typedef struct Write Write;
13 28b49df3 2006-07-18 devnull struct Write
15 28b49df3 2006-07-18 devnull uchar *p;
17 28b49df3 2006-07-18 devnull uvlong o;
18 28b49df3 2006-07-18 devnull int error;
21 28b49df3 2006-07-18 devnull Part *src;
22 28b49df3 2006-07-18 devnull Part *dst;
23 28b49df3 2006-07-18 devnull int force;
24 28b49df3 2006-07-18 devnull int verbose;
25 92baf59b 2007-08-23 rsc int dosha1 = 1;
26 28b49df3 2006-07-18 devnull char *status;
27 28b49df3 2006-07-18 devnull uvlong astart, aend;
30 28b49df3 2006-07-18 devnull usage(void)
32 92baf59b 2007-08-23 rsc fprint(2, "usage: mirrorarenas [-sv] src dst [ranges]\n");
33 28b49df3 2006-07-18 devnull threadexitsall("usage");
36 27d28098 2007-04-21 devnull char *tagged;
37 beaf4875 2008-12-23 rsc char *tagname;
41 beaf4875 2008-12-23 rsc tag(int indx, char *name, char *fmt, ...)
43 27d28098 2007-04-21 devnull va_list arg;
45 27d28098 2007-04-21 devnull if(tagged){
46 27d28098 2007-04-21 devnull free(tagged);
47 27d28098 2007-04-21 devnull tagged = nil;
49 beaf4875 2008-12-23 rsc tagindx = indx;
50 beaf4875 2008-12-23 rsc tagname = name;
51 27d28098 2007-04-21 devnull va_start(arg, fmt);
52 27d28098 2007-04-21 devnull tagged = vsmprint(fmt, arg);
53 27d28098 2007-04-21 devnull va_end(arg);
59 beaf4875 2008-12-23 rsc Mirrored = 2,
64 beaf4875 2008-12-23 rsc setstatus(int bits)
66 beaf4875 2008-12-23 rsc static int startindx = -1, endindx;
67 beaf4875 2008-12-23 rsc static char *startname, *endname;
68 beaf4875 2008-12-23 rsc static int lastbits;
69 beaf4875 2008-12-23 rsc char buf[100];
71 beaf4875 2008-12-23 rsc if(bits != lastbits) {
72 beaf4875 2008-12-23 rsc if(startindx >= 0) {
73 beaf4875 2008-12-23 rsc switch(lastbits) {
75 beaf4875 2008-12-23 rsc snprint(buf, sizeof buf, "sealed");
77 beaf4875 2008-12-23 rsc case Mirrored:
78 beaf4875 2008-12-23 rsc snprint(buf, sizeof buf, "mirrored");
80 beaf4875 2008-12-23 rsc case Sealed+Mirrored:
81 beaf4875 2008-12-23 rsc snprint(buf, sizeof buf, "mirrored sealed");
84 beaf4875 2008-12-23 rsc snprint(buf, sizeof buf, "empty");
87 beaf4875 2008-12-23 rsc snprint(buf, sizeof buf, "%d", bits);
90 beaf4875 2008-12-23 rsc print("%T %s-%s %s\n", startname, endname, buf);
92 beaf4875 2008-12-23 rsc lastbits = bits;
93 beaf4875 2008-12-23 rsc startindx = tagindx;
94 beaf4875 2008-12-23 rsc endindx = tagindx;
95 beaf4875 2008-12-23 rsc startname = tagname;
96 beaf4875 2008-12-23 rsc endname = tagname;
98 beaf4875 2008-12-23 rsc endindx = tagindx;
99 beaf4875 2008-12-23 rsc endname = tagname;
101 beaf4875 2008-12-23 rsc if(bits < 0) {
102 beaf4875 2008-12-23 rsc startindx = -1;
103 beaf4875 2008-12-23 rsc endindx = -1;
109 27d28098 2007-04-21 devnull chat(char *fmt, ...)
111 27d28098 2007-04-21 devnull va_list arg;
113 beaf4875 2008-12-23 rsc setstatus(-1);
115 27d28098 2007-04-21 devnull if(tagged){
116 27d28098 2007-04-21 devnull write(1, tagged, strlen(tagged));
117 27d28098 2007-04-21 devnull free(tagged);
118 27d28098 2007-04-21 devnull tagged = nil;
120 27d28098 2007-04-21 devnull va_start(arg, fmt);
121 27d28098 2007-04-21 devnull vfprint(1, fmt, arg);
122 27d28098 2007-04-21 devnull va_end(arg);
125 27d28098 2007-04-21 devnull #pragma varargck argpos tag 1
126 27d28098 2007-04-21 devnull #pragma varargck argpos chat 1
130 28b49df3 2006-07-18 devnull ereadpart(Part *p, u64int offset, u8int *buf, u32int count)
132 28b49df3 2006-07-18 devnull if(readpart(p, offset, buf, count) != count){
133 27d28098 2007-04-21 devnull chat("%T readpart %s at %#llux+%ud: %r\n", p->name, offset, count);
134 28b49df3 2006-07-18 devnull return -1;
136 28b49df3 2006-07-18 devnull return 0;
140 28b49df3 2006-07-18 devnull ewritepart(Part *p, u64int offset, u8int *buf, u32int count)
142 e46cacb0 2007-04-27 devnull if(writepart(p, offset, buf, count) != count || flushpart(p) < 0){
143 27d28098 2007-04-21 devnull chat("%T writepart %s at %#llux+%ud: %r\n", p->name, offset, count);
144 28b49df3 2006-07-18 devnull return -1;
146 28b49df3 2006-07-18 devnull return 0;
150 28b49df3 2006-07-18 devnull * Extra proc to do writes to dst, so that we can overlap reading
151 28b49df3 2006-07-18 devnull * src with writing dst during copy. This is an easy factor of two
152 28b49df3 2006-07-18 devnull * (almost) in performance.
154 6610dac9 2007-08-23 rsc static Write wsync;
155 28b49df3 2006-07-18 devnull static void
156 28b49df3 2006-07-18 devnull writeproc(void *v)
158 28b49df3 2006-07-18 devnull Write *w;
160 28b49df3 2006-07-18 devnull USED(v);
161 28b49df3 2006-07-18 devnull while((w = recvp(writechan)) != nil){
162 6610dac9 2007-08-23 rsc if(w == &wsync)
163 28b49df3 2006-07-18 devnull continue;
164 28b49df3 2006-07-18 devnull if(ewritepart(dst, w->o, w->p, w->n) < 0)
165 28b49df3 2006-07-18 devnull w->error = 1;
170 28b49df3 2006-07-18 devnull copy(uvlong start, uvlong end, char *what, DigestState *ds)
172 28b49df3 2006-07-18 devnull int i, n;
173 28b49df3 2006-07-18 devnull uvlong o;
175 beaf4875 2008-12-23 rsc Chunk = 1024*1024
177 beaf4875 2008-12-23 rsc static uchar tmpbuf[2*Chunk+MaxIo];
178 beaf4875 2008-12-23 rsc static uchar *tmp[2];
180 28b49df3 2006-07-18 devnull Write w[2];
182 28b49df3 2006-07-18 devnull assert(start <= end);
183 28b49df3 2006-07-18 devnull assert(astart <= start && start < aend);
184 28b49df3 2006-07-18 devnull assert(astart <= end && end <= aend);
186 beaf4875 2008-12-23 rsc // align the buffers so readpart/writepart can do big transfers
188 beaf4875 2008-12-23 rsc if((uintptr)p%MaxIo)
189 beaf4875 2008-12-23 rsc p += MaxIo - (uintptr)p%MaxIo;
191 beaf4875 2008-12-23 rsc tmp[1] = p + Chunk;
193 28b49df3 2006-07-18 devnull if(verbose && start != end)
194 27d28098 2007-04-21 devnull chat("%T copy %,llud-%,llud %s\n", start, end, what);
197 28b49df3 2006-07-18 devnull memset(w, 0, sizeof w);
198 28b49df3 2006-07-18 devnull for(o=start; o<end; o+=n){
199 28b49df3 2006-07-18 devnull if(w[i].error)
200 28b49df3 2006-07-18 devnull goto error;
202 28b49df3 2006-07-18 devnull if(o+n > end)
203 28b49df3 2006-07-18 devnull n = end - o;
204 28b49df3 2006-07-18 devnull if(ereadpart(src, o, tmp[i], n) < 0)
205 28b49df3 2006-07-18 devnull goto error;
206 28b49df3 2006-07-18 devnull w[i].p = tmp[i];
207 28b49df3 2006-07-18 devnull w[i].o = o;
208 28b49df3 2006-07-18 devnull w[i].n = n;
209 28b49df3 2006-07-18 devnull w[i].error = 0;
210 28b49df3 2006-07-18 devnull sendp(writechan, &w[i]);
212 28b49df3 2006-07-18 devnull sha1(tmp[i], n, nil, ds);
213 28b49df3 2006-07-18 devnull i = 1-i;
215 28b49df3 2006-07-18 devnull if(w[i].error)
216 28b49df3 2006-07-18 devnull goto error;
219 28b49df3 2006-07-18 devnull * wait for queued write to finish
221 6610dac9 2007-08-23 rsc sendp(writechan, &wsync);
222 28b49df3 2006-07-18 devnull i = 1-i;
223 28b49df3 2006-07-18 devnull if(w[i].error)
224 28b49df3 2006-07-18 devnull return -1;
225 28b49df3 2006-07-18 devnull return 0;
229 28b49df3 2006-07-18 devnull * sync with write proc
231 28b49df3 2006-07-18 devnull w[i].p = nil;
232 28b49df3 2006-07-18 devnull w[i].o = 0;
233 28b49df3 2006-07-18 devnull w[i].n = 0;
234 28b49df3 2006-07-18 devnull w[i].error = 0;
235 28b49df3 2006-07-18 devnull sendp(writechan, &w[i]);
236 28b49df3 2006-07-18 devnull return -1;
239 28b49df3 2006-07-18 devnull /* single-threaded, for reference */
241 28b49df3 2006-07-18 devnull copy1(uvlong start, uvlong end, char *what, DigestState *ds)
244 28b49df3 2006-07-18 devnull uvlong o;
245 28b49df3 2006-07-18 devnull static uchar tmp[1024*1024];
247 28b49df3 2006-07-18 devnull assert(start <= end);
248 28b49df3 2006-07-18 devnull assert(astart <= start && start < aend);
249 28b49df3 2006-07-18 devnull assert(astart <= end && end <= aend);
251 28b49df3 2006-07-18 devnull if(verbose && start != end)
252 27d28098 2007-04-21 devnull chat("%T copy %,llud-%,llud %s\n", start, end, what);
254 28b49df3 2006-07-18 devnull for(o=start; o<end; o+=n){
255 28b49df3 2006-07-18 devnull n = sizeof tmp;
256 28b49df3 2006-07-18 devnull if(o+n > end)
257 28b49df3 2006-07-18 devnull n = end - o;
258 28b49df3 2006-07-18 devnull if(ereadpart(src, o, tmp, n) < 0)
259 28b49df3 2006-07-18 devnull return -1;
261 28b49df3 2006-07-18 devnull sha1(tmp, n, nil, ds);
262 28b49df3 2006-07-18 devnull if(ewritepart(dst, o, tmp, n) < 0)
263 28b49df3 2006-07-18 devnull return -1;
265 28b49df3 2006-07-18 devnull return 0;
269 28b49df3 2006-07-18 devnull asha1(Part *p, uvlong start, uvlong end, DigestState *ds)
272 28b49df3 2006-07-18 devnull uvlong o;
273 28b49df3 2006-07-18 devnull static uchar tmp[1024*1024];
275 28b49df3 2006-07-18 devnull if(start == end)
276 28b49df3 2006-07-18 devnull return 0;
277 28b49df3 2006-07-18 devnull assert(start < end);
279 28b49df3 2006-07-18 devnull if(verbose)
280 27d28098 2007-04-21 devnull chat("%T sha1 %,llud-%,llud\n", start, end);
282 28b49df3 2006-07-18 devnull for(o=start; o<end; o+=n){
283 28b49df3 2006-07-18 devnull n = sizeof tmp;
284 28b49df3 2006-07-18 devnull if(o+n > end)
285 28b49df3 2006-07-18 devnull n = end - o;
286 28b49df3 2006-07-18 devnull if(ereadpart(p, o, tmp, n) < 0)
287 28b49df3 2006-07-18 devnull return -1;
288 28b49df3 2006-07-18 devnull sha1(tmp, n, nil, ds);
290 28b49df3 2006-07-18 devnull return 0;
294 28b49df3 2006-07-18 devnull rdown(uvlong a, int b)
296 28b49df3 2006-07-18 devnull return a-a%b;
300 28b49df3 2006-07-18 devnull rup(uvlong a, int b)
302 28b49df3 2006-07-18 devnull if(a%b == 0)
303 28b49df3 2006-07-18 devnull return a;
304 28b49df3 2006-07-18 devnull return a+b-a%b;
308 beaf4875 2008-12-23 rsc mirror(int indx, Arena *sa, Arena *da)
310 28b49df3 2006-07-18 devnull vlong v, si, di, end;
311 92baf59b 2007-08-23 rsc int clumpmax, blocksize, sealed;
312 28b49df3 2006-07-18 devnull static uchar buf[MaxIoSize];
313 28b49df3 2006-07-18 devnull ArenaHead h;
314 28b49df3 2006-07-18 devnull DigestState xds, *ds;
315 28b49df3 2006-07-18 devnull vlong shaoff, base;
317 28b49df3 2006-07-18 devnull base = sa->base;
318 28b49df3 2006-07-18 devnull blocksize = sa->blocksize;
319 28b49df3 2006-07-18 devnull end = sa->base + sa->size;
321 28b49df3 2006-07-18 devnull astart = base - blocksize;
322 28b49df3 2006-07-18 devnull aend = end + blocksize;
324 beaf4875 2008-12-23 rsc tag(indx, sa->name, "%T %s (%,llud-%,llud)\n", sa->name, astart, aend);
326 28b49df3 2006-07-18 devnull if(force){
327 28b49df3 2006-07-18 devnull copy(astart, aend, "all", nil);
331 28b49df3 2006-07-18 devnull if(sa->diskstats.sealed && da->diskstats.sealed && scorecmp(da->score, zeroscore) != 0){
332 ebcef6f0 2007-04-24 devnull if(scorecmp(sa->score, da->score) == 0){
333 beaf4875 2008-12-23 rsc setstatus(Sealed+Mirrored);
334 beaf4875 2008-12-23 rsc if(verbose > 1)
335 ebcef6f0 2007-04-24 devnull chat("%T %s: %V sealed mirrored\n", sa->name, sa->score);
338 6a5a2a95 2007-05-03 devnull chat("%T %s: warning: sealed score mismatch %V vs %V\n", sa->name, sa->score, da->score);
339 6a5a2a95 2007-05-03 devnull /* Keep executing; will correct seal if possible. */
341 6a5a2a95 2007-05-03 devnull if(!sa->diskstats.sealed && da->diskstats.sealed && scorecmp(da->score, zeroscore) != 0){
342 ebcef6f0 2007-04-24 devnull chat("%T %s: dst is sealed, src is not\n", sa->name);
343 28b49df3 2006-07-18 devnull status = "errors";
346 28b49df3 2006-07-18 devnull if(sa->diskstats.used < da->diskstats.used){
347 ebcef6f0 2007-04-24 devnull chat("%T %s: src used %,lld < dst used %,lld\n", sa->name, sa->diskstats.used, da->diskstats.used);
348 28b49df3 2006-07-18 devnull status = "errors";
352 28b49df3 2006-07-18 devnull if(da->clumpmagic != sa->clumpmagic){
354 28b49df3 2006-07-18 devnull * Write this now to reduce the window in which
355 28b49df3 2006-07-18 devnull * the head and tail disagree about clumpmagic.
357 28b49df3 2006-07-18 devnull da->clumpmagic = sa->clumpmagic;
358 28b49df3 2006-07-18 devnull memset(buf, 0, sizeof buf);
359 28b49df3 2006-07-18 devnull packarena(da, buf);
360 28b49df3 2006-07-18 devnull if(ewritepart(dst, end, buf, blocksize) < 0)
364 28b49df3 2006-07-18 devnull memset(&h, 0, sizeof h);
365 28b49df3 2006-07-18 devnull h.version = da->version;
366 28b49df3 2006-07-18 devnull strcpy(h.name, da->name);
367 28b49df3 2006-07-18 devnull h.blocksize = da->blocksize;
368 28b49df3 2006-07-18 devnull h.size = da->size + 2*da->blocksize;
369 28b49df3 2006-07-18 devnull h.clumpmagic = da->clumpmagic;
370 28b49df3 2006-07-18 devnull memset(buf, 0, sizeof buf);
371 28b49df3 2006-07-18 devnull packarenahead(&h, buf);
372 28b49df3 2006-07-18 devnull if(ewritepart(dst, base - blocksize, buf, blocksize) < 0)
375 6932098c 2007-04-21 devnull shaoff = 0;
376 28b49df3 2006-07-18 devnull ds = nil;
377 92baf59b 2007-08-23 rsc sealed = sa->diskstats.sealed && scorecmp(sa->score, zeroscore) != 0;
378 92baf59b 2007-08-23 rsc if(sealed && dosha1){
379 28b49df3 2006-07-18 devnull /* start sha1 state with header */
380 28b49df3 2006-07-18 devnull memset(&xds, 0, sizeof xds);
381 28b49df3 2006-07-18 devnull ds = &xds;
382 28b49df3 2006-07-18 devnull sha1(buf, blocksize, nil, ds);
383 28b49df3 2006-07-18 devnull shaoff = base;
386 28b49df3 2006-07-18 devnull if(sa->diskstats.used != da->diskstats.used){
387 28b49df3 2006-07-18 devnull di = base+rdown(da->diskstats.used, blocksize);
388 28b49df3 2006-07-18 devnull si = base+rup(sa->diskstats.used, blocksize);
389 28b49df3 2006-07-18 devnull if(ds && asha1(dst, shaoff, di, ds) < 0)
391 28b49df3 2006-07-18 devnull if(copy(di, si, "data", ds) < 0)
393 28b49df3 2006-07-18 devnull shaoff = si;
396 28b49df3 2006-07-18 devnull clumpmax = sa->clumpmax;
397 28b49df3 2006-07-18 devnull di = end - da->diskstats.clumps/clumpmax * blocksize;
398 28b49df3 2006-07-18 devnull si = end - (sa->diskstats.clumps+clumpmax-1)/clumpmax * blocksize;
400 28b49df3 2006-07-18 devnull if(sa->diskstats.sealed){
402 28b49df3 2006-07-18 devnull * might be a small hole between the end of the
403 28b49df3 2006-07-18 devnull * data and the beginning of the directory.
405 28b49df3 2006-07-18 devnull v = base+rup(sa->diskstats.used, blocksize);
406 28b49df3 2006-07-18 devnull if(ds && asha1(dst, shaoff, v, ds) < 0)
408 28b49df3 2006-07-18 devnull if(copy(v, si, "hole", ds) < 0)
410 28b49df3 2006-07-18 devnull shaoff = si;
413 28b49df3 2006-07-18 devnull if(da->diskstats.clumps != sa->diskstats.clumps){
414 28b49df3 2006-07-18 devnull if(ds && asha1(dst, shaoff, si, ds) < 0)
416 28b49df3 2006-07-18 devnull if(copy(si, di, "directory", ds) < 0) /* si < di because clumpinfo blocks grow down */
418 28b49df3 2006-07-18 devnull shaoff = di;
421 28b49df3 2006-07-18 devnull da->ctime = sa->ctime;
422 28b49df3 2006-07-18 devnull da->wtime = sa->wtime;
423 28b49df3 2006-07-18 devnull da->diskstats = sa->diskstats;
424 28b49df3 2006-07-18 devnull da->diskstats.sealed = 0;
427 ebcef6f0 2007-04-24 devnull * Repack the arena tail information
428 ebcef6f0 2007-04-24 devnull * and save it for next time...
430 28b49df3 2006-07-18 devnull memset(buf, 0, sizeof buf);
431 28b49df3 2006-07-18 devnull packarena(da, buf);
432 28b49df3 2006-07-18 devnull if(ewritepart(dst, end, buf, blocksize) < 0)
437 ebcef6f0 2007-04-24 devnull * ... but on the final pass, copy the encoding
438 ebcef6f0 2007-04-24 devnull * of the tail information from the source
439 ebcef6f0 2007-04-24 devnull * arena itself. There are multiple possible
440 ebcef6f0 2007-04-24 devnull * ways to write the tail info out (the exact
441 ebcef6f0 2007-04-24 devnull * details have changed as venti went through
442 ebcef6f0 2007-04-24 devnull * revisions), and to keep the SHA1 hash the
443 ebcef6f0 2007-04-24 devnull * same, we have to use what the disk uses.
445 ebcef6f0 2007-04-24 devnull if(asha1(dst, shaoff, end, ds) < 0
446 ebcef6f0 2007-04-24 devnull || copy(end, end+blocksize-VtScoreSize, "tail", ds) < 0)
449 92baf59b 2007-08-23 rsc memset(buf, 0, VtScoreSize);
450 92baf59b 2007-08-23 rsc sha1(buf, VtScoreSize, da->score, ds);
451 92baf59b 2007-08-23 rsc if(scorecmp(sa->score, da->score) == 0){
452 beaf4875 2008-12-23 rsc setstatus(Sealed+Mirrored);
453 beaf4875 2008-12-23 rsc if(verbose > 1)
454 92baf59b 2007-08-23 rsc chat("%T %s: %V sealed mirrored\n", sa->name, sa->score);
455 92baf59b 2007-08-23 rsc if(ewritepart(dst, end+blocksize-VtScoreSize, da->score, VtScoreSize) < 0)
458 92baf59b 2007-08-23 rsc chat("%T %s: sealing dst: score mismatch: %V vs %V\n", sa->name, sa->score, da->score);
459 92baf59b 2007-08-23 rsc memset(&xds, 0, sizeof xds);
460 92baf59b 2007-08-23 rsc asha1(dst, base-blocksize, end+blocksize-VtScoreSize, &xds);
461 92baf59b 2007-08-23 rsc sha1(buf, VtScoreSize, 0, &xds);
462 92baf59b 2007-08-23 rsc chat("%T reseal: %V\n", da->score);
463 92baf59b 2007-08-23 rsc status = "errors";
466 beaf4875 2008-12-23 rsc setstatus(Mirrored);
467 beaf4875 2008-12-23 rsc if(verbose > 1)
468 92baf59b 2007-08-23 rsc chat("%T %s: %V mirrored\n", sa->name, sa->score);
469 92baf59b 2007-08-23 rsc if(ewritepart(dst, end+blocksize-VtScoreSize, sa->score, VtScoreSize) < 0)
473 beaf4875 2008-12-23 rsc if(sa->diskstats.used > 0 || verbose > 1) {
474 beaf4875 2008-12-23 rsc chat("%T %s: %,lld used mirrored\n",
475 beaf4875 2008-12-23 rsc sa->name, sa->diskstats.used);
477 beaf4875 2008-12-23 rsc if(sa->diskstats.used > 0)
478 beaf4875 2008-12-23 rsc setstatus(Mirrored);
480 beaf4875 2008-12-23 rsc setstatus(Empty);
485 28b49df3 2006-07-18 devnull mirrormany(ArenaPart *sp, ArenaPart *dp, char *range)
487 28b49df3 2006-07-18 devnull int i, lo, hi;
488 28b49df3 2006-07-18 devnull char *s, *t;
489 28b49df3 2006-07-18 devnull Arena *sa, *da;
491 28b49df3 2006-07-18 devnull if(range == nil){
492 28b49df3 2006-07-18 devnull for(i=0; i<sp->narenas; i++){
493 28b49df3 2006-07-18 devnull sa = sp->arenas[i];
494 28b49df3 2006-07-18 devnull da = dp->arenas[i];
495 beaf4875 2008-12-23 rsc mirror(i, sa, da);
497 beaf4875 2008-12-23 rsc setstatus(-1);
500 28b49df3 2006-07-18 devnull if(strcmp(range, "none") == 0)
503 28b49df3 2006-07-18 devnull for(s=range; *s; s=t){
504 28b49df3 2006-07-18 devnull t = strchr(s, ',');
506 28b49df3 2006-07-18 devnull *t++ = 0;
508 28b49df3 2006-07-18 devnull t = s+strlen(s);
509 28b49df3 2006-07-18 devnull if(*s == '-')
512 28b49df3 2006-07-18 devnull lo = strtol(s, &s, 0);
513 28b49df3 2006-07-18 devnull hi = lo;
514 28b49df3 2006-07-18 devnull if(*s == '-'){
516 28b49df3 2006-07-18 devnull if(*s == 0)
517 28b49df3 2006-07-18 devnull hi = sp->narenas-1;
519 28b49df3 2006-07-18 devnull hi = strtol(s, &s, 0);
521 28b49df3 2006-07-18 devnull if(*s != 0){
522 27d28098 2007-04-21 devnull chat("%T bad arena range: %s\n", s);
523 28b49df3 2006-07-18 devnull continue;
525 28b49df3 2006-07-18 devnull for(i=lo; i<=hi; i++){
526 28b49df3 2006-07-18 devnull sa = sp->arenas[i];
527 28b49df3 2006-07-18 devnull da = dp->arenas[i];
528 beaf4875 2008-12-23 rsc mirror(i, sa, da);
530 beaf4875 2008-12-23 rsc setstatus(-1);
536 28b49df3 2006-07-18 devnull threadmain(int argc, char **argv)
539 28b49df3 2006-07-18 devnull Arena *sa, *da;
540 28b49df3 2006-07-18 devnull ArenaPart *s, *d;
541 28b49df3 2006-07-18 devnull char *ranges;
543 28b49df3 2006-07-18 devnull ventifmtinstall();
545 28b49df3 2006-07-18 devnull ARGBEGIN{
546 28b49df3 2006-07-18 devnull case 'F':
547 28b49df3 2006-07-18 devnull force = 1;
549 28b49df3 2006-07-18 devnull case 'v':
550 28b49df3 2006-07-18 devnull verbose++;
555 28b49df3 2006-07-18 devnull default:
556 28b49df3 2006-07-18 devnull usage();
559 28b49df3 2006-07-18 devnull if(argc != 2 && argc != 3)
560 28b49df3 2006-07-18 devnull usage();
561 28b49df3 2006-07-18 devnull ranges = nil;
562 28b49df3 2006-07-18 devnull if(argc == 3)
563 28b49df3 2006-07-18 devnull ranges = argv[2];
565 28b49df3 2006-07-18 devnull if((src = initpart(argv[0], OREAD)) == nil)
566 28b49df3 2006-07-18 devnull sysfatal("initpart %s: %r", argv[0]);
567 28b49df3 2006-07-18 devnull if((dst = initpart(argv[1], ORDWR)) == nil)
568 28b49df3 2006-07-18 devnull sysfatal("initpart %s: %r", argv[1]);
569 28b49df3 2006-07-18 devnull if((s = initarenapart(src)) == nil)
570 28b49df3 2006-07-18 devnull sysfatal("initarenapart %s: %r", argv[0]);
571 28b49df3 2006-07-18 devnull for(i=0; i<s->narenas; i++)
572 28b49df3 2006-07-18 devnull delarena(s->arenas[i]);
573 28b49df3 2006-07-18 devnull if((d = initarenapart(dst)) == nil)
574 28b49df3 2006-07-18 devnull sysfatal("loadarenapart %s: %r", argv[1]);
575 28b49df3 2006-07-18 devnull for(i=0; i<d->narenas; i++)
576 28b49df3 2006-07-18 devnull delarena(d->arenas[i]);
579 28b49df3 2006-07-18 devnull * The arena geometries must match or all bets are off.
581 28b49df3 2006-07-18 devnull if(s->narenas != d->narenas)
582 28b49df3 2006-07-18 devnull sysfatal("arena count mismatch: %d vs %d", s->narenas, d->narenas);
583 28b49df3 2006-07-18 devnull for(i=0; i<s->narenas; i++){
584 28b49df3 2006-07-18 devnull sa = s->arenas[i];
585 28b49df3 2006-07-18 devnull da = d->arenas[i];
586 28b49df3 2006-07-18 devnull if(sa->version != da->version)
587 28b49df3 2006-07-18 devnull sysfatal("arena %d: version mismatch: %d vs %d", i, sa->version, da->version);
588 28b49df3 2006-07-18 devnull if(sa->blocksize != da->blocksize)
589 28b49df3 2006-07-18 devnull sysfatal("arena %d: blocksize mismatch: %d vs %d", i, sa->blocksize, da->blocksize);
590 28b49df3 2006-07-18 devnull if(sa->size != da->size)
591 28b49df3 2006-07-18 devnull sysfatal("arena %d: size mismatch: %,lld vs %,lld", i, sa->size, da->size);
592 28b49df3 2006-07-18 devnull if(strcmp(sa->name, da->name) != 0)
593 28b49df3 2006-07-18 devnull sysfatal("arena %d: name mismatch: %s vs %s", i, sa->name, da->name);
597 28b49df3 2006-07-18 devnull * Mirror one arena at a time.
599 28b49df3 2006-07-18 devnull writechan = chancreate(sizeof(void*), 0);
600 28b49df3 2006-07-18 devnull vtproc(writeproc, nil);
601 28b49df3 2006-07-18 devnull mirrormany(s, d, ranges);
602 28b49df3 2006-07-18 devnull sendp(writechan, nil);
603 28b49df3 2006-07-18 devnull threadexitsall(status);