xref: /plan9/sys/src/cmd/cwfs/mworm.c (revision 850dd0ca1bdf035e1410f3ad77ab360045f4571d)
1 #include	"all.h"
2 
3 /*
4  * multiple cat devices
5  */
6 void
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
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
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 %Z block %lld beyond end %lld\n",
61 		d, (Wideoff)b, (Wideoff)l);
62 	return 1;
63 }
64 
65 int
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 %Z block %lld beyond end %lld\n",
83 		d, (Wideoff)b, (Wideoff)l);
84 	return 1;
85 }
86 
87 /*
88  * multiple interleave devices
89  */
90 void
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
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
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
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
148 partinit(Device *d)
149 {
150 
151 	devinit(d->part.d);
152 	d->part.d->size = devsize(d->part.d);
153 }
154 
155 Devsize
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
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 %lld %lld\n", (Wideoff)b, (Wideoff)size);
180 	return 1;
181 }
182 
183 int
184 partwrite(Device *d, Off b, void *c)
185 {
186 	Devsize base, size, l;
187 
188 	l = d->part.d->size / 100;
189 	base = d->part.base * l;
190 	size = d->part.size * l;
191 	if(size == 0)
192 		size = l*100;
193 	if(b < size)
194 		return devwrite(d->part.d, base+b, c);
195 	print("partwrite %lld %lld\n", (Wideoff)b, (Wideoff)size);
196 	return 1;
197 }
198 
199 /*
200  * mirror device
201  */
202 void
203 mirrinit(Device *d)
204 {
205 	Device *x;
206 
207 	mcatinit(d);
208 	for(x=d->cat.first; x; x=x->link)
209 		x->size = devsize(x);
210 }
211 
212 Devsize
213 mirrsize(Device *d)
214 {
215 	Device *x;
216 	int n;
217 	Devsize m, min;
218 
219 	min = 0;
220 	n = 0;
221 	for(x=d->cat.first; x; x=x->link) {
222 		m = x->size;
223 		if(m == 0) {
224 			m = devsize(x);
225 			x->size = m;
226 		}
227 		if(min == 0 || m < min)
228 			min = m;
229 		n++;
230 	}
231 	return min;
232 }
233 
234 int
235 mirrread(Device *d, Off b, void *c)
236 {
237 	Device *x;
238 
239 	for(x=d->cat.first; x; x=x->link) {
240 		if(x->size == 0)
241 			x->size = devsize(x);
242 		if (devread(x, b, c) == 0)	/* okay? */
243 			return 0;
244 	}
245 	// DANGER WILL ROBINSON - all copies of this block were bad
246 	print("mirrread %Z error at block %lld\n", d, (Wideoff)b);
247 	return 1;
248 }
249 
250 /*
251  * write the mirror(s) first so that a power outage, for example, will
252  * find the main device written only if the mirrors are too, thus
253  * checking the main device will also correctly check the mirror(s).
254  *
255  * devread and devwrite are synchronous; all buffering must be
256  * implemented at higher levels.
257  */
258 static int
259 ewrite(Device *x, Off b, void *c)
260 {
261 	if(x->size == 0)
262 		x->size = devsize(x);
263 	if (devwrite(x, b, c) != 0) {
264 		print("mirrwrite %Z error at block %lld\n", x, (Wideoff)b);
265 		return 1;
266 	}
267 	return 0;
268 }
269 
270 static int
271 wrmirrs1st(Device *x, Off b, void *c)	// write any mirrors of x, then x
272 {
273 	int e;
274 
275 	if (x == nil)
276 		return 0;
277 	e = wrmirrs1st(x->link, b, c);
278 	return e | ewrite(x, b, c);
279 }
280 
281 int
282 mirrwrite(Device *d, Off b, void *c)
283 {
284 	return wrmirrs1st(d->cat.first, b, c);
285 }
286