2 fa325e9b 2020-01-10 cross * 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 220c15d2 2012-10-20 rsc static int startindx = -1;
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 startname = tagname;
95 beaf4875 2008-12-23 rsc endname = tagname;
97 beaf4875 2008-12-23 rsc endname = tagname;
99 beaf4875 2008-12-23 rsc if(bits < 0) {
100 beaf4875 2008-12-23 rsc startindx = -1;
106 27d28098 2007-04-21 devnull chat(char *fmt, ...)
108 27d28098 2007-04-21 devnull va_list arg;
110 beaf4875 2008-12-23 rsc setstatus(-1);
112 27d28098 2007-04-21 devnull if(tagged){
113 27d28098 2007-04-21 devnull write(1, tagged, strlen(tagged));
114 27d28098 2007-04-21 devnull free(tagged);
115 27d28098 2007-04-21 devnull tagged = nil;
117 27d28098 2007-04-21 devnull va_start(arg, fmt);
118 27d28098 2007-04-21 devnull vfprint(1, fmt, arg);
119 27d28098 2007-04-21 devnull va_end(arg);
122 3155ec71 2011-06-13 rsc #pragma varargck argpos tag 3
123 27d28098 2007-04-21 devnull #pragma varargck argpos chat 1
127 28b49df3 2006-07-18 devnull ereadpart(Part *p, u64int offset, u8int *buf, u32int count)
129 28b49df3 2006-07-18 devnull if(readpart(p, offset, buf, count) != count){
130 27d28098 2007-04-21 devnull chat("%T readpart %s at %#llux+%ud: %r\n", p->name, offset, count);
131 28b49df3 2006-07-18 devnull return -1;
133 28b49df3 2006-07-18 devnull return 0;
137 28b49df3 2006-07-18 devnull ewritepart(Part *p, u64int offset, u8int *buf, u32int count)
139 e46cacb0 2007-04-27 devnull if(writepart(p, offset, buf, count) != count || flushpart(p) < 0){
140 27d28098 2007-04-21 devnull chat("%T writepart %s at %#llux+%ud: %r\n", p->name, offset, count);
141 28b49df3 2006-07-18 devnull return -1;
143 28b49df3 2006-07-18 devnull return 0;
147 28b49df3 2006-07-18 devnull * Extra proc to do writes to dst, so that we can overlap reading
148 28b49df3 2006-07-18 devnull * src with writing dst during copy. This is an easy factor of two
149 28b49df3 2006-07-18 devnull * (almost) in performance.
151 6610dac9 2007-08-23 rsc static Write wsync;
152 28b49df3 2006-07-18 devnull static void
153 28b49df3 2006-07-18 devnull writeproc(void *v)
155 28b49df3 2006-07-18 devnull Write *w;
157 28b49df3 2006-07-18 devnull USED(v);
158 28b49df3 2006-07-18 devnull while((w = recvp(writechan)) != nil){
159 6610dac9 2007-08-23 rsc if(w == &wsync)
160 28b49df3 2006-07-18 devnull continue;
161 28b49df3 2006-07-18 devnull if(ewritepart(dst, w->o, w->p, w->n) < 0)
162 28b49df3 2006-07-18 devnull w->error = 1;
167 28b49df3 2006-07-18 devnull copy(uvlong start, uvlong end, char *what, DigestState *ds)
169 28b49df3 2006-07-18 devnull int i, n;
170 28b49df3 2006-07-18 devnull uvlong o;
172 beaf4875 2008-12-23 rsc Chunk = 1024*1024
174 beaf4875 2008-12-23 rsc static uchar tmpbuf[2*Chunk+MaxIo];
175 beaf4875 2008-12-23 rsc static uchar *tmp[2];
177 28b49df3 2006-07-18 devnull Write w[2];
179 28b49df3 2006-07-18 devnull assert(start <= end);
180 28b49df3 2006-07-18 devnull assert(astart <= start && start < aend);
181 28b49df3 2006-07-18 devnull assert(astart <= end && end <= aend);
183 beaf4875 2008-12-23 rsc // align the buffers so readpart/writepart can do big transfers
185 beaf4875 2008-12-23 rsc if((uintptr)p%MaxIo)
186 beaf4875 2008-12-23 rsc p += MaxIo - (uintptr)p%MaxIo;
188 beaf4875 2008-12-23 rsc tmp[1] = p + Chunk;
190 28b49df3 2006-07-18 devnull if(verbose && start != end)
191 27d28098 2007-04-21 devnull chat("%T copy %,llud-%,llud %s\n", start, end, what);
194 28b49df3 2006-07-18 devnull memset(w, 0, sizeof w);
195 28b49df3 2006-07-18 devnull for(o=start; o<end; o+=n){
196 28b49df3 2006-07-18 devnull if(w[i].error)
197 28b49df3 2006-07-18 devnull goto error;
199 28b49df3 2006-07-18 devnull if(o+n > end)
200 28b49df3 2006-07-18 devnull n = end - o;
201 28b49df3 2006-07-18 devnull if(ereadpart(src, o, tmp[i], n) < 0)
202 28b49df3 2006-07-18 devnull goto error;
203 28b49df3 2006-07-18 devnull w[i].p = tmp[i];
204 28b49df3 2006-07-18 devnull w[i].o = o;
205 28b49df3 2006-07-18 devnull w[i].n = n;
206 28b49df3 2006-07-18 devnull w[i].error = 0;
207 28b49df3 2006-07-18 devnull sendp(writechan, &w[i]);
209 28b49df3 2006-07-18 devnull sha1(tmp[i], n, nil, ds);
210 28b49df3 2006-07-18 devnull i = 1-i;
212 28b49df3 2006-07-18 devnull if(w[i].error)
213 28b49df3 2006-07-18 devnull goto error;
216 28b49df3 2006-07-18 devnull * wait for queued write to finish
218 6610dac9 2007-08-23 rsc sendp(writechan, &wsync);
219 28b49df3 2006-07-18 devnull i = 1-i;
220 28b49df3 2006-07-18 devnull if(w[i].error)
221 28b49df3 2006-07-18 devnull return -1;
222 28b49df3 2006-07-18 devnull return 0;
226 28b49df3 2006-07-18 devnull * sync with write proc
228 28b49df3 2006-07-18 devnull w[i].p = nil;
229 28b49df3 2006-07-18 devnull w[i].o = 0;
230 28b49df3 2006-07-18 devnull w[i].n = 0;
231 28b49df3 2006-07-18 devnull w[i].error = 0;
232 28b49df3 2006-07-18 devnull sendp(writechan, &w[i]);
233 28b49df3 2006-07-18 devnull return -1;
236 28b49df3 2006-07-18 devnull /* single-threaded, for reference */
238 28b49df3 2006-07-18 devnull copy1(uvlong start, uvlong end, char *what, DigestState *ds)
241 28b49df3 2006-07-18 devnull uvlong o;
242 28b49df3 2006-07-18 devnull static uchar tmp[1024*1024];
244 28b49df3 2006-07-18 devnull assert(start <= end);
245 28b49df3 2006-07-18 devnull assert(astart <= start && start < aend);
246 28b49df3 2006-07-18 devnull assert(astart <= end && end <= aend);
248 28b49df3 2006-07-18 devnull if(verbose && start != end)
249 27d28098 2007-04-21 devnull chat("%T copy %,llud-%,llud %s\n", start, end, what);
251 28b49df3 2006-07-18 devnull for(o=start; o<end; o+=n){
252 28b49df3 2006-07-18 devnull n = sizeof tmp;
253 28b49df3 2006-07-18 devnull if(o+n > end)
254 28b49df3 2006-07-18 devnull n = end - o;
255 28b49df3 2006-07-18 devnull if(ereadpart(src, o, tmp, n) < 0)
256 28b49df3 2006-07-18 devnull return -1;
258 28b49df3 2006-07-18 devnull sha1(tmp, n, nil, ds);
259 28b49df3 2006-07-18 devnull if(ewritepart(dst, o, tmp, n) < 0)
260 28b49df3 2006-07-18 devnull return -1;
262 28b49df3 2006-07-18 devnull return 0;
266 28b49df3 2006-07-18 devnull asha1(Part *p, uvlong start, uvlong end, DigestState *ds)
269 28b49df3 2006-07-18 devnull uvlong o;
270 28b49df3 2006-07-18 devnull static uchar tmp[1024*1024];
272 28b49df3 2006-07-18 devnull if(start == end)
273 28b49df3 2006-07-18 devnull return 0;
274 28b49df3 2006-07-18 devnull assert(start < end);
276 28b49df3 2006-07-18 devnull if(verbose)
277 27d28098 2007-04-21 devnull chat("%T sha1 %,llud-%,llud\n", start, end);
279 28b49df3 2006-07-18 devnull for(o=start; o<end; o+=n){
280 28b49df3 2006-07-18 devnull n = sizeof tmp;
281 28b49df3 2006-07-18 devnull if(o+n > end)
282 28b49df3 2006-07-18 devnull n = end - o;
283 28b49df3 2006-07-18 devnull if(ereadpart(p, o, tmp, n) < 0)
284 28b49df3 2006-07-18 devnull return -1;
285 28b49df3 2006-07-18 devnull sha1(tmp, n, nil, ds);
287 28b49df3 2006-07-18 devnull return 0;
291 28b49df3 2006-07-18 devnull rdown(uvlong a, int b)
293 28b49df3 2006-07-18 devnull return a-a%b;
297 28b49df3 2006-07-18 devnull rup(uvlong a, int b)
299 28b49df3 2006-07-18 devnull if(a%b == 0)
300 28b49df3 2006-07-18 devnull return a;
301 28b49df3 2006-07-18 devnull return a+b-a%b;
305 beaf4875 2008-12-23 rsc mirror(int indx, Arena *sa, Arena *da)
307 28b49df3 2006-07-18 devnull vlong v, si, di, end;
308 92baf59b 2007-08-23 rsc int clumpmax, blocksize, sealed;
309 28b49df3 2006-07-18 devnull static uchar buf[MaxIoSize];
310 28b49df3 2006-07-18 devnull ArenaHead h;
311 28b49df3 2006-07-18 devnull DigestState xds, *ds;
312 28b49df3 2006-07-18 devnull vlong shaoff, base;
314 28b49df3 2006-07-18 devnull base = sa->base;
315 28b49df3 2006-07-18 devnull blocksize = sa->blocksize;
316 28b49df3 2006-07-18 devnull end = sa->base + sa->size;
318 28b49df3 2006-07-18 devnull astart = base - blocksize;
319 28b49df3 2006-07-18 devnull aend = end + blocksize;
321 beaf4875 2008-12-23 rsc tag(indx, sa->name, "%T %s (%,llud-%,llud)\n", sa->name, astart, aend);
323 28b49df3 2006-07-18 devnull if(force){
324 28b49df3 2006-07-18 devnull copy(astart, aend, "all", nil);
328 28b49df3 2006-07-18 devnull if(sa->diskstats.sealed && da->diskstats.sealed && scorecmp(da->score, zeroscore) != 0){
329 ebcef6f0 2007-04-24 devnull if(scorecmp(sa->score, da->score) == 0){
330 beaf4875 2008-12-23 rsc setstatus(Sealed+Mirrored);
331 beaf4875 2008-12-23 rsc if(verbose > 1)
332 ebcef6f0 2007-04-24 devnull chat("%T %s: %V sealed mirrored\n", sa->name, sa->score);
335 6a5a2a95 2007-05-03 devnull chat("%T %s: warning: sealed score mismatch %V vs %V\n", sa->name, sa->score, da->score);
336 6a5a2a95 2007-05-03 devnull /* Keep executing; will correct seal if possible. */
338 6a5a2a95 2007-05-03 devnull if(!sa->diskstats.sealed && da->diskstats.sealed && scorecmp(da->score, zeroscore) != 0){
339 ebcef6f0 2007-04-24 devnull chat("%T %s: dst is sealed, src is not\n", sa->name);
340 28b49df3 2006-07-18 devnull status = "errors";
343 28b49df3 2006-07-18 devnull if(sa->diskstats.used < da->diskstats.used){
344 ebcef6f0 2007-04-24 devnull chat("%T %s: src used %,lld < dst used %,lld\n", sa->name, sa->diskstats.used, da->diskstats.used);
345 28b49df3 2006-07-18 devnull status = "errors";
349 28b49df3 2006-07-18 devnull if(da->clumpmagic != sa->clumpmagic){
351 28b49df3 2006-07-18 devnull * Write this now to reduce the window in which
352 28b49df3 2006-07-18 devnull * the head and tail disagree about clumpmagic.
354 28b49df3 2006-07-18 devnull da->clumpmagic = sa->clumpmagic;
355 28b49df3 2006-07-18 devnull memset(buf, 0, sizeof buf);
356 28b49df3 2006-07-18 devnull packarena(da, buf);
357 28b49df3 2006-07-18 devnull if(ewritepart(dst, end, buf, blocksize) < 0)
361 28b49df3 2006-07-18 devnull memset(&h, 0, sizeof h);
362 28b49df3 2006-07-18 devnull h.version = da->version;
363 28b49df3 2006-07-18 devnull strcpy(h.name, da->name);
364 28b49df3 2006-07-18 devnull h.blocksize = da->blocksize;
365 28b49df3 2006-07-18 devnull h.size = da->size + 2*da->blocksize;
366 28b49df3 2006-07-18 devnull h.clumpmagic = da->clumpmagic;
367 28b49df3 2006-07-18 devnull memset(buf, 0, sizeof buf);
368 28b49df3 2006-07-18 devnull packarenahead(&h, buf);
369 28b49df3 2006-07-18 devnull if(ewritepart(dst, base - blocksize, buf, blocksize) < 0)
372 6932098c 2007-04-21 devnull shaoff = 0;
373 28b49df3 2006-07-18 devnull ds = nil;
374 92baf59b 2007-08-23 rsc sealed = sa->diskstats.sealed && scorecmp(sa->score, zeroscore) != 0;
375 92baf59b 2007-08-23 rsc if(sealed && dosha1){
376 28b49df3 2006-07-18 devnull /* start sha1 state with header */
377 28b49df3 2006-07-18 devnull memset(&xds, 0, sizeof xds);
378 28b49df3 2006-07-18 devnull ds = &xds;
379 28b49df3 2006-07-18 devnull sha1(buf, blocksize, nil, ds);
380 28b49df3 2006-07-18 devnull shaoff = base;
383 28b49df3 2006-07-18 devnull if(sa->diskstats.used != da->diskstats.used){
384 28b49df3 2006-07-18 devnull di = base+rdown(da->diskstats.used, blocksize);
385 28b49df3 2006-07-18 devnull si = base+rup(sa->diskstats.used, blocksize);
386 28b49df3 2006-07-18 devnull if(ds && asha1(dst, shaoff, di, ds) < 0)
388 28b49df3 2006-07-18 devnull if(copy(di, si, "data", ds) < 0)
390 28b49df3 2006-07-18 devnull shaoff = si;
393 28b49df3 2006-07-18 devnull clumpmax = sa->clumpmax;
394 28b49df3 2006-07-18 devnull di = end - da->diskstats.clumps/clumpmax * blocksize;
395 28b49df3 2006-07-18 devnull si = end - (sa->diskstats.clumps+clumpmax-1)/clumpmax * blocksize;
397 28b49df3 2006-07-18 devnull if(sa->diskstats.sealed){
399 fa325e9b 2020-01-10 cross * might be a small hole between the end of the
400 28b49df3 2006-07-18 devnull * data and the beginning of the directory.
402 28b49df3 2006-07-18 devnull v = base+rup(sa->diskstats.used, blocksize);
403 28b49df3 2006-07-18 devnull if(ds && asha1(dst, shaoff, v, ds) < 0)
405 28b49df3 2006-07-18 devnull if(copy(v, si, "hole", ds) < 0)
407 28b49df3 2006-07-18 devnull shaoff = si;
410 28b49df3 2006-07-18 devnull if(da->diskstats.clumps != sa->diskstats.clumps){
411 28b49df3 2006-07-18 devnull if(ds && asha1(dst, shaoff, si, ds) < 0)
413 28b49df3 2006-07-18 devnull if(copy(si, di, "directory", ds) < 0) /* si < di because clumpinfo blocks grow down */
415 28b49df3 2006-07-18 devnull shaoff = di;
418 28b49df3 2006-07-18 devnull da->ctime = sa->ctime;
419 28b49df3 2006-07-18 devnull da->wtime = sa->wtime;
420 28b49df3 2006-07-18 devnull da->diskstats = sa->diskstats;
421 28b49df3 2006-07-18 devnull da->diskstats.sealed = 0;
424 ebcef6f0 2007-04-24 devnull * Repack the arena tail information
425 ebcef6f0 2007-04-24 devnull * and save it for next time...
427 28b49df3 2006-07-18 devnull memset(buf, 0, sizeof buf);
428 28b49df3 2006-07-18 devnull packarena(da, buf);
429 28b49df3 2006-07-18 devnull if(ewritepart(dst, end, buf, blocksize) < 0)
434 ebcef6f0 2007-04-24 devnull * ... but on the final pass, copy the encoding
435 ebcef6f0 2007-04-24 devnull * of the tail information from the source
436 ebcef6f0 2007-04-24 devnull * arena itself. There are multiple possible
437 ebcef6f0 2007-04-24 devnull * ways to write the tail info out (the exact
438 ebcef6f0 2007-04-24 devnull * details have changed as venti went through
439 ebcef6f0 2007-04-24 devnull * revisions), and to keep the SHA1 hash the
440 ebcef6f0 2007-04-24 devnull * same, we have to use what the disk uses.
442 ebcef6f0 2007-04-24 devnull if(asha1(dst, shaoff, end, ds) < 0
443 ebcef6f0 2007-04-24 devnull || copy(end, end+blocksize-VtScoreSize, "tail", ds) < 0)
446 92baf59b 2007-08-23 rsc memset(buf, 0, VtScoreSize);
447 92baf59b 2007-08-23 rsc sha1(buf, VtScoreSize, da->score, ds);
448 92baf59b 2007-08-23 rsc if(scorecmp(sa->score, da->score) == 0){
449 beaf4875 2008-12-23 rsc setstatus(Sealed+Mirrored);
450 beaf4875 2008-12-23 rsc if(verbose > 1)
451 92baf59b 2007-08-23 rsc chat("%T %s: %V sealed mirrored\n", sa->name, sa->score);
452 92baf59b 2007-08-23 rsc if(ewritepart(dst, end+blocksize-VtScoreSize, da->score, VtScoreSize) < 0)
455 92baf59b 2007-08-23 rsc chat("%T %s: sealing dst: score mismatch: %V vs %V\n", sa->name, sa->score, da->score);
456 92baf59b 2007-08-23 rsc memset(&xds, 0, sizeof xds);
457 92baf59b 2007-08-23 rsc asha1(dst, base-blocksize, end+blocksize-VtScoreSize, &xds);
458 92baf59b 2007-08-23 rsc sha1(buf, VtScoreSize, 0, &xds);
459 92baf59b 2007-08-23 rsc chat("%T reseal: %V\n", da->score);
460 92baf59b 2007-08-23 rsc status = "errors";
463 beaf4875 2008-12-23 rsc setstatus(Mirrored);
464 beaf4875 2008-12-23 rsc if(verbose > 1)
465 92baf59b 2007-08-23 rsc chat("%T %s: %V mirrored\n", sa->name, sa->score);
466 92baf59b 2007-08-23 rsc if(ewritepart(dst, end+blocksize-VtScoreSize, sa->score, VtScoreSize) < 0)
470 beaf4875 2008-12-23 rsc if(sa->diskstats.used > 0 || verbose > 1) {
471 beaf4875 2008-12-23 rsc chat("%T %s: %,lld used mirrored\n",
472 beaf4875 2008-12-23 rsc sa->name, sa->diskstats.used);
474 beaf4875 2008-12-23 rsc if(sa->diskstats.used > 0)
475 beaf4875 2008-12-23 rsc setstatus(Mirrored);
477 beaf4875 2008-12-23 rsc setstatus(Empty);
482 28b49df3 2006-07-18 devnull mirrormany(ArenaPart *sp, ArenaPart *dp, char *range)
484 28b49df3 2006-07-18 devnull int i, lo, hi;
485 28b49df3 2006-07-18 devnull char *s, *t;
486 28b49df3 2006-07-18 devnull Arena *sa, *da;
488 28b49df3 2006-07-18 devnull if(range == nil){
489 28b49df3 2006-07-18 devnull for(i=0; i<sp->narenas; i++){
490 28b49df3 2006-07-18 devnull sa = sp->arenas[i];
491 28b49df3 2006-07-18 devnull da = dp->arenas[i];
492 beaf4875 2008-12-23 rsc mirror(i, sa, da);
494 beaf4875 2008-12-23 rsc setstatus(-1);
497 28b49df3 2006-07-18 devnull if(strcmp(range, "none") == 0)
500 28b49df3 2006-07-18 devnull for(s=range; *s; s=t){
501 28b49df3 2006-07-18 devnull t = strchr(s, ',');
503 28b49df3 2006-07-18 devnull *t++ = 0;
505 28b49df3 2006-07-18 devnull t = s+strlen(s);
506 28b49df3 2006-07-18 devnull if(*s == '-')
509 28b49df3 2006-07-18 devnull lo = strtol(s, &s, 0);
510 28b49df3 2006-07-18 devnull hi = lo;
511 28b49df3 2006-07-18 devnull if(*s == '-'){
513 28b49df3 2006-07-18 devnull if(*s == 0)
514 28b49df3 2006-07-18 devnull hi = sp->narenas-1;
516 28b49df3 2006-07-18 devnull hi = strtol(s, &s, 0);
518 28b49df3 2006-07-18 devnull if(*s != 0){
519 27d28098 2007-04-21 devnull chat("%T bad arena range: %s\n", s);
520 28b49df3 2006-07-18 devnull continue;
522 28b49df3 2006-07-18 devnull for(i=lo; i<=hi; i++){
523 28b49df3 2006-07-18 devnull sa = sp->arenas[i];
524 28b49df3 2006-07-18 devnull da = dp->arenas[i];
525 beaf4875 2008-12-23 rsc mirror(i, sa, da);
527 beaf4875 2008-12-23 rsc setstatus(-1);
533 28b49df3 2006-07-18 devnull threadmain(int argc, char **argv)
536 28b49df3 2006-07-18 devnull Arena *sa, *da;
537 28b49df3 2006-07-18 devnull ArenaPart *s, *d;
538 28b49df3 2006-07-18 devnull char *ranges;
540 28b49df3 2006-07-18 devnull ventifmtinstall();
542 28b49df3 2006-07-18 devnull ARGBEGIN{
543 28b49df3 2006-07-18 devnull case 'F':
544 28b49df3 2006-07-18 devnull force = 1;
546 28b49df3 2006-07-18 devnull case 'v':
547 28b49df3 2006-07-18 devnull verbose++;
552 28b49df3 2006-07-18 devnull default:
553 28b49df3 2006-07-18 devnull usage();
556 28b49df3 2006-07-18 devnull if(argc != 2 && argc != 3)
557 28b49df3 2006-07-18 devnull usage();
558 28b49df3 2006-07-18 devnull ranges = nil;
559 28b49df3 2006-07-18 devnull if(argc == 3)
560 28b49df3 2006-07-18 devnull ranges = argv[2];
562 28b49df3 2006-07-18 devnull if((src = initpart(argv[0], OREAD)) == nil)
563 28b49df3 2006-07-18 devnull sysfatal("initpart %s: %r", argv[0]);
564 28b49df3 2006-07-18 devnull if((dst = initpart(argv[1], ORDWR)) == nil)
565 28b49df3 2006-07-18 devnull sysfatal("initpart %s: %r", argv[1]);
566 28b49df3 2006-07-18 devnull if((s = initarenapart(src)) == nil)
567 28b49df3 2006-07-18 devnull sysfatal("initarenapart %s: %r", argv[0]);
568 28b49df3 2006-07-18 devnull for(i=0; i<s->narenas; i++)
569 28b49df3 2006-07-18 devnull delarena(s->arenas[i]);
570 28b49df3 2006-07-18 devnull if((d = initarenapart(dst)) == nil)
571 28b49df3 2006-07-18 devnull sysfatal("loadarenapart %s: %r", argv[1]);
572 28b49df3 2006-07-18 devnull for(i=0; i<d->narenas; i++)
573 28b49df3 2006-07-18 devnull delarena(d->arenas[i]);
576 28b49df3 2006-07-18 devnull * The arena geometries must match or all bets are off.
578 28b49df3 2006-07-18 devnull if(s->narenas != d->narenas)
579 28b49df3 2006-07-18 devnull sysfatal("arena count mismatch: %d vs %d", s->narenas, d->narenas);
580 28b49df3 2006-07-18 devnull for(i=0; i<s->narenas; i++){
581 28b49df3 2006-07-18 devnull sa = s->arenas[i];
582 28b49df3 2006-07-18 devnull da = d->arenas[i];
583 28b49df3 2006-07-18 devnull if(sa->version != da->version)
584 28b49df3 2006-07-18 devnull sysfatal("arena %d: version mismatch: %d vs %d", i, sa->version, da->version);
585 28b49df3 2006-07-18 devnull if(sa->blocksize != da->blocksize)
586 28b49df3 2006-07-18 devnull sysfatal("arena %d: blocksize mismatch: %d vs %d", i, sa->blocksize, da->blocksize);
587 28b49df3 2006-07-18 devnull if(sa->size != da->size)
588 28b49df3 2006-07-18 devnull sysfatal("arena %d: size mismatch: %,lld vs %,lld", i, sa->size, da->size);
589 28b49df3 2006-07-18 devnull if(strcmp(sa->name, da->name) != 0)
590 28b49df3 2006-07-18 devnull sysfatal("arena %d: name mismatch: %s vs %s", i, sa->name, da->name);
594 28b49df3 2006-07-18 devnull * Mirror one arena at a time.
596 28b49df3 2006-07-18 devnull writechan = chancreate(sizeof(void*), 0);
597 28b49df3 2006-07-18 devnull vtproc(writeproc, nil);
598 28b49df3 2006-07-18 devnull mirrormany(s, d, ranges);
599 28b49df3 2006-07-18 devnull sendp(writechan, nil);
600 28b49df3 2006-07-18 devnull threadexitsall(status);