101a344a2SDavid du Colombier #include "all.h"
201a344a2SDavid du Colombier
301a344a2SDavid du Colombier /*
401a344a2SDavid du Colombier * multiple cat devices
501a344a2SDavid du Colombier */
601a344a2SDavid du Colombier void
mcatinit(Device * d)701a344a2SDavid du Colombier mcatinit(Device *d)
801a344a2SDavid du Colombier {
901a344a2SDavid du Colombier Device *x, **list;
1001a344a2SDavid du Colombier
1101a344a2SDavid du Colombier d->cat.ndev = 0;
1201a344a2SDavid du Colombier for(x=d->cat.first; x; x=x->link) {
1301a344a2SDavid du Colombier devinit(x);
1401a344a2SDavid du Colombier d->cat.ndev++;
1501a344a2SDavid du Colombier }
1601a344a2SDavid du Colombier
1701a344a2SDavid du Colombier list = malloc(d->cat.ndev*sizeof(Device*));
1801a344a2SDavid du Colombier d->private = list;
1901a344a2SDavid du Colombier for(x=d->cat.first; x; x=x->link) {
2001a344a2SDavid du Colombier *list++ = x;
2101a344a2SDavid du Colombier x->size = devsize(x);
2201a344a2SDavid du Colombier }
2301a344a2SDavid du Colombier }
2401a344a2SDavid du Colombier
2501a344a2SDavid du Colombier Devsize
mcatsize(Device * d)2601a344a2SDavid du Colombier mcatsize(Device *d)
2701a344a2SDavid du Colombier {
2801a344a2SDavid du Colombier Device *x;
2901a344a2SDavid du Colombier Devsize l, m;
3001a344a2SDavid du Colombier
3101a344a2SDavid du Colombier l = 0;
3201a344a2SDavid du Colombier for(x=d->cat.first; x; x=x->link) {
3301a344a2SDavid du Colombier m = x->size;
3401a344a2SDavid du Colombier if(m == 0) {
3501a344a2SDavid du Colombier m = devsize(x);
3601a344a2SDavid du Colombier x->size = m;
3701a344a2SDavid du Colombier }
3801a344a2SDavid du Colombier l += m;
3901a344a2SDavid du Colombier }
4001a344a2SDavid du Colombier return l;
4101a344a2SDavid du Colombier }
4201a344a2SDavid du Colombier
4301a344a2SDavid du Colombier int
mcatread(Device * d,Off b,void * c)4401a344a2SDavid du Colombier mcatread(Device *d, Off b, void *c)
4501a344a2SDavid du Colombier {
4601a344a2SDavid du Colombier Device *x;
4701a344a2SDavid du Colombier Devsize l, m;
4801a344a2SDavid du Colombier
4901a344a2SDavid du Colombier l = 0;
5001a344a2SDavid du Colombier for(x=d->cat.first; x; x=x->link) {
5101a344a2SDavid du Colombier m = x->size;
5201a344a2SDavid du Colombier if(m == 0) {
5301a344a2SDavid du Colombier m = devsize(x);
5401a344a2SDavid du Colombier x->size = m;
5501a344a2SDavid du Colombier }
5601a344a2SDavid du Colombier if(b < l+m)
5701a344a2SDavid du Colombier return devread(x, b-l, c);
5801a344a2SDavid du Colombier l += m;
5901a344a2SDavid du Colombier }
60*f9e1cf08SDavid du Colombier print("mcatread past end: %Z block %lld, %lld beyond end\n",
6101a344a2SDavid du Colombier d, (Wideoff)b, (Wideoff)l);
6201a344a2SDavid du Colombier return 1;
6301a344a2SDavid du Colombier }
6401a344a2SDavid du Colombier
6501a344a2SDavid du Colombier int
mcatwrite(Device * d,Off b,void * c)6601a344a2SDavid du Colombier mcatwrite(Device *d, Off b, void *c)
6701a344a2SDavid du Colombier {
6801a344a2SDavid du Colombier Device *x;
6901a344a2SDavid du Colombier Devsize l, m;
7001a344a2SDavid du Colombier
7101a344a2SDavid du Colombier l = 0;
7201a344a2SDavid du Colombier for(x=d->cat.first; x; x=x->link) {
7301a344a2SDavid du Colombier m = x->size;
7401a344a2SDavid du Colombier if(m == 0) {
7501a344a2SDavid du Colombier m = devsize(x);
7601a344a2SDavid du Colombier x->size = m;
7701a344a2SDavid du Colombier }
7801a344a2SDavid du Colombier if(b < l+m)
7901a344a2SDavid du Colombier return devwrite(x, b-l, c);
8001a344a2SDavid du Colombier l += m;
8101a344a2SDavid du Colombier }
82*f9e1cf08SDavid du Colombier print("mcatwrite past end: %Z block %lld, %lld beyond end\n",
8301a344a2SDavid du Colombier d, (Wideoff)b, (Wideoff)l);
8401a344a2SDavid du Colombier return 1;
8501a344a2SDavid du Colombier }
8601a344a2SDavid du Colombier
8701a344a2SDavid du Colombier /*
8801a344a2SDavid du Colombier * multiple interleave devices
8901a344a2SDavid du Colombier */
9001a344a2SDavid du Colombier void
mlevinit(Device * d)9101a344a2SDavid du Colombier mlevinit(Device *d)
9201a344a2SDavid du Colombier {
9301a344a2SDavid du Colombier Device *x;
9401a344a2SDavid du Colombier
9501a344a2SDavid du Colombier mcatinit(d);
9601a344a2SDavid du Colombier for(x=d->cat.first; x; x=x->link)
9701a344a2SDavid du Colombier x->size = devsize(x);
9801a344a2SDavid du Colombier }
9901a344a2SDavid du Colombier
10001a344a2SDavid du Colombier Devsize
mlevsize(Device * d)10101a344a2SDavid du Colombier mlevsize(Device *d)
10201a344a2SDavid du Colombier {
10301a344a2SDavid du Colombier Device *x;
10401a344a2SDavid du Colombier int n;
10501a344a2SDavid du Colombier Devsize m, min;
10601a344a2SDavid du Colombier
10701a344a2SDavid du Colombier min = 0;
10801a344a2SDavid du Colombier n = 0;
10901a344a2SDavid du Colombier for(x=d->cat.first; x; x=x->link) {
11001a344a2SDavid du Colombier m = x->size;
11101a344a2SDavid du Colombier if(m == 0) {
11201a344a2SDavid du Colombier m = devsize(x);
11301a344a2SDavid du Colombier x->size = m;
11401a344a2SDavid du Colombier }
11501a344a2SDavid du Colombier if(min == 0 || m < min)
11601a344a2SDavid du Colombier min = m;
11701a344a2SDavid du Colombier n++;
11801a344a2SDavid du Colombier }
11901a344a2SDavid du Colombier return n * min;
12001a344a2SDavid du Colombier }
12101a344a2SDavid du Colombier
12201a344a2SDavid du Colombier int
mlevread(Device * d,Off b,void * c)12301a344a2SDavid du Colombier mlevread(Device *d, Off b, void *c)
12401a344a2SDavid du Colombier {
12501a344a2SDavid du Colombier int n;
12601a344a2SDavid du Colombier Device **list;
12701a344a2SDavid du Colombier
12801a344a2SDavid du Colombier n = d->cat.ndev;
12901a344a2SDavid du Colombier list = d->private;
13001a344a2SDavid du Colombier return devread(list[b%n], b/n, c);
13101a344a2SDavid du Colombier }
13201a344a2SDavid du Colombier
13301a344a2SDavid du Colombier int
mlevwrite(Device * d,Off b,void * c)13401a344a2SDavid du Colombier mlevwrite(Device *d, Off b, void *c)
13501a344a2SDavid du Colombier {
13601a344a2SDavid du Colombier int n;
13701a344a2SDavid du Colombier Device **list;
13801a344a2SDavid du Colombier
13901a344a2SDavid du Colombier n = d->cat.ndev;
14001a344a2SDavid du Colombier list = d->private;
14101a344a2SDavid du Colombier return devwrite(list[b%n], b/n, c);
14201a344a2SDavid du Colombier }
14301a344a2SDavid du Colombier
14401a344a2SDavid du Colombier /*
14501a344a2SDavid du Colombier * partition device
14601a344a2SDavid du Colombier */
14701a344a2SDavid du Colombier void
partinit(Device * d)14801a344a2SDavid du Colombier partinit(Device *d)
14901a344a2SDavid du Colombier {
15001a344a2SDavid du Colombier
15101a344a2SDavid du Colombier devinit(d->part.d);
15201a344a2SDavid du Colombier d->part.d->size = devsize(d->part.d);
15301a344a2SDavid du Colombier }
15401a344a2SDavid du Colombier
15501a344a2SDavid du Colombier Devsize
partsize(Device * d)15601a344a2SDavid du Colombier partsize(Device *d)
15701a344a2SDavid du Colombier {
15801a344a2SDavid du Colombier Devsize size, l;
15901a344a2SDavid du Colombier
16001a344a2SDavid du Colombier l = d->part.d->size / 100;
16101a344a2SDavid du Colombier size = d->part.size * l;
16201a344a2SDavid du Colombier if(size == 0)
16301a344a2SDavid du Colombier size = l*100;
16401a344a2SDavid du Colombier return size;
16501a344a2SDavid du Colombier }
16601a344a2SDavid du Colombier
16701a344a2SDavid du Colombier int
partread(Device * d,Off b,void * c)16801a344a2SDavid du Colombier partread(Device *d, Off b, void *c)
16901a344a2SDavid du Colombier {
17001a344a2SDavid du Colombier Devsize base, size, l;
17101a344a2SDavid du Colombier
17201a344a2SDavid du Colombier l = d->part.d->size / 100;
17301a344a2SDavid du Colombier base = d->part.base * l;
17401a344a2SDavid du Colombier size = d->part.size * l;
17501a344a2SDavid du Colombier if(size == 0)
17601a344a2SDavid du Colombier size = l*100;
17701a344a2SDavid du Colombier if(b < size)
17801a344a2SDavid du Colombier return devread(d->part.d, base+b, c);
179*f9e1cf08SDavid du Colombier print("partread past end: %Z blk %lld size %lld\n",
180*f9e1cf08SDavid du Colombier d, (Wideoff)b, (Wideoff)size);
18101a344a2SDavid du Colombier return 1;
18201a344a2SDavid du Colombier }
18301a344a2SDavid du Colombier
18401a344a2SDavid du Colombier int
partwrite(Device * d,Off b,void * c)18501a344a2SDavid du Colombier partwrite(Device *d, Off b, void *c)
18601a344a2SDavid du Colombier {
18701a344a2SDavid du Colombier Devsize base, size, l;
18801a344a2SDavid du Colombier
18901a344a2SDavid du Colombier l = d->part.d->size / 100;
19001a344a2SDavid du Colombier base = d->part.base * l;
19101a344a2SDavid du Colombier size = d->part.size * l;
19201a344a2SDavid du Colombier if(size == 0)
19301a344a2SDavid du Colombier size = l*100;
19401a344a2SDavid du Colombier if(b < size)
19501a344a2SDavid du Colombier return devwrite(d->part.d, base+b, c);
196*f9e1cf08SDavid du Colombier print("partwrite past end: %Z blk %lld size %lld\n",
197*f9e1cf08SDavid du Colombier d, (Wideoff)b, (Wideoff)size);
19801a344a2SDavid du Colombier return 1;
19901a344a2SDavid du Colombier }
20001a344a2SDavid du Colombier
20101a344a2SDavid du Colombier /*
20201a344a2SDavid du Colombier * mirror device
20301a344a2SDavid du Colombier */
20401a344a2SDavid du Colombier void
mirrinit(Device * d)20501a344a2SDavid du Colombier mirrinit(Device *d)
20601a344a2SDavid du Colombier {
20701a344a2SDavid du Colombier Device *x;
20801a344a2SDavid du Colombier
20901a344a2SDavid du Colombier mcatinit(d);
21001a344a2SDavid du Colombier for(x=d->cat.first; x; x=x->link)
21101a344a2SDavid du Colombier x->size = devsize(x);
21201a344a2SDavid du Colombier }
21301a344a2SDavid du Colombier
21401a344a2SDavid du Colombier Devsize
mirrsize(Device * d)21501a344a2SDavid du Colombier mirrsize(Device *d)
21601a344a2SDavid du Colombier {
21701a344a2SDavid du Colombier Device *x;
21801a344a2SDavid du Colombier int n;
21901a344a2SDavid du Colombier Devsize m, min;
22001a344a2SDavid du Colombier
22101a344a2SDavid du Colombier min = 0;
22201a344a2SDavid du Colombier n = 0;
22301a344a2SDavid du Colombier for(x=d->cat.first; x; x=x->link) {
22401a344a2SDavid du Colombier m = x->size;
22501a344a2SDavid du Colombier if(m == 0) {
22601a344a2SDavid du Colombier m = devsize(x);
22701a344a2SDavid du Colombier x->size = m;
22801a344a2SDavid du Colombier }
22901a344a2SDavid du Colombier if(min == 0 || m < min)
23001a344a2SDavid du Colombier min = m;
23101a344a2SDavid du Colombier n++;
23201a344a2SDavid du Colombier }
23301a344a2SDavid du Colombier return min;
23401a344a2SDavid du Colombier }
23501a344a2SDavid du Colombier
23601a344a2SDavid du Colombier int
mirrread(Device * d,Off b,void * c)23701a344a2SDavid du Colombier mirrread(Device *d, Off b, void *c)
23801a344a2SDavid du Colombier {
23901a344a2SDavid du Colombier Device *x;
24001a344a2SDavid du Colombier
241*f9e1cf08SDavid du Colombier if (d->cat.first == nil) {
242*f9e1cf08SDavid du Colombier print("mirrread: empty mirror %Z\n", d);
243*f9e1cf08SDavid du Colombier return 1;
244*f9e1cf08SDavid du Colombier }
24501a344a2SDavid du Colombier for(x=d->cat.first; x; x=x->link) {
24601a344a2SDavid du Colombier if(x->size == 0)
24701a344a2SDavid du Colombier x->size = devsize(x);
24801a344a2SDavid du Colombier if (devread(x, b, c) == 0) /* okay? */
24901a344a2SDavid du Colombier return 0;
25001a344a2SDavid du Colombier }
251*f9e1cf08SDavid du Colombier // DANGER WILL ROBINSON
252*f9e1cf08SDavid du Colombier print("mirrread: all mirrors of %Z block %lld are bad\n",
253*f9e1cf08SDavid du Colombier d, (Wideoff)b);
25401a344a2SDavid du Colombier return 1;
25501a344a2SDavid du Colombier }
25601a344a2SDavid du Colombier
25701a344a2SDavid du Colombier /*
25801a344a2SDavid du Colombier * write the mirror(s) first so that a power outage, for example, will
25901a344a2SDavid du Colombier * find the main device written only if the mirrors are too, thus
26001a344a2SDavid du Colombier * checking the main device will also correctly check the mirror(s).
26101a344a2SDavid du Colombier *
26201a344a2SDavid du Colombier * devread and devwrite are synchronous; all buffering must be
26301a344a2SDavid du Colombier * implemented at higher levels.
26401a344a2SDavid du Colombier */
26501a344a2SDavid du Colombier static int
ewrite(Device * x,Off b,void * c)26601a344a2SDavid du Colombier ewrite(Device *x, Off b, void *c)
26701a344a2SDavid du Colombier {
26801a344a2SDavid du Colombier if(x->size == 0)
26901a344a2SDavid du Colombier x->size = devsize(x);
27001a344a2SDavid du Colombier if (devwrite(x, b, c) != 0) {
271*f9e1cf08SDavid du Colombier print("mirrwrite: error at %Z block %lld\n", x, (Wideoff)b);
27201a344a2SDavid du Colombier return 1;
27301a344a2SDavid du Colombier }
27401a344a2SDavid du Colombier return 0;
27501a344a2SDavid du Colombier }
27601a344a2SDavid du Colombier
27701a344a2SDavid du Colombier static int
wrmirrs1st(Device * x,Off b,void * c)27801a344a2SDavid du Colombier wrmirrs1st(Device *x, Off b, void *c) // write any mirrors of x, then x
27901a344a2SDavid du Colombier {
28001a344a2SDavid du Colombier int e;
28101a344a2SDavid du Colombier
28201a344a2SDavid du Colombier if (x == nil)
28301a344a2SDavid du Colombier return 0;
28401a344a2SDavid du Colombier e = wrmirrs1st(x->link, b, c);
28501a344a2SDavid du Colombier return e | ewrite(x, b, c);
28601a344a2SDavid du Colombier }
28701a344a2SDavid du Colombier
28801a344a2SDavid du Colombier int
mirrwrite(Device * d,Off b,void * c)28901a344a2SDavid du Colombier mirrwrite(Device *d, Off b, void *c)
29001a344a2SDavid du Colombier {
291*f9e1cf08SDavid du Colombier if (d->cat.first == nil) {
292*f9e1cf08SDavid du Colombier print("mirrwrite: empty mirror %Z\n", d);
293*f9e1cf08SDavid du Colombier return 1;
294*f9e1cf08SDavid du Colombier }
29501a344a2SDavid du Colombier return wrmirrs1st(d->cat.first, b, c);
29601a344a2SDavid du Colombier }
297