diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/cwfs/mworm.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/cwfs/mworm.c')
-rwxr-xr-x | sys/src/cmd/cwfs/mworm.c | 296 |
1 files changed, 296 insertions, 0 deletions
diff --git a/sys/src/cmd/cwfs/mworm.c b/sys/src/cmd/cwfs/mworm.c new file mode 100755 index 000000000..407ad6a09 --- /dev/null +++ b/sys/src/cmd/cwfs/mworm.c @@ -0,0 +1,296 @@ +#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); +} |