xref: /plan9/sys/src/cmd/cwfs/mworm.c (revision f9e1cf08d3be51592e03e639fc848a68dc31a55e)
1 #include	"all.h"
2 
3 /*
4  * multiple cat devices
5  */
6 void
mcatinit(Device * d)7 mcatinit(Device *d)
8 {
9 	Device *x, **list;
10 
11 	d->cat.ndev = 0;
12 	for(x=d->cat.first; x; x=x->link) {
13 		devinit(x);
14 		d->cat.ndev++;
15 	}
16 
17 	list = malloc(d->cat.ndev*sizeof(Device*));
18 	d->private = list;
19 	for(x=d->cat.first; x; x=x->link) {
20 		*list++ = x;
21 		x->size = devsize(x);
22 	}
23 }
24 
25 Devsize
mcatsize(Device * d)26 mcatsize(Device *d)
27 {
28 	Device *x;
29 	Devsize l, m;
30 
31 	l = 0;
32 	for(x=d->cat.first; x; x=x->link) {
33 		m = x->size;
34 		if(m == 0) {
35 			m = devsize(x);
36 			x->size = m;
37 		}
38 		l += m;
39 	}
40 	return l;
41 }
42 
43 int
mcatread(Device * d,Off b,void * c)44 mcatread(Device *d, Off b, void *c)
45 {
46 	Device *x;
47 	Devsize l, m;
48 
49 	l = 0;
50 	for(x=d->cat.first; x; x=x->link) {
51 		m = x->size;
52 		if(m == 0) {
53 			m = devsize(x);
54 			x->size = m;
55 		}
56 		if(b < l+m)
57 			return devread(x, b-l, c);
58 		l += m;
59 	}
60 	print("mcatread past end: %Z block %lld, %lld beyond end\n",
61 		d, (Wideoff)b, (Wideoff)l);
62 	return 1;
63 }
64 
65 int
mcatwrite(Device * d,Off b,void * c)66 mcatwrite(Device *d, Off b, void *c)
67 {
68 	Device *x;
69 	Devsize l, m;
70 
71 	l = 0;
72 	for(x=d->cat.first; x; x=x->link) {
73 		m = x->size;
74 		if(m == 0) {
75 			m = devsize(x);
76 			x->size = m;
77 		}
78 		if(b < l+m)
79 			return devwrite(x, b-l, c);
80 		l += m;
81 	}
82 	print("mcatwrite past end: %Z block %lld, %lld beyond end\n",
83 		d, (Wideoff)b, (Wideoff)l);
84 	return 1;
85 }
86 
87 /*
88  * multiple interleave devices
89  */
90 void
mlevinit(Device * d)91 mlevinit(Device *d)
92 {
93 	Device *x;
94 
95 	mcatinit(d);
96 	for(x=d->cat.first; x; x=x->link)
97 		x->size = devsize(x);
98 }
99 
100 Devsize
mlevsize(Device * d)101 mlevsize(Device *d)
102 {
103 	Device *x;
104 	int n;
105 	Devsize m, min;
106 
107 	min = 0;
108 	n = 0;
109 	for(x=d->cat.first; x; x=x->link) {
110 		m = x->size;
111 		if(m == 0) {
112 			m = devsize(x);
113 			x->size = m;
114 		}
115 		if(min == 0 || m < min)
116 			min = m;
117 		n++;
118 	}
119 	return n * min;
120 }
121 
122 int
mlevread(Device * d,Off b,void * c)123 mlevread(Device *d, Off b, void *c)
124 {
125 	int n;
126 	Device **list;
127 
128 	n = d->cat.ndev;
129 	list = d->private;
130 	return devread(list[b%n], b/n, c);
131 }
132 
133 int
mlevwrite(Device * d,Off b,void * c)134 mlevwrite(Device *d, Off b, void *c)
135 {
136 	int n;
137 	Device **list;
138 
139 	n = d->cat.ndev;
140 	list = d->private;
141 	return devwrite(list[b%n], b/n, c);
142 }
143 
144 /*
145  * partition device
146  */
147 void
partinit(Device * d)148 partinit(Device *d)
149 {
150 
151 	devinit(d->part.d);
152 	d->part.d->size = devsize(d->part.d);
153 }
154 
155 Devsize
partsize(Device * d)156 partsize(Device *d)
157 {
158 	Devsize size, l;
159 
160 	l = d->part.d->size / 100;
161 	size = d->part.size * l;
162 	if(size == 0)
163 		size = l*100;
164 	return size;
165 }
166 
167 int
partread(Device * d,Off b,void * c)168 partread(Device *d, Off b, void *c)
169 {
170 	Devsize base, size, l;
171 
172 	l = d->part.d->size / 100;
173 	base = d->part.base * l;
174 	size = d->part.size * l;
175 	if(size == 0)
176 		size = l*100;
177 	if(b < size)
178 		return devread(d->part.d, base+b, c);
179 	print("partread past end: %Z blk %lld size %lld\n",
180 		d, (Wideoff)b, (Wideoff)size);
181 	return 1;
182 }
183 
184 int
partwrite(Device * d,Off b,void * c)185 partwrite(Device *d, Off b, void *c)
186 {
187 	Devsize base, size, l;
188 
189 	l = d->part.d->size / 100;
190 	base = d->part.base * l;
191 	size = d->part.size * l;
192 	if(size == 0)
193 		size = l*100;
194 	if(b < size)
195 		return devwrite(d->part.d, base+b, c);
196 	print("partwrite past end: %Z blk %lld size %lld\n",
197 		d, (Wideoff)b, (Wideoff)size);
198 	return 1;
199 }
200 
201 /*
202  * mirror device
203  */
204 void
mirrinit(Device * d)205 mirrinit(Device *d)
206 {
207 	Device *x;
208 
209 	mcatinit(d);
210 	for(x=d->cat.first; x; x=x->link)
211 		x->size = devsize(x);
212 }
213 
214 Devsize
mirrsize(Device * d)215 mirrsize(Device *d)
216 {
217 	Device *x;
218 	int n;
219 	Devsize m, min;
220 
221 	min = 0;
222 	n = 0;
223 	for(x=d->cat.first; x; x=x->link) {
224 		m = x->size;
225 		if(m == 0) {
226 			m = devsize(x);
227 			x->size = m;
228 		}
229 		if(min == 0 || m < min)
230 			min = m;
231 		n++;
232 	}
233 	return min;
234 }
235 
236 int
mirrread(Device * d,Off b,void * c)237 mirrread(Device *d, Off b, void *c)
238 {
239 	Device *x;
240 
241 	if (d->cat.first == nil) {
242 		print("mirrread: empty mirror %Z\n", d);
243 		return 1;
244 	}
245 	for(x=d->cat.first; x; x=x->link) {
246 		if(x->size == 0)
247 			x->size = devsize(x);
248 		if (devread(x, b, c) == 0)	/* okay? */
249 			return 0;
250 	}
251 	// DANGER WILL ROBINSON
252 	print("mirrread: all mirrors of %Z block %lld are bad\n",
253 		d, (Wideoff)b);
254 	return 1;
255 }
256 
257 /*
258  * write the mirror(s) first so that a power outage, for example, will
259  * find the main device written only if the mirrors are too, thus
260  * checking the main device will also correctly check the mirror(s).
261  *
262  * devread and devwrite are synchronous; all buffering must be
263  * implemented at higher levels.
264  */
265 static int
ewrite(Device * x,Off b,void * c)266 ewrite(Device *x, Off b, void *c)
267 {
268 	if(x->size == 0)
269 		x->size = devsize(x);
270 	if (devwrite(x, b, c) != 0) {
271 		print("mirrwrite: error at %Z block %lld\n", x, (Wideoff)b);
272 		return 1;
273 	}
274 	return 0;
275 }
276 
277 static int
wrmirrs1st(Device * x,Off b,void * c)278 wrmirrs1st(Device *x, Off b, void *c)	// write any mirrors of x, then x
279 {
280 	int e;
281 
282 	if (x == nil)
283 		return 0;
284 	e = wrmirrs1st(x->link, b, c);
285 	return e | ewrite(x, b, c);
286 }
287 
288 int
mirrwrite(Device * d,Off b,void * c)289 mirrwrite(Device *d, Off b, void *c)
290 {
291 	if (d->cat.first == nil) {
292 		print("mirrwrite: empty mirror %Z\n", d);
293 		return 1;
294 	}
295 	return wrmirrs1st(d->cat.first, b, c);
296 }
297