#include "all.h" void mwormream(Device *d, int) { Device *l; for(l=d->cat.first; l; l=l->link) devream(l, 0); } /* * 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 = ialloc(d->cat.ndev*sizeof(Device*), 0); 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 %lld %lld\n", (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 %lld %lld\n", (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; this is a crock! */ void partinit(Device *d) { devinit(d->part.d); d->part.d->size = devsize(d->part.d); } Devsize partsize(Device *d) { Devsize size, l; if(d->part.size < 101){ l = d->part.d->size / 100; size = d->part.size * l; if(size == 0) size = l*100; }else size = d->part.size; return size; } int partread(Device *d, Off b, void *c) { Devsize base, size, l; if(d->part.size < 101){ l = d->part.d->size / 100; base = d->part.base * l; size = d->part.size * l; if(size == 0) size = l*100; }else{ base = d->part.base; size = d->part.size; } if(b < size) return devread(d->part.d, base+b, c); print("partread %lld %lld\n", (Wideoff)b, (Wideoff)size); return 1; } int partwrite(Device *d, Off b, void *c) { Devsize base, size, l; if(d->part.size < 101){ l = d->part.d->size / 100; base = d->part.base * l; size = d->part.size * l; if(size == 0) size = l*100; }else{ base = d->part.base; size = d->part.size; } if(b < size) return devwrite(d->part.d, base+b, c); print("partwrite %lld %lld\n", (Wideoff)b, (Wideoff)size); return 1; } void partream(Device *d, int) { devream(d->part.d, 0); } /* * 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; 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 - all copies of this block were bad print("mirrread %Z error at block %lld\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 %Z error at 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) { return wrmirrs1st(d->cat.first, b, c); }