void devream(Device *d, int top) { Device *l; loop: print("\tdevream: %Z %d\n", d, top); switch(d->type) { default: print("ream: unknown dev type %Z\n", d); return; case Devcw: devream(d->cw.w, 0); devream(d->cw.c, 0); if(top) { wlock(&mainlock); cwream(d); wunlock(&mainlock); } devinit(d); return; case Devfworm: devream(d->fw.fw, 0); fwormream(d); break; case Devpart: devream(d->part.d, 0); break; case Devmlev: case Devmcat: case Devmirr: for(l=d->cat.first; l; l=l->link) devream(l, 0); break; case Devjuke: case Devworm: case Devlworm: case Devwren: break; case Devswab: d = d->swab.d; goto loop; } devinit(d); if(top) { wlock(&mainlock); rootream(d, ROOT_ADDR); superream(d, SUPER_ADDR); wunlock(&mainlock); } }
/* copy worm fs from "main"'s inner worm to "output" */ static void dowormcopy(void) { Filsys *f1, *f2; Device *fdev, *from, *to = nil; Iobuf *p; Off a; Devsize lim; /* * convert file system names into Filsyss and Devices. */ f1 = fsstr("main"); if(f1 == nil) panic("main file system missing"); fdev = f1->dev; from = wormof(fdev); /* fake worm special */ if (from->type != Devfworm && from->type != Devcw) { print("main file system is not a worm; copyworm may not do what you want!\n"); print("waiting for 20 seconds...\n"); delay(20000); } f2 = fsstr("output"); if(f2 == nil) { print("no output file system - check only\n\n"); print("reading worm from %Z (worm %Z)\n", fdev, from); } else { to = f2->dev; print("\ncopying worm from %Z (worm %Z) to %Z, starting in 8 seconds\n", fdev, from, to); delay(8000); } if (userabort("preparing to copy")) return; /* * initialise devices, size them, more sanity checking. */ devinit(from); if (0 && fdev != from) { devinit(fdev); print("debugging, sizing %Z first\n", fdev); writtensize(fdev); } lim = writtensize(from); if(lim == 0) panic("no blocks to copy on %Z", from); if (to) { print("reaming %Z in 8 seconds\n", to); delay(8000); if (userabort("preparing to ream & copy")) return; devream(to, 0); devinit(to); print("copying worm: %lld blocks from %Z to %Z\n", (Wideoff)lim, from, to); } /* can't read to's blocks in case to is a real WORM device */ /* * Copy written fs blocks, a block at a time (or just read * if no "output" fs). */ for (a = 0; a < lim; a++) { if (userabort("copy")) break; p = getbuf(from, a, Brd); /* * if from is a real WORM device, we'll get errors trying to * read unwritten blocks, but the unwritten blocks need not * be contiguous. */ if (p == 0) { print("%lld not written yet; can't read\n", (Wideoff)a); continue; } if (to != 0 && devwrite(to, p->addr, p->iobuf) != 0) { print("out block %lld: write error; bailing", (Wideoff)a); break; } putbuf(p); if(a % 20000 == 0) print("block %lld %T\n", (Wideoff)a, time(nil)); } /* * wrap up: sync target, loop */ print("copied %lld blocks from %Z to %Z\n", (Wideoff)a, from, to); sync("wormcopy"); delay(2000); print("looping; reset the machine at any time.\n"); for (; ; ) continue; /* await reset */ }
void sysinit(void) { int error; char *cp, *ep; Device *d; Filsys *fs; Fspar *fsp; Iobuf *p; cons.chan = fs_chaninit(Devcon, 1, 0); start: /* * part 1 -- read the config file */ devnone = iconfig("n"); cp = nvrgetconfig(); print("config %s\n", cp); confdev = d = iconfig(cp); devinit(d); if(f.newconf) { p = getbuf(d, 0, Bmod); memset(p->iobuf, 0, RBUFSIZE); settag(p, Tconfig, 0); } else p = getbuf(d, 0, Brd|Bmod); if(!p || checktag(p, Tconfig, 0)) panic("config io"); mergeconf(p); if (resetparams) { for (fsp = fspar; fsp->name != nil; fsp++) fsp->declared = 0; resetparams = 0; } for (fsp = fspar; fsp->name != nil; fsp++) { /* supply defaults from this cwfs instance */ if (fsp->declared == 0) { fsp->declared = fsp->actual; f.modconf = 1; } /* warn if declared value is not our compiled-in value */ if (fsp->declared != fsp->actual) print("warning: config %s %ld != compiled-in %ld\n", fsp->name, fsp->declared, fsp->actual); } if(f.modconf) { memset(p->iobuf, 0, BUFSIZE); p->flags |= Bmod|Bimm; cp = p->iobuf; ep = p->iobuf + RBUFSIZE - 1; if(service[0]) cp = seprint(cp, ep, "service %s\n", service); for(fs=filsys; fs->name; fs++) if(fs->conf && fs->conf[0] != '\0') cp = seprint(cp, ep, "filsys %s %s\n", fs->name, fs->conf); for (fsp = fspar; fsp->name != nil; fsp++) cp = seprint(cp, ep, "%s %ld\n", fsp->name, fsp->declared); putbuf(p); f.modconf = f.newconf = 0; print("config block written\n"); goto start; } putbuf(p); print("service %s\n", service); loop: /* * part 2 -- squeeze out the deleted filesystems */ for(fs=filsys; fs->name; fs++) if(fs->conf == nil || fs->conf[0] == '\0') { for(; fs->name; fs++) *fs = *(fs+1); goto loop; } if(filsys[0].name == nil) panic("no filsys"); /* * part 3 -- compile the device expression */ error = 0; for(fs=filsys; fs->name; fs++) { print("filsys %s %s\n", fs->name, fs->conf); fs->dev = iconfig(fs->conf); if(f.error) { error = 1; continue; } } if(error) panic("fs config"); /* * part 4 -- initialize the devices */ for(fs=filsys; fs->name; fs++) { delay(3000); print("sysinit: %s\n", fs->name); if(fs->flags & FREAM) devream(fs->dev, 1); if(fs->flags & FRECOVER) devrecover(fs->dev); devinit(fs->dev); } /* * part 5 -- optionally copy devices or worms */ if (copyworm) { dowormcopy(); /* can return if user quits early */ panic("copyworm bailed out!"); } if (copydev) if (dodevcopy() < 0) panic("copydev failed!"); else panic("copydev done."); }