xref: /plan9/sys/src/cmd/cwfs/mworm.c (revision f9e1cf08d3be51592e03e639fc848a68dc31a55e)
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