13ff48bf5SDavid du Colombier #include <u.h> 23ff48bf5SDavid du Colombier #include <libc.h> 33ff48bf5SDavid du Colombier #include <auth.h> 43ff48bf5SDavid du Colombier #include <fcall.h> 53ff48bf5SDavid du Colombier #include <thread.h> 63ff48bf5SDavid du Colombier #include <9p.h> 73ff48bf5SDavid du Colombier 83ff48bf5SDavid du Colombier typedef struct Part Part; 93ff48bf5SDavid du Colombier typedef struct Trip Trip; 103ff48bf5SDavid du Colombier typedef struct Dbl Dbl; 113ff48bf5SDavid du Colombier typedef struct Ind Ind; 123ff48bf5SDavid du Colombier 133ff48bf5SDavid du Colombier /* 143ff48bf5SDavid du Colombier * with 8192-byte blocks and 4-byte pointers, 153ff48bf5SDavid du Colombier * double-indirect gets us 34 GB. 163ff48bf5SDavid du Colombier * triple-indirect gets us 70,368 GB. 173ff48bf5SDavid du Colombier */ 183ff48bf5SDavid du Colombier 193ff48bf5SDavid du Colombier enum 203ff48bf5SDavid du Colombier { 213ff48bf5SDavid du Colombier LOGBLKSZ = 13, 223ff48bf5SDavid du Colombier BLKSZ = 1<<LOGBLKSZ, /* 8192 */ 233ff48bf5SDavid du Colombier LOGNPTR = LOGBLKSZ-2, /* assume sizeof(void*) == 4 */ 243ff48bf5SDavid du Colombier NPTR = 1<<LOGNPTR, 253ff48bf5SDavid du Colombier }; 263ff48bf5SDavid du Colombier 273ff48bf5SDavid du Colombier struct Trip 283ff48bf5SDavid du Colombier { 293ff48bf5SDavid du Colombier Dbl *dbl[NPTR]; 303ff48bf5SDavid du Colombier }; 313ff48bf5SDavid du Colombier 323ff48bf5SDavid du Colombier struct Dbl 333ff48bf5SDavid du Colombier { 343ff48bf5SDavid du Colombier Ind *ind[NPTR]; 353ff48bf5SDavid du Colombier }; 363ff48bf5SDavid du Colombier 373ff48bf5SDavid du Colombier struct Ind 383ff48bf5SDavid du Colombier { 393ff48bf5SDavid du Colombier uchar *blk[NPTR]; 403ff48bf5SDavid du Colombier }; 413ff48bf5SDavid du Colombier 423ff48bf5SDavid du Colombier Trip trip; 433ff48bf5SDavid du Colombier 443ff48bf5SDavid du Colombier struct Part 453ff48bf5SDavid du Colombier { 463ff48bf5SDavid du Colombier int inuse; 473ff48bf5SDavid du Colombier int vers; 483ff48bf5SDavid du Colombier ulong mode; 493ff48bf5SDavid du Colombier char *name; 503ff48bf5SDavid du Colombier vlong offset; /* in sectors */ 513ff48bf5SDavid du Colombier vlong length; /* in sectors */ 523ff48bf5SDavid du Colombier }; 533ff48bf5SDavid du Colombier 543ff48bf5SDavid du Colombier enum 553ff48bf5SDavid du Colombier { 563ff48bf5SDavid du Colombier Qroot = 0, 573ff48bf5SDavid du Colombier Qdir, 583ff48bf5SDavid du Colombier Qctl, 593ff48bf5SDavid du Colombier Qpart, 603ff48bf5SDavid du Colombier }; 613ff48bf5SDavid du Colombier 623ff48bf5SDavid du Colombier Part tab[64]; 63*11e1fb05SDavid du Colombier int fd = -1; 643ff48bf5SDavid du Colombier char *sdname = "sdXX"; 653ff48bf5SDavid du Colombier ulong ctlmode = 0666; 663ff48bf5SDavid du Colombier char *inquiry = "aux/disksim hard drive"; 673ff48bf5SDavid du Colombier vlong nsect, sectsize, c, h, s; 683ff48bf5SDavid du Colombier ulong time0; 69*11e1fb05SDavid du Colombier int rdonly; 703ff48bf5SDavid du Colombier 713ff48bf5SDavid du Colombier char* 723ff48bf5SDavid du Colombier ctlstring(void) 733ff48bf5SDavid du Colombier { 743ff48bf5SDavid du Colombier int i; 753ff48bf5SDavid du Colombier Fmt fmt; 763ff48bf5SDavid du Colombier 773ff48bf5SDavid du Colombier fmtstrinit(&fmt); 783ff48bf5SDavid du Colombier fmtprint(&fmt, "inquiry %s\n", inquiry); 793ff48bf5SDavid du Colombier fmtprint(&fmt, "geometry %lld %lld %lld %lld %lld\n", nsect, sectsize, c, h, s); 803ff48bf5SDavid du Colombier for(i=0; i<nelem(tab); i++) 813ff48bf5SDavid du Colombier if(tab[i].inuse) 823ff48bf5SDavid du Colombier fmtprint(&fmt, "part %s %lld %lld\n", tab[i].name, tab[i].offset, tab[i].length); 833ff48bf5SDavid du Colombier return fmtstrflush(&fmt); 843ff48bf5SDavid du Colombier } 853ff48bf5SDavid du Colombier 863ff48bf5SDavid du Colombier int 873ff48bf5SDavid du Colombier addpart(char *name, vlong start, vlong end) 883ff48bf5SDavid du Colombier { 893ff48bf5SDavid du Colombier int i; 903ff48bf5SDavid du Colombier 913ff48bf5SDavid du Colombier if(start < 0 || start > end || end > nsect){ 923ff48bf5SDavid du Colombier werrstr("bad partition boundaries"); 933ff48bf5SDavid du Colombier return -1; 943ff48bf5SDavid du Colombier } 953ff48bf5SDavid du Colombier 963ff48bf5SDavid du Colombier for(i=0; i<nelem(tab); i++) 973ff48bf5SDavid du Colombier if(tab[i].inuse == 0) 983ff48bf5SDavid du Colombier break; 993ff48bf5SDavid du Colombier if(i == nelem(tab)){ 1003ff48bf5SDavid du Colombier werrstr("no free partition slots"); 1013ff48bf5SDavid du Colombier return -1; 1023ff48bf5SDavid du Colombier } 1033ff48bf5SDavid du Colombier 1043ff48bf5SDavid du Colombier free(tab[i].name); 1053ff48bf5SDavid du Colombier tab[i].inuse = 1; 1063ff48bf5SDavid du Colombier tab[i].name = estrdup9p(name); 1073ff48bf5SDavid du Colombier tab[i].offset = start; 1083ff48bf5SDavid du Colombier tab[i].length = end - start; 1093ff48bf5SDavid du Colombier tab[i].mode = ctlmode; 1103ff48bf5SDavid du Colombier tab[i].vers++; 1113ff48bf5SDavid du Colombier 1123ff48bf5SDavid du Colombier return 0; 1133ff48bf5SDavid du Colombier } 1143ff48bf5SDavid du Colombier 1153ff48bf5SDavid du Colombier int 1163ff48bf5SDavid du Colombier delpart(char *s) 1173ff48bf5SDavid du Colombier { 1183ff48bf5SDavid du Colombier int i; 1193ff48bf5SDavid du Colombier 1203ff48bf5SDavid du Colombier for(i=0; i<nelem(tab); i++) 1213ff48bf5SDavid du Colombier if(tab[i].inuse && strcmp(tab[i].name, s) == 0) 1223ff48bf5SDavid du Colombier break; 1233ff48bf5SDavid du Colombier if(i==nelem(tab)){ 1243ff48bf5SDavid du Colombier werrstr("partition not found"); 1253ff48bf5SDavid du Colombier return -1; 1263ff48bf5SDavid du Colombier } 1273ff48bf5SDavid du Colombier 1283ff48bf5SDavid du Colombier tab[i].inuse = 0; 1293ff48bf5SDavid du Colombier free(tab[i].name); 1303ff48bf5SDavid du Colombier tab[i].name = 0; 1313ff48bf5SDavid du Colombier return 0; 1323ff48bf5SDavid du Colombier } 1333ff48bf5SDavid du Colombier 1343ff48bf5SDavid du Colombier void 1353ff48bf5SDavid du Colombier ctlwrite(Req *r) 1363ff48bf5SDavid du Colombier { 1373ff48bf5SDavid du Colombier int i; 1383ff48bf5SDavid du Colombier Cmdbuf *cb; 1393ff48bf5SDavid du Colombier vlong start, end; 1403ff48bf5SDavid du Colombier 1413ff48bf5SDavid du Colombier r->ofcall.count = r->ifcall.count; 1423ff48bf5SDavid du Colombier cb = parsecmd(r->ifcall.data, r->ifcall.count); 1433ff48bf5SDavid du Colombier if(cb->nf < 1){ 1443ff48bf5SDavid du Colombier respond(r, "empty control message"); 1453ff48bf5SDavid du Colombier free(cb); 1463ff48bf5SDavid du Colombier return; 1473ff48bf5SDavid du Colombier } 1483ff48bf5SDavid du Colombier 1493ff48bf5SDavid du Colombier if(strcmp(cb->f[0], "part") == 0){ 1503ff48bf5SDavid du Colombier if(cb->nf != 4){ 1513ff48bf5SDavid du Colombier respondcmderror(r, cb, "part takes 3 args"); 1523ff48bf5SDavid du Colombier free(cb); 1533ff48bf5SDavid du Colombier return; 1543ff48bf5SDavid du Colombier } 1553ff48bf5SDavid du Colombier start = strtoll(cb->f[2], 0, 0); 1563ff48bf5SDavid du Colombier end = strtoll(cb->f[3], 0, 0); 1573ff48bf5SDavid du Colombier if(addpart(cb->f[1], start, end) < 0){ 1583ff48bf5SDavid du Colombier respondcmderror(r, cb, "%r"); 1593ff48bf5SDavid du Colombier free(cb); 1603ff48bf5SDavid du Colombier return; 1613ff48bf5SDavid du Colombier } 1623ff48bf5SDavid du Colombier } 1633ff48bf5SDavid du Colombier else if(strcmp(cb->f[0], "delpart") == 0){ 1643ff48bf5SDavid du Colombier if(cb->nf != 2){ 1653ff48bf5SDavid du Colombier respondcmderror(r, cb, "delpart takes 1 arg"); 1663ff48bf5SDavid du Colombier free(cb); 1673ff48bf5SDavid du Colombier return; 1683ff48bf5SDavid du Colombier } 1693ff48bf5SDavid du Colombier if(delpart(cb->f[1]) < 0){ 1703ff48bf5SDavid du Colombier respondcmderror(r, cb, "%r"); 1713ff48bf5SDavid du Colombier free(cb); 1723ff48bf5SDavid du Colombier return; 1733ff48bf5SDavid du Colombier } 1743ff48bf5SDavid du Colombier } 1753ff48bf5SDavid du Colombier else if(strcmp(cb->f[0], "inquiry") == 0){ 1763ff48bf5SDavid du Colombier if(cb->nf != 2){ 1773ff48bf5SDavid du Colombier respondcmderror(r, cb, "inquiry takes 1 arg"); 1783ff48bf5SDavid du Colombier free(cb); 1793ff48bf5SDavid du Colombier return; 1803ff48bf5SDavid du Colombier } 1813ff48bf5SDavid du Colombier free(inquiry); 1823ff48bf5SDavid du Colombier inquiry = estrdup9p(cb->f[1]); 1833ff48bf5SDavid du Colombier } 1843ff48bf5SDavid du Colombier else if(strcmp(cb->f[0], "geometry") == 0){ 1853ff48bf5SDavid du Colombier if(cb->nf != 6){ 1863ff48bf5SDavid du Colombier respondcmderror(r, cb, "geometry takes 5 args"); 1873ff48bf5SDavid du Colombier free(cb); 1883ff48bf5SDavid du Colombier return; 1893ff48bf5SDavid du Colombier } 1903ff48bf5SDavid du Colombier nsect = strtoll(cb->f[1], 0, 0); 1913ff48bf5SDavid du Colombier sectsize = strtoll(cb->f[2], 0, 0); 1923ff48bf5SDavid du Colombier c = strtoll(cb->f[3], 0, 0); 1933ff48bf5SDavid du Colombier h = strtoll(cb->f[4], 0, 0); 1943ff48bf5SDavid du Colombier s = strtoll(cb->f[5], 0, 0); 1953ff48bf5SDavid du Colombier if(tab[0].inuse && strcmp(tab[0].name, "data") == 0 && tab[0].vers == 0){ 1963ff48bf5SDavid du Colombier tab[0].offset = 0; 1973ff48bf5SDavid du Colombier tab[0].length = nsect; 1983ff48bf5SDavid du Colombier } 1993ff48bf5SDavid du Colombier for(i=0; i<nelem(tab); i++){ 2003ff48bf5SDavid du Colombier if(tab[i].inuse && tab[i].offset+tab[i].length > nsect){ 2013ff48bf5SDavid du Colombier tab[i].inuse = 0; 2023ff48bf5SDavid du Colombier free(tab[i].name); 2033ff48bf5SDavid du Colombier tab[i].name = 0; 2043ff48bf5SDavid du Colombier } 2053ff48bf5SDavid du Colombier } 2063ff48bf5SDavid du Colombier } 2073ff48bf5SDavid du Colombier else{ 2083ff48bf5SDavid du Colombier respondcmderror(r, cb, "unknown control message"); 2093ff48bf5SDavid du Colombier free(cb); 2103ff48bf5SDavid du Colombier return; 2113ff48bf5SDavid du Colombier } 2123ff48bf5SDavid du Colombier 2133ff48bf5SDavid du Colombier free(cb); 2143ff48bf5SDavid du Colombier respond(r, nil); 2153ff48bf5SDavid du Colombier } 2163ff48bf5SDavid du Colombier 2173ff48bf5SDavid du Colombier void* 218*11e1fb05SDavid du Colombier allocblk(vlong addr) 2193ff48bf5SDavid du Colombier { 2203ff48bf5SDavid du Colombier uchar *op; 2213ff48bf5SDavid du Colombier static uchar *p; 2223ff48bf5SDavid du Colombier static ulong n; 2233ff48bf5SDavid du Colombier 2243ff48bf5SDavid du Colombier if(n == 0){ 2253ff48bf5SDavid du Colombier p = malloc(4*1024*1024); 2263ff48bf5SDavid du Colombier if(p == 0) 2273ff48bf5SDavid du Colombier sysfatal("out of memory"); 2283ff48bf5SDavid du Colombier n = 4*1024*1024; 2293ff48bf5SDavid du Colombier } 2303ff48bf5SDavid du Colombier op = p; 2313ff48bf5SDavid du Colombier p += BLKSZ; 2323ff48bf5SDavid du Colombier n -= BLKSZ; 2333ff48bf5SDavid du Colombier memset(op, 0, BLKSZ); 234*11e1fb05SDavid du Colombier if(fd != -1 && addr != -1) 235*11e1fb05SDavid du Colombier pread(fd, op, BLKSZ, addr); 2363ff48bf5SDavid du Colombier return op; 2373ff48bf5SDavid du Colombier } 2383ff48bf5SDavid du Colombier 2393ff48bf5SDavid du Colombier uchar* 2403ff48bf5SDavid du Colombier getblock(vlong addr, int alloc) 2413ff48bf5SDavid du Colombier { 2423ff48bf5SDavid du Colombier static uchar zero[BLKSZ]; 2433ff48bf5SDavid du Colombier Dbl *p2; 2443ff48bf5SDavid du Colombier Ind *p1; 2453ff48bf5SDavid du Colombier uchar *p0; 2463ff48bf5SDavid du Colombier uint i0, i1, i2; 247*11e1fb05SDavid du Colombier vlong oaddr; 248*11e1fb05SDavid du Colombier 249*11e1fb05SDavid du Colombier if(fd) 250*11e1fb05SDavid du Colombier alloc = 1; 2513ff48bf5SDavid du Colombier 2523ff48bf5SDavid du Colombier addr >>= LOGBLKSZ; 253*11e1fb05SDavid du Colombier oaddr = addr<<LOGBLKSZ; 2543ff48bf5SDavid du Colombier i0 = addr & (NPTR-1); 2553ff48bf5SDavid du Colombier addr >>= LOGNPTR; 2563ff48bf5SDavid du Colombier i1 = addr & (NPTR-1); 2573ff48bf5SDavid du Colombier addr >>= LOGNPTR; 2583ff48bf5SDavid du Colombier i2 = addr & (NPTR-1); 2593ff48bf5SDavid du Colombier addr >>= LOGNPTR; 2603ff48bf5SDavid du Colombier assert(addr == 0); 2613ff48bf5SDavid du Colombier 2623ff48bf5SDavid du Colombier if((p2 = trip.dbl[i2]) == 0){ 2633ff48bf5SDavid du Colombier if(!alloc) 2643ff48bf5SDavid du Colombier return zero; 265*11e1fb05SDavid du Colombier trip.dbl[i2] = p2 = allocblk(-1); 2663ff48bf5SDavid du Colombier } 2673ff48bf5SDavid du Colombier 2683ff48bf5SDavid du Colombier if((p1 = p2->ind[i1]) == 0){ 2693ff48bf5SDavid du Colombier if(!alloc) 2703ff48bf5SDavid du Colombier return zero; 271*11e1fb05SDavid du Colombier p2->ind[i1] = p1 = allocblk(-1); 2723ff48bf5SDavid du Colombier } 2733ff48bf5SDavid du Colombier 2743ff48bf5SDavid du Colombier if((p0 = p1->blk[i0]) == 0){ 2753ff48bf5SDavid du Colombier if(!alloc) 2763ff48bf5SDavid du Colombier return zero; 277*11e1fb05SDavid du Colombier p1->blk[i0] = p0 = allocblk(oaddr); 2783ff48bf5SDavid du Colombier } 2793ff48bf5SDavid du Colombier return p0; 2803ff48bf5SDavid du Colombier } 2813ff48bf5SDavid du Colombier 282*11e1fb05SDavid du Colombier void 283*11e1fb05SDavid du Colombier dirty(vlong addr, uchar *buf) 284*11e1fb05SDavid du Colombier { 285*11e1fb05SDavid du Colombier vlong oaddr; 286*11e1fb05SDavid du Colombier 287*11e1fb05SDavid du Colombier if(fd == -1 || rdonly) 288*11e1fb05SDavid du Colombier return; 289*11e1fb05SDavid du Colombier oaddr = addr&~((vlong)BLKSZ-1); 290*11e1fb05SDavid du Colombier if(pwrite(fd, buf, BLKSZ, oaddr) != BLKSZ) 291*11e1fb05SDavid du Colombier sysfatal("write: %r"); 292*11e1fb05SDavid du Colombier } 293*11e1fb05SDavid du Colombier 2943ff48bf5SDavid du Colombier int 2953ff48bf5SDavid du Colombier rootgen(int off, Dir *d, void*) 2963ff48bf5SDavid du Colombier { 2973ff48bf5SDavid du Colombier memset(d, 0, sizeof *d); 2983ff48bf5SDavid du Colombier d->atime = time0; 2993ff48bf5SDavid du Colombier d->mtime = time0; 3003ff48bf5SDavid du Colombier if(off == 0){ 3013ff48bf5SDavid du Colombier d->name = estrdup9p(sdname); 3023ff48bf5SDavid du Colombier d->mode = DMDIR|0777; 3033ff48bf5SDavid du Colombier d->qid.path = Qdir; 3043ff48bf5SDavid du Colombier d->qid.type = QTDIR; 3053ff48bf5SDavid du Colombier d->uid = estrdup9p("disksim"); 3063ff48bf5SDavid du Colombier d->gid = estrdup9p("disksim"); 3073ff48bf5SDavid du Colombier d->muid = estrdup9p(""); 3083ff48bf5SDavid du Colombier return 0; 3093ff48bf5SDavid du Colombier } 3103ff48bf5SDavid du Colombier return -1; 3113ff48bf5SDavid du Colombier } 3123ff48bf5SDavid du Colombier 3133ff48bf5SDavid du Colombier int 3143ff48bf5SDavid du Colombier dirgen(int off, Dir *d, void*) 3153ff48bf5SDavid du Colombier { 3163ff48bf5SDavid du Colombier int n, j; 3173ff48bf5SDavid du Colombier 3183ff48bf5SDavid du Colombier memset(d, 0, sizeof *d); 3193ff48bf5SDavid du Colombier d->atime = time0; 3203ff48bf5SDavid du Colombier d->mtime = time0; 3213ff48bf5SDavid du Colombier if(off == 0){ 3223ff48bf5SDavid du Colombier d->name = estrdup9p("ctl"); 3233ff48bf5SDavid du Colombier d->mode = ctlmode; 3243ff48bf5SDavid du Colombier d->qid.path = Qctl; 3253ff48bf5SDavid du Colombier goto Have; 3263ff48bf5SDavid du Colombier } 3273ff48bf5SDavid du Colombier 3283ff48bf5SDavid du Colombier off--; 3293ff48bf5SDavid du Colombier n = 0; 3303ff48bf5SDavid du Colombier for(j=0; j<nelem(tab); j++){ 3313ff48bf5SDavid du Colombier if(tab[j].inuse==0) 3323ff48bf5SDavid du Colombier continue; 3333ff48bf5SDavid du Colombier if(n == off){ 3343ff48bf5SDavid du Colombier d->name = estrdup9p(tab[j].name); 33581cf8742SDavid du Colombier d->length = tab[j].length*sectsize; 3363ff48bf5SDavid du Colombier d->mode = tab[j].mode; 3373ff48bf5SDavid du Colombier d->qid.path = Qpart+j; 3383ff48bf5SDavid du Colombier d->qid.vers = tab[j].vers; 3393ff48bf5SDavid du Colombier goto Have; 3403ff48bf5SDavid du Colombier } 3413ff48bf5SDavid du Colombier n++; 3423ff48bf5SDavid du Colombier } 3433ff48bf5SDavid du Colombier return -1; 3443ff48bf5SDavid du Colombier 3453ff48bf5SDavid du Colombier Have: 3463ff48bf5SDavid du Colombier d->uid = estrdup9p("disksim"); 3473ff48bf5SDavid du Colombier d->gid = estrdup9p("disksim"); 3483ff48bf5SDavid du Colombier d->muid = estrdup9p(""); 3493ff48bf5SDavid du Colombier return 0; 3503ff48bf5SDavid du Colombier } 3513ff48bf5SDavid du Colombier 3523ff48bf5SDavid du Colombier void* 3533ff48bf5SDavid du Colombier evommem(void *a, void *b, ulong n) 3543ff48bf5SDavid du Colombier { 3553ff48bf5SDavid du Colombier return memmove(b, a, n); 3563ff48bf5SDavid du Colombier } 3573ff48bf5SDavid du Colombier 3583ff48bf5SDavid du Colombier int 3593ff48bf5SDavid du Colombier rdwrpart(Req *r) 3603ff48bf5SDavid du Colombier { 3613ff48bf5SDavid du Colombier int q; 3623ff48bf5SDavid du Colombier Part *p; 3633ff48bf5SDavid du Colombier vlong offset; 3643ff48bf5SDavid du Colombier long count, tot, n, o; 3653ff48bf5SDavid du Colombier uchar *blk, *dat; 3663ff48bf5SDavid du Colombier void *(*move)(void*, void*, ulong); 3673ff48bf5SDavid du Colombier 3683ff48bf5SDavid du Colombier q = r->fid->qid.path-Qpart; 3693ff48bf5SDavid du Colombier if(q < 0 || q > nelem(tab) || !tab[q].inuse || tab[q].vers != r->fid->qid.vers){ 3703ff48bf5SDavid du Colombier respond(r, "unknown partition"); 3713ff48bf5SDavid du Colombier return -1; 3723ff48bf5SDavid du Colombier } 3733ff48bf5SDavid du Colombier 3743ff48bf5SDavid du Colombier p = &tab[q]; 3753ff48bf5SDavid du Colombier offset = r->ifcall.offset; 3763ff48bf5SDavid du Colombier count = r->ifcall.count; 3773ff48bf5SDavid du Colombier if(offset < 0){ 3783ff48bf5SDavid du Colombier respond(r, "negative offset"); 3793ff48bf5SDavid du Colombier return -1; 3803ff48bf5SDavid du Colombier } 3813ff48bf5SDavid du Colombier if(count < 0){ 3823ff48bf5SDavid du Colombier respond(r, "negative count"); 3833ff48bf5SDavid du Colombier return -1; 3843ff48bf5SDavid du Colombier } 3853ff48bf5SDavid du Colombier if(offset > p->length*sectsize){ 3863ff48bf5SDavid du Colombier respond(r, "offset past end of partition"); 3873ff48bf5SDavid du Colombier return -1; 3883ff48bf5SDavid du Colombier } 3893ff48bf5SDavid du Colombier if(offset+count > p->length*sectsize) 3903ff48bf5SDavid du Colombier count = p->length*sectsize - offset; 3913ff48bf5SDavid du Colombier offset += p->offset*sectsize; 3923ff48bf5SDavid du Colombier 3933ff48bf5SDavid du Colombier if(r->ifcall.type == Tread) 3943ff48bf5SDavid du Colombier move = memmove; 3953ff48bf5SDavid du Colombier else 3963ff48bf5SDavid du Colombier move = evommem; 3973ff48bf5SDavid du Colombier 3983ff48bf5SDavid du Colombier tot = 0; 3993ff48bf5SDavid du Colombier if(r->ifcall.type == Tread) 4003ff48bf5SDavid du Colombier dat = (uchar*)r->ofcall.data; 4013ff48bf5SDavid du Colombier else 4023ff48bf5SDavid du Colombier dat = (uchar*)r->ifcall.data; 4033ff48bf5SDavid du Colombier o = offset & (BLKSZ-1); 4043ff48bf5SDavid du Colombier 4053ff48bf5SDavid du Colombier /* left fringe block */ 4063ff48bf5SDavid du Colombier if(o && count){ 4073ff48bf5SDavid du Colombier blk = getblock(offset, r->ifcall.type==Twrite); 4083ff48bf5SDavid du Colombier if(blk == nil) 4093ff48bf5SDavid du Colombier abort(); 4103ff48bf5SDavid du Colombier n = BLKSZ - o; 4113ff48bf5SDavid du Colombier if(n > count) 4123ff48bf5SDavid du Colombier n = count; 4133ff48bf5SDavid du Colombier (*move)(dat, blk+o, n); 414*11e1fb05SDavid du Colombier if(r->ifcall.type == Twrite) 415*11e1fb05SDavid du Colombier dirty(offset, blk); 4163ff48bf5SDavid du Colombier tot += n; 4173ff48bf5SDavid du Colombier } 4183ff48bf5SDavid du Colombier /* full and right fringe blocks */ 4193ff48bf5SDavid du Colombier while(tot < count){ 4203ff48bf5SDavid du Colombier blk = getblock(offset+tot, r->ifcall.type==Twrite); 4213ff48bf5SDavid du Colombier if(blk == nil) 4223ff48bf5SDavid du Colombier abort(); 4233ff48bf5SDavid du Colombier n = BLKSZ; 424*11e1fb05SDavid du Colombier if(n > count-tot) 425*11e1fb05SDavid du Colombier n = count-tot; 4263ff48bf5SDavid du Colombier (*move)(dat+tot, blk, n); 427*11e1fb05SDavid du Colombier if(r->ifcall.type == Twrite) 428*11e1fb05SDavid du Colombier dirty(offset+tot, blk); 4293ff48bf5SDavid du Colombier tot += n; 4303ff48bf5SDavid du Colombier } 4313ff48bf5SDavid du Colombier r->ofcall.count = tot; 4323ff48bf5SDavid du Colombier respond(r, nil); 4333ff48bf5SDavid du Colombier return 0; 4343ff48bf5SDavid du Colombier } 4353ff48bf5SDavid du Colombier 4363ff48bf5SDavid du Colombier void 4373ff48bf5SDavid du Colombier fsread(Req *r) 4383ff48bf5SDavid du Colombier { 4393ff48bf5SDavid du Colombier char *s; 4403ff48bf5SDavid du Colombier 4413ff48bf5SDavid du Colombier switch((int)r->fid->qid.path){ 4423ff48bf5SDavid du Colombier case Qroot: 4433ff48bf5SDavid du Colombier dirread9p(r, rootgen, nil); 4443ff48bf5SDavid du Colombier respond(r, nil); 4453ff48bf5SDavid du Colombier break; 4463ff48bf5SDavid du Colombier 4473ff48bf5SDavid du Colombier case Qdir: 4483ff48bf5SDavid du Colombier dirread9p(r, dirgen, nil); 4493ff48bf5SDavid du Colombier respond(r, nil); 4503ff48bf5SDavid du Colombier break; 4513ff48bf5SDavid du Colombier 4523ff48bf5SDavid du Colombier case Qctl: 4533ff48bf5SDavid du Colombier s = ctlstring(); 4543ff48bf5SDavid du Colombier readstr(r, s); 4553ff48bf5SDavid du Colombier free(s); 4563ff48bf5SDavid du Colombier respond(r, nil); 4573ff48bf5SDavid du Colombier break; 4583ff48bf5SDavid du Colombier 4593ff48bf5SDavid du Colombier default: 4603ff48bf5SDavid du Colombier rdwrpart(r); 4613ff48bf5SDavid du Colombier break; 4623ff48bf5SDavid du Colombier } 4633ff48bf5SDavid du Colombier } 4643ff48bf5SDavid du Colombier 4653ff48bf5SDavid du Colombier void 4663ff48bf5SDavid du Colombier fswrite(Req *r) 4673ff48bf5SDavid du Colombier { 4683ff48bf5SDavid du Colombier switch((int)r->fid->qid.path){ 4693ff48bf5SDavid du Colombier case Qroot: 4703ff48bf5SDavid du Colombier case Qdir: 4713ff48bf5SDavid du Colombier respond(r, "write to a directory?"); 4723ff48bf5SDavid du Colombier break; 4733ff48bf5SDavid du Colombier 4743ff48bf5SDavid du Colombier case Qctl: 4753ff48bf5SDavid du Colombier ctlwrite(r); 4763ff48bf5SDavid du Colombier break; 4773ff48bf5SDavid du Colombier 4783ff48bf5SDavid du Colombier default: 4793ff48bf5SDavid du Colombier rdwrpart(r); 4803ff48bf5SDavid du Colombier break; 4813ff48bf5SDavid du Colombier } 4823ff48bf5SDavid du Colombier } 4833ff48bf5SDavid du Colombier 4843ff48bf5SDavid du Colombier void 4853ff48bf5SDavid du Colombier fsopen(Req *r) 4863ff48bf5SDavid du Colombier { 4873ff48bf5SDavid du Colombier if(r->ifcall.mode&ORCLOSE) 4883ff48bf5SDavid du Colombier respond(r, "cannot open ORCLOSE"); 4893ff48bf5SDavid du Colombier 4903ff48bf5SDavid du Colombier switch((int)r->fid->qid.path){ 4913ff48bf5SDavid du Colombier case Qroot: 4923ff48bf5SDavid du Colombier case Qdir: 4933ff48bf5SDavid du Colombier if(r->ifcall.mode != OREAD){ 4943ff48bf5SDavid du Colombier respond(r, "bad mode for directory open"); 4953ff48bf5SDavid du Colombier return; 4963ff48bf5SDavid du Colombier } 4973ff48bf5SDavid du Colombier } 4983ff48bf5SDavid du Colombier 4993ff48bf5SDavid du Colombier respond(r, nil); 5003ff48bf5SDavid du Colombier } 5013ff48bf5SDavid du Colombier 5023ff48bf5SDavid du Colombier void 5033ff48bf5SDavid du Colombier fsstat(Req *r) 5043ff48bf5SDavid du Colombier { 5053ff48bf5SDavid du Colombier int q; 5063ff48bf5SDavid du Colombier Dir *d; 5073ff48bf5SDavid du Colombier Part *p; 5083ff48bf5SDavid du Colombier 5093ff48bf5SDavid du Colombier d = &r->d; 5103ff48bf5SDavid du Colombier memset(d, 0, sizeof *d); 5113ff48bf5SDavid du Colombier d->qid = r->fid->qid; 5123ff48bf5SDavid du Colombier d->atime = d->mtime = time0; 5133ff48bf5SDavid du Colombier q = r->fid->qid.path; 5143ff48bf5SDavid du Colombier switch(q){ 5153ff48bf5SDavid du Colombier case Qroot: 5163ff48bf5SDavid du Colombier d->name = estrdup9p("/"); 5173ff48bf5SDavid du Colombier d->mode = DMDIR|0777; 5183ff48bf5SDavid du Colombier break; 5193ff48bf5SDavid du Colombier 5203ff48bf5SDavid du Colombier case Qdir: 5213ff48bf5SDavid du Colombier d->name = estrdup9p(sdname); 5223ff48bf5SDavid du Colombier d->mode = DMDIR|0777; 5233ff48bf5SDavid du Colombier break; 5243ff48bf5SDavid du Colombier 5253ff48bf5SDavid du Colombier default: 5263ff48bf5SDavid du Colombier q -= Qpart; 5273ff48bf5SDavid du Colombier if(q < 0 || q > nelem(tab) || tab[q].inuse==0 || r->fid->qid.vers != tab[q].vers){ 5283ff48bf5SDavid du Colombier respond(r, "partition no longer exists"); 5293ff48bf5SDavid du Colombier return; 5303ff48bf5SDavid du Colombier } 5313ff48bf5SDavid du Colombier p = &tab[q]; 5323ff48bf5SDavid du Colombier d->name = estrdup9p(p->name); 5333ff48bf5SDavid du Colombier d->length = p->length * sectsize; 5343ff48bf5SDavid du Colombier d->mode = p->mode; 5353ff48bf5SDavid du Colombier break; 5363ff48bf5SDavid du Colombier } 5373ff48bf5SDavid du Colombier 5383ff48bf5SDavid du Colombier d->uid = estrdup9p("disksim"); 5393ff48bf5SDavid du Colombier d->gid = estrdup9p("disksim"); 5403ff48bf5SDavid du Colombier d->muid = estrdup9p(""); 5413ff48bf5SDavid du Colombier respond(r, nil); 5423ff48bf5SDavid du Colombier } 5433ff48bf5SDavid du Colombier 5443ff48bf5SDavid du Colombier void 5453ff48bf5SDavid du Colombier fsattach(Req *r) 5463ff48bf5SDavid du Colombier { 5473ff48bf5SDavid du Colombier char *spec; 5483ff48bf5SDavid du Colombier 5493ff48bf5SDavid du Colombier spec = r->ifcall.aname; 5503ff48bf5SDavid du Colombier if(spec && spec[0]){ 5513ff48bf5SDavid du Colombier respond(r, "invalid attach specifier"); 5523ff48bf5SDavid du Colombier return; 5533ff48bf5SDavid du Colombier } 5543ff48bf5SDavid du Colombier r->ofcall.qid = (Qid){Qroot, 0, QTDIR}; 5553ff48bf5SDavid du Colombier r->fid->qid = r->ofcall.qid; 5563ff48bf5SDavid du Colombier respond(r, nil); 5573ff48bf5SDavid du Colombier } 5583ff48bf5SDavid du Colombier 5593ff48bf5SDavid du Colombier char* 5603ff48bf5SDavid du Colombier fswalk1(Fid *fid, char *name, Qid *qid) 5613ff48bf5SDavid du Colombier { 5623ff48bf5SDavid du Colombier int i; 5633ff48bf5SDavid du Colombier switch((int)fid->qid.path){ 5643ff48bf5SDavid du Colombier case Qroot: 5653ff48bf5SDavid du Colombier if(strcmp(name, sdname) == 0){ 5663ff48bf5SDavid du Colombier fid->qid.path = Qdir; 5673ff48bf5SDavid du Colombier fid->qid.type = QTDIR; 5683ff48bf5SDavid du Colombier *qid = fid->qid; 5693ff48bf5SDavid du Colombier return nil; 5703ff48bf5SDavid du Colombier } 5713ff48bf5SDavid du Colombier break; 5723ff48bf5SDavid du Colombier case Qdir: 5733ff48bf5SDavid du Colombier if(strcmp(name, "ctl") == 0){ 5743ff48bf5SDavid du Colombier fid->qid.path = Qctl; 5753ff48bf5SDavid du Colombier fid->qid.vers = 0; 5763ff48bf5SDavid du Colombier fid->qid.type = 0; 5773ff48bf5SDavid du Colombier *qid = fid->qid; 5783ff48bf5SDavid du Colombier return nil; 5793ff48bf5SDavid du Colombier } 5803ff48bf5SDavid du Colombier for(i=0; i<nelem(tab); i++){ 5813ff48bf5SDavid du Colombier if(tab[i].inuse && strcmp(tab[i].name, name) == 0){ 5823ff48bf5SDavid du Colombier fid->qid.path = i+Qpart; 5833ff48bf5SDavid du Colombier fid->qid.vers = tab[i].vers; 5843ff48bf5SDavid du Colombier fid->qid.type = 0; 5853ff48bf5SDavid du Colombier *qid = fid->qid; 5863ff48bf5SDavid du Colombier return nil; 5873ff48bf5SDavid du Colombier } 5883ff48bf5SDavid du Colombier } 5893ff48bf5SDavid du Colombier break; 5903ff48bf5SDavid du Colombier } 5913ff48bf5SDavid du Colombier return "file not found"; 5923ff48bf5SDavid du Colombier } 5933ff48bf5SDavid du Colombier 5943ff48bf5SDavid du Colombier Srv fs = { 5953ff48bf5SDavid du Colombier .attach= fsattach, 5963ff48bf5SDavid du Colombier .open= fsopen, 5973ff48bf5SDavid du Colombier .read= fsread, 5983ff48bf5SDavid du Colombier .write= fswrite, 5993ff48bf5SDavid du Colombier .stat= fsstat, 6003ff48bf5SDavid du Colombier .walk1= fswalk1, 6013ff48bf5SDavid du Colombier }; 6023ff48bf5SDavid du Colombier 6033ff48bf5SDavid du Colombier char *mtpt = "/dev"; 6043ff48bf5SDavid du Colombier char *srvname; 6053ff48bf5SDavid du Colombier 6063ff48bf5SDavid du Colombier void 6073ff48bf5SDavid du Colombier usage(void) 6083ff48bf5SDavid du Colombier { 609*11e1fb05SDavid du Colombier fprint(2, "usage: aux/disksim [-D] [-f file] [-s srvname] [-m mtpt] [sdXX]\n"); 6103ff48bf5SDavid du Colombier fprint(2, "\tdefault mtpt is /dev\n"); 6113ff48bf5SDavid du Colombier exits("usage"); 6123ff48bf5SDavid du Colombier } 6133ff48bf5SDavid du Colombier 6143ff48bf5SDavid du Colombier void 6153ff48bf5SDavid du Colombier main(int argc, char **argv) 6163ff48bf5SDavid du Colombier { 617*11e1fb05SDavid du Colombier char *file; 618*11e1fb05SDavid du Colombier 619*11e1fb05SDavid du Colombier file = nil; 6203ff48bf5SDavid du Colombier quotefmtinstall(); 6213ff48bf5SDavid du Colombier time0 = time(0); 6223ff48bf5SDavid du Colombier if(NPTR != BLKSZ/sizeof(void*)) 6233ff48bf5SDavid du Colombier sysfatal("unexpected pointer size"); 6243ff48bf5SDavid du Colombier 6253ff48bf5SDavid du Colombier ARGBEGIN{ 6263ff48bf5SDavid du Colombier case 'D': 6273ff48bf5SDavid du Colombier chatty9p++; 6283ff48bf5SDavid du Colombier break; 629*11e1fb05SDavid du Colombier case 'f': 630*11e1fb05SDavid du Colombier file = EARGF(usage()); 631*11e1fb05SDavid du Colombier break; 632*11e1fb05SDavid du Colombier case 'r': 633*11e1fb05SDavid du Colombier rdonly = 1; 634*11e1fb05SDavid du Colombier break; 6353ff48bf5SDavid du Colombier case 's': 6363ff48bf5SDavid du Colombier srvname = EARGF(usage()); 6373ff48bf5SDavid du Colombier break; 6383ff48bf5SDavid du Colombier case 'm': 6393ff48bf5SDavid du Colombier mtpt = EARGF(usage()); 6403ff48bf5SDavid du Colombier break; 6413ff48bf5SDavid du Colombier default: 6423ff48bf5SDavid du Colombier usage(); 6433ff48bf5SDavid du Colombier }ARGEND 6443ff48bf5SDavid du Colombier 6453ff48bf5SDavid du Colombier if(argc > 1) 6463ff48bf5SDavid du Colombier usage(); 6473ff48bf5SDavid du Colombier if(argc == 1) 6483ff48bf5SDavid du Colombier sdname = argv[0]; 6493ff48bf5SDavid du Colombier 650*11e1fb05SDavid du Colombier if(file){ 651*11e1fb05SDavid du Colombier if((fd = open(file, rdonly ? OREAD : ORDWR)) < 0) 652*11e1fb05SDavid du Colombier sysfatal("open %s: %r", file); 653*11e1fb05SDavid du Colombier } 654*11e1fb05SDavid du Colombier 6553ff48bf5SDavid du Colombier inquiry = estrdup9p(inquiry); 6563ff48bf5SDavid du Colombier tab[0].name = estrdup9p("data"); 6573ff48bf5SDavid du Colombier tab[0].inuse = 1; 6583ff48bf5SDavid du Colombier tab[0].mode = 0666; 6593ff48bf5SDavid du Colombier 6603ff48bf5SDavid du Colombier postmountsrv(&fs, srvname, mtpt, MBEFORE); 6613ff48bf5SDavid du Colombier exits(nil); 6623ff48bf5SDavid du Colombier } 663