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 }; 26*bbd061d4SDavid du Colombier static uchar zero[BLKSZ]; 273ff48bf5SDavid du Colombier 283ff48bf5SDavid du Colombier struct Trip 293ff48bf5SDavid du Colombier { 303ff48bf5SDavid du Colombier Dbl *dbl[NPTR]; 313ff48bf5SDavid du Colombier }; 323ff48bf5SDavid du Colombier 333ff48bf5SDavid du Colombier struct Dbl 343ff48bf5SDavid du Colombier { 353ff48bf5SDavid du Colombier Ind *ind[NPTR]; 363ff48bf5SDavid du Colombier }; 373ff48bf5SDavid du Colombier 383ff48bf5SDavid du Colombier struct Ind 393ff48bf5SDavid du Colombier { 403ff48bf5SDavid du Colombier uchar *blk[NPTR]; 413ff48bf5SDavid du Colombier }; 423ff48bf5SDavid du Colombier 433ff48bf5SDavid du Colombier Trip trip; 443ff48bf5SDavid du Colombier 453ff48bf5SDavid du Colombier struct Part 463ff48bf5SDavid du Colombier { 473ff48bf5SDavid du Colombier int inuse; 483ff48bf5SDavid du Colombier int vers; 493ff48bf5SDavid du Colombier ulong mode; 503ff48bf5SDavid du Colombier char *name; 513ff48bf5SDavid du Colombier vlong offset; /* in sectors */ 523ff48bf5SDavid du Colombier vlong length; /* in sectors */ 533ff48bf5SDavid du Colombier }; 543ff48bf5SDavid du Colombier 553ff48bf5SDavid du Colombier enum 563ff48bf5SDavid du Colombier { 573ff48bf5SDavid du Colombier Qroot = 0, 583ff48bf5SDavid du Colombier Qdir, 593ff48bf5SDavid du Colombier Qctl, 603ff48bf5SDavid du Colombier Qpart, 613ff48bf5SDavid du Colombier }; 623ff48bf5SDavid du Colombier 633ff48bf5SDavid du Colombier Part tab[64]; 6411e1fb05SDavid du Colombier int fd = -1; 653ff48bf5SDavid du Colombier char *sdname = "sdXX"; 663ff48bf5SDavid du Colombier ulong ctlmode = 0666; 673ff48bf5SDavid du Colombier char *inquiry = "aux/disksim hard drive"; 683ff48bf5SDavid du Colombier vlong nsect, sectsize, c, h, s; 693ff48bf5SDavid du Colombier ulong time0; 7011e1fb05SDavid du Colombier int rdonly; 713ff48bf5SDavid du Colombier 723ff48bf5SDavid du Colombier char* 733ff48bf5SDavid du Colombier ctlstring(void) 743ff48bf5SDavid du Colombier { 753ff48bf5SDavid du Colombier int i; 763ff48bf5SDavid du Colombier Fmt fmt; 773ff48bf5SDavid du Colombier 783ff48bf5SDavid du Colombier fmtstrinit(&fmt); 793ff48bf5SDavid du Colombier fmtprint(&fmt, "inquiry %s\n", inquiry); 803ff48bf5SDavid du Colombier fmtprint(&fmt, "geometry %lld %lld %lld %lld %lld\n", nsect, sectsize, c, h, s); 813ff48bf5SDavid du Colombier for(i=0; i<nelem(tab); i++) 823ff48bf5SDavid du Colombier if(tab[i].inuse) 833ff48bf5SDavid du Colombier fmtprint(&fmt, "part %s %lld %lld\n", tab[i].name, tab[i].offset, tab[i].length); 843ff48bf5SDavid du Colombier return fmtstrflush(&fmt); 853ff48bf5SDavid du Colombier } 863ff48bf5SDavid du Colombier 873ff48bf5SDavid du Colombier int 883ff48bf5SDavid du Colombier addpart(char *name, vlong start, vlong end) 893ff48bf5SDavid du Colombier { 903ff48bf5SDavid du Colombier int i; 913ff48bf5SDavid du Colombier 923ff48bf5SDavid du Colombier if(start < 0 || start > end || end > nsect){ 933ff48bf5SDavid du Colombier werrstr("bad partition boundaries"); 943ff48bf5SDavid du Colombier return -1; 953ff48bf5SDavid du Colombier } 963ff48bf5SDavid du Colombier 973ff48bf5SDavid du Colombier for(i=0; i<nelem(tab); i++) 983ff48bf5SDavid du Colombier if(tab[i].inuse == 0) 993ff48bf5SDavid du Colombier break; 1003ff48bf5SDavid du Colombier if(i == nelem(tab)){ 1013ff48bf5SDavid du Colombier werrstr("no free partition slots"); 1023ff48bf5SDavid du Colombier return -1; 1033ff48bf5SDavid du Colombier } 1043ff48bf5SDavid du Colombier 1053ff48bf5SDavid du Colombier free(tab[i].name); 1063ff48bf5SDavid du Colombier tab[i].inuse = 1; 1073ff48bf5SDavid du Colombier tab[i].name = estrdup9p(name); 1083ff48bf5SDavid du Colombier tab[i].offset = start; 1093ff48bf5SDavid du Colombier tab[i].length = end - start; 1103ff48bf5SDavid du Colombier tab[i].mode = ctlmode; 1113ff48bf5SDavid du Colombier tab[i].vers++; 1123ff48bf5SDavid du Colombier 1133ff48bf5SDavid du Colombier return 0; 1143ff48bf5SDavid du Colombier } 1153ff48bf5SDavid du Colombier 1163ff48bf5SDavid du Colombier int 1173ff48bf5SDavid du Colombier delpart(char *s) 1183ff48bf5SDavid du Colombier { 1193ff48bf5SDavid du Colombier int i; 1203ff48bf5SDavid du Colombier 1213ff48bf5SDavid du Colombier for(i=0; i<nelem(tab); i++) 1223ff48bf5SDavid du Colombier if(tab[i].inuse && strcmp(tab[i].name, s) == 0) 1233ff48bf5SDavid du Colombier break; 1243ff48bf5SDavid du Colombier if(i==nelem(tab)){ 1253ff48bf5SDavid du Colombier werrstr("partition not found"); 1263ff48bf5SDavid du Colombier return -1; 1273ff48bf5SDavid du Colombier } 1283ff48bf5SDavid du Colombier 1293ff48bf5SDavid du Colombier tab[i].inuse = 0; 1303ff48bf5SDavid du Colombier free(tab[i].name); 1313ff48bf5SDavid du Colombier tab[i].name = 0; 1323ff48bf5SDavid du Colombier return 0; 1333ff48bf5SDavid du Colombier } 1343ff48bf5SDavid du Colombier 1353ff48bf5SDavid du Colombier void 1363ff48bf5SDavid du Colombier ctlwrite(Req *r) 1373ff48bf5SDavid du Colombier { 1383ff48bf5SDavid du Colombier int i; 1393ff48bf5SDavid du Colombier Cmdbuf *cb; 1403ff48bf5SDavid du Colombier vlong start, end; 1413ff48bf5SDavid du Colombier 1423ff48bf5SDavid du Colombier r->ofcall.count = r->ifcall.count; 1433ff48bf5SDavid du Colombier cb = parsecmd(r->ifcall.data, r->ifcall.count); 1443ff48bf5SDavid du Colombier if(cb->nf < 1){ 1453ff48bf5SDavid du Colombier respond(r, "empty control message"); 1463ff48bf5SDavid du Colombier free(cb); 1473ff48bf5SDavid du Colombier return; 1483ff48bf5SDavid du Colombier } 1493ff48bf5SDavid du Colombier 1503ff48bf5SDavid du Colombier if(strcmp(cb->f[0], "part") == 0){ 1513ff48bf5SDavid du Colombier if(cb->nf != 4){ 1523ff48bf5SDavid du Colombier respondcmderror(r, cb, "part takes 3 args"); 1533ff48bf5SDavid du Colombier free(cb); 1543ff48bf5SDavid du Colombier return; 1553ff48bf5SDavid du Colombier } 1563ff48bf5SDavid du Colombier start = strtoll(cb->f[2], 0, 0); 1573ff48bf5SDavid du Colombier end = strtoll(cb->f[3], 0, 0); 1583ff48bf5SDavid du Colombier if(addpart(cb->f[1], start, end) < 0){ 1593ff48bf5SDavid du Colombier respondcmderror(r, cb, "%r"); 1603ff48bf5SDavid du Colombier free(cb); 1613ff48bf5SDavid du Colombier return; 1623ff48bf5SDavid du Colombier } 1633ff48bf5SDavid du Colombier } 1643ff48bf5SDavid du Colombier else if(strcmp(cb->f[0], "delpart") == 0){ 1653ff48bf5SDavid du Colombier if(cb->nf != 2){ 1663ff48bf5SDavid du Colombier respondcmderror(r, cb, "delpart takes 1 arg"); 1673ff48bf5SDavid du Colombier free(cb); 1683ff48bf5SDavid du Colombier return; 1693ff48bf5SDavid du Colombier } 1703ff48bf5SDavid du Colombier if(delpart(cb->f[1]) < 0){ 1713ff48bf5SDavid du Colombier respondcmderror(r, cb, "%r"); 1723ff48bf5SDavid du Colombier free(cb); 1733ff48bf5SDavid du Colombier return; 1743ff48bf5SDavid du Colombier } 1753ff48bf5SDavid du Colombier } 1763ff48bf5SDavid du Colombier else if(strcmp(cb->f[0], "inquiry") == 0){ 1773ff48bf5SDavid du Colombier if(cb->nf != 2){ 1783ff48bf5SDavid du Colombier respondcmderror(r, cb, "inquiry takes 1 arg"); 1793ff48bf5SDavid du Colombier free(cb); 1803ff48bf5SDavid du Colombier return; 1813ff48bf5SDavid du Colombier } 1823ff48bf5SDavid du Colombier free(inquiry); 1833ff48bf5SDavid du Colombier inquiry = estrdup9p(cb->f[1]); 1843ff48bf5SDavid du Colombier } 1853ff48bf5SDavid du Colombier else if(strcmp(cb->f[0], "geometry") == 0){ 1863ff48bf5SDavid du Colombier if(cb->nf != 6){ 1873ff48bf5SDavid du Colombier respondcmderror(r, cb, "geometry takes 5 args"); 1883ff48bf5SDavid du Colombier free(cb); 1893ff48bf5SDavid du Colombier return; 1903ff48bf5SDavid du Colombier } 1913ff48bf5SDavid du Colombier nsect = strtoll(cb->f[1], 0, 0); 1923ff48bf5SDavid du Colombier sectsize = strtoll(cb->f[2], 0, 0); 1933ff48bf5SDavid du Colombier c = strtoll(cb->f[3], 0, 0); 1943ff48bf5SDavid du Colombier h = strtoll(cb->f[4], 0, 0); 1953ff48bf5SDavid du Colombier s = strtoll(cb->f[5], 0, 0); 1963ff48bf5SDavid du Colombier if(tab[0].inuse && strcmp(tab[0].name, "data") == 0 && tab[0].vers == 0){ 1973ff48bf5SDavid du Colombier tab[0].offset = 0; 1983ff48bf5SDavid du Colombier tab[0].length = nsect; 1993ff48bf5SDavid du Colombier } 2003ff48bf5SDavid du Colombier for(i=0; i<nelem(tab); i++){ 2013ff48bf5SDavid du Colombier if(tab[i].inuse && tab[i].offset+tab[i].length > nsect){ 2023ff48bf5SDavid du Colombier tab[i].inuse = 0; 2033ff48bf5SDavid du Colombier free(tab[i].name); 2043ff48bf5SDavid du Colombier tab[i].name = 0; 2053ff48bf5SDavid du Colombier } 2063ff48bf5SDavid du Colombier } 2073ff48bf5SDavid du Colombier } 2083ff48bf5SDavid du Colombier else{ 2093ff48bf5SDavid du Colombier respondcmderror(r, cb, "unknown control message"); 2103ff48bf5SDavid du Colombier free(cb); 2113ff48bf5SDavid du Colombier return; 2123ff48bf5SDavid du Colombier } 2133ff48bf5SDavid du Colombier 2143ff48bf5SDavid du Colombier free(cb); 2153ff48bf5SDavid du Colombier respond(r, nil); 2163ff48bf5SDavid du Colombier } 2173ff48bf5SDavid du Colombier 2183ff48bf5SDavid du Colombier void* 21911e1fb05SDavid du Colombier allocblk(vlong addr) 2203ff48bf5SDavid du Colombier { 2213ff48bf5SDavid du Colombier uchar *op; 2223ff48bf5SDavid du Colombier static uchar *p; 2233ff48bf5SDavid du Colombier static ulong n; 2243ff48bf5SDavid du Colombier 2253ff48bf5SDavid du Colombier if(n == 0){ 2263ff48bf5SDavid du Colombier p = malloc(4*1024*1024); 2273ff48bf5SDavid du Colombier if(p == 0) 2283ff48bf5SDavid du Colombier sysfatal("out of memory"); 2293ff48bf5SDavid du Colombier n = 4*1024*1024; 2303ff48bf5SDavid du Colombier } 2313ff48bf5SDavid du Colombier op = p; 2323ff48bf5SDavid du Colombier p += BLKSZ; 2333ff48bf5SDavid du Colombier n -= BLKSZ; 2343ff48bf5SDavid du Colombier memset(op, 0, BLKSZ); 23511e1fb05SDavid du Colombier if(fd != -1 && addr != -1) 23611e1fb05SDavid du Colombier pread(fd, op, BLKSZ, addr); 2373ff48bf5SDavid du Colombier return op; 2383ff48bf5SDavid du Colombier } 2393ff48bf5SDavid du Colombier 2403ff48bf5SDavid du Colombier uchar* 2413ff48bf5SDavid du Colombier getblock(vlong addr, int alloc) 2423ff48bf5SDavid du Colombier { 2433ff48bf5SDavid du Colombier Dbl *p2; 2443ff48bf5SDavid du Colombier Ind *p1; 2453ff48bf5SDavid du Colombier uchar *p0; 2463ff48bf5SDavid du Colombier uint i0, i1, i2; 24711e1fb05SDavid du Colombier vlong oaddr; 24811e1fb05SDavid du Colombier 2490b9a5132SDavid du Colombier if(fd >= 0) 25011e1fb05SDavid du Colombier alloc = 1; 2513ff48bf5SDavid du Colombier 2523ff48bf5SDavid du Colombier addr >>= LOGBLKSZ; 25311e1fb05SDavid 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; 26511e1fb05SDavid 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; 27111e1fb05SDavid 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; 27711e1fb05SDavid du Colombier p1->blk[i0] = p0 = allocblk(oaddr); 2783ff48bf5SDavid du Colombier } 2793ff48bf5SDavid du Colombier return p0; 2803ff48bf5SDavid du Colombier } 2813ff48bf5SDavid du Colombier 28211e1fb05SDavid du Colombier void 28311e1fb05SDavid du Colombier dirty(vlong addr, uchar *buf) 28411e1fb05SDavid du Colombier { 28511e1fb05SDavid du Colombier vlong oaddr; 28611e1fb05SDavid du Colombier 28711e1fb05SDavid du Colombier if(fd == -1 || rdonly) 28811e1fb05SDavid du Colombier return; 28911e1fb05SDavid du Colombier oaddr = addr&~((vlong)BLKSZ-1); 29011e1fb05SDavid du Colombier if(pwrite(fd, buf, BLKSZ, oaddr) != BLKSZ) 29111e1fb05SDavid du Colombier sysfatal("write: %r"); 29211e1fb05SDavid du Colombier } 29311e1fb05SDavid 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 359*bbd061d4SDavid du Colombier isnonzero(void *v, ulong n) 360*bbd061d4SDavid du Colombier { 361*bbd061d4SDavid du Colombier uchar *a, *ea; 362*bbd061d4SDavid du Colombier 363*bbd061d4SDavid du Colombier a = v; 364*bbd061d4SDavid du Colombier ea = a+n; 365*bbd061d4SDavid du Colombier for(; a<ea; a++) 366*bbd061d4SDavid du Colombier if(*a) 367*bbd061d4SDavid du Colombier return 1; 368*bbd061d4SDavid du Colombier return 0; 369*bbd061d4SDavid du Colombier } 370*bbd061d4SDavid du Colombier 371*bbd061d4SDavid du Colombier int 3723ff48bf5SDavid du Colombier rdwrpart(Req *r) 3733ff48bf5SDavid du Colombier { 374*bbd061d4SDavid du Colombier int q, nonzero; 3753ff48bf5SDavid du Colombier Part *p; 3763ff48bf5SDavid du Colombier vlong offset; 3773ff48bf5SDavid du Colombier long count, tot, n, o; 3783ff48bf5SDavid du Colombier uchar *blk, *dat; 3793ff48bf5SDavid du Colombier void *(*move)(void*, void*, ulong); 3803ff48bf5SDavid du Colombier 3813ff48bf5SDavid du Colombier q = r->fid->qid.path-Qpart; 3823ff48bf5SDavid du Colombier if(q < 0 || q > nelem(tab) || !tab[q].inuse || tab[q].vers != r->fid->qid.vers){ 3833ff48bf5SDavid du Colombier respond(r, "unknown partition"); 3843ff48bf5SDavid du Colombier return -1; 3853ff48bf5SDavid du Colombier } 3863ff48bf5SDavid du Colombier 3873ff48bf5SDavid du Colombier p = &tab[q]; 3883ff48bf5SDavid du Colombier offset = r->ifcall.offset; 3893ff48bf5SDavid du Colombier count = r->ifcall.count; 3903ff48bf5SDavid du Colombier if(offset < 0){ 3913ff48bf5SDavid du Colombier respond(r, "negative offset"); 3923ff48bf5SDavid du Colombier return -1; 3933ff48bf5SDavid du Colombier } 3943ff48bf5SDavid du Colombier if(count < 0){ 3953ff48bf5SDavid du Colombier respond(r, "negative count"); 3963ff48bf5SDavid du Colombier return -1; 3973ff48bf5SDavid du Colombier } 3983ff48bf5SDavid du Colombier if(offset > p->length*sectsize){ 3993ff48bf5SDavid du Colombier respond(r, "offset past end of partition"); 4003ff48bf5SDavid du Colombier return -1; 4013ff48bf5SDavid du Colombier } 4023ff48bf5SDavid du Colombier if(offset+count > p->length*sectsize) 4033ff48bf5SDavid du Colombier count = p->length*sectsize - offset; 4043ff48bf5SDavid du Colombier offset += p->offset*sectsize; 4053ff48bf5SDavid du Colombier 4063ff48bf5SDavid du Colombier if(r->ifcall.type == Tread) 4073ff48bf5SDavid du Colombier move = memmove; 4083ff48bf5SDavid du Colombier else 4093ff48bf5SDavid du Colombier move = evommem; 4103ff48bf5SDavid du Colombier 4113ff48bf5SDavid du Colombier tot = 0; 412*bbd061d4SDavid du Colombier nonzero = 1; 4133ff48bf5SDavid du Colombier if(r->ifcall.type == Tread) 4143ff48bf5SDavid du Colombier dat = (uchar*)r->ofcall.data; 415*bbd061d4SDavid du Colombier else{ 4163ff48bf5SDavid du Colombier dat = (uchar*)r->ifcall.data; 417*bbd061d4SDavid du Colombier nonzero = isnonzero(dat, r->ifcall.count); 418*bbd061d4SDavid du Colombier } 4193ff48bf5SDavid du Colombier o = offset & (BLKSZ-1); 4203ff48bf5SDavid du Colombier 4213ff48bf5SDavid du Colombier /* left fringe block */ 4223ff48bf5SDavid du Colombier if(o && count){ 423*bbd061d4SDavid du Colombier blk = getblock(offset, r->ifcall.type==Twrite && nonzero); 4243ff48bf5SDavid du Colombier n = BLKSZ - o; 4253ff48bf5SDavid du Colombier if(n > count) 4263ff48bf5SDavid du Colombier n = count; 427*bbd061d4SDavid du Colombier if(r->ifcall.type != Twrite || blk != zero) 4283ff48bf5SDavid du Colombier (*move)(dat, blk+o, n); 42911e1fb05SDavid du Colombier if(r->ifcall.type == Twrite) 43011e1fb05SDavid du Colombier dirty(offset, blk); 4313ff48bf5SDavid du Colombier tot += n; 4323ff48bf5SDavid du Colombier } 433*bbd061d4SDavid du Colombier next: 4343ff48bf5SDavid du Colombier /* full and right fringe blocks */ 4353ff48bf5SDavid du Colombier while(tot < count){ 436*bbd061d4SDavid du Colombier blk = getblock(offset+tot, r->ifcall.type==Twrite && nonzero); 4373ff48bf5SDavid du Colombier n = BLKSZ; 43811e1fb05SDavid du Colombier if(n > count-tot) 43911e1fb05SDavid du Colombier n = count-tot; 440*bbd061d4SDavid du Colombier if(r->ifcall.type != Twrite || blk != zero) 4413ff48bf5SDavid du Colombier (*move)(dat+tot, blk, n); 44211e1fb05SDavid du Colombier if(r->ifcall.type == Twrite) 44311e1fb05SDavid du Colombier dirty(offset+tot, blk); 4443ff48bf5SDavid du Colombier tot += n; 4453ff48bf5SDavid du Colombier } 4463ff48bf5SDavid du Colombier r->ofcall.count = tot; 4473ff48bf5SDavid du Colombier respond(r, nil); 4483ff48bf5SDavid du Colombier return 0; 4493ff48bf5SDavid du Colombier } 4503ff48bf5SDavid du Colombier 4513ff48bf5SDavid du Colombier void 4523ff48bf5SDavid du Colombier fsread(Req *r) 4533ff48bf5SDavid du Colombier { 4543ff48bf5SDavid du Colombier char *s; 4553ff48bf5SDavid du Colombier 4563ff48bf5SDavid du Colombier switch((int)r->fid->qid.path){ 4573ff48bf5SDavid du Colombier case Qroot: 4583ff48bf5SDavid du Colombier dirread9p(r, rootgen, nil); 4593ff48bf5SDavid du Colombier respond(r, nil); 4603ff48bf5SDavid du Colombier break; 4613ff48bf5SDavid du Colombier 4623ff48bf5SDavid du Colombier case Qdir: 4633ff48bf5SDavid du Colombier dirread9p(r, dirgen, nil); 4643ff48bf5SDavid du Colombier respond(r, nil); 4653ff48bf5SDavid du Colombier break; 4663ff48bf5SDavid du Colombier 4673ff48bf5SDavid du Colombier case Qctl: 4683ff48bf5SDavid du Colombier s = ctlstring(); 4693ff48bf5SDavid du Colombier readstr(r, s); 4703ff48bf5SDavid du Colombier free(s); 4713ff48bf5SDavid du Colombier respond(r, nil); 4723ff48bf5SDavid du Colombier break; 4733ff48bf5SDavid du Colombier 4743ff48bf5SDavid du Colombier default: 4753ff48bf5SDavid du Colombier rdwrpart(r); 4763ff48bf5SDavid du Colombier break; 4773ff48bf5SDavid du Colombier } 4783ff48bf5SDavid du Colombier } 4793ff48bf5SDavid du Colombier 4803ff48bf5SDavid du Colombier void 4813ff48bf5SDavid du Colombier fswrite(Req *r) 4823ff48bf5SDavid du Colombier { 4833ff48bf5SDavid du Colombier switch((int)r->fid->qid.path){ 4843ff48bf5SDavid du Colombier case Qroot: 4853ff48bf5SDavid du Colombier case Qdir: 4863ff48bf5SDavid du Colombier respond(r, "write to a directory?"); 4873ff48bf5SDavid du Colombier break; 4883ff48bf5SDavid du Colombier 4893ff48bf5SDavid du Colombier case Qctl: 4903ff48bf5SDavid du Colombier ctlwrite(r); 4913ff48bf5SDavid du Colombier break; 4923ff48bf5SDavid du Colombier 4933ff48bf5SDavid du Colombier default: 4943ff48bf5SDavid du Colombier rdwrpart(r); 4953ff48bf5SDavid du Colombier break; 4963ff48bf5SDavid du Colombier } 4973ff48bf5SDavid du Colombier } 4983ff48bf5SDavid du Colombier 4993ff48bf5SDavid du Colombier void 5003ff48bf5SDavid du Colombier fsopen(Req *r) 5013ff48bf5SDavid du Colombier { 5023ff48bf5SDavid du Colombier if(r->ifcall.mode&ORCLOSE) 5033ff48bf5SDavid du Colombier respond(r, "cannot open ORCLOSE"); 5043ff48bf5SDavid du Colombier 5053ff48bf5SDavid du Colombier switch((int)r->fid->qid.path){ 5063ff48bf5SDavid du Colombier case Qroot: 5073ff48bf5SDavid du Colombier case Qdir: 5083ff48bf5SDavid du Colombier if(r->ifcall.mode != OREAD){ 5093ff48bf5SDavid du Colombier respond(r, "bad mode for directory open"); 5103ff48bf5SDavid du Colombier return; 5113ff48bf5SDavid du Colombier } 5123ff48bf5SDavid du Colombier } 5133ff48bf5SDavid du Colombier 5143ff48bf5SDavid du Colombier respond(r, nil); 5153ff48bf5SDavid du Colombier } 5163ff48bf5SDavid du Colombier 5173ff48bf5SDavid du Colombier void 5183ff48bf5SDavid du Colombier fsstat(Req *r) 5193ff48bf5SDavid du Colombier { 5203ff48bf5SDavid du Colombier int q; 5213ff48bf5SDavid du Colombier Dir *d; 5223ff48bf5SDavid du Colombier Part *p; 5233ff48bf5SDavid du Colombier 5243ff48bf5SDavid du Colombier d = &r->d; 5253ff48bf5SDavid du Colombier memset(d, 0, sizeof *d); 5263ff48bf5SDavid du Colombier d->qid = r->fid->qid; 5273ff48bf5SDavid du Colombier d->atime = d->mtime = time0; 5283ff48bf5SDavid du Colombier q = r->fid->qid.path; 5293ff48bf5SDavid du Colombier switch(q){ 5303ff48bf5SDavid du Colombier case Qroot: 5313ff48bf5SDavid du Colombier d->name = estrdup9p("/"); 5323ff48bf5SDavid du Colombier d->mode = DMDIR|0777; 5333ff48bf5SDavid du Colombier break; 5343ff48bf5SDavid du Colombier 5353ff48bf5SDavid du Colombier case Qdir: 5363ff48bf5SDavid du Colombier d->name = estrdup9p(sdname); 5373ff48bf5SDavid du Colombier d->mode = DMDIR|0777; 5383ff48bf5SDavid du Colombier break; 5393ff48bf5SDavid du Colombier 5403ff48bf5SDavid du Colombier default: 5413ff48bf5SDavid du Colombier q -= Qpart; 5423ff48bf5SDavid du Colombier if(q < 0 || q > nelem(tab) || tab[q].inuse==0 || r->fid->qid.vers != tab[q].vers){ 5433ff48bf5SDavid du Colombier respond(r, "partition no longer exists"); 5443ff48bf5SDavid du Colombier return; 5453ff48bf5SDavid du Colombier } 5463ff48bf5SDavid du Colombier p = &tab[q]; 5473ff48bf5SDavid du Colombier d->name = estrdup9p(p->name); 5483ff48bf5SDavid du Colombier d->length = p->length * sectsize; 5493ff48bf5SDavid du Colombier d->mode = p->mode; 5503ff48bf5SDavid du Colombier break; 5513ff48bf5SDavid du Colombier } 5523ff48bf5SDavid du Colombier 5533ff48bf5SDavid du Colombier d->uid = estrdup9p("disksim"); 5543ff48bf5SDavid du Colombier d->gid = estrdup9p("disksim"); 5553ff48bf5SDavid du Colombier d->muid = estrdup9p(""); 5563ff48bf5SDavid du Colombier respond(r, nil); 5573ff48bf5SDavid du Colombier } 5583ff48bf5SDavid du Colombier 5593ff48bf5SDavid du Colombier void 5603ff48bf5SDavid du Colombier fsattach(Req *r) 5613ff48bf5SDavid du Colombier { 5623ff48bf5SDavid du Colombier char *spec; 5633ff48bf5SDavid du Colombier 5643ff48bf5SDavid du Colombier spec = r->ifcall.aname; 5653ff48bf5SDavid du Colombier if(spec && spec[0]){ 5663ff48bf5SDavid du Colombier respond(r, "invalid attach specifier"); 5673ff48bf5SDavid du Colombier return; 5683ff48bf5SDavid du Colombier } 5693ff48bf5SDavid du Colombier r->ofcall.qid = (Qid){Qroot, 0, QTDIR}; 5703ff48bf5SDavid du Colombier r->fid->qid = r->ofcall.qid; 5713ff48bf5SDavid du Colombier respond(r, nil); 5723ff48bf5SDavid du Colombier } 5733ff48bf5SDavid du Colombier 5743ff48bf5SDavid du Colombier char* 5753ff48bf5SDavid du Colombier fswalk1(Fid *fid, char *name, Qid *qid) 5763ff48bf5SDavid du Colombier { 5773ff48bf5SDavid du Colombier int i; 5783ff48bf5SDavid du Colombier switch((int)fid->qid.path){ 5793ff48bf5SDavid du Colombier case Qroot: 5803ff48bf5SDavid du Colombier if(strcmp(name, sdname) == 0){ 5813ff48bf5SDavid du Colombier fid->qid.path = Qdir; 5823ff48bf5SDavid du Colombier fid->qid.type = QTDIR; 5833ff48bf5SDavid du Colombier *qid = fid->qid; 5843ff48bf5SDavid du Colombier return nil; 5853ff48bf5SDavid du Colombier } 5863ff48bf5SDavid du Colombier break; 5873ff48bf5SDavid du Colombier case Qdir: 5883ff48bf5SDavid du Colombier if(strcmp(name, "ctl") == 0){ 5893ff48bf5SDavid du Colombier fid->qid.path = Qctl; 5903ff48bf5SDavid du Colombier fid->qid.vers = 0; 5913ff48bf5SDavid du Colombier fid->qid.type = 0; 5923ff48bf5SDavid du Colombier *qid = fid->qid; 5933ff48bf5SDavid du Colombier return nil; 5943ff48bf5SDavid du Colombier } 5953ff48bf5SDavid du Colombier for(i=0; i<nelem(tab); i++){ 5963ff48bf5SDavid du Colombier if(tab[i].inuse && strcmp(tab[i].name, name) == 0){ 5973ff48bf5SDavid du Colombier fid->qid.path = i+Qpart; 5983ff48bf5SDavid du Colombier fid->qid.vers = tab[i].vers; 5993ff48bf5SDavid du Colombier fid->qid.type = 0; 6003ff48bf5SDavid du Colombier *qid = fid->qid; 6013ff48bf5SDavid du Colombier return nil; 6023ff48bf5SDavid du Colombier } 6033ff48bf5SDavid du Colombier } 6043ff48bf5SDavid du Colombier break; 6053ff48bf5SDavid du Colombier } 6063ff48bf5SDavid du Colombier return "file not found"; 6073ff48bf5SDavid du Colombier } 6083ff48bf5SDavid du Colombier 6093ff48bf5SDavid du Colombier Srv fs = { 6103ff48bf5SDavid du Colombier .attach= fsattach, 6113ff48bf5SDavid du Colombier .open= fsopen, 6123ff48bf5SDavid du Colombier .read= fsread, 6133ff48bf5SDavid du Colombier .write= fswrite, 6143ff48bf5SDavid du Colombier .stat= fsstat, 6153ff48bf5SDavid du Colombier .walk1= fswalk1, 6163ff48bf5SDavid du Colombier }; 6173ff48bf5SDavid du Colombier 6183ff48bf5SDavid du Colombier char *mtpt = "/dev"; 6193ff48bf5SDavid du Colombier char *srvname; 6203ff48bf5SDavid du Colombier 6213ff48bf5SDavid du Colombier void 6223ff48bf5SDavid du Colombier usage(void) 6233ff48bf5SDavid du Colombier { 62411e1fb05SDavid du Colombier fprint(2, "usage: aux/disksim [-D] [-f file] [-s srvname] [-m mtpt] [sdXX]\n"); 6253ff48bf5SDavid du Colombier fprint(2, "\tdefault mtpt is /dev\n"); 6263ff48bf5SDavid du Colombier exits("usage"); 6273ff48bf5SDavid du Colombier } 6283ff48bf5SDavid du Colombier 6293ff48bf5SDavid du Colombier void 6303ff48bf5SDavid du Colombier main(int argc, char **argv) 6313ff48bf5SDavid du Colombier { 63211e1fb05SDavid du Colombier char *file; 63311e1fb05SDavid du Colombier 63411e1fb05SDavid du Colombier file = nil; 6353ff48bf5SDavid du Colombier quotefmtinstall(); 6363ff48bf5SDavid du Colombier time0 = time(0); 6373ff48bf5SDavid du Colombier if(NPTR != BLKSZ/sizeof(void*)) 6383ff48bf5SDavid du Colombier sysfatal("unexpected pointer size"); 6393ff48bf5SDavid du Colombier 6403ff48bf5SDavid du Colombier ARGBEGIN{ 6413ff48bf5SDavid du Colombier case 'D': 6423ff48bf5SDavid du Colombier chatty9p++; 6433ff48bf5SDavid du Colombier break; 64411e1fb05SDavid du Colombier case 'f': 64511e1fb05SDavid du Colombier file = EARGF(usage()); 64611e1fb05SDavid du Colombier break; 64711e1fb05SDavid du Colombier case 'r': 64811e1fb05SDavid du Colombier rdonly = 1; 64911e1fb05SDavid du Colombier break; 6503ff48bf5SDavid du Colombier case 's': 6513ff48bf5SDavid du Colombier srvname = EARGF(usage()); 6523ff48bf5SDavid du Colombier break; 6533ff48bf5SDavid du Colombier case 'm': 6543ff48bf5SDavid du Colombier mtpt = EARGF(usage()); 6553ff48bf5SDavid du Colombier break; 6563ff48bf5SDavid du Colombier default: 6573ff48bf5SDavid du Colombier usage(); 6583ff48bf5SDavid du Colombier }ARGEND 6593ff48bf5SDavid du Colombier 6603ff48bf5SDavid du Colombier if(argc > 1) 6613ff48bf5SDavid du Colombier usage(); 6623ff48bf5SDavid du Colombier if(argc == 1) 6633ff48bf5SDavid du Colombier sdname = argv[0]; 6643ff48bf5SDavid du Colombier 66511e1fb05SDavid du Colombier if(file){ 66611e1fb05SDavid du Colombier if((fd = open(file, rdonly ? OREAD : ORDWR)) < 0) 66711e1fb05SDavid du Colombier sysfatal("open %s: %r", file); 66811e1fb05SDavid du Colombier } 66911e1fb05SDavid du Colombier 6703ff48bf5SDavid du Colombier inquiry = estrdup9p(inquiry); 6713ff48bf5SDavid du Colombier tab[0].name = estrdup9p("data"); 6723ff48bf5SDavid du Colombier tab[0].inuse = 1; 6733ff48bf5SDavid du Colombier tab[0].mode = 0666; 6743ff48bf5SDavid du Colombier 6753ff48bf5SDavid du Colombier postmountsrv(&fs, srvname, mtpt, MBEFORE); 6763ff48bf5SDavid du Colombier exits(nil); 6773ff48bf5SDavid du Colombier } 678