]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/cwfs/mworm.c
b4d44423603ef1ca48bcf21d125597adb09d22cd
[plan9front.git] / sys / src / cmd / cwfs / mworm.c
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 = ialloc(d->cat.ndev * sizeof(Device*), 0);
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         fprint(2, "mcatread past end: %Z block %lld, %lld beyond end\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         fprint(2, "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
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         fprint(2, "partread past end: %Z blk %lld size %lld\n",
180                 d, (Wideoff)b, (Wideoff)size);
181         return 1;
182 }
183
184 int
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         fprint(2, "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
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
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
237 mirrread(Device *d, Off b, void *c)
238 {
239         Device *x;
240
241         if (d->cat.first == nil) {
242                 fprint(2, "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         fprint(2, "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
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                 fprint(2, "mirrwrite: error at %Z block %lld\n", x, (Wideoff)b);
272                 return 1;
273         }
274         return 0;
275 }
276
277 static int
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
289 mirrwrite(Device *d, Off b, void *c)
290 {
291         if (d->cat.first == nil) {
292                 fprint(2, "mirrwrite: empty mirror %Z\n", d);
293                 return 1;
294         }
295         return wrmirrs1st(d->cat.first, b, c);
296 }