Blame


1 28b49df3 2006-07-18 devnull /*
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.
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 fa325e9b 2020-01-10 cross
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 fa325e9b 2020-01-10 cross 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 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];
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 startname = tagname;
95 beaf4875 2008-12-23 rsc endname = tagname;
96 beaf4875 2008-12-23 rsc } else {
97 beaf4875 2008-12-23 rsc endname = tagname;
98 beaf4875 2008-12-23 rsc }
99 beaf4875 2008-12-23 rsc if(bits < 0) {
100 beaf4875 2008-12-23 rsc startindx = -1;
101 beaf4875 2008-12-23 rsc return;
102 fa325e9b 2020-01-10 cross }
103 beaf4875 2008-12-23 rsc }
104 beaf4875 2008-12-23 rsc
105 beaf4875 2008-12-23 rsc void
106 27d28098 2007-04-21 devnull chat(char *fmt, ...)
107 27d28098 2007-04-21 devnull {
108 27d28098 2007-04-21 devnull va_list arg;
109 27d28098 2007-04-21 devnull
110 beaf4875 2008-12-23 rsc setstatus(-1);
111 beaf4875 2008-12-23 rsc
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;
116 27d28098 2007-04-21 devnull }
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);
120 27d28098 2007-04-21 devnull }
121 27d28098 2007-04-21 devnull
122 3155ec71 2011-06-13 rsc #pragma varargck argpos tag 3
123 27d28098 2007-04-21 devnull #pragma varargck argpos chat 1
124 28b49df3 2006-07-18 devnull
125 27d28098 2007-04-21 devnull
126 28b49df3 2006-07-18 devnull int
127 28b49df3 2006-07-18 devnull ereadpart(Part *p, u64int offset, u8int *buf, u32int count)
128 28b49df3 2006-07-18 devnull {
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;
132 28b49df3 2006-07-18 devnull }
133 28b49df3 2006-07-18 devnull return 0;
134 28b49df3 2006-07-18 devnull }
135 fa325e9b 2020-01-10 cross
136 28b49df3 2006-07-18 devnull int
137 28b49df3 2006-07-18 devnull ewritepart(Part *p, u64int offset, u8int *buf, u32int count)
138 28b49df3 2006-07-18 devnull {
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;
142 28b49df3 2006-07-18 devnull }
143 28b49df3 2006-07-18 devnull return 0;
144 28b49df3 2006-07-18 devnull }
145 28b49df3 2006-07-18 devnull
146 28b49df3 2006-07-18 devnull /*
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.
150 28b49df3 2006-07-18 devnull */
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)
154 28b49df3 2006-07-18 devnull {
155 28b49df3 2006-07-18 devnull Write *w;
156 fa325e9b 2020-01-10 cross
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;
163 28b49df3 2006-07-18 devnull }
164 28b49df3 2006-07-18 devnull }
165 28b49df3 2006-07-18 devnull
166 28b49df3 2006-07-18 devnull int
167 28b49df3 2006-07-18 devnull copy(uvlong start, uvlong end, char *what, DigestState *ds)
168 28b49df3 2006-07-18 devnull {
169 28b49df3 2006-07-18 devnull int i, n;
170 28b49df3 2006-07-18 devnull uvlong o;
171 beaf4875 2008-12-23 rsc enum {
172 beaf4875 2008-12-23 rsc Chunk = 1024*1024
173 beaf4875 2008-12-23 rsc };
174 beaf4875 2008-12-23 rsc static uchar tmpbuf[2*Chunk+MaxIo];
175 beaf4875 2008-12-23 rsc static uchar *tmp[2];
176 beaf4875 2008-12-23 rsc uchar *p;
177 28b49df3 2006-07-18 devnull Write w[2];
178 fa325e9b 2020-01-10 cross
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);
182 28b49df3 2006-07-18 devnull
183 beaf4875 2008-12-23 rsc // align the buffers so readpart/writepart can do big transfers
184 beaf4875 2008-12-23 rsc p = tmpbuf;
185 beaf4875 2008-12-23 rsc if((uintptr)p%MaxIo)
186 beaf4875 2008-12-23 rsc p += MaxIo - (uintptr)p%MaxIo;
187 beaf4875 2008-12-23 rsc tmp[0] = p;
188 beaf4875 2008-12-23 rsc tmp[1] = p + Chunk;
189 beaf4875 2008-12-23 rsc
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);
192 28b49df3 2006-07-18 devnull
193 28b49df3 2006-07-18 devnull i = 0;
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;
198 beaf4875 2008-12-23 rsc n = Chunk;
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]);
208 28b49df3 2006-07-18 devnull if(ds)
209 28b49df3 2006-07-18 devnull sha1(tmp[i], n, nil, ds);
210 28b49df3 2006-07-18 devnull i = 1-i;
211 28b49df3 2006-07-18 devnull }
212 28b49df3 2006-07-18 devnull if(w[i].error)
213 28b49df3 2006-07-18 devnull goto error;
214 28b49df3 2006-07-18 devnull
215 28b49df3 2006-07-18 devnull /*
216 28b49df3 2006-07-18 devnull * wait for queued write to finish
217 28b49df3 2006-07-18 devnull */
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;
223 28b49df3 2006-07-18 devnull
224 28b49df3 2006-07-18 devnull error:
225 28b49df3 2006-07-18 devnull /*
226 28b49df3 2006-07-18 devnull * sync with write proc
227 28b49df3 2006-07-18 devnull */
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;
234 28b49df3 2006-07-18 devnull }
235 28b49df3 2006-07-18 devnull
236 28b49df3 2006-07-18 devnull /* single-threaded, for reference */
237 28b49df3 2006-07-18 devnull int
238 28b49df3 2006-07-18 devnull copy1(uvlong start, uvlong end, char *what, DigestState *ds)
239 28b49df3 2006-07-18 devnull {
240 28b49df3 2006-07-18 devnull int n;
241 28b49df3 2006-07-18 devnull uvlong o;
242 28b49df3 2006-07-18 devnull static uchar tmp[1024*1024];
243 fa325e9b 2020-01-10 cross
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);
247 28b49df3 2006-07-18 devnull
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);
250 28b49df3 2006-07-18 devnull
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;
257 28b49df3 2006-07-18 devnull if(ds)
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;
261 28b49df3 2006-07-18 devnull }
262 28b49df3 2006-07-18 devnull return 0;
263 28b49df3 2006-07-18 devnull }
264 28b49df3 2006-07-18 devnull
265 28b49df3 2006-07-18 devnull int
266 28b49df3 2006-07-18 devnull asha1(Part *p, uvlong start, uvlong end, DigestState *ds)
267 28b49df3 2006-07-18 devnull {
268 28b49df3 2006-07-18 devnull int n;
269 28b49df3 2006-07-18 devnull uvlong o;
270 28b49df3 2006-07-18 devnull static uchar tmp[1024*1024];
271 28b49df3 2006-07-18 devnull
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);
275 28b49df3 2006-07-18 devnull
276 28b49df3 2006-07-18 devnull if(verbose)
277 27d28098 2007-04-21 devnull chat("%T sha1 %,llud-%,llud\n", start, end);
278 28b49df3 2006-07-18 devnull
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);
286 28b49df3 2006-07-18 devnull }
287 28b49df3 2006-07-18 devnull return 0;
288 28b49df3 2006-07-18 devnull }
289 28b49df3 2006-07-18 devnull
290 28b49df3 2006-07-18 devnull uvlong
291 28b49df3 2006-07-18 devnull rdown(uvlong a, int b)
292 28b49df3 2006-07-18 devnull {
293 28b49df3 2006-07-18 devnull return a-a%b;
294 28b49df3 2006-07-18 devnull }
295 28b49df3 2006-07-18 devnull
296 28b49df3 2006-07-18 devnull uvlong
297 28b49df3 2006-07-18 devnull rup(uvlong a, int b)
298 28b49df3 2006-07-18 devnull {
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;
302 28b49df3 2006-07-18 devnull }
303 28b49df3 2006-07-18 devnull
304 28b49df3 2006-07-18 devnull void
305 beaf4875 2008-12-23 rsc mirror(int indx, Arena *sa, Arena *da)
306 28b49df3 2006-07-18 devnull {
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;
313 fa325e9b 2020-01-10 cross
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;
317 fa325e9b 2020-01-10 cross
318 28b49df3 2006-07-18 devnull astart = base - blocksize;
319 28b49df3 2006-07-18 devnull aend = end + blocksize;
320 28b49df3 2006-07-18 devnull
321 beaf4875 2008-12-23 rsc tag(indx, sa->name, "%T %s (%,llud-%,llud)\n", sa->name, astart, aend);
322 fa325e9b 2020-01-10 cross
323 28b49df3 2006-07-18 devnull if(force){
324 28b49df3 2006-07-18 devnull copy(astart, aend, "all", nil);
325 28b49df3 2006-07-18 devnull return;
326 28b49df3 2006-07-18 devnull }
327 28b49df3 2006-07-18 devnull
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);
333 28b49df3 2006-07-18 devnull return;
334 ebcef6f0 2007-04-24 devnull }
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. */
337 28b49df3 2006-07-18 devnull }
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";
341 28b49df3 2006-07-18 devnull return;
342 28b49df3 2006-07-18 devnull }
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";
346 28b49df3 2006-07-18 devnull return;
347 28b49df3 2006-07-18 devnull }
348 28b49df3 2006-07-18 devnull
349 28b49df3 2006-07-18 devnull if(da->clumpmagic != sa->clumpmagic){
350 28b49df3 2006-07-18 devnull /*
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.
353 28b49df3 2006-07-18 devnull */
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)
358 28b49df3 2006-07-18 devnull return;
359 28b49df3 2006-07-18 devnull }
360 fa325e9b 2020-01-10 cross
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)
370 28b49df3 2006-07-18 devnull return;
371 28b49df3 2006-07-18 devnull
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;
381 28b49df3 2006-07-18 devnull }
382 fa325e9b 2020-01-10 cross
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)
387 28b49df3 2006-07-18 devnull return;
388 28b49df3 2006-07-18 devnull if(copy(di, si, "data", ds) < 0)
389 28b49df3 2006-07-18 devnull return;
390 28b49df3 2006-07-18 devnull shaoff = si;
391 28b49df3 2006-07-18 devnull }
392 fa325e9b 2020-01-10 cross
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;
396 28b49df3 2006-07-18 devnull
397 28b49df3 2006-07-18 devnull if(sa->diskstats.sealed){
398 28b49df3 2006-07-18 devnull /*
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.
401 28b49df3 2006-07-18 devnull */
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)
404 28b49df3 2006-07-18 devnull return;
405 28b49df3 2006-07-18 devnull if(copy(v, si, "hole", ds) < 0)
406 28b49df3 2006-07-18 devnull return;
407 28b49df3 2006-07-18 devnull shaoff = si;
408 28b49df3 2006-07-18 devnull }
409 28b49df3 2006-07-18 devnull
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)
412 28b49df3 2006-07-18 devnull return;
413 28b49df3 2006-07-18 devnull if(copy(si, di, "directory", ds) < 0) /* si < di because clumpinfo blocks grow down */
414 28b49df3 2006-07-18 devnull return;
415 28b49df3 2006-07-18 devnull shaoff = di;
416 28b49df3 2006-07-18 devnull }
417 28b49df3 2006-07-18 devnull
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;
422 fa325e9b 2020-01-10 cross
423 ebcef6f0 2007-04-24 devnull /*
424 ebcef6f0 2007-04-24 devnull * Repack the arena tail information
425 ebcef6f0 2007-04-24 devnull * and save it for next time...
426 ebcef6f0 2007-04-24 devnull */
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)
430 28b49df3 2006-07-18 devnull return;
431 28b49df3 2006-07-18 devnull
432 92baf59b 2007-08-23 rsc if(sealed){
433 ebcef6f0 2007-04-24 devnull /*
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.
441 ebcef6f0 2007-04-24 devnull */
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)
444 ebcef6f0 2007-04-24 devnull return;
445 92baf59b 2007-08-23 rsc if(dosha1){
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)
453 92baf59b 2007-08-23 rsc return;
454 92baf59b 2007-08-23 rsc }else{
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";
461 92baf59b 2007-08-23 rsc }
462 92baf59b 2007-08-23 rsc }else{
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)
467 28b49df3 2006-07-18 devnull return;
468 28b49df3 2006-07-18 devnull }
469 ebcef6f0 2007-04-24 devnull }else{
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);
473 beaf4875 2008-12-23 rsc }
474 beaf4875 2008-12-23 rsc if(sa->diskstats.used > 0)
475 beaf4875 2008-12-23 rsc setstatus(Mirrored);
476 beaf4875 2008-12-23 rsc else
477 beaf4875 2008-12-23 rsc setstatus(Empty);
478 28b49df3 2006-07-18 devnull }
479 28b49df3 2006-07-18 devnull }
480 28b49df3 2006-07-18 devnull
481 28b49df3 2006-07-18 devnull void
482 28b49df3 2006-07-18 devnull mirrormany(ArenaPart *sp, ArenaPart *dp, char *range)
483 28b49df3 2006-07-18 devnull {
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;
487 28b49df3 2006-07-18 devnull
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);
493 28b49df3 2006-07-18 devnull }
494 beaf4875 2008-12-23 rsc setstatus(-1);
495 28b49df3 2006-07-18 devnull return;
496 28b49df3 2006-07-18 devnull }
497 28b49df3 2006-07-18 devnull if(strcmp(range, "none") == 0)
498 28b49df3 2006-07-18 devnull return;
499 28b49df3 2006-07-18 devnull
500 28b49df3 2006-07-18 devnull for(s=range; *s; s=t){
501 28b49df3 2006-07-18 devnull t = strchr(s, ',');
502 28b49df3 2006-07-18 devnull if(t)
503 28b49df3 2006-07-18 devnull *t++ = 0;
504 28b49df3 2006-07-18 devnull else
505 28b49df3 2006-07-18 devnull t = s+strlen(s);
506 28b49df3 2006-07-18 devnull if(*s == '-')
507 28b49df3 2006-07-18 devnull lo = 0;
508 28b49df3 2006-07-18 devnull else
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 == '-'){
512 28b49df3 2006-07-18 devnull s++;
513 28b49df3 2006-07-18 devnull if(*s == 0)
514 28b49df3 2006-07-18 devnull hi = sp->narenas-1;
515 28b49df3 2006-07-18 devnull else
516 28b49df3 2006-07-18 devnull hi = strtol(s, &s, 0);
517 28b49df3 2006-07-18 devnull }
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;
521 28b49df3 2006-07-18 devnull }
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);
526 28b49df3 2006-07-18 devnull }
527 beaf4875 2008-12-23 rsc setstatus(-1);
528 fa325e9b 2020-01-10 cross }
529 28b49df3 2006-07-18 devnull }
530 28b49df3 2006-07-18 devnull
531 28b49df3 2006-07-18 devnull
532 28b49df3 2006-07-18 devnull void
533 28b49df3 2006-07-18 devnull threadmain(int argc, char **argv)
534 28b49df3 2006-07-18 devnull {
535 28b49df3 2006-07-18 devnull int i;
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;
539 fa325e9b 2020-01-10 cross
540 28b49df3 2006-07-18 devnull ventifmtinstall();
541 28b49df3 2006-07-18 devnull
542 28b49df3 2006-07-18 devnull ARGBEGIN{
543 28b49df3 2006-07-18 devnull case 'F':
544 28b49df3 2006-07-18 devnull force = 1;
545 28b49df3 2006-07-18 devnull break;
546 28b49df3 2006-07-18 devnull case 'v':
547 28b49df3 2006-07-18 devnull verbose++;
548 28b49df3 2006-07-18 devnull break;
549 92baf59b 2007-08-23 rsc case 's':
550 92baf59b 2007-08-23 rsc dosha1 = 0;
551 92baf59b 2007-08-23 rsc break;
552 28b49df3 2006-07-18 devnull default:
553 28b49df3 2006-07-18 devnull usage();
554 28b49df3 2006-07-18 devnull }ARGEND
555 fa325e9b 2020-01-10 cross
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];
561 28b49df3 2006-07-18 devnull
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]);
574 fa325e9b 2020-01-10 cross
575 28b49df3 2006-07-18 devnull /*
576 28b49df3 2006-07-18 devnull * The arena geometries must match or all bets are off.
577 28b49df3 2006-07-18 devnull */
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);
591 28b49df3 2006-07-18 devnull }
592 fa325e9b 2020-01-10 cross
593 28b49df3 2006-07-18 devnull /*
594 28b49df3 2006-07-18 devnull * Mirror one arena at a time.
595 28b49df3 2006-07-18 devnull */
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);
601 28b49df3 2006-07-18 devnull }