diff --git a/lib/rob b/lib/rob index cbbdab8ef..fa3ae8f16 100644 --- a/lib/rob +++ b/lib/rob @@ -262,3 +262,6 @@ I told the truth as I saw it. Wait, teletypes are finally gone so we need *pseudo* teletypes? I started complaining about this long ago and nobody cared then, either. It is very unlikely to change. +Don't do that. +This is just me speaking, not the Go team. +Go doesn't have it. diff --git a/lib/theo b/lib/theo index 09a2c7696..19549cee2 100644 --- a/lib/theo +++ b/lib/theo @@ -420,3 +420,6 @@ Welcome to the real world. Sorry. Violates POSIX and C89, which violate best practice in this century. Look, this is rather simple. +Oh really. +It ends badly. +I explained that. diff --git a/lib/troll b/lib/troll index 04e254407..5dc1f47b7 100644 --- a/lib/troll +++ b/lib/troll @@ -194,3 +194,4 @@ I am using p9p version of upas/nedmail and upas/marshal. Is there anyway this github repo could be synchronized with the main plan9-labs repo? Has anyone used Plan-9 have feedback on running it? UX-wise (and generally speaking, for most common uses of a computer these days), Plan9 is, sadly, almost useless. +Most of the complaining about fossil's stability comes from outdated info. diff --git a/sys/games/lib/fortunes b/sys/games/lib/fortunes index 17e8ad3fb..2807ad6b0 100644 --- a/sys/games/lib/fortunes +++ b/sys/games/lib/fortunes @@ -5108,3 +5108,6 @@ Every joke is a tiny revolution -- George Orwell I'm kind of like a designer who writes code; this may become apparent as you read on As an interface designer Plan9 have always fascinated me yet I found it incredible hard to find many other designers who were into it's concepts. Tandy Leather, which later grew in to the Tandy Corporation, was a family-owned leather goods company based in Fort Worth, Texas. +I want to get into web development. +The modern Plan 9 codebase is officially developed and maintained by Vita Nuova as the product named Inferno. +User interface improvements included the "layers" windowing system for the DMD 5620 graphics terminal, and the SVR3.2 curses libraries that offered eight or more color pairs and other at this time important features (forms, panels, menus, etc.). diff --git a/sys/man/1/sam b/sys/man/1/sam index 1ecb55ede..f9e9afdac 100644 --- a/sys/man/1/sam +++ b/sys/man/1/sam @@ -496,11 +496,20 @@ Plan 9 command. Send the range to the standard input of the Plan 9 command. .TP +.BI ^ " Plan 9-command +Send the standard output of the Plan 9 command +to the command window. +.TP .BI | " Plan 9-command Send the range to the standard input, and replace it by the standard output, of the Plan 9 command. .TP +.BI _ " Plan 9-command +Send the range to the standard input, and send the +standard output of the Plan 9 command to the command +window. +.TP .BI \*a! " Plan 9-command Run the Plan 9 command. @@ -515,6 +524,8 @@ is used. In any of .BR < , .BR > , +.BR ^ , +.BR _ , .B | or .BR ! , diff --git a/sys/man/3/aoe b/sys/man/3/aoe index d6ae374f3..71f3fb865 100644 --- a/sys/man/3/aoe +++ b/sys/man/3/aoe @@ -271,7 +271,7 @@ Unused. .\" .IR vblade (1), .IR sd (3), .IR sdaoe (3), -.IR aoesrv (8), +.IR vblade (8), .IR snoopy (8) .br .BR http://www.coraid.com/documents/AoEr10.txt diff --git a/sys/man/3/sdaoe b/sys/man/3/sdaoe index 62677497b..d0470fb4e 100644 --- a/sys/man/3/sdaoe +++ b/sys/man/3/sdaoe @@ -68,7 +68,7 @@ over Ethernet interfaces 0 and 1, .IP .EX aoeif=ether0 ether1 -aoedev=e!#æ/aoe/42.0 +aoedev=e!42.0 .EE .SH SOURCE .B /sys/src/9/port/sdaoe.c diff --git a/sys/man/4/hgfs b/sys/man/4/hgfs index 94ab79b7a..1684f7c5d 100644 --- a/sys/man/4/hgfs +++ b/sys/man/4/hgfs @@ -122,5 +122,10 @@ and \fB.\fI0\fR yields the same file as when omitting the appendix. Same as .B files, but contains only the changed files of the changeset. +.SH SOURCE +.B /sys/src/cmd/hgfs .SH SEE ALSO .IR hg (1) +.SH HISTORY +.I Hgfs +first appeared in 9front (June, 2011). diff --git a/sys/man/8/vblade b/sys/man/8/vblade new file mode 100644 index 000000000..a180a8bc2 --- /dev/null +++ b/sys/man/8/vblade @@ -0,0 +1,85 @@ +.TH VBLADE 8 +.SH NAME +vblade \- virtual AoE target +.SH SYNOPSIS +.B disk/vblade +[ +.B -ir +] [ +.B -s +.I size +] [ +.B -a +.I shelf.slot +] [ +.B -c +.I config +] +.B file +[ +.B -e +ether +] +.SH DESCRIPTION +For each +.I file +specified, +.I vblade +serves it as an AoE (ATA-over-Ethernet) target via +the specified interfaces. The default interface is +.BR /net/ether0 . +Since AoE uses raw Ethernet frames, the target is +only visible on the local ethernet segment. +.PP +All target-related options are reset for each +.IR file . +.SS Options +.TP \w'\fL-e\ \fIetherXX'u +.B -i +Initialize the configuration header in +.IR file . +All previous configuration information is lost. Without this option, +configuration is read from +.I file +and command like options override previous settings. +.TP +.B -r +Raw. Do not use a configuration header. This is useful when +exporting a device or file not generally exported by +.IR vblade . +.TP +.BI -s " n" +The exported target will have size +.IR n , +rather than the available space in the target. A size may end in +.LR p , +.LR t , +.LR g , +.LR m , +or +.LR k +to specify a customary +.I binary +multiplier. +.TP +.BI -a " m.n" +Specify the shelf and slot (or major and minor) address of the target. +Valid shelf numbers are between 0 and 65534. Valid slots are 0-255. +.TP +.BI -c " s" +Set the AoE config string to +.IR s . +.TP +.BI -e " ether" +Listen to the network port +.IR ether. +Multiple ports may be specified. +.SH SEE ALSO +.IR aoe (3), +.IR sdaoe (3), +.IR http://www.coraid.com/documents/AoEr11.txt . +.SH SOURCE +.B /sys/src/cmd/disk/vblade +.SH BUGS +Security depends on control of the local Ethernet segment. It may be +unwise to serve AoE on a segment bridged to a wireless network. diff --git a/sys/src/9/pc/archacpi.c b/sys/src/9/pc/archacpi.c index 6805f5c87..644df59b9 100644 --- a/sys/src/9/pc/archacpi.c +++ b/sys/src/9/pc/archacpi.c @@ -625,12 +625,42 @@ Foundapic: mpinit(); } +static void +acpireset(void) +{ + uchar *p; + Tbl *t; + int i; + + /* stop application processors */ + mpshutdown(); + + /* locate and write platform reset register */ + for(i=0; i < ntblmap; i++){ + t = tblmap[i]; + if(memcmp(t->sig, "FACP", 4) != 0) + continue; + if(get32(t->len) <= 128) + break; + p = (uchar*)t; + if((get32(p + 112) & (1<<10)) == 0) + break; + if(p[116+0] != IoSpace) + break; + outb(get32(p+116+4), p[128]); + break; + } + + /* acpi shutdown failed, try generic reset */ + archreset(); +} + static int identify(void); PCArch archacpi = { .id= "ACPI", .ident= identify, -.reset= mpshutdown, +.reset= acpireset, .intrinit= acpiinit, .intrenable= mpintrenable, .intron= lapicintron, @@ -887,29 +917,3 @@ amldelay(int us) { microdelay(us); } - -/* - * reset machine by writing acpi reset register. - */ -void -acpireset(void) -{ - uchar *p; - Tbl *t; - int i; - - for(i=0; i < ntblmap; i++){ - t = tblmap[i]; - if(memcmp(t->sig, "FACP", 4) != 0) - continue; - if(get32(t->len) <= 128) - break; - p = (uchar*)t; - if((get32(p + 112) & (1<<10)) == 0) - break; - if(p[116+0] != IoSpace) - break; - outb(get32(p+116+4), p[128]); - break; - } -} diff --git a/sys/src/9/pc/archmp.c b/sys/src/9/pc/archmp.c index 8fb269569..723433db8 100644 --- a/sys/src/9/pc/archmp.c +++ b/sys/src/9/pc/archmp.c @@ -354,12 +354,22 @@ pcmpinit(void) mpinit(); } +static void +mpreset(void) +{ + /* stop application processors */ + mpshutdown(); + + /* do generic reset */ + archreset(); +} + static int identify(void); PCArch archmp = { .id= "_MP_", .ident= identify, -.reset= mpshutdown, +.reset= mpreset, .intrinit= pcmpinit, .intrenable= mpintrenable, .intron= lapicintron, diff --git a/sys/src/9/pc/devarch.c b/sys/src/9/pc/devarch.c index 412ca767e..24c5f0e7b 100644 --- a/sys/src/9/pc/devarch.c +++ b/sys/src/9/pc/devarch.c @@ -528,7 +528,7 @@ nop(void) { } -static void +void archreset(void) { i8042reset(); @@ -548,6 +548,7 @@ archreset(void) outb(0xcf9, 0x02); outb(0xcf9, 0x06); + print("can't reset\n"); for(;;) idle(); } diff --git a/sys/src/9/pc/fns.h b/sys/src/9/pc/fns.h index ccf5ea092..77eebd2fc 100644 --- a/sys/src/9/pc/fns.h +++ b/sys/src/9/pc/fns.h @@ -1,9 +1,9 @@ #include "../port/portfns.h" void aamloop(int); -void acpireset(void); Dirtab* addarchfile(char*, int, long(*)(Chan*,void*,long,vlong), long(*)(Chan*,void*,long,vlong)); void archinit(void); +void archreset(void); int bios32call(BIOS32ci*, u16int[3]); int bios32ci(BIOS32si*, BIOS32ci*); void bios32close(BIOS32si*); diff --git a/sys/src/9/pc/main.c b/sys/src/9/pc/main.c index 857c918cb..9d95c9f8a 100644 --- a/sys/src/9/pc/main.c +++ b/sys/src/9/pc/main.c @@ -121,7 +121,6 @@ options(void) } } -extern void mmuinit0(void); extern void (*i8237alloc)(void); extern void bootscreeninit(void); @@ -138,8 +137,6 @@ main(void) print("\nPlan 9\n"); trapinit0(); - mmuinit0(); - kbdinit(); i8253init(); cpuidentify(); @@ -908,8 +905,8 @@ shutdown(int ispanic) once = active.machs & (1<machno); /* * setting exiting will make hzclock() on each processor call exit(0), - * which calls shutdown(0) and arch->reset(), which on mp systems is - * mpshutdown, from which there is no return: the processor is idled + * which calls shutdown(0) and arch->reset(), which on mp systems calls + * mpshutdown(), from which there is no return: the processor is idled * or initiates a reboot. clearing our bit in machs avoids calling * exit(0) from hzclock() on this processor. */ diff --git a/sys/src/9/pc/mmu.c b/sys/src/9/pc/mmu.c index 6fbc323af..0994d7be2 100644 --- a/sys/src/9/pc/mmu.c +++ b/sys/src/9/pc/mmu.c @@ -66,12 +66,6 @@ static void memglobal(void); #define VPTX(va) (((ulong)(va))>>12) #define vpd (vpt+VPTX(VPT)) -void -mmuinit0(void) -{ - memmove(m->gdt, gdt, sizeof gdt); -} - void mmuinit(void) { diff --git a/sys/src/9/pc/mp.c b/sys/src/9/pc/mp.c index 63fe687fa..8bfc52204 100644 --- a/sys/src/9/pc/mp.c +++ b/sys/src/9/pc/mp.c @@ -562,7 +562,6 @@ mpintrenable(Vctl* v) return -1; } - void mpshutdown(void) { @@ -572,7 +571,7 @@ mpshutdown(void) if(m->machno != 0){ splhi(); arch->introff(); - idle(); + for(;;) idle(); } print("mpshutdown: active = %#8.8ux\n", active.machs); @@ -585,24 +584,4 @@ mpshutdown(void) lapicicrw(0, 0x000C0000|ApicINIT); pcireset(); - acpireset(); - i8042reset(); - - /* - * Often the BIOS hangs during restart if a conventional 8042 - * warm-boot sequence is tried. The following is Intel specific and - * seems to perform a cold-boot, but at least it comes back. - * And sometimes there is no keyboard... - * - * The reset register (0xcf9) is usually in one of the bridge - * chips. The actual location and sequence could be extracted from - * ACPI but why bother, this is the end of the line anyway. - */ - print("no kbd; trying bios warm boot..."); - *(ushort*)KADDR(0x472) = 0x1234; /* BIOS warm-boot flag */ - outb(0xCF9, 0x02); - outb(0xCF9, 0x06); - - print("can't reset\n"); - idle(); } diff --git a/sys/src/9/pc64/fns.h b/sys/src/9/pc64/fns.h index 652d07737..0af15138f 100644 --- a/sys/src/9/pc64/fns.h +++ b/sys/src/9/pc64/fns.h @@ -1,9 +1,9 @@ #include "../port/portfns.h" void aamloop(int); -void acpireset(void); Dirtab* addarchfile(char*, int, long(*)(Chan*,void*,long,vlong), long(*)(Chan*,void*,long,vlong)); void archinit(void); +void archreset(void); int bios32call(BIOS32ci*, u16int[3]); int bios32ci(BIOS32si*, BIOS32ci*); void bios32close(BIOS32si*); diff --git a/sys/src/9/pc64/main.c b/sys/src/9/pc64/main.c index ee67d0b52..087450c55 100644 --- a/sys/src/9/pc64/main.c +++ b/sys/src/9/pc64/main.c @@ -537,8 +537,8 @@ shutdown(int ispanic) once = active.machs & (1<machno); /* * setting exiting will make hzclock() on each processor call exit(0), - * which calls shutdown(0) and arch->reset(), which on mp systems is - * mpshutdown, from which there is no return: the processor is idled + * which calls shutdown(0) and arch->reset(), which on mp systems calls + * mpshutdown(), from which there is no return: the processor is idled * or initiates a reboot. clearing our bit in machs avoids calling * exit(0) from hzclock() on this processor. */ diff --git a/sys/src/9/pc64/pc64 b/sys/src/9/pc64/pc64 index 0512bec61..9270ac820 100644 --- a/sys/src/9/pc64/pc64 +++ b/sys/src/9/pc64/pc64 @@ -28,7 +28,7 @@ dev sd # floppy dma -# aoe + aoe # lpt audio dma @@ -87,7 +87,7 @@ misc archmp mp apic squidboy mtrr -# sdaoe + sdaoe sdide pci sdscsi # sd53c8xx pci sdscsi # sdmylex pci sdscsi @@ -95,7 +95,7 @@ misc # sdodin pci sdscsi led sdvirtio pci sdscsi sdmmc pci pmmc -# sdloop + sdloop uarti8250 # uartisa diff --git a/sys/src/9/pc64/pccpu64 b/sys/src/9/pc64/pccpu64 index ef82503d3..d9f556499 100644 --- a/sys/src/9/pc64/pccpu64 +++ b/sys/src/9/pc64/pccpu64 @@ -28,7 +28,7 @@ dev sd # floppy dma -# aoe + aoe # lpt audio dma @@ -87,15 +87,15 @@ misc archmp mp apic squidboy mtrr -# sdaoe + sdaoe sdide pci sdscsi # sd53c8xx pci sdscsi # sdmylex pci sdscsi sdiahci pci sdscsi led # sdodin pci sdscsi led sdvirtio pci sdscsi -# sdmmc pci pmmc -# sdloop + sdmmc pci pmmc + sdloop uarti8250 # uartisa diff --git a/sys/src/9/port/devdup.c b/sys/src/9/port/devdup.c index c3a30caef..f526d963b 100644 --- a/sys/src/9/port/devdup.c +++ b/sys/src/9/port/devdup.c @@ -109,7 +109,7 @@ dupread(Chan *c, void *va, long n, vlong offset) fd = twicefd/2; if(twicefd & 1){ c = fdtochan(fd, -1, 0, 1); - procfdprint(c, fd, 0, buf, sizeof buf); + procfdprint(c, fd, buf, sizeof buf); cclose(c); return readstr((ulong)offset, va, n, buf); } diff --git a/sys/src/9/port/devproc.c b/sys/src/9/port/devproc.c index 93d92a10b..dc378e499 100644 --- a/sys/src/9/port/devproc.c +++ b/sys/src/9/port/devproc.c @@ -155,7 +155,6 @@ void procctlreq(Proc*, char*, int); int procctlmemio(Proc*, uintptr, int, void*, int); Chan* proctext(Chan*, Proc*); int procstopped(void*); -void mntscan(Mntwalk*, Proc*); ulong procpagecount(Proc *); static Traceevent *tevents; @@ -400,6 +399,7 @@ procopen(Chan *c, int omode) case Qkregs: case Qsegment: case Qprofile: + case Qns: case Qfd: if(omode != OREAD) error(Eperm); @@ -428,12 +428,6 @@ procopen(Chan *c, int omode) nonone(p); break; - case Qns: - if(omode != OREAD) - error(Eperm); - c->aux = smalloc(sizeof(Mntwalk)); - break; - case Qnotepg: nonone(p); pg = p->pgrp; @@ -514,103 +508,6 @@ procwstat(Chan *c, uchar *db, int n) return n; } - -static long -procoffset(long offset, char *va, int *np) -{ - if(offset > 0) { - offset -= *np; - if(offset < 0) { - memmove(va, va+*np+offset, -offset); - *np = -offset; - } - else - *np = 0; - } - return offset; -} - -static int -procqidwidth(Chan *c) -{ - char buf[32]; - - return sprint(buf, "%lud", c->qid.vers); -} - -int -procfdprint(Chan *c, int fd, int w, char *s, int ns) -{ - int n; - - if(w == 0) - w = procqidwidth(c); - n = snprint(s, ns, "%3d %.2s %C %4ld (%.16llux %*lud %.2ux) %5ld %8lld %s\n", - fd, - &"r w rw"[(c->mode&3)<<1], - devtab[c->type]->dc, c->dev, - c->qid.path, w, c->qid.vers, c->qid.type, - c->iounit, c->offset, c->path->s); - return n; -} - -static int -procfds(Proc *p, char *va, int count, long offset) -{ - Fgrp *f; - Chan *c; - char buf[256]; - int n, i, w, ww; - char *a; - - /* print to buf to avoid holding fgrp lock while writing to user space */ - if(count > sizeof buf) - count = sizeof buf; - a = buf; - - eqlock(&p->debug); - f = p->fgrp; - if(f == nil || p->dot == nil){ - qunlock(&p->debug); - return 0; - } - lock(f); - if(waserror()){ - unlock(f); - qunlock(&p->debug); - nexterror(); - } - - n = readstr(0, a, count, p->dot->path->s); - n += snprint(a+n, count-n, "\n"); - offset = procoffset(offset, a, &n); - /* compute width of qid.path */ - w = 0; - for(i = 0; i <= f->maxfd; i++) { - c = f->fd[i]; - if(c == nil) - continue; - ww = procqidwidth(c); - if(ww > w) - w = ww; - } - for(i = 0; i <= f->maxfd; i++) { - c = f->fd[i]; - if(c == nil) - continue; - n += procfdprint(c, i, w, a+n, count-n); - offset = procoffset(offset, a, &n); - } - unlock(f); - qunlock(&p->debug); - poperror(); - - /* copy result to user space, now that locks are released */ - memmove(va, buf, n); - - return n; -} - static void procclose(Chan *c) { @@ -622,29 +519,6 @@ procclose(Chan *c) proctrace = nil; unlock(&tlock); } - if(QID(c->qid) == Qns && c->aux != nil){ - free(c->aux); - c->aux = nil; - } -} - -static void -int2flag(int flag, char *s) -{ - if(flag == 0){ - *s = '\0'; - return; - } - *s++ = '-'; - if(flag & MAFTER) - *s++ = 'a'; - if(flag & MBEFORE) - *s++ = 'b'; - if(flag & MCREATE) - *s++ = 'c'; - if(flag & MCACHE) - *s++ = 'C'; - *s = '\0'; } static int @@ -690,6 +564,127 @@ prochaswaitq(void *x) return p->pid != PID(c->qid) || p->waitq != nil; } +static void +int2flag(int flag, char *s) +{ + if(flag == 0){ + *s = '\0'; + return; + } + *s++ = '-'; + if(flag & MAFTER) + *s++ = 'a'; + if(flag & MBEFORE) + *s++ = 'b'; + if(flag & MCREATE) + *s++ = 'c'; + if(flag & MCACHE) + *s++ = 'C'; + *s = '\0'; +} + +static int +readns1(Chan *c, Proc *p, char *buf, int nbuf) +{ + Pgrp *pg; + Mount *t, *cm; + Mhead *f, *mh; + ulong minid, bestmid; + char flag[10], *srv; + int i; + + pg = p->pgrp; + if(pg == nil || p->dot == nil || p->pid != PID(c->qid)) + error(Eprocdied); + + bestmid = ~0; + minid = c->nrock; + if(minid == bestmid) + return 0; + + rlock(&pg->ns); + + mh = nil; + cm = nil; + for(i = 0; i < MNTHASH; i++) { + for(f = pg->mnthash[i]; f != nil; f = f->hash) { + for(t = f->mount; t != nil; t = t->next) { + if(t->mountid >= minid && t->mountid < bestmid) { + bestmid = t->mountid; + cm = t; + mh = f; + } + } + } + } + + if(bestmid == ~0) { + c->nrock = bestmid; + i = snprint(buf, nbuf, "cd %s\n", p->dot->path->s); + } else { + c->nrock = bestmid+1; + + int2flag(cm->mflag, flag); + if(strcmp(cm->to->path->s, "#M") == 0){ + srv = srvname(cm->to->mchan); + i = snprint(buf, nbuf, "mount %s %s %s %s\n", flag, + srv==nil? cm->to->mchan->path->s : srv, + mh->from->path->s, cm->spec? cm->spec : ""); + free(srv); + }else{ + i = snprint(buf, nbuf, "bind %s %s %s\n", flag, + cm->to->path->s, mh->from->path->s); + } + } + + runlock(&pg->ns); + + return i; +} + +int +procfdprint(Chan *c, int fd, char *s, int ns) +{ + return snprint(s, ns, "%3d %.2s %C %4ld (%.16llux %lud %.2ux) %5ld %8lld %s\n", + fd, + &"r w rw"[(c->mode&3)<<1], + devtab[c->type]->dc, c->dev, + c->qid.path, c->qid.vers, c->qid.type, + c->iounit, c->offset, c->path->s); +} + +static int +readfd1(Chan *c, Proc *p, char *buf, int nbuf) +{ + Fgrp *fg; + int n, i; + + fg = p->fgrp; + if(fg == nil || p->dot == nil || p->pid != PID(c->qid)) + return 0; + + if(c->nrock == 0){ + c->nrock = 1; + return snprint(buf, nbuf, "%s\n", p->dot->path->s); + } + + lock(fg); + n = 0; + for(;;){ + i = c->nrock-1; + if(i < 0 || i > fg->maxfd) + break; + c->nrock++; + if(fg->fd[i] != nil){ + n = procfdprint(fg->fd[i], i, buf, nbuf); + break; + } + } + unlock(fg); + + return n; +} + /* * userspace can't pass negative file offset for a * 64 bit kernel address, so we use 63 bit and sign @@ -706,15 +701,13 @@ off2addr(vlong off) static long procread(Chan *c, void *va, long n, vlong off) { - /* NSEG*32 was too small for worst cases */ - char *a, flag[10], *sps, *srv, statbuf[NSEG*64]; - int i, j, m, navail, ne, rsize; + char *a, *sps, statbuf[1024]; + int i, j, navail, ne, rsize; long l; uchar *rptr; uintptr addr; ulong offset; Confmem *cm; - Mntwalk *mw; Proc *p; Segment *sg, *s; Ureg kur; @@ -753,14 +746,16 @@ procread(Chan *c, void *va, long n, vlong off) switch(QID(c->qid)){ case Qargs: eqlock(&p->debug); - j = procargs(p, up->genbuf, sizeof up->genbuf); + j = procargs(p, statbuf, sizeof(statbuf)); qunlock(&p->debug); if(offset >= j) return 0; if(offset+n > j) n = j-offset; - memmove(a, &up->genbuf[offset], n); + statbufread: + memmove(a, statbuf+offset, n); return n; + case Qsyscall: eqlock(&p->debug); if(waserror()){ @@ -769,13 +764,12 @@ procread(Chan *c, void *va, long n, vlong off) } if(p->pid != PID(c->qid)) error(Eprocdied); + j = 0; if(p->syscalltrace != nil) - n = readstr(offset, a, n, p->syscalltrace); - else - n = 0; + j = readstr(offset, a, n, p->syscalltrace); qunlock(&p->debug); poperror(); - return n; + return j; case Qmem: addr = off2addr(off); @@ -830,17 +824,15 @@ procread(Chan *c, void *va, long n, vlong off) if(p->nnote == 0) n = 0; else { - m = strlen(p->note[0].msg) + 1; - if(m > n) - m = n; - memmove(va, p->note[0].msg, m-1); - ((char*)va)[m-1] = '\0'; - p->nnote--; + i = strlen(p->note[0].msg) + 1; + if(i < n) + n = i; + memmove(a, p->note[0].msg, n-1); + a[n-1] = '\0'; + if(--p->nnote == 0) + p->notepending = 0; memmove(p->note, p->note+1, p->nnote*sizeof(Note)); - n = m; } - if(p->nnote == 0) - p->notepending = 0; poperror(); qunlock(&p->debug); return n; @@ -905,8 +897,7 @@ procread(Chan *c, void *va, long n, vlong off) readnum(0, statbuf+j+NUMSIZE*6, NUMSIZE, procpagecount(p)*BY2PG/1024, NUMSIZE); readnum(0, statbuf+j+NUMSIZE*7, NUMSIZE, p->basepri, NUMSIZE); readnum(0, statbuf+j+NUMSIZE*8, NUMSIZE, p->priority, NUMSIZE); - memmove(a, statbuf+offset, n); - return n; + goto statbufread; case Qsegment: j = 0; @@ -924,10 +915,7 @@ procread(Chan *c, void *va, long n, vlong off) return 0; if(offset+n > j) n = j-offset; - if(n == 0 && offset == 0) - exhausted("segments"); - memmove(a, &statbuf[offset], n); - return n; + goto statbufread; case Qwait: if(!canqlock(&p->qwaitr)) @@ -959,98 +947,57 @@ procread(Chan *c, void *va, long n, vlong off) qunlock(&p->qwaitr); poperror(); - n = snprint(a, n, "%d %lud %lud %lud %q", + + j = snprint(statbuf, sizeof(statbuf), "%d %lud %lud %lud %q", wq->w.pid, wq->w.time[TUser], wq->w.time[TSys], wq->w.time[TReal], wq->w.msg); free(wq); - return n; + if(j < n) + n = j; + offset = 0; + goto statbufread; case Qns: + case Qfd: eqlock(&p->debug); if(waserror()){ qunlock(&p->debug); nexterror(); } - if(p->pgrp == nil || p->dot == nil || p->pid != PID(c->qid)) - error(Eprocdied); - mw = c->aux; - if(mw->cddone){ - qunlock(&p->debug); - poperror(); - return 0; - } - mntscan(mw, p); - if(mw->mh == nil){ - mw->cddone = 1; - i = snprint(a, n, "cd %s\n", p->dot->path->s); - qunlock(&p->debug); - poperror(); - return i; - } - int2flag(mw->cm->mflag, flag); - if(strcmp(mw->cm->to->path->s, "#M") == 0){ - srv = srvname(mw->cm->to->mchan); - i = snprint(a, n, "mount %s %s %s %s\n", flag, - srv==nil? mw->cm->to->mchan->path->s : srv, - mw->mh->from->path->s, mw->cm->spec? mw->cm->spec : ""); - free(srv); - }else - i = snprint(a, n, "bind %s %s %s\n", flag, - mw->cm->to->path->s, mw->mh->from->path->s); + if(offset == 0 || offset != c->mrock) + c->nrock = c->mrock = 0; + do { + if(QID(c->qid) == Qns) + j = readns1(c, p, statbuf, sizeof(statbuf)); + else + j = readfd1(c, p, statbuf, sizeof(statbuf)); + if(j == 0) + break; + c->mrock += j; + } while(c->mrock <= offset); + i = c->mrock - offset; qunlock(&p->debug); poperror(); - return i; + + if(i <= 0) + return 0; + if(i < n) + n = i; + offset = j - i; + goto statbufread; case Qnoteid: return readnum(offset, va, n, p->noteid, NUMSIZE); + case Qppid: return readnum(offset, va, n, p->parentpid, NUMSIZE); - case Qfd: - return procfds(p, va, n, offset); + } error(Egreg); return 0; /* not reached */ } -void -mntscan(Mntwalk *mw, Proc *p) -{ - Pgrp *pg; - Mount *t; - Mhead *f; - int nxt, i; - ulong last, bestmid; - - pg = p->pgrp; - rlock(&pg->ns); - - nxt = 0; - bestmid = ~0; - - last = 0; - if(mw->mh != nil) - last = mw->cm->mountid; - - for(i = 0; i < MNTHASH; i++) { - for(f = pg->mnthash[i]; f != nil; f = f->hash) { - for(t = f->mount; t != nil; t = t->next) { - if(mw->mh == nil || - (t->mountid > last && t->mountid < bestmid)) { - mw->cm = t; - mw->mh = f; - bestmid = mw->cm->mountid; - nxt = 1; - } - } - } - } - if(nxt == 0) - mw->mh = nil; - - runlock(&pg->ns); -} - static long procwrite(Chan *c, void *va, long n, vlong off) { diff --git a/sys/src/9/port/fault.c b/sys/src/9/port/fault.c index 478e29f3d..45c3959b3 100644 --- a/sys/src/9/port/fault.c +++ b/sys/src/9/port/fault.c @@ -389,7 +389,6 @@ extern void checkmmu(uintptr, uintptr); void checkpages(void) { - int checked; uintptr addr, off; Pte *p; Page *pg; @@ -398,7 +397,6 @@ checkpages(void) if(up == nil) return; - checked = 0; for(sp=up->seg, ep=&up->seg[NSEG]; sppa); - checked++; } qunlock(s); } - print("%ld %s: checked %d page table entries\n", up->pid, up->text, checked); } diff --git a/sys/src/9/port/portdat.h b/sys/src/9/port/portdat.h index b65b73b68..71fd1d2b4 100644 --- a/sys/src/9/port/portdat.h +++ b/sys/src/9/port/portdat.h @@ -17,7 +17,6 @@ typedef struct Logflag Logflag; typedef struct Mntcache Mntcache; typedef struct Mount Mount; typedef struct Mntrpc Mntrpc; -typedef struct Mntwalk Mntwalk; typedef struct Mnt Mnt; typedef struct Mhead Mhead; typedef struct Note Note; @@ -242,13 +241,6 @@ enum NSCACHE = (1< id!#æ/aoe/lun + * because we cannot type æ in the bootloader console. + */ + if(strchr(p, '/') == nil){ + char tmp[64]; + + snprint(tmp, sizeof(tmp), "%c!#æ/aoe/%s", (char)id, p); + + probef[i] = nil; + kstrdup(&probef[i], tmp); + } s = malloc(sizeof *s); if(s == nil) break; diff --git a/sys/src/9/port/sdloop.c b/sys/src/9/port/sdloop.c index 80118369d..49ea6886d 100644 --- a/sys/src/9/port/sdloop.c +++ b/sys/src/9/port/sdloop.c @@ -14,9 +14,6 @@ #include "../port/netif.h" extern char Echange[]; -extern char Enotup[]; - -#define uprint(...) snprint(up->genbuf, sizeof up->genbuf, __VA_ARGS__); enum { Maxpath = 256, @@ -302,7 +299,7 @@ loopbio(SDunit *u, int, int write, void *a, long count, uvlong lba) if(waserror()){ if(strcmp(up->errstr, Echange) == 0 || - strcmp(up->errstr, Enotup) == 0) + strstr(up->errstr, "device is down") != nil) u->sectors = 0; nexterror(); } diff --git a/sys/src/9/xen/fns.h b/sys/src/9/xen/fns.h index 3659354fa..71e64ac4c 100644 --- a/sys/src/9/xen/fns.h +++ b/sys/src/9/xen/fns.h @@ -4,8 +4,6 @@ Dirtab* addarchfile(char*, int, long(*)(Chan*,void*,long,vlong), long(*)(Chan*,v void archinit(void); void bootargs(ulong); ulong cankaddr(ulong); -int cistrcmp(char*, char*); -int cistrncmp(char*, char*, int); #define clearmmucache() /* x86 doesn't have one */ void clockintr(Ureg*, void*); int (*cmpswap)(long*, long, long); @@ -63,10 +61,7 @@ void ioinit(void); int isaconfig(char*, int, ISAConf*); void kbdenable(void); #define kmapinval() -void lgdt(ushort[3]); // XXX remove and in l.s -void lidt(ushort[3]); // XXX remove and in l.s void links(void); -void ltr(ulong); // XXX remove? void mach0init(void); void mathinit(void); void mb386(void); diff --git a/sys/src/9/xen/l.s b/sys/src/9/xen/l.s index ff9515c33..dbfbf248e 100644 --- a/sys/src/9/xen/l.s +++ b/sys/src/9/xen/l.s @@ -54,25 +54,6 @@ _idle: * CR4 and the 'model specific registers' should only be read/written * after it has been determined the processor supports them */ -TEXT lgdt(SB), $0 /* GDTR - global descriptor table */ - MOVL gdtptr+0(FP), AX - MOVL (AX), GDTR - RET - -TEXT lidt(SB), $0 /* IDTR - interrupt descriptor table */ - MOVL idtptr+0(FP), AX - MOVL (AX), IDTR - RET - -TEXT ltr(SB), $0 /* TR - task register */ - MOVL tptr+0(FP), AX - MOVW AX, TASK - RET - -TEXT rtsr(SB), $0 - MOVW TASK, AX - RET - TEXT _cycles(SB), $0 /* time stamp counter; cycles since power up */ RDTSC MOVL vlong+0(FP), CX /* &vlong */ @@ -88,13 +69,9 @@ TEXT rdmsr(SB), $0 /* model-specific register */ MOVL DX, 4(CX) /* hi */ RET +/* Xen doesn't let us do this */ TEXT wrmsr(SB), $0 - MOVL index+0(FP), CX - MOVL lo+4(FP), AX - MOVL hi+8(FP), DX -/* Xen doesn't let us do this - WRMSR - */ + MOVL $-1, AX RET /* diff --git a/sys/src/9/xen/main.c b/sys/src/9/xen/main.c index cc06a4306..2cc4e2ca6 100644 --- a/sys/src/9/xen/main.c +++ b/sys/src/9/xen/main.c @@ -118,9 +118,6 @@ mach0init(void) conf.nmach = 1; MACHP(0) = (Mach*)CPU0MACH; m->pdb = (ulong*)xenstart->pt_base; -#ifdef NOT - m->gdt = (Segdesc*)CPU0GDT; -#endif machinit(); @@ -133,15 +130,12 @@ machinit(void) { int machno; ulong *pdb; - Segdesc *gdt; machno = m->machno; pdb = m->pdb; - gdt = m->gdt; memset(m, 0, sizeof(Mach)); m->machno = machno; m->pdb = pdb; - m->gdt = gdt; m->perf.period = 1; /* @@ -585,16 +579,6 @@ procfork(Proc *p) p->kentry = up->kentry; p->pcycles = -p->kentry; - /* inherit user descriptors */ - memmove(p->gdt, up->gdt, sizeof(p->gdt)); - - /* copy local descriptor table */ - if(up->ldt != nil && up->nldt > 0){ - p->ldt = smalloc(sizeof(Segdesc) * up->nldt); - memmove(p->ldt, up->ldt, sizeof(Segdesc) * up->nldt); - p->nldt = up->nldt; - } - /* save floating point state */ s = splhi(); switch(up->fpstate & ~FPillegal){ @@ -750,51 +734,3 @@ exit(int ispanic) shutdown(ispanic); arch->reset(); } - -int -cistrcmp(char *a, char *b) -{ - int ac, bc; - - for(;;){ - ac = *a++; - bc = *b++; - - if(ac >= 'A' && ac <= 'Z') - ac = 'a' + (ac - 'A'); - if(bc >= 'A' && bc <= 'Z') - bc = 'a' + (bc - 'A'); - ac -= bc; - if(ac) - return ac; - if(bc == 0) - break; - } - return 0; -} - -int -cistrncmp(char *a, char *b, int n) -{ - unsigned ac, bc; - - while(n > 0){ - ac = *a++; - bc = *b++; - n--; - - if(ac >= 'A' && ac <= 'Z') - ac = 'a' + (ac - 'A'); - if(bc >= 'A' && bc <= 'Z') - bc = 'a' + (bc - 'A'); - - ac -= bc; - if(ac) - return ac; - if(bc == 0) - break; - } - - return 0; -} - diff --git a/sys/src/9/xen/mem.h b/sys/src/9/xen/mem.h index d0b3cc356..c4a6886ef 100644 --- a/sys/src/9/xen/mem.h +++ b/sys/src/9/xen/mem.h @@ -63,67 +63,14 @@ /* * known x86 segments (in GDT) and their selectors + * using the selectors that xen gives us. */ -#define NULLSEG 0 /* null segment */ -#define KDSEG 1 /* kernel data/stack */ -#define KESEG 2 /* kernel executable */ -#define UDSEG 3 /* user data/stack */ -#define UESEG 4 /* user executable */ -#define TSSSEG 5 /* task segment */ -#define APMCSEG 6 /* APM code segment */ -#define APMCSEG16 7 /* APM 16-bit code segment */ -#define APMDSEG 8 /* APM data segment */ -#define PROCSEG0 11 /* per process descriptor0 */ -#define NPROCSEG 3 /* number of per process descriptors */ -#define NGDT 13 /* number of GDT entries required */ -/* #define APM40SEG 8 /* APM segment 0x40 */ - -#define SELGDT (0<<2) /* selector is in gdt */ -#define SELLDT (1<<2) /* selector is in ldt */ - -#define SELECTOR(i, t, p) (((i)<<3) | (t) | (p)) - -#define NULLSEL SELECTOR(NULLSEG, SELGDT, 0) -/* these are replaced by XEN entries */ -#ifdef NOPE // XXX investigate more -#define KDSEL SELECTOR(KDSEG, SELGDT, 0) -#define KESEL SELECTOR(KESEG, SELGDT, 0) -#define UESEL SELECTOR(UESEG, SELGDT, 3) -#define UDSEL SELECTOR(UDSEG, SELGDT, 3) -/* comment out to make sure unused ... */ - -#define TSSSEL SELECTOR(TSSSEG, SELGDT, 0) -#define APMCSEL SELECTOR(APMCSEG, SELGDT, 0) -#define APMCSEL16 SELECTOR(APMCSEG16, SELGDT, 0) -#define APMDSEL SELECTOR(APMDSEG, SELGDT, 0) -/* #define APM40SEL SELECTOR(APM40SEG, SELGDT, 0) */ -#else -/* use the selectors that xen gives us */ #define KESEL FLAT_KERNEL_CS #define KDSEL FLAT_KERNEL_DS #define UESEL FLAT_USER_CS #define UDSEL FLAT_USER_DS -#endif -/* - * fields in segment descriptors - */ -#define SEGDATA (0x10<<8) /* data/stack segment */ -#define SEGEXEC (0x18<<8) /* executable segment */ -#define SEGTSS (0x9<<8) /* TSS segment */ -#define SEGCG (0x0C<<8) /* call gate */ -#define SEGIG (0x0E<<8) /* interrupt gate */ -#define SEGTG (0x0F<<8) /* trap gate */ -#define SEGTYPE (0x1F<<8) - -#define SEGP (1<<15) /* segment present */ -#define SEGPL(x) ((x)<<13) /* priority level */ -#define SEGB (1<<22) /* granularity 1==4k (for expand-down) */ -#define SEGG (1<<23) /* granularity 1==4k (for other) */ -#define SEGE (1<<10) /* expand down */ -#define SEGW (1<<9) /* writable (for data/stack) */ -#define SEGR (1<<9) /* readable (for code) */ -#define SEGD (1<<22) /* default 1==32bit (for code) */ +#define NPROCSEG 1 /* number of per process descriptors */ /* * virtual MMU diff --git a/sys/src/9/xen/mmu.c b/sys/src/9/xen/mmu.c index cd51b47ff..9adc9cfea 100644 --- a/sys/src/9/xen/mmu.c +++ b/sys/src/9/xen/mmu.c @@ -13,35 +13,10 @@ uvlong *xenpdpt; /* this needs to go in Mach for multiprocessor guest */ #define MFN(pa) (patomfn[(pa)>>PGSHIFT]) #define MAPPN(x) (paemode? matopfn[*(uvlong*)(&x)>>PGSHIFT]<>PGSHIFT]<>16)&0xFF)|SEGTSS|SEGPL(p)|SEGP } - -Segdesc gdt[NGDT] = -{ -[NULLSEG] { 0, 0}, /* null descriptor */ -[KDSEG] DATASEGM(0), /* kernel data/stack */ -[KESEG] EXECSEGM(0), /* kernel code */ -[UDSEG] DATASEGM(3), /* user data/stack */ -[UESEG] EXECSEGM(3), /* user code */ -[TSSSEG] TSSSEGM(0,0), /* tss segment */ -}; - /* note: pdb must already be pinned */ static void taskswitch(Page *pdb, ulong stack) { - Tss *tss; - - tss = m->tss; - tss->ss0 = KDSEL; - tss->esp0 = stack; - tss->ss1 = KDSEL; - tss->esp1 = stack; - tss->ss2 = KDSEL; - tss->esp2 = stack; - //tss->cr3 = pdb; HYPERVISOR_stack_switch(KDSEL, stack); mmuflushtlb(pdb); } @@ -164,10 +139,7 @@ mmumapcpu0(void) void mmuinit(void) { -//XXX ulong x; -//XXX ushort ptr[3]; ulong *pte, npgs, pa; - extern int rtsr(void); if(paemode){ int i; @@ -193,39 +165,6 @@ mmuinit(void) memglobal(); - m->tss = malloc(sizeof(Tss)); - memset(m->tss, 0, sizeof(Tss)); - m->tss->iomap = 0xDFFF<<16; - - /* - * We used to keep the GDT in the Mach structure, but it - * turns out that that slows down access to the rest of the - * page. Since the Mach structure is accessed quite often, - * it pays off anywhere from a factor of 1.25 to 2 on real - * hardware to separate them (the AMDs are more sensitive - * than Intels in this regard). Under VMware it pays off - * a factor of about 10 to 100. - */ - -#ifdef we_dont_set_gdt_or_lidt - memmove(m->gdt, gdt, sizeof gdt); - x = (ulong)m->tss; - m->gdt[TSSSEG].d0 = (x<<16)|sizeof(Tss); - m->gdt[TSSSEG].d1 = (x&0xFF000000)|((x>>16)&0xFF)|SEGTSS|SEGPL(0)|SEGP; - - ptr[0] = sizeof(gdt)-1; - x = (ulong)m->gdt; - ptr[1] = x & 0xFFFF; - ptr[2] = (x>>16) & 0xFFFF; - lgdt(ptr); - - ptr[0] = sizeof(Segdesc)*256-1; - x = IDTADDR; - ptr[1] = x & 0xFFFF; - ptr[2] = (x>>16) & 0xFFFF; - lidt(ptr); -#endif - #ifdef we_may_eventually_want_this /* make kernel text unwritable */ for(x = KTZERO; x < (ulong)etext; x += BY2PG){ @@ -237,9 +176,6 @@ mmuinit(void) #endif taskswitch(0, (ulong)m + BY2PG); -#ifdef we_dont_do_this - ltr(TSSSEL); -#endif } void diff --git a/sys/src/cmd/disk/mkfile b/sys/src/cmd/disk/mkfile index c762df038..7acb0fcef 100644 --- a/sys/src/cmd/disk/mkfile +++ b/sys/src/cmd/disk/mkfile @@ -14,6 +14,7 @@ DIRS=\ prep\ smart\ # sacfs\ + vblade\ OFILES= diff --git a/sys/src/cmd/disk/vblade/aoe.h b/sys/src/cmd/disk/vblade/aoe.h new file mode 100644 index 000000000..1a9592a22 --- /dev/null +++ b/sys/src/cmd/disk/vblade/aoe.h @@ -0,0 +1,70 @@ +enum{ + ACata, + ACconfig, +}; + +enum{ + AQCread, + AQCtest, + AQCprefix, + AQCset, + AQCfset, +}; + +enum{ + AEcmd = 1, + AEarg, + AEdev, + AEcfg, + AEver, +}; + +enum{ + Aoetype = 0x88a2, + Aoesectsz = 512, + Aoemaxcfg = 1024, + + Aoehsz = 24, + Aoeatasz = 12, + Aoecfgsz = 8, + Aoerrsz = 2, + Aoemsz = 4, + Aoemdsz = 8, + + Aoever = 1, + + AFerr = 1<<2, + AFrsp = 1<<3, + + AAFwrite = 1, + AAFext = 1<<6, +}; + +typedef struct{ + uchar dst[Eaddrlen]; + uchar src[Eaddrlen]; + uchar type[2]; + uchar verflag; + uchar error; + uchar major[2]; + uchar minor; + uchar cmd; + uchar tag[4]; +}Aoehdr; + +typedef struct{ + uchar aflag; + uchar errfeat; + uchar scnt; + uchar cmdstat; + uchar lba[6]; + uchar res[2]; +}Aoeata; + +typedef struct{ + uchar bufcnt[2]; + uchar fwver[2]; + uchar scnt; + uchar verccmd; + uchar cslen[2]; +}Aoeqc; diff --git a/sys/src/cmd/disk/vblade/mkfile b/sys/src/cmd/disk/vblade/mkfile new file mode 100644 index 000000000..a03a7d0ef --- /dev/null +++ b/sys/src/cmd/disk/vblade/mkfile @@ -0,0 +1,12 @@ + +#include +#include +#include /* irony */ +#include + +enum { + Eaddrlen = 6, /* only defined in kernel */ +}; +#include "aoe.h" + +enum { + Fclone, + Fdata, + Flast, + + Fraw = 1<<0, + + Nether = 8, + Nvblade = 8, + Maxpkt = 10000, + Hdrlba = 128, + Conflen = 1024, +}; + +typedef struct { + int iflag; + int flag; + int shelf; + int slot; + uvlong maxlba; + char *config; +} Conf; + +typedef struct { + char magic[32]; + char size[32]; + char address[16]; + char configlen[6]; + char pad[512-32-32-16-6]; + char config[Conflen]; +} Vbhdr; + +typedef struct { + Vbhdr hdr; + vlong maxlba; + vlong hdrsz; + int shelf; + int slot; + int clen; + int flag; + int fd; +} Vblade; + +static Vblade vblade[Nvblade]; +static int nblade; + +static char *ethertab[Nether] = { + "/net/ether0", +}; +static int etheridx = 1; +static int efdtab[Nether*Flast]; +static char pkttab[Nether][Maxpkt]; +static char bctab[Nether][Maxpkt]; +static int mtutab[Nether]; +static char Magic[] = "aoe vblade\n"; + +static int +getmtu(char *p) +{ + char buf[50]; + int fd, mtu; + + snprint(buf, sizeof buf, "%s/mtu", p); + if((fd = open(buf, OREAD)) == -1) + return 2; + if(read(fd, buf, 36) < 0) + return 2; + close(fd); + buf[36] = 0; + mtu = strtoul(buf+12, 0, 0)-Aoehsz; + return mtu>>9; +} + +int +parseshelf(char *s, int *shelf, int *slot) +{ + int a, b; + + a = strtoul(s, &s, 0); + if(*s++ != '.') + return -1; + b = strtoul(s, &s, 0); + if(*s != 0) + return -1; + *shelf = a; + *slot = b; + return 0; +} + +static vlong +getsize(char *s) +{ + static char tab[] = "ptgmk"; + char *p; + vlong v; + + v = strtoull(s, &s, 0); + while((p = strchr(tab, *s++)) && *p) + while(*p++) + v *= 1024; + if(s[-1]) + return -1; + return v; +} + +vlong +sizetolba(vlong size) +{ + if(size < 512 || size & 0x1ff){ + fprint(2, "invalid size %lld\n", size); + exits("size"); + } + return size>>9; +} + +static int +savevblade(int fd, Vblade *vb) +{ + int n, r; + char *p; + + sprint(vb->hdr.size, "%lld", vb->maxlba<<9); + sprint(vb->hdr.address, "%d.%d", vb->shelf, vb->slot); + sprint(vb->hdr.configlen, "%d", vb->clen); + + if(vb->flag & Fraw) + return 0; + p = (char*)vb; + for(n = 0; n < sizeof *vb; n += r) + if((r = pwrite(fd, p+n, sizeof *vb-n, n)) <= 0) + break; + if(n != sizeof *vb) + return -1; + return 0; +} + +static char* +chkvblade(int fd, Vblade *vb) +{ + Vbhdr *h; + + h = &vb->hdr; + if(readn(fd, (char*)h, sizeof *h) != sizeof *h) + return "bad read"; + if(memcmp(h->magic, Magic, sizeof Magic)) + return "bad magic"; + h->size[sizeof h->size-1] = 0; + vb->maxlba = sizetolba(strtoull(h->size, 0, 0)); + if(parseshelf(h->address, &vb->shelf, &vb->slot) == -1) + return "bad shelf"; + h->configlen[sizeof h->configlen-1] = 0; + vb->clen = strtoul(h->configlen, 0, 0); + return 0; +} + +void +checkfile(char *s, Vblade *vb, int iflag) +{ + char *e; + + vb->fd = open(s, ORDWR); + if(vb->fd == -1) + sysfatal("can't open backing store: %r"); + if(iflag == 0 && (e = chkvblade(vb->fd, vb))) + sysfatal("invalid vblade %s", e); +} + +void +recheck(int fd, Vblade *vb) +{ + Dir *d; + vlong v; + + d = dirfstat(fd); + if(d == 0) + sysfatal("can't stat: %r"); + if((vb->flag & Fraw) == 0) + vb->hdrsz = Hdrlba; + v = sizetolba(d->length & ~0x1ff) - vb->hdrsz; + free(d); + if(vb->maxlba > v) + sysfatal("cmdline size too large (%lld sector overhead)", vb->hdrsz); + if(vb->maxlba == 0) + vb->maxlba = v; + + savevblade(fd, vb); +} + +int +aoeopen(char *e, int fds[]) +{ + char buf[128], ctl[13]; + int n; + + snprint(buf, sizeof buf, "%s/clone", e); + if((fds[Fclone] = open(buf, ORDWR)) == -1) + return -1; + memset(ctl, 0, sizeof ctl); + if(read(fds[Fclone], ctl, sizeof ctl - 1) < 0) + return -1; + n = atoi(ctl); + snprint(buf, sizeof buf, "connect %d", Aoetype); + if(write(fds[Fclone], buf, strlen(buf)) != strlen(buf)) + return -1; + snprint(buf, sizeof buf, "%s/%d/data", e, n); + fds[Fdata] = open(buf, ORDWR); + return fds[Fdata]; +} + +void +replyhdr(Aoehdr *h, Vblade *vblade) +{ + uchar ea[Eaddrlen]; + + memmove(ea, h->dst, Eaddrlen); + memmove(h->dst, h->src, Eaddrlen); + memmove(h->src, ea, Eaddrlen); + + hnputs(h->major, vblade->shelf); + h->minor = vblade->slot; + h->verflag |= AFrsp; +} + +static int +serveconfig(Aoehdr *h, Vblade *vb, int mtu) +{ + int cmd, reqlen, len; + char *cfg; + Aoeqc *q; + + if(memcmp(h->src, h->dst, Eaddrlen) == 0) + return -1; + + q = (Aoeqc*)((char*)h + Aoehsz); + reqlen = nhgets(q->cslen); + len = vb->clen; + cmd = q->verccmd&0xf; + cfg = (char*)q + Aoecfgsz; + + switch(cmd){ + case AQCtest: + if(reqlen != len) + return -1; + case AQCprefix: + if(reqlen > len) + return -1; + if(memcmp(vb->hdr.config, cfg, reqlen) != 0) + return -1; + case AQCread: + break; + case AQCset: + if(len && len != reqlen || memcmp(vb->hdr.config, cfg, reqlen) != 0){ + h->verflag |= AFerr; + h->error = AEcfg; + break; + } + case AQCfset: + if(reqlen > Conflen){ + h->verflag |= AFerr; + h->error = AEarg; + break; + } + memset(vb->hdr.config, 0, sizeof vb->hdr.config); + memmove(vb->hdr.config, cfg, reqlen); + vb->clen = len = reqlen; + savevblade(vb->fd, vb); + break; + default: + h->verflag |= AFerr; + h->error = AEarg; + } + + memmove(cfg, vb->hdr.config, len); + hnputs(q->cslen, len); + hnputs(q->bufcnt, 24); + q->scnt = mtu; + hnputs(q->fwver, 2323); + q->verccmd = Aoever<<4 | cmd; + + return Aoehsz+Aoecfgsz + len; +} + +static ushort ident[256] = { + [47] 0x8000, + [49] 0x0200, + [50] 0x4000, + [83] 0x5400, + [84] 0x4000, + [86] 0x1400, + [87] 0x4000, + [93] 0x400b, +}; + +static void +idmoveto(char *a, int idx, int len, char *s) +{ + char *p; + + p = a+idx*2; + for(; len > 0; len -= 2) { + if(*s == 0) + p[1] = ' '; + else + p[1] = *s++; + if (*s == 0) + p[0] = ' '; + else + p[0] = *s++; + p += 2; + } +} + +static void +lbamoveto(char *p, int idx, int n, vlong lba) +{ + int i; + + p += idx*2; + for(i = 0; i < n; i++) + *p++ = lba>>i*8; +} + +enum { + Crd = 0x20, + Crdext = 0x24, + Cwr = 0x30, + Cwrext = 0x34, + Cid = 0xec, +}; + +static uvlong +getlba(uchar *p) +{ + uvlong v; + + v = p[0]; + v |= p[1]<<8; + v |= p[2]<<16; + v |= p[3]<<24; + v |= (uvlong)p[4]<<32; + v |= (uvlong)p[5]<<40; + return v; +} + +static void +putlba(uchar *p, vlong lba) +{ + p[0] = lba; + p[1] = lba>>8; + p[2] = lba>>16; + p[3] = lba>>24; + p[5] = lba>>32; + p[6] = lba>>40; +} + +static int +serveata(Aoehdr *h, Vblade *vb, int mtu) +{ + Aoeata *a; + char *buf; + int rbytes, bytes, len; + vlong lba, off; + + a = (Aoeata*)((char*)h + Aoehsz); + buf = (char*)a + Aoeatasz; + lba = getlba(a->lba); + len = a->scnt<<9; + off = lba+vb->hdrsz<<9; + + rbytes = 0; + if(a->scnt > mtu || a->scnt == 0){ + h->verflag |= AFerr; + a->cmdstat = ASdrdy|ASerr; + h->error = AEarg; + goto out; + } + + if(a->cmdstat != Cid) + if(lba+a->scnt > vb->maxlba){ + a->errfeat = Eidnf; + a->cmdstat = ASdrdy|ASerr; + goto out; + } + + if(a->cmdstat&0xf0 == 0x20) + lba &= 0xfffffff; + switch(a->cmdstat){ + default: + a->errfeat = Eabrt; + a->cmdstat = ASdrdy|ASerr; + goto out; + case Cid: + memmove(buf, ident, sizeof ident); + idmoveto(buf, 27, 40, "Plan 9 Vblade"); + idmoveto(buf, 10, 20, "serial#"); + idmoveto(buf, 23, 8, "2"); + lbamoveto(buf, 60, 4, vb->maxlba); + lbamoveto(buf, 100, 8, vb->maxlba); + a->cmdstat = ASdrdy; + rbytes = 512; + goto out; + case Crd: + case Crdext: + bytes = pread(vb->fd, buf, len, off); + rbytes = bytes; + break; + case Cwr: + case Cwrext: + bytes = pwrite(vb->fd, buf, len, off); + break; + } + if(bytes != len){ + a->errfeat = Eabrt; + a->cmdstat = ASdf|ASerr; + putlba(a->lba, lba+(len-bytes)>>9); + rbytes = 0; + goto out; + } + + putlba(a->lba, lba+a->scnt); + a->scnt = 0; + a->errfeat = 0; + a->cmdstat = ASdrdy; +out: + return Aoehsz+Aoeatasz + rbytes; +} + +static int +myea(uchar ea[6], char *p) +{ + char buf[50]; + int fd; + + snprint(buf, sizeof buf, "%s/addr", p); + if((fd = open(buf, OREAD)) == -1) + return -1; + if(read(fd, buf, 12) < 12) + return -1; + close(fd); + return parseether(ea, buf); +} + +static void +bcastpkt(Aoehdr *h, uint shelf, uint slot, int i) +{ + myea(h->dst, ethertab[i]); + memset(h->src, 0xff, Eaddrlen); + hnputs(h->type, Aoetype); + hnputs(h->major, shelf); + h->minor = slot; + h->cmd = ACconfig; + h->tag[0] = h->tag[1] = h->tag[2] = h->tag[3] = 0; +} + +int +bladereply(Vblade *v, int i, int fd, char *pkt) +{ + int n; + Aoehdr *h; + + h = (Aoehdr*)pkt; + switch(h->cmd){ + case ACata: + n = serveata(h, v, mtutab[i]); + break; + case ACconfig: + n = serveconfig(h, v, mtutab[i]); + break; + default: + n = -1; + break; + } + if(n == -1) + return -1; + replyhdr(h, v); + if(n < 60){ + memset(pkt+n, 0, 60-n); + n = 60; + } + if(write(fd, h, n) != n){ + fprint(2, "write to %s failed: %r\n", ethertab[i]); + return -1; + } + return 0; +} + +void +serve(void *v) +{ + int i, j, popcnt, vec, n, s, efd; + char *pkt, *bcpkt; + Aoehdr *h; + +fmtinstall('E', eipfmt); + i = (int)(uintptr)v; + + efd = efdtab[i*Flast+Fdata]; + pkt = pkttab[i]; + bcpkt = bctab[i]; + + n = 60; + h = (Aoehdr*)pkt; + bcastpkt(h, 0xffff, 0xff, i); + goto start; + + for(;;){ + n = read(efd, pkt, Maxpkt); + start: + if(n < 60 || h->verflag & AFrsp) + continue; + s = nhgets(h->major); + popcnt = 0; + vec = 0; + for(j = 0; j < nblade; j++){ + if((vblade[j].shelf == s || s == 0xffff) + && (vblade[j].slot == h->minor || h->minor == 0xff)){ + popcnt++; + vec |= 1<0 && j < nblade; j++){ + if((vec & 1<0){ + memcpy(bcpkt, pkt, n); + bladereply(vblade + j, i, efd, bcpkt); + }else + bladereply(vblade + j, i, efd, pkt); + popcnt--; + } + } +} + +void +launch(char *tab[], int fdtab[]) +{ + int i; + + for(i = 0; tab[i]; i++){ + if(aoeopen(tab[i], fdtab+Flast*i) < 0) + sysfatal("network open: %r"); + /* + * use proc not threads. otherwise we will block on read/write. + */ + proccreate(serve, (void*)i, 32*1024); + } +} + +void +usage(void) +{ + fprint(2, "vblade [-ir] [-s size] [-a shelf.slot] [-c config] [-e ether] file\n"); + exits("usage"); +} + +void +goblade(Vblade *vblade, char *file, Conf *c) +{ + char *anal; + + if(c->iflag == 1) + memcpy(vblade->hdr.magic, Magic, sizeof Magic); + checkfile(file, vblade, c->iflag); + + vblade->flag = c->flag; + if(c->shelf != -1){ + vblade->shelf = c->shelf; + vblade->slot = c->slot; + } + if(c->maxlba > 0) + vblade->maxlba = c->maxlba; + if(c->config != nil) + memmove(vblade->hdr.config, c->config, vblade->clen = strlen(c->config)); + + recheck(vblade->fd, vblade); + + anal = ""; + if(vblade->maxlba > 1) + anal = "s"; + fprint(2, "lblade %d.%d %lld sector%s\n", vblade->shelf, vblade->slot, vblade->maxlba, anal); +} + +void +threadmain(int argc, char **argv) +{ + int i, lastc, anye; + Conf c; + + anye = 0; + for(;;){ + if(nblade == nelem(vblade)) + sysfatal("too many blades"); + c = (Conf){0, 0, -1, -1, 0, nil}; + lastc = 0; + ARGBEGIN{ + case 'a': + lastc = 'a'; + if(parseshelf(EARGF(usage()), &c.shelf, &c.slot) == -1) + sysfatal("bad vblade address"); + break; + case 'c': + lastc = 'c'; + c.config = EARGF(usage()); + break; + case 'e': + lastc = 'e'; + if(anye++ == 0) + etheridx = 0; + if(etheridx == nelem(ethertab)) + sysfatal("too many interfaces"); + ethertab[etheridx++] = EARGF(usage()); + break; + case 'i': + lastc = 'i'; + c.iflag = 1; + break; + case 'r': + lastc = 'r'; + c.flag |= Fraw; + c.iflag = 1; + break; + case 's': + lastc = 's'; + c.maxlba = sizetolba(getsize(EARGF(usage()))); + break; + default: + lastc = '?'; + usage(); + }ARGEND; + + if(argc == 0 && lastc == 'e') + break; + if(argc == 0) + usage(); + goblade(vblade + nblade++, *argv, &c); + if(argc == 1) + break; + } + + if(nblade == 0) + usage(); + for(i = 0; i < etheridx; i++) + mtutab[i] = getmtu(ethertab[i]); + + launch(ethertab, efdtab); + + for(; sleep(1*1000) != -1;) + ; + threadexitsall("interrupted"); +} diff --git a/sys/src/cmd/sam/cmd.c b/sys/src/cmd/sam/cmd.c index a0e336f01..6e8efa094 100644 --- a/sys/src/cmd/sam/cmd.c +++ b/sys/src/cmd/sam/cmd.c @@ -35,6 +35,8 @@ Cmdtab cmdtab[]={ '>', 0, 0, 0, 0, aDot, 0, linex, plan9_cmd, '<', 0, 0, 0, 0, aDot, 0, linex, plan9_cmd, '|', 0, 0, 0, 0, aDot, 0, linex, plan9_cmd, + '^', 0, 0, 0, 0, aDot, 0, linex, plan9_cmd, + '_', 0, 0, 0, 0, aDot, 0, linex, plan9_cmd, '=', 0, 0, 0, 0, aDot, 0, linex, eq_cmd, 'c'|0x100,0, 0, 0, 0, aNo, 0, wordx, cd_cmd, 0, 0, 0, 0, 0, 0, 0, 0, @@ -76,7 +78,13 @@ inputc(void) Again: nbuf = 0; - if(downloaded){ + if(cmdbufpos > cmdbuf.nc && cmdbuf.nc > 0){ + cmdbufpos = 0; + bufreset(&cmdbuf); + } + if(cmdbufpos < cmdbuf.nc && cmdbuf.nc > 0) + bufread(&cmdbuf, cmdbufpos++, &r, 1); + else if(downloaded){ while(termoutp == terminp){ cmdupdate(); if(patset) diff --git a/sys/src/cmd/sam/sam.h b/sys/src/cmd/sam/sam.h index a5ff1b9a2..f1cbd8ac0 100644 --- a/sys/src/cmd/sam/sam.h +++ b/sys/src/cmd/sam/sam.h @@ -361,6 +361,8 @@ extern int quitok; extern Address addr; extern Buffer snarfbuf; extern Buffer plan9buf; +extern Buffer cmdbuf; +extern int cmdbufpos; extern List file; extern List tempfile; extern File *cmd; diff --git a/sys/src/cmd/sam/shell.c b/sys/src/cmd/sam/shell.c index fe9162fc6..c0eced359 100644 --- a/sys/src/cmd/sam/shell.c +++ b/sys/src/cmd/sam/shell.c @@ -7,6 +7,8 @@ char errfile[64]; String plan9cmd; /* null terminated */ Buffer plan9buf; void checkerrs(void); +Buffer cmdbuf; +int cmdbufpos; int plan9(File *f, int type, String *s, int nest) @@ -28,7 +30,7 @@ plan9(File *f, int type, String *s, int nest) } if(type!='!' && pipe(pipe1)==-1) error(Epipe); - if(type=='|') + if(type=='|' || type=='_') snarf(f, addr.r.p1, addr.r.p2, &plan9buf, 1); if((pid=fork()) == 0){ if(downloaded){ /* also put nasty fd's into errfile */ @@ -48,14 +50,14 @@ plan9(File *f, int type, String *s, int nest) } } if(type != '!') { - if(type=='<' || type=='|') - dup(pipe1[1], 1); - else if(type == '>') + if(type == '>') dup(pipe1[0], 0); + else + dup(pipe1[1], 1); close(pipe1[0]); close(pipe1[1]); } - if(type == '|'){ + if(type == '|' || type == '_'){ if(pipe(pipe2) == -1) exits("pipe"); if((pid = fork())==0){ @@ -87,7 +89,7 @@ plan9(File *f, int type, String *s, int nest) close(pipe2[0]); close(pipe2[1]); } - if(type=='<'){ + if(type=='<' || type=='^'){ close(0); /* so it won't read from terminal */ open("/dev/null", 0); } @@ -115,9 +117,14 @@ plan9(File *f, int type, String *s, int nest) writeio(f); bpipeok = 0; closeio((Posn)-1); + }else if(type == '^' || type == '_'){ + int nulls; + close(pipe1[1]); + bufload(&cmdbuf, cmdbufpos, pipe1[0], &nulls); + close(pipe1[0]); } retmsg = waitfor(pid); - if(type=='|' || type=='<') + if(type=='|' || type=='<' || type=='_' || type=='^') if(retmsg[0]!=0) warn_s(Wbadstatus, retmsg); if(downloaded) diff --git a/sys/src/cmd/tee.c b/sys/src/cmd/tee.c index 83db8a08f..40a3171fa 100644 --- a/sys/src/cmd/tee.c +++ b/sys/src/cmd/tee.c @@ -5,9 +5,12 @@ #include #include +enum { + FDSTART = 3, +}; + int uflag; int aflag; -int openf[100]; char in[8192]; @@ -42,26 +45,29 @@ main(int argc, char **argv) n = 0; while(*argv) { if(aflag) { - openf[n] = open(argv[0], OWRITE); - if(openf[n] < 0) - openf[n] = create(argv[0], OWRITE, 0666); - seek(openf[n], 0L, 2); + i = open(argv[0], OWRITE); + if(i < 0) + i = create(argv[0], OWRITE, 0666); + seek(i, 0L, 2); } else - openf[n] = create(argv[0], OWRITE, 0666); - if(openf[n] < 0) { + i = create(argv[0], OWRITE, 0666); + if(i < 0) { fprint(2, "tee: cannot open %s: %r\n", argv[0]); - } else + } else { + if(i != n+FDSTART) + dup(i, n+FDSTART); n++; + } argv++; } - openf[n++] = 1; for(;;) { r = read(0, in, sizeof in); if(r <= 0) exits(nil); for(i=0; i