#include "all.h"
/*
* multiple cat devices
*/
void
mcatinit(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);
}
}
Devsize
mcatsize(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;
}
int
mcatread(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;
}
int
mcatwrite(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
*/
void
mlevinit(Device *d)
{
Device *x;
mcatinit(d);
for(x=d->cat.first; x; x=x->link)
x->size = devsize(x);
}
Devsize
mlevsize(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;
}
int
mlevread(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);
}
int
mlevwrite(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
*/
void
partinit(Device *d)
{
devinit(d->part.d);
d->part.d->size = devsize(d->part.d);
}
Devsize
partsize(Device *d)
{
Devsize size, l;
l = d->part.d->size / 100;
size = d->part.size * l;
if(size == 0)
size = l*100;
return size;
}
int
partread(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;
}
int
partwrite(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
*/
void
mirrinit(Device *d)
{
Device *x;
mcatinit(d);
for(x=d->cat.first; x; x=x->link)
x->size = devsize(x);
}
Devsize
mirrsize(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;
}
int
mirrread(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 int
ewrite(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 int
wrmirrs1st(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);
}
int
mirrwrite(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);
}
|