Blame


1 28b49df3 2006-07-18 devnull /*
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.
4 28b49df3 2006-07-18 devnull */
5 28b49df3 2006-07-18 devnull
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"
9 28b49df3 2006-07-18 devnull
10 28b49df3 2006-07-18 devnull Channel *writechan;
11 28b49df3 2006-07-18 devnull
12 28b49df3 2006-07-18 devnull typedef struct Write Write;
13 28b49df3 2006-07-18 devnull struct Write
14 28b49df3 2006-07-18 devnull {
15 28b49df3 2006-07-18 devnull uchar *p;
16 28b49df3 2006-07-18 devnull int n;
17 28b49df3 2006-07-18 devnull uvlong o;
18 28b49df3 2006-07-18 devnull int error;
19 28b49df3 2006-07-18 devnull };
20 28b49df3 2006-07-18 devnull
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;
28 28b49df3 2006-07-18 devnull
29 28b49df3 2006-07-18 devnull void
30 28b49df3 2006-07-18 devnull usage(void)
31 28b49df3 2006-07-18 devnull {
32 92baf59b 2007-08-23 rsc fprint(2, "usage: mirrorarenas [-sv] src dst [ranges]\n");
33 28b49df3 2006-07-18 devnull threadexitsall("usage");
34 28b49df3 2006-07-18 devnull }
35 27d28098 2007-04-21 devnull
36 27d28098 2007-04-21 devnull char *tagged;
37 beaf4875 2008-12-23 rsc char *tagname;
38 beaf4875 2008-12-23 rsc int tagindx;
39 27d28098 2007-04-21 devnull
40 27d28098 2007-04-21 devnull void
41 beaf4875 2008-12-23 rsc tag(int indx, char *name, char *fmt, ...)
42 27d28098 2007-04-21 devnull {
43 27d28098 2007-04-21 devnull va_list arg;
44 27d28098 2007-04-21 devnull
45 27d28098 2007-04-21 devnull if(tagged){
46 27d28098 2007-04-21 devnull free(tagged);
47 27d28098 2007-04-21 devnull tagged = nil;
48 27d28098 2007-04-21 devnull }
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);
54 27d28098 2007-04-21 devnull }
55 27d28098 2007-04-21 devnull
56 beaf4875 2008-12-23 rsc enum
57 beaf4875 2008-12-23 rsc {
58 beaf4875 2008-12-23 rsc Sealed = 1,
59 beaf4875 2008-12-23 rsc Mirrored = 2,
60 beaf4875 2008-12-23 rsc Empty = 4,
61 beaf4875 2008-12-23 rsc };
62 beaf4875 2008-12-23 rsc
63 27d28098 2007-04-21 devnull void
64 beaf4875 2008-12-23 rsc setstatus(int bits)
65 beaf4875 2008-12-23 rsc {
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];
70 beaf4875 2008-12-23 rsc
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) {
74 beaf4875 2008-12-23 rsc case Sealed:
75 beaf4875 2008-12-23 rsc snprint(buf, sizeof buf, "sealed");
76 beaf4875 2008-12-23 rsc break;
77 beaf4875 2008-12-23 rsc case Mirrored:
78 beaf4875 2008-12-23 rsc snprint(buf, sizeof buf, "mirrored");
79 beaf4875 2008-12-23 rsc break;
80 beaf4875 2008-12-23 rsc case Sealed+Mirrored:
81 beaf4875 2008-12-23 rsc snprint(buf, sizeof buf, "mirrored sealed");
82 beaf4875 2008-12-23 rsc break;
83 beaf4875 2008-12-23 rsc case Empty:
84 beaf4875 2008-12-23 rsc snprint(buf, sizeof buf, "empty");
85 beaf4875 2008-12-23 rsc break;
86 beaf4875 2008-12-23 rsc default:
87 beaf4875 2008-12-23 rsc snprint(buf, sizeof buf, "%d", bits);
88 beaf4875 2008-12-23 rsc break;
89 beaf4875 2008-12-23 rsc }
90 beaf4875 2008-12-23 rsc print("%T %s-%s %s\n", startname, endname, buf);
91 beaf4875 2008-12-23 rsc }
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;
97 beaf4875 2008-12-23 rsc } else {
98 beaf4875 2008-12-23 rsc endindx = tagindx;
99 beaf4875 2008-12-23 rsc endname = tagname;
100 beaf4875 2008-12-23 rsc }
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;
104 beaf4875 2008-12-23 rsc return;
105 beaf4875 2008-12-23 rsc }
106 beaf4875 2008-12-23 rsc }
107 beaf4875 2008-12-23 rsc
108 beaf4875 2008-12-23 rsc void
109 27d28098 2007-04-21 devnull chat(char *fmt, ...)
110 27d28098 2007-04-21 devnull {
111 27d28098 2007-04-21 devnull va_list arg;
112 27d28098 2007-04-21 devnull
113 beaf4875 2008-12-23 rsc setstatus(-1);
114 beaf4875 2008-12-23 rsc
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;
119 27d28098 2007-04-21 devnull }
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);
123 27d28098 2007-04-21 devnull }
124 27d28098 2007-04-21 devnull
125 27d28098 2007-04-21 devnull #pragma varargck argpos tag 1
126 27d28098 2007-04-21 devnull #pragma varargck argpos chat 1
127 28b49df3 2006-07-18 devnull
128 27d28098 2007-04-21 devnull
129 28b49df3 2006-07-18 devnull int
130 28b49df3 2006-07-18 devnull ereadpart(Part *p, u64int offset, u8int *buf, u32int count)
131 28b49df3 2006-07-18 devnull {
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;
135 28b49df3 2006-07-18 devnull }
136 28b49df3 2006-07-18 devnull return 0;
137 28b49df3 2006-07-18 devnull }
138 28b49df3 2006-07-18 devnull
139 28b49df3 2006-07-18 devnull int
140 28b49df3 2006-07-18 devnull ewritepart(Part *p, u64int offset, u8int *buf, u32int count)
141 28b49df3 2006-07-18 devnull {
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;
145 28b49df3 2006-07-18 devnull }
146 28b49df3 2006-07-18 devnull return 0;
147 28b49df3 2006-07-18 devnull }
148 28b49df3 2006-07-18 devnull
149 28b49df3 2006-07-18 devnull /*
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.
153 28b49df3 2006-07-18 devnull */
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)
157 28b49df3 2006-07-18 devnull {
158 28b49df3 2006-07-18 devnull Write *w;
159 28b49df3 2006-07-18 devnull
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;
166 28b49df3 2006-07-18 devnull }
167 28b49df3 2006-07-18 devnull }
168 28b49df3 2006-07-18 devnull
169 28b49df3 2006-07-18 devnull int
170 28b49df3 2006-07-18 devnull copy(uvlong start, uvlong end, char *what, DigestState *ds)
171 28b49df3 2006-07-18 devnull {
172 28b49df3 2006-07-18 devnull int i, n;
173 28b49df3 2006-07-18 devnull uvlong o;
174 beaf4875 2008-12-23 rsc enum {
175 beaf4875 2008-12-23 rsc Chunk = 1024*1024
176 beaf4875 2008-12-23 rsc };
177 beaf4875 2008-12-23 rsc static uchar tmpbuf[2*Chunk+MaxIo];
178 beaf4875 2008-12-23 rsc static uchar *tmp[2];
179 beaf4875 2008-12-23 rsc uchar *p;
180 28b49df3 2006-07-18 devnull Write w[2];
181 28b49df3 2006-07-18 devnull
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);
185 28b49df3 2006-07-18 devnull
186 beaf4875 2008-12-23 rsc // align the buffers so readpart/writepart can do big transfers
187 beaf4875 2008-12-23 rsc p = tmpbuf;
188 beaf4875 2008-12-23 rsc if((uintptr)p%MaxIo)
189 beaf4875 2008-12-23 rsc p += MaxIo - (uintptr)p%MaxIo;
190 beaf4875 2008-12-23 rsc tmp[0] = p;
191 beaf4875 2008-12-23 rsc tmp[1] = p + Chunk;
192 beaf4875 2008-12-23 rsc
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);
195 28b49df3 2006-07-18 devnull
196 28b49df3 2006-07-18 devnull i = 0;
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;
201 beaf4875 2008-12-23 rsc n = Chunk;
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]);
211 28b49df3 2006-07-18 devnull if(ds)
212 28b49df3 2006-07-18 devnull sha1(tmp[i], n, nil, ds);
213 28b49df3 2006-07-18 devnull i = 1-i;
214 28b49df3 2006-07-18 devnull }
215 28b49df3 2006-07-18 devnull if(w[i].error)
216 28b49df3 2006-07-18 devnull goto error;
217 28b49df3 2006-07-18 devnull
218 28b49df3 2006-07-18 devnull /*
219 28b49df3 2006-07-18 devnull * wait for queued write to finish
220 28b49df3 2006-07-18 devnull */
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;
226 28b49df3 2006-07-18 devnull
227 28b49df3 2006-07-18 devnull error:
228 28b49df3 2006-07-18 devnull /*
229 28b49df3 2006-07-18 devnull * sync with write proc
230 28b49df3 2006-07-18 devnull */
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;
237 28b49df3 2006-07-18 devnull }
238 28b49df3 2006-07-18 devnull
239 28b49df3 2006-07-18 devnull /* single-threaded, for reference */
240 28b49df3 2006-07-18 devnull int
241 28b49df3 2006-07-18 devnull copy1(uvlong start, uvlong end, char *what, DigestState *ds)
242 28b49df3 2006-07-18 devnull {
243 28b49df3 2006-07-18 devnull int n;
244 28b49df3 2006-07-18 devnull uvlong o;
245 28b49df3 2006-07-18 devnull static uchar tmp[1024*1024];
246 28b49df3 2006-07-18 devnull
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);
250 28b49df3 2006-07-18 devnull
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);
253 28b49df3 2006-07-18 devnull
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;
260 28b49df3 2006-07-18 devnull if(ds)
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;
264 28b49df3 2006-07-18 devnull }
265 28b49df3 2006-07-18 devnull return 0;
266 28b49df3 2006-07-18 devnull }
267 28b49df3 2006-07-18 devnull
268 28b49df3 2006-07-18 devnull int
269 28b49df3 2006-07-18 devnull asha1(Part *p, uvlong start, uvlong end, DigestState *ds)
270 28b49df3 2006-07-18 devnull {
271 28b49df3 2006-07-18 devnull int n;
272 28b49df3 2006-07-18 devnull uvlong o;
273 28b49df3 2006-07-18 devnull static uchar tmp[1024*1024];
274 28b49df3 2006-07-18 devnull
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);
278 28b49df3 2006-07-18 devnull
279 28b49df3 2006-07-18 devnull if(verbose)
280 27d28098 2007-04-21 devnull chat("%T sha1 %,llud-%,llud\n", start, end);
281 28b49df3 2006-07-18 devnull
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);
289 28b49df3 2006-07-18 devnull }
290 28b49df3 2006-07-18 devnull return 0;
291 28b49df3 2006-07-18 devnull }
292 28b49df3 2006-07-18 devnull
293 28b49df3 2006-07-18 devnull uvlong
294 28b49df3 2006-07-18 devnull rdown(uvlong a, int b)
295 28b49df3 2006-07-18 devnull {
296 28b49df3 2006-07-18 devnull return a-a%b;
297 28b49df3 2006-07-18 devnull }
298 28b49df3 2006-07-18 devnull
299 28b49df3 2006-07-18 devnull uvlong
300 28b49df3 2006-07-18 devnull rup(uvlong a, int b)
301 28b49df3 2006-07-18 devnull {
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;
305 28b49df3 2006-07-18 devnull }
306 28b49df3 2006-07-18 devnull
307 28b49df3 2006-07-18 devnull void
308 beaf4875 2008-12-23 rsc mirror(int indx, Arena *sa, Arena *da)
309 28b49df3 2006-07-18 devnull {
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;
316 28b49df3 2006-07-18 devnull
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;
320 28b49df3 2006-07-18 devnull
321 28b49df3 2006-07-18 devnull astart = base - blocksize;
322 28b49df3 2006-07-18 devnull aend = end + blocksize;
323 28b49df3 2006-07-18 devnull
324 beaf4875 2008-12-23 rsc tag(indx, sa->name, "%T %s (%,llud-%,llud)\n", sa->name, astart, aend);
325 27d28098 2007-04-21 devnull
326 28b49df3 2006-07-18 devnull if(force){
327 28b49df3 2006-07-18 devnull copy(astart, aend, "all", nil);
328 28b49df3 2006-07-18 devnull return;
329 28b49df3 2006-07-18 devnull }
330 28b49df3 2006-07-18 devnull
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);
336 28b49df3 2006-07-18 devnull return;
337 ebcef6f0 2007-04-24 devnull }
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. */
340 28b49df3 2006-07-18 devnull }
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";
344 28b49df3 2006-07-18 devnull return;
345 28b49df3 2006-07-18 devnull }
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";
349 28b49df3 2006-07-18 devnull return;
350 28b49df3 2006-07-18 devnull }
351 28b49df3 2006-07-18 devnull
352 28b49df3 2006-07-18 devnull if(da->clumpmagic != sa->clumpmagic){
353 28b49df3 2006-07-18 devnull /*
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.
356 28b49df3 2006-07-18 devnull */
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)
361 28b49df3 2006-07-18 devnull return;
362 28b49df3 2006-07-18 devnull }
363 28b49df3 2006-07-18 devnull
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)
373 28b49df3 2006-07-18 devnull return;
374 28b49df3 2006-07-18 devnull
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;
384 28b49df3 2006-07-18 devnull }
385 28b49df3 2006-07-18 devnull
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)
390 28b49df3 2006-07-18 devnull return;
391 28b49df3 2006-07-18 devnull if(copy(di, si, "data", ds) < 0)
392 28b49df3 2006-07-18 devnull return;
393 28b49df3 2006-07-18 devnull shaoff = si;
394 28b49df3 2006-07-18 devnull }
395 28b49df3 2006-07-18 devnull
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;
399 28b49df3 2006-07-18 devnull
400 28b49df3 2006-07-18 devnull if(sa->diskstats.sealed){
401 28b49df3 2006-07-18 devnull /*
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.
404 28b49df3 2006-07-18 devnull */
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)
407 28b49df3 2006-07-18 devnull return;
408 28b49df3 2006-07-18 devnull if(copy(v, si, "hole", ds) < 0)
409 28b49df3 2006-07-18 devnull return;
410 28b49df3 2006-07-18 devnull shaoff = si;
411 28b49df3 2006-07-18 devnull }
412 28b49df3 2006-07-18 devnull
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)
415 28b49df3 2006-07-18 devnull return;
416 28b49df3 2006-07-18 devnull if(copy(si, di, "directory", ds) < 0) /* si < di because clumpinfo blocks grow down */
417 28b49df3 2006-07-18 devnull return;
418 28b49df3 2006-07-18 devnull shaoff = di;
419 28b49df3 2006-07-18 devnull }
420 28b49df3 2006-07-18 devnull
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;
425 28b49df3 2006-07-18 devnull
426 ebcef6f0 2007-04-24 devnull /*
427 ebcef6f0 2007-04-24 devnull * Repack the arena tail information
428 ebcef6f0 2007-04-24 devnull * and save it for next time...
429 ebcef6f0 2007-04-24 devnull */
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)
433 28b49df3 2006-07-18 devnull return;
434 28b49df3 2006-07-18 devnull
435 92baf59b 2007-08-23 rsc if(sealed){
436 ebcef6f0 2007-04-24 devnull /*
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.
444 ebcef6f0 2007-04-24 devnull */
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)
447 ebcef6f0 2007-04-24 devnull return;
448 92baf59b 2007-08-23 rsc if(dosha1){
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)
456 92baf59b 2007-08-23 rsc return;
457 92baf59b 2007-08-23 rsc }else{
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";
464 92baf59b 2007-08-23 rsc }
465 92baf59b 2007-08-23 rsc }else{
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)
470 28b49df3 2006-07-18 devnull return;
471 28b49df3 2006-07-18 devnull }
472 ebcef6f0 2007-04-24 devnull }else{
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);
476 beaf4875 2008-12-23 rsc }
477 beaf4875 2008-12-23 rsc if(sa->diskstats.used > 0)
478 beaf4875 2008-12-23 rsc setstatus(Mirrored);
479 beaf4875 2008-12-23 rsc else
480 beaf4875 2008-12-23 rsc setstatus(Empty);
481 28b49df3 2006-07-18 devnull }
482 28b49df3 2006-07-18 devnull }
483 28b49df3 2006-07-18 devnull
484 28b49df3 2006-07-18 devnull void
485 28b49df3 2006-07-18 devnull mirrormany(ArenaPart *sp, ArenaPart *dp, char *range)
486 28b49df3 2006-07-18 devnull {
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;
490 28b49df3 2006-07-18 devnull
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);
496 28b49df3 2006-07-18 devnull }
497 beaf4875 2008-12-23 rsc setstatus(-1);
498 28b49df3 2006-07-18 devnull return;
499 28b49df3 2006-07-18 devnull }
500 28b49df3 2006-07-18 devnull if(strcmp(range, "none") == 0)
501 28b49df3 2006-07-18 devnull return;
502 28b49df3 2006-07-18 devnull
503 28b49df3 2006-07-18 devnull for(s=range; *s; s=t){
504 28b49df3 2006-07-18 devnull t = strchr(s, ',');
505 28b49df3 2006-07-18 devnull if(t)
506 28b49df3 2006-07-18 devnull *t++ = 0;
507 28b49df3 2006-07-18 devnull else
508 28b49df3 2006-07-18 devnull t = s+strlen(s);
509 28b49df3 2006-07-18 devnull if(*s == '-')
510 28b49df3 2006-07-18 devnull lo = 0;
511 28b49df3 2006-07-18 devnull else
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 == '-'){
515 28b49df3 2006-07-18 devnull s++;
516 28b49df3 2006-07-18 devnull if(*s == 0)
517 28b49df3 2006-07-18 devnull hi = sp->narenas-1;
518 28b49df3 2006-07-18 devnull else
519 28b49df3 2006-07-18 devnull hi = strtol(s, &s, 0);
520 28b49df3 2006-07-18 devnull }
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;
524 28b49df3 2006-07-18 devnull }
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);
529 28b49df3 2006-07-18 devnull }
530 beaf4875 2008-12-23 rsc setstatus(-1);
531 28b49df3 2006-07-18 devnull }
532 28b49df3 2006-07-18 devnull }
533 28b49df3 2006-07-18 devnull
534 28b49df3 2006-07-18 devnull
535 28b49df3 2006-07-18 devnull void
536 28b49df3 2006-07-18 devnull threadmain(int argc, char **argv)
537 28b49df3 2006-07-18 devnull {
538 28b49df3 2006-07-18 devnull int i;
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;
542 28b49df3 2006-07-18 devnull
543 28b49df3 2006-07-18 devnull ventifmtinstall();
544 28b49df3 2006-07-18 devnull
545 28b49df3 2006-07-18 devnull ARGBEGIN{
546 28b49df3 2006-07-18 devnull case 'F':
547 28b49df3 2006-07-18 devnull force = 1;
548 28b49df3 2006-07-18 devnull break;
549 28b49df3 2006-07-18 devnull case 'v':
550 28b49df3 2006-07-18 devnull verbose++;
551 28b49df3 2006-07-18 devnull break;
552 92baf59b 2007-08-23 rsc case 's':
553 92baf59b 2007-08-23 rsc dosha1 = 0;
554 92baf59b 2007-08-23 rsc break;
555 28b49df3 2006-07-18 devnull default:
556 28b49df3 2006-07-18 devnull usage();
557 28b49df3 2006-07-18 devnull }ARGEND
558 28b49df3 2006-07-18 devnull
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];
564 28b49df3 2006-07-18 devnull
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]);
577 28b49df3 2006-07-18 devnull
578 28b49df3 2006-07-18 devnull /*
579 28b49df3 2006-07-18 devnull * The arena geometries must match or all bets are off.
580 28b49df3 2006-07-18 devnull */
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);
594 28b49df3 2006-07-18 devnull }
595 28b49df3 2006-07-18 devnull
596 28b49df3 2006-07-18 devnull /*
597 28b49df3 2006-07-18 devnull * Mirror one arena at a time.
598 28b49df3 2006-07-18 devnull */
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);
604 28b49df3 2006-07-18 devnull }