305 lines · 4.8 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include	"all.h" /* * multiple cat devices */voidmcatinit(Device *d){	Device *x, **list; 	d->cat.ndev = 0;	for(x=d->cat.first; x; x=x->link) {		devinit(x);		d->cat.ndev++;	} 	list = malloc(d->cat.ndev*sizeof(Device*));	d->private = list;	for(x=d->cat.first; x; x=x->link) {		*list++ = x;		x->size = devsize(x);	}} Devsizemcatsize(Device *d){	Device *x;	Devsize l, m; 	l = 0;	for(x=d->cat.first; x; x=x->link) {		m = x->size;		if(m == 0) {			m = devsize(x);			x->size = m;		}		l += m;	}	return l;} intmcatread(Device *d, Off b, void *c){	Device *x;	Devsize l, m; 	l = 0;	for(x=d->cat.first; x; x=x->link) {		m = x->size;		if(m == 0) {			m = devsize(x);			x->size = m;		}		if(b < l+m)			return devread(x, b-l, c);		l += m;	}	print("mcatread past end: %Z block %lld, %lld beyond end\n",		d, (Wideoff)b, (Wideoff)l);	return 1;} intmcatwrite(Device *d, Off b, void *c){	Device *x;	Devsize l, m; 	l = 0;	for(x=d->cat.first; x; x=x->link) {		m = x->size;		if(m == 0) {			m = devsize(x);			x->size = m;		}		if(b < l+m)			return devwrite(x, b-l, c);		l += m;	}	print("mcatwrite past end: %Z block %lld, %lld beyond end\n",		d, (Wideoff)b, (Wideoff)l);	return 1;} /* * multiple interleave devices */voidmlevinit(Device *d){	Device *x; 	mcatinit(d);	for(x=d->cat.first; x; x=x->link)		x->size = devsize(x);} Devsizemlevsize(Device *d){	Device *x;	int n;	Devsize m, min; 	min = 0;	n = 0;	for(x=d->cat.first; x; x=x->link) {		m = x->size;		if(m == 0) {			m = devsize(x);			x->size = m;		}		if(min == 0 || m < min)			min = m;		n++;	}	return n * min;} intmlevread(Device *d, Off b, void *c){	int n;	Device **list; 	n = d->cat.ndev;	list = d->private;	return devread(list[b%n], b/n, c);} intmlevwrite(Device *d, Off b, void *c){	int n;	Device **list; 	n = d->cat.ndev;	list = d->private;	return devwrite(list[b%n], b/n, c);} /* * partition device */voidpartinit(Device *d){ 	devinit(d->part.d);	d->part.d->size = devsize(d->part.d);} Devsizepartsize(Device *d){	Devsize size, l; 	l = d->part.d->size / 100;	size = d->part.size * l;	if(size == 0)		size = l*100;	return size;} intpartread(Device *d, Off b, void *c){	Devsize base, size, l; 	l = d->part.d->size / 100;	base = d->part.base * l;	size = d->part.size * l;	if(size == 0)		size = l*100;	if(b < size)		return devread(d->part.d, base+b, c);	print("partread past end: %Z blk %lld size %lld\n",		d, (Wideoff)b, (Wideoff)size);	return 1;} intpartwrite(Device *d, Off b, void *c){	Devsize base, size, l; 	l = d->part.d->size / 100;	base = d->part.base * l;	size = d->part.size * l;	if(size == 0)		size = l*100;	if(b < size)		return devwrite(d->part.d, base+b, c);	print("partwrite past end: %Z blk %lld size %lld\n",		d, (Wideoff)b, (Wideoff)size);	return 1;} /* * mirror device */voidmirrinit(Device *d){	Device *x; 	mcatinit(d);	for(x=d->cat.first; x; x=x->link)		x->size = devsize(x);} Devsizemirrsize(Device *d){	Device *x;	int n;	Devsize m, min; 	min = 0;	n = 0;	for(x=d->cat.first; x; x=x->link) {		m = x->size;		if(m == 0) {			m = devsize(x);			x->size = m;		}		if(min == 0 || m < min)			min = m;		n++;	}	return min;} intmirrread(Device *d, Off b, void *c){	Device *x; 	if (d->cat.first == nil) {		print("mirrread: empty mirror %Z\n", d);		return 1;	}	for(x=d->cat.first; x; x=x->link) {		if(x->size == 0)			x->size = devsize(x);		if (devread(x, b, c) == 0)	/* okay? */			return 0;	}	// DANGER WILL ROBINSON	print("mirrread: all mirrors of %Z block %lld are bad\n",		d, (Wideoff)b);	return 1;} /* * write the mirror(s) first so that a power outage, for example, will * find the main device written only if the mirrors are too, thus * checking the main device will also correctly check the mirror(s). * * devread and devwrite are synchronous; all buffering must be * implemented at higher levels. */static intewrite(Device *x, Off b, void *c){	if(x->size == 0)		x->size = devsize(x);	if (devwrite(x, b, c) != 0) {		print("mirrwrite: error at %Z block %lld\n", x, (Wideoff)b);		return 1;	}	return 0;} static intwrmirrs1st(Device *x, Off b, void *c)	// write any mirrors of x, then x{	int e; 	if (x == nil)		return 0;	e = wrmirrs1st(x->link, b, c);	return e | ewrite(x, b, c);} intmirrwrite(Device *d, Off b, void *c){	if (d->cat.first == nil) {		print("mirrwrite: empty mirror %Z\n", d);		return 1;	}	return wrmirrs1st(d->cat.first, b, c);}