summaryrefslogtreecommitdiff
path: root/sys/src/cmd/cwfs/mworm.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /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-xsys/src/cmd/cwfs/mworm.c296
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);
+}