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]; 633ff48bf5SDavid du Colombier 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; 693ff48bf5SDavid du Colombier 703ff48bf5SDavid du Colombier char* 713ff48bf5SDavid du Colombier ctlstring(void) 723ff48bf5SDavid du Colombier { 733ff48bf5SDavid du Colombier int i; 743ff48bf5SDavid du Colombier Fmt fmt; 753ff48bf5SDavid du Colombier 763ff48bf5SDavid du Colombier fmtstrinit(&fmt); 773ff48bf5SDavid du Colombier fmtprint(&fmt, "inquiry %s\n", inquiry); 783ff48bf5SDavid du Colombier fmtprint(&fmt, "geometry %lld %lld %lld %lld %lld\n", nsect, sectsize, c, h, s); 793ff48bf5SDavid du Colombier for(i=0; i<nelem(tab); i++) 803ff48bf5SDavid du Colombier if(tab[i].inuse) 813ff48bf5SDavid du Colombier fmtprint(&fmt, "part %s %lld %lld\n", tab[i].name, tab[i].offset, tab[i].length); 823ff48bf5SDavid du Colombier return fmtstrflush(&fmt); 833ff48bf5SDavid du Colombier } 843ff48bf5SDavid du Colombier 853ff48bf5SDavid du Colombier int 863ff48bf5SDavid du Colombier addpart(char *name, vlong start, vlong end) 873ff48bf5SDavid du Colombier { 883ff48bf5SDavid du Colombier int i; 893ff48bf5SDavid du Colombier 903ff48bf5SDavid du Colombier if(start < 0 || start > end || end > nsect){ 913ff48bf5SDavid du Colombier werrstr("bad partition boundaries"); 923ff48bf5SDavid du Colombier return -1; 933ff48bf5SDavid du Colombier } 943ff48bf5SDavid du Colombier 953ff48bf5SDavid du Colombier for(i=0; i<nelem(tab); i++) 963ff48bf5SDavid du Colombier if(tab[i].inuse == 0) 973ff48bf5SDavid du Colombier break; 983ff48bf5SDavid du Colombier if(i == nelem(tab)){ 993ff48bf5SDavid du Colombier werrstr("no free partition slots"); 1003ff48bf5SDavid du Colombier return -1; 1013ff48bf5SDavid du Colombier } 1023ff48bf5SDavid du Colombier 1033ff48bf5SDavid du Colombier free(tab[i].name); 1043ff48bf5SDavid du Colombier tab[i].inuse = 1; 1053ff48bf5SDavid du Colombier tab[i].name = estrdup9p(name); 1063ff48bf5SDavid du Colombier tab[i].offset = start; 1073ff48bf5SDavid du Colombier tab[i].length = end - start; 1083ff48bf5SDavid du Colombier tab[i].mode = ctlmode; 1093ff48bf5SDavid du Colombier tab[i].vers++; 1103ff48bf5SDavid du Colombier 1113ff48bf5SDavid du Colombier return 0; 1123ff48bf5SDavid du Colombier } 1133ff48bf5SDavid du Colombier 1143ff48bf5SDavid du Colombier int 1153ff48bf5SDavid du Colombier delpart(char *s) 1163ff48bf5SDavid du Colombier { 1173ff48bf5SDavid du Colombier int i; 1183ff48bf5SDavid du Colombier 1193ff48bf5SDavid du Colombier for(i=0; i<nelem(tab); i++) 1203ff48bf5SDavid du Colombier if(tab[i].inuse && strcmp(tab[i].name, s) == 0) 1213ff48bf5SDavid du Colombier break; 1223ff48bf5SDavid du Colombier if(i==nelem(tab)){ 1233ff48bf5SDavid du Colombier werrstr("partition not found"); 1243ff48bf5SDavid du Colombier return -1; 1253ff48bf5SDavid du Colombier } 1263ff48bf5SDavid du Colombier 1273ff48bf5SDavid du Colombier tab[i].inuse = 0; 1283ff48bf5SDavid du Colombier free(tab[i].name); 1293ff48bf5SDavid du Colombier tab[i].name = 0; 1303ff48bf5SDavid du Colombier return 0; 1313ff48bf5SDavid du Colombier } 1323ff48bf5SDavid du Colombier 1333ff48bf5SDavid du Colombier void 1343ff48bf5SDavid du Colombier ctlwrite(Req *r) 1353ff48bf5SDavid du Colombier { 1363ff48bf5SDavid du Colombier int i; 1373ff48bf5SDavid du Colombier Cmdbuf *cb; 1383ff48bf5SDavid du Colombier vlong start, end; 1393ff48bf5SDavid du Colombier 1403ff48bf5SDavid du Colombier r->ofcall.count = r->ifcall.count; 1413ff48bf5SDavid du Colombier cb = parsecmd(r->ifcall.data, r->ifcall.count); 1423ff48bf5SDavid du Colombier if(cb->nf < 1){ 1433ff48bf5SDavid du Colombier respond(r, "empty control message"); 1443ff48bf5SDavid du Colombier free(cb); 1453ff48bf5SDavid du Colombier return; 1463ff48bf5SDavid du Colombier } 1473ff48bf5SDavid du Colombier 1483ff48bf5SDavid du Colombier if(strcmp(cb->f[0], "part") == 0){ 1493ff48bf5SDavid du Colombier if(cb->nf != 4){ 1503ff48bf5SDavid du Colombier respondcmderror(r, cb, "part takes 3 args"); 1513ff48bf5SDavid du Colombier free(cb); 1523ff48bf5SDavid du Colombier return; 1533ff48bf5SDavid du Colombier } 1543ff48bf5SDavid du Colombier start = strtoll(cb->f[2], 0, 0); 1553ff48bf5SDavid du Colombier end = strtoll(cb->f[3], 0, 0); 1563ff48bf5SDavid du Colombier if(addpart(cb->f[1], start, end) < 0){ 1573ff48bf5SDavid du Colombier respondcmderror(r, cb, "%r"); 1583ff48bf5SDavid du Colombier free(cb); 1593ff48bf5SDavid du Colombier return; 1603ff48bf5SDavid du Colombier } 1613ff48bf5SDavid du Colombier } 1623ff48bf5SDavid du Colombier else if(strcmp(cb->f[0], "delpart") == 0){ 1633ff48bf5SDavid du Colombier if(cb->nf != 2){ 1643ff48bf5SDavid du Colombier respondcmderror(r, cb, "delpart takes 1 arg"); 1653ff48bf5SDavid du Colombier free(cb); 1663ff48bf5SDavid du Colombier return; 1673ff48bf5SDavid du Colombier } 1683ff48bf5SDavid du Colombier if(delpart(cb->f[1]) < 0){ 1693ff48bf5SDavid du Colombier respondcmderror(r, cb, "%r"); 1703ff48bf5SDavid du Colombier free(cb); 1713ff48bf5SDavid du Colombier return; 1723ff48bf5SDavid du Colombier } 1733ff48bf5SDavid du Colombier } 1743ff48bf5SDavid du Colombier else if(strcmp(cb->f[0], "inquiry") == 0){ 1753ff48bf5SDavid du Colombier if(cb->nf != 2){ 1763ff48bf5SDavid du Colombier respondcmderror(r, cb, "inquiry takes 1 arg"); 1773ff48bf5SDavid du Colombier free(cb); 1783ff48bf5SDavid du Colombier return; 1793ff48bf5SDavid du Colombier } 1803ff48bf5SDavid du Colombier free(inquiry); 1813ff48bf5SDavid du Colombier inquiry = estrdup9p(cb->f[1]); 1823ff48bf5SDavid du Colombier } 1833ff48bf5SDavid du Colombier else if(strcmp(cb->f[0], "geometry") == 0){ 1843ff48bf5SDavid du Colombier if(cb->nf != 6){ 1853ff48bf5SDavid du Colombier respondcmderror(r, cb, "geometry takes 5 args"); 1863ff48bf5SDavid du Colombier free(cb); 1873ff48bf5SDavid du Colombier return; 1883ff48bf5SDavid du Colombier } 1893ff48bf5SDavid du Colombier nsect = strtoll(cb->f[1], 0, 0); 1903ff48bf5SDavid du Colombier sectsize = strtoll(cb->f[2], 0, 0); 1913ff48bf5SDavid du Colombier c = strtoll(cb->f[3], 0, 0); 1923ff48bf5SDavid du Colombier h = strtoll(cb->f[4], 0, 0); 1933ff48bf5SDavid du Colombier s = strtoll(cb->f[5], 0, 0); 1943ff48bf5SDavid du Colombier if(tab[0].inuse && strcmp(tab[0].name, "data") == 0 && tab[0].vers == 0){ 1953ff48bf5SDavid du Colombier tab[0].offset = 0; 1963ff48bf5SDavid du Colombier tab[0].length = nsect; 1973ff48bf5SDavid du Colombier } 1983ff48bf5SDavid du Colombier for(i=0; i<nelem(tab); i++){ 1993ff48bf5SDavid du Colombier if(tab[i].inuse && tab[i].offset+tab[i].length > nsect){ 2003ff48bf5SDavid du Colombier tab[i].inuse = 0; 2013ff48bf5SDavid du Colombier free(tab[i].name); 2023ff48bf5SDavid du Colombier tab[i].name = 0; 2033ff48bf5SDavid du Colombier } 2043ff48bf5SDavid du Colombier } 2053ff48bf5SDavid du Colombier } 2063ff48bf5SDavid du Colombier else{ 2073ff48bf5SDavid du Colombier respondcmderror(r, cb, "unknown control message"); 2083ff48bf5SDavid du Colombier free(cb); 2093ff48bf5SDavid du Colombier return; 2103ff48bf5SDavid du Colombier } 2113ff48bf5SDavid du Colombier 2123ff48bf5SDavid du Colombier free(cb); 2133ff48bf5SDavid du Colombier respond(r, nil); 2143ff48bf5SDavid du Colombier } 2153ff48bf5SDavid du Colombier 2163ff48bf5SDavid du Colombier void* 2173ff48bf5SDavid du Colombier allocblk(void) 2183ff48bf5SDavid du Colombier { 2193ff48bf5SDavid du Colombier uchar *op; 2203ff48bf5SDavid du Colombier static uchar *p; 2213ff48bf5SDavid du Colombier static ulong n; 2223ff48bf5SDavid du Colombier 2233ff48bf5SDavid du Colombier if(n == 0){ 2243ff48bf5SDavid du Colombier p = malloc(4*1024*1024); 2253ff48bf5SDavid du Colombier if(p == 0) 2263ff48bf5SDavid du Colombier sysfatal("out of memory"); 2273ff48bf5SDavid du Colombier n = 4*1024*1024; 2283ff48bf5SDavid du Colombier } 2293ff48bf5SDavid du Colombier op = p; 2303ff48bf5SDavid du Colombier p += BLKSZ; 2313ff48bf5SDavid du Colombier n -= BLKSZ; 2323ff48bf5SDavid du Colombier memset(op, 0, BLKSZ); 2333ff48bf5SDavid du Colombier return op; 2343ff48bf5SDavid du Colombier } 2353ff48bf5SDavid du Colombier 2363ff48bf5SDavid du Colombier uchar* 2373ff48bf5SDavid du Colombier getblock(vlong addr, int alloc) 2383ff48bf5SDavid du Colombier { 2393ff48bf5SDavid du Colombier static uchar zero[BLKSZ]; 2403ff48bf5SDavid du Colombier Dbl *p2; 2413ff48bf5SDavid du Colombier Ind *p1; 2423ff48bf5SDavid du Colombier uchar *p0; 2433ff48bf5SDavid du Colombier uint i0, i1, i2; 2443ff48bf5SDavid du Colombier 2453ff48bf5SDavid du Colombier addr >>= LOGBLKSZ; 2463ff48bf5SDavid du Colombier i0 = addr & (NPTR-1); 2473ff48bf5SDavid du Colombier addr >>= LOGNPTR; 2483ff48bf5SDavid du Colombier i1 = addr & (NPTR-1); 2493ff48bf5SDavid du Colombier addr >>= LOGNPTR; 2503ff48bf5SDavid du Colombier i2 = addr & (NPTR-1); 2513ff48bf5SDavid du Colombier addr >>= LOGNPTR; 2523ff48bf5SDavid du Colombier assert(addr == 0); 2533ff48bf5SDavid du Colombier 2543ff48bf5SDavid du Colombier if((p2 = trip.dbl[i2]) == 0){ 2553ff48bf5SDavid du Colombier if(!alloc) 2563ff48bf5SDavid du Colombier return zero; 2573ff48bf5SDavid du Colombier trip.dbl[i2] = p2 = allocblk(); 2583ff48bf5SDavid du Colombier } 2593ff48bf5SDavid du Colombier 2603ff48bf5SDavid du Colombier if((p1 = p2->ind[i1]) == 0){ 2613ff48bf5SDavid du Colombier if(!alloc) 2623ff48bf5SDavid du Colombier return zero; 2633ff48bf5SDavid du Colombier p2->ind[i1] = p1 = allocblk(); 2643ff48bf5SDavid du Colombier } 2653ff48bf5SDavid du Colombier 2663ff48bf5SDavid du Colombier if((p0 = p1->blk[i0]) == 0){ 2673ff48bf5SDavid du Colombier if(!alloc) 2683ff48bf5SDavid du Colombier return zero; 2693ff48bf5SDavid du Colombier p1->blk[i0] = p0 = allocblk(); 2703ff48bf5SDavid du Colombier } 2713ff48bf5SDavid du Colombier return p0; 2723ff48bf5SDavid du Colombier } 2733ff48bf5SDavid du Colombier 2743ff48bf5SDavid du Colombier int 2753ff48bf5SDavid du Colombier rootgen(int off, Dir *d, void*) 2763ff48bf5SDavid du Colombier { 2773ff48bf5SDavid du Colombier memset(d, 0, sizeof *d); 2783ff48bf5SDavid du Colombier d->atime = time0; 2793ff48bf5SDavid du Colombier d->mtime = time0; 2803ff48bf5SDavid du Colombier if(off == 0){ 2813ff48bf5SDavid du Colombier d->name = estrdup9p(sdname); 2823ff48bf5SDavid du Colombier d->mode = DMDIR|0777; 2833ff48bf5SDavid du Colombier d->qid.path = Qdir; 2843ff48bf5SDavid du Colombier d->qid.type = QTDIR; 2853ff48bf5SDavid du Colombier d->uid = estrdup9p("disksim"); 2863ff48bf5SDavid du Colombier d->gid = estrdup9p("disksim"); 2873ff48bf5SDavid du Colombier d->muid = estrdup9p(""); 2883ff48bf5SDavid du Colombier return 0; 2893ff48bf5SDavid du Colombier } 2903ff48bf5SDavid du Colombier return -1; 2913ff48bf5SDavid du Colombier } 2923ff48bf5SDavid du Colombier 2933ff48bf5SDavid du Colombier int 2943ff48bf5SDavid du Colombier dirgen(int off, Dir *d, void*) 2953ff48bf5SDavid du Colombier { 2963ff48bf5SDavid du Colombier int n, j; 2973ff48bf5SDavid du Colombier 2983ff48bf5SDavid du Colombier memset(d, 0, sizeof *d); 2993ff48bf5SDavid du Colombier d->atime = time0; 3003ff48bf5SDavid du Colombier d->mtime = time0; 3013ff48bf5SDavid du Colombier if(off == 0){ 3023ff48bf5SDavid du Colombier d->name = estrdup9p("ctl"); 3033ff48bf5SDavid du Colombier d->mode = ctlmode; 3043ff48bf5SDavid du Colombier d->qid.path = Qctl; 3053ff48bf5SDavid du Colombier goto Have; 3063ff48bf5SDavid du Colombier } 3073ff48bf5SDavid du Colombier 3083ff48bf5SDavid du Colombier off--; 3093ff48bf5SDavid du Colombier n = 0; 3103ff48bf5SDavid du Colombier for(j=0; j<nelem(tab); j++){ 3113ff48bf5SDavid du Colombier if(tab[j].inuse==0) 3123ff48bf5SDavid du Colombier continue; 3133ff48bf5SDavid du Colombier if(n == off){ 3143ff48bf5SDavid du Colombier d->name = estrdup9p(tab[j].name); 315*81cf8742SDavid du Colombier d->length = tab[j].length*sectsize; 3163ff48bf5SDavid du Colombier d->mode = tab[j].mode; 3173ff48bf5SDavid du Colombier d->qid.path = Qpart+j; 3183ff48bf5SDavid du Colombier d->qid.vers = tab[j].vers; 3193ff48bf5SDavid du Colombier goto Have; 3203ff48bf5SDavid du Colombier } 3213ff48bf5SDavid du Colombier n++; 3223ff48bf5SDavid du Colombier } 3233ff48bf5SDavid du Colombier return -1; 3243ff48bf5SDavid du Colombier 3253ff48bf5SDavid du Colombier Have: 3263ff48bf5SDavid du Colombier d->uid = estrdup9p("disksim"); 3273ff48bf5SDavid du Colombier d->gid = estrdup9p("disksim"); 3283ff48bf5SDavid du Colombier d->muid = estrdup9p(""); 3293ff48bf5SDavid du Colombier return 0; 3303ff48bf5SDavid du Colombier } 3313ff48bf5SDavid du Colombier 3323ff48bf5SDavid du Colombier void* 3333ff48bf5SDavid du Colombier evommem(void *a, void *b, ulong n) 3343ff48bf5SDavid du Colombier { 3353ff48bf5SDavid du Colombier return memmove(b, a, n); 3363ff48bf5SDavid du Colombier } 3373ff48bf5SDavid du Colombier 3383ff48bf5SDavid du Colombier int 3393ff48bf5SDavid du Colombier rdwrpart(Req *r) 3403ff48bf5SDavid du Colombier { 3413ff48bf5SDavid du Colombier int q; 3423ff48bf5SDavid du Colombier Part *p; 3433ff48bf5SDavid du Colombier vlong offset; 3443ff48bf5SDavid du Colombier long count, tot, n, o; 3453ff48bf5SDavid du Colombier uchar *blk, *dat; 3463ff48bf5SDavid du Colombier void *(*move)(void*, void*, ulong); 3473ff48bf5SDavid du Colombier 3483ff48bf5SDavid du Colombier q = r->fid->qid.path-Qpart; 3493ff48bf5SDavid du Colombier if(q < 0 || q > nelem(tab) || !tab[q].inuse || tab[q].vers != r->fid->qid.vers){ 3503ff48bf5SDavid du Colombier respond(r, "unknown partition"); 3513ff48bf5SDavid du Colombier return -1; 3523ff48bf5SDavid du Colombier } 3533ff48bf5SDavid du Colombier 3543ff48bf5SDavid du Colombier p = &tab[q]; 3553ff48bf5SDavid du Colombier offset = r->ifcall.offset; 3563ff48bf5SDavid du Colombier count = r->ifcall.count; 3573ff48bf5SDavid du Colombier if(offset < 0){ 3583ff48bf5SDavid du Colombier respond(r, "negative offset"); 3593ff48bf5SDavid du Colombier return -1; 3603ff48bf5SDavid du Colombier } 3613ff48bf5SDavid du Colombier if(count < 0){ 3623ff48bf5SDavid du Colombier respond(r, "negative count"); 3633ff48bf5SDavid du Colombier return -1; 3643ff48bf5SDavid du Colombier } 3653ff48bf5SDavid du Colombier if(offset > p->length*sectsize){ 3663ff48bf5SDavid du Colombier respond(r, "offset past end of partition"); 3673ff48bf5SDavid du Colombier return -1; 3683ff48bf5SDavid du Colombier } 3693ff48bf5SDavid du Colombier if(offset+count > p->length*sectsize) 3703ff48bf5SDavid du Colombier count = p->length*sectsize - offset; 3713ff48bf5SDavid du Colombier offset += p->offset*sectsize; 3723ff48bf5SDavid du Colombier 3733ff48bf5SDavid du Colombier if(r->ifcall.type == Tread) 3743ff48bf5SDavid du Colombier move = memmove; 3753ff48bf5SDavid du Colombier else 3763ff48bf5SDavid du Colombier move = evommem; 3773ff48bf5SDavid du Colombier 3783ff48bf5SDavid du Colombier tot = 0; 3793ff48bf5SDavid du Colombier if(r->ifcall.type == Tread) 3803ff48bf5SDavid du Colombier dat = (uchar*)r->ofcall.data; 3813ff48bf5SDavid du Colombier else 3823ff48bf5SDavid du Colombier dat = (uchar*)r->ifcall.data; 3833ff48bf5SDavid du Colombier o = offset & (BLKSZ-1); 3843ff48bf5SDavid du Colombier 3853ff48bf5SDavid du Colombier /* left fringe block */ 3863ff48bf5SDavid du Colombier if(o && count){ 3873ff48bf5SDavid du Colombier blk = getblock(offset, r->ifcall.type==Twrite); 3883ff48bf5SDavid du Colombier if(blk == nil) 3893ff48bf5SDavid du Colombier abort(); 3903ff48bf5SDavid du Colombier n = BLKSZ - o; 3913ff48bf5SDavid du Colombier if(n > count) 3923ff48bf5SDavid du Colombier n = count; 3933ff48bf5SDavid du Colombier (*move)(dat, blk+o, n); 3943ff48bf5SDavid du Colombier tot += n; 3953ff48bf5SDavid du Colombier } 3963ff48bf5SDavid du Colombier /* full and right fringe blocks */ 3973ff48bf5SDavid du Colombier while(tot < count){ 3983ff48bf5SDavid du Colombier blk = getblock(offset+tot, r->ifcall.type==Twrite); 3993ff48bf5SDavid du Colombier if(blk == nil) 4003ff48bf5SDavid du Colombier abort(); 4013ff48bf5SDavid du Colombier n = BLKSZ; 4023ff48bf5SDavid du Colombier if(n > count) 4033ff48bf5SDavid du Colombier n = count; 4043ff48bf5SDavid du Colombier (*move)(dat+tot, blk, n); 4053ff48bf5SDavid du Colombier tot += n; 4063ff48bf5SDavid du Colombier } 4073ff48bf5SDavid du Colombier r->ofcall.count = tot; 4083ff48bf5SDavid du Colombier respond(r, nil); 4093ff48bf5SDavid du Colombier return 0; 4103ff48bf5SDavid du Colombier } 4113ff48bf5SDavid du Colombier 4123ff48bf5SDavid du Colombier void 4133ff48bf5SDavid du Colombier fsread(Req *r) 4143ff48bf5SDavid du Colombier { 4153ff48bf5SDavid du Colombier char *s; 4163ff48bf5SDavid du Colombier 4173ff48bf5SDavid du Colombier switch((int)r->fid->qid.path){ 4183ff48bf5SDavid du Colombier case Qroot: 4193ff48bf5SDavid du Colombier dirread9p(r, rootgen, nil); 4203ff48bf5SDavid du Colombier respond(r, nil); 4213ff48bf5SDavid du Colombier break; 4223ff48bf5SDavid du Colombier 4233ff48bf5SDavid du Colombier case Qdir: 4243ff48bf5SDavid du Colombier dirread9p(r, dirgen, nil); 4253ff48bf5SDavid du Colombier respond(r, nil); 4263ff48bf5SDavid du Colombier break; 4273ff48bf5SDavid du Colombier 4283ff48bf5SDavid du Colombier case Qctl: 4293ff48bf5SDavid du Colombier s = ctlstring(); 4303ff48bf5SDavid du Colombier readstr(r, s); 4313ff48bf5SDavid du Colombier free(s); 4323ff48bf5SDavid du Colombier respond(r, nil); 4333ff48bf5SDavid du Colombier break; 4343ff48bf5SDavid du Colombier 4353ff48bf5SDavid du Colombier default: 4363ff48bf5SDavid du Colombier rdwrpart(r); 4373ff48bf5SDavid du Colombier break; 4383ff48bf5SDavid du Colombier } 4393ff48bf5SDavid du Colombier } 4403ff48bf5SDavid du Colombier 4413ff48bf5SDavid du Colombier void 4423ff48bf5SDavid du Colombier fswrite(Req *r) 4433ff48bf5SDavid du Colombier { 4443ff48bf5SDavid du Colombier switch((int)r->fid->qid.path){ 4453ff48bf5SDavid du Colombier case Qroot: 4463ff48bf5SDavid du Colombier case Qdir: 4473ff48bf5SDavid du Colombier respond(r, "write to a directory?"); 4483ff48bf5SDavid du Colombier break; 4493ff48bf5SDavid du Colombier 4503ff48bf5SDavid du Colombier case Qctl: 4513ff48bf5SDavid du Colombier ctlwrite(r); 4523ff48bf5SDavid du Colombier break; 4533ff48bf5SDavid du Colombier 4543ff48bf5SDavid du Colombier default: 4553ff48bf5SDavid du Colombier rdwrpart(r); 4563ff48bf5SDavid du Colombier break; 4573ff48bf5SDavid du Colombier } 4583ff48bf5SDavid du Colombier } 4593ff48bf5SDavid du Colombier 4603ff48bf5SDavid du Colombier void 4613ff48bf5SDavid du Colombier fsopen(Req *r) 4623ff48bf5SDavid du Colombier { 4633ff48bf5SDavid du Colombier if(r->ifcall.mode&ORCLOSE) 4643ff48bf5SDavid du Colombier respond(r, "cannot open ORCLOSE"); 4653ff48bf5SDavid du Colombier 4663ff48bf5SDavid du Colombier switch((int)r->fid->qid.path){ 4673ff48bf5SDavid du Colombier case Qroot: 4683ff48bf5SDavid du Colombier case Qdir: 4693ff48bf5SDavid du Colombier if(r->ifcall.mode != OREAD){ 4703ff48bf5SDavid du Colombier respond(r, "bad mode for directory open"); 4713ff48bf5SDavid du Colombier return; 4723ff48bf5SDavid du Colombier } 4733ff48bf5SDavid du Colombier } 4743ff48bf5SDavid du Colombier 4753ff48bf5SDavid du Colombier respond(r, nil); 4763ff48bf5SDavid du Colombier } 4773ff48bf5SDavid du Colombier 4783ff48bf5SDavid du Colombier void 4793ff48bf5SDavid du Colombier fsstat(Req *r) 4803ff48bf5SDavid du Colombier { 4813ff48bf5SDavid du Colombier int q; 4823ff48bf5SDavid du Colombier Dir *d; 4833ff48bf5SDavid du Colombier Part *p; 4843ff48bf5SDavid du Colombier 4853ff48bf5SDavid du Colombier d = &r->d; 4863ff48bf5SDavid du Colombier memset(d, 0, sizeof *d); 4873ff48bf5SDavid du Colombier d->qid = r->fid->qid; 4883ff48bf5SDavid du Colombier d->atime = d->mtime = time0; 4893ff48bf5SDavid du Colombier q = r->fid->qid.path; 4903ff48bf5SDavid du Colombier switch(q){ 4913ff48bf5SDavid du Colombier case Qroot: 4923ff48bf5SDavid du Colombier d->name = estrdup9p("/"); 4933ff48bf5SDavid du Colombier d->mode = DMDIR|0777; 4943ff48bf5SDavid du Colombier break; 4953ff48bf5SDavid du Colombier 4963ff48bf5SDavid du Colombier case Qdir: 4973ff48bf5SDavid du Colombier d->name = estrdup9p(sdname); 4983ff48bf5SDavid du Colombier d->mode = DMDIR|0777; 4993ff48bf5SDavid du Colombier break; 5003ff48bf5SDavid du Colombier 5013ff48bf5SDavid du Colombier default: 5023ff48bf5SDavid du Colombier q -= Qpart; 5033ff48bf5SDavid du Colombier if(q < 0 || q > nelem(tab) || tab[q].inuse==0 || r->fid->qid.vers != tab[q].vers){ 5043ff48bf5SDavid du Colombier respond(r, "partition no longer exists"); 5053ff48bf5SDavid du Colombier return; 5063ff48bf5SDavid du Colombier } 5073ff48bf5SDavid du Colombier p = &tab[q]; 5083ff48bf5SDavid du Colombier d->name = estrdup9p(p->name); 5093ff48bf5SDavid du Colombier d->length = p->length * sectsize; 5103ff48bf5SDavid du Colombier d->mode = p->mode; 5113ff48bf5SDavid du Colombier break; 5123ff48bf5SDavid du Colombier } 5133ff48bf5SDavid du Colombier 5143ff48bf5SDavid du Colombier d->uid = estrdup9p("disksim"); 5153ff48bf5SDavid du Colombier d->gid = estrdup9p("disksim"); 5163ff48bf5SDavid du Colombier d->muid = estrdup9p(""); 5173ff48bf5SDavid du Colombier respond(r, nil); 5183ff48bf5SDavid du Colombier } 5193ff48bf5SDavid du Colombier 5203ff48bf5SDavid du Colombier void 5213ff48bf5SDavid du Colombier fsattach(Req *r) 5223ff48bf5SDavid du Colombier { 5233ff48bf5SDavid du Colombier char *spec; 5243ff48bf5SDavid du Colombier 5253ff48bf5SDavid du Colombier spec = r->ifcall.aname; 5263ff48bf5SDavid du Colombier if(spec && spec[0]){ 5273ff48bf5SDavid du Colombier respond(r, "invalid attach specifier"); 5283ff48bf5SDavid du Colombier return; 5293ff48bf5SDavid du Colombier } 5303ff48bf5SDavid du Colombier r->ofcall.qid = (Qid){Qroot, 0, QTDIR}; 5313ff48bf5SDavid du Colombier r->fid->qid = r->ofcall.qid; 5323ff48bf5SDavid du Colombier respond(r, nil); 5333ff48bf5SDavid du Colombier } 5343ff48bf5SDavid du Colombier 5353ff48bf5SDavid du Colombier char* 5363ff48bf5SDavid du Colombier fswalk1(Fid *fid, char *name, Qid *qid) 5373ff48bf5SDavid du Colombier { 5383ff48bf5SDavid du Colombier int i; 5393ff48bf5SDavid du Colombier switch((int)fid->qid.path){ 5403ff48bf5SDavid du Colombier case Qroot: 5413ff48bf5SDavid du Colombier if(strcmp(name, sdname) == 0){ 5423ff48bf5SDavid du Colombier fid->qid.path = Qdir; 5433ff48bf5SDavid du Colombier fid->qid.type = QTDIR; 5443ff48bf5SDavid du Colombier *qid = fid->qid; 5453ff48bf5SDavid du Colombier return nil; 5463ff48bf5SDavid du Colombier } 5473ff48bf5SDavid du Colombier break; 5483ff48bf5SDavid du Colombier case Qdir: 5493ff48bf5SDavid du Colombier if(strcmp(name, "ctl") == 0){ 5503ff48bf5SDavid du Colombier fid->qid.path = Qctl; 5513ff48bf5SDavid du Colombier fid->qid.vers = 0; 5523ff48bf5SDavid du Colombier fid->qid.type = 0; 5533ff48bf5SDavid du Colombier *qid = fid->qid; 5543ff48bf5SDavid du Colombier return nil; 5553ff48bf5SDavid du Colombier } 5563ff48bf5SDavid du Colombier for(i=0; i<nelem(tab); i++){ 5573ff48bf5SDavid du Colombier if(tab[i].inuse && strcmp(tab[i].name, name) == 0){ 5583ff48bf5SDavid du Colombier fid->qid.path = i+Qpart; 5593ff48bf5SDavid du Colombier fid->qid.vers = tab[i].vers; 5603ff48bf5SDavid du Colombier fid->qid.type = 0; 5613ff48bf5SDavid du Colombier *qid = fid->qid; 5623ff48bf5SDavid du Colombier return nil; 5633ff48bf5SDavid du Colombier } 5643ff48bf5SDavid du Colombier } 5653ff48bf5SDavid du Colombier break; 5663ff48bf5SDavid du Colombier } 5673ff48bf5SDavid du Colombier return "file not found"; 5683ff48bf5SDavid du Colombier } 5693ff48bf5SDavid du Colombier 5703ff48bf5SDavid du Colombier Srv fs = { 5713ff48bf5SDavid du Colombier .attach= fsattach, 5723ff48bf5SDavid du Colombier .open= fsopen, 5733ff48bf5SDavid du Colombier .read= fsread, 5743ff48bf5SDavid du Colombier .write= fswrite, 5753ff48bf5SDavid du Colombier .stat= fsstat, 5763ff48bf5SDavid du Colombier .walk1= fswalk1, 5773ff48bf5SDavid du Colombier }; 5783ff48bf5SDavid du Colombier 5793ff48bf5SDavid du Colombier char *mtpt = "/dev"; 5803ff48bf5SDavid du Colombier char *srvname; 5813ff48bf5SDavid du Colombier 5823ff48bf5SDavid du Colombier void 5833ff48bf5SDavid du Colombier usage(void) 5843ff48bf5SDavid du Colombier { 5853ff48bf5SDavid du Colombier fprint(2, "usage: aux/disksim [-D] [-s srvname] [-m mtpt] [sdXX]\n"); 5863ff48bf5SDavid du Colombier fprint(2, "\tdefault mtpt is /dev\n"); 5873ff48bf5SDavid du Colombier exits("usage"); 5883ff48bf5SDavid du Colombier } 5893ff48bf5SDavid du Colombier 5903ff48bf5SDavid du Colombier void 5913ff48bf5SDavid du Colombier main(int argc, char **argv) 5923ff48bf5SDavid du Colombier { 5933ff48bf5SDavid du Colombier quotefmtinstall(); 5943ff48bf5SDavid du Colombier time0 = time(0); 5953ff48bf5SDavid du Colombier if(NPTR != BLKSZ/sizeof(void*)) 5963ff48bf5SDavid du Colombier sysfatal("unexpected pointer size"); 5973ff48bf5SDavid du Colombier 5983ff48bf5SDavid du Colombier ARGBEGIN{ 5993ff48bf5SDavid du Colombier case 'D': 6003ff48bf5SDavid du Colombier chatty9p++; 6013ff48bf5SDavid du Colombier break; 6023ff48bf5SDavid du Colombier case 's': 6033ff48bf5SDavid du Colombier srvname = EARGF(usage()); 6043ff48bf5SDavid du Colombier break; 6053ff48bf5SDavid du Colombier case 'm': 6063ff48bf5SDavid du Colombier mtpt = EARGF(usage()); 6073ff48bf5SDavid du Colombier break; 6083ff48bf5SDavid du Colombier default: 6093ff48bf5SDavid du Colombier usage(); 6103ff48bf5SDavid du Colombier }ARGEND 6113ff48bf5SDavid du Colombier 6123ff48bf5SDavid du Colombier if(argc > 1) 6133ff48bf5SDavid du Colombier usage(); 6143ff48bf5SDavid du Colombier if(argc == 1) 6153ff48bf5SDavid du Colombier sdname = argv[0]; 6163ff48bf5SDavid du Colombier 6173ff48bf5SDavid du Colombier inquiry = estrdup9p(inquiry); 6183ff48bf5SDavid du Colombier tab[0].name = estrdup9p("data"); 6193ff48bf5SDavid du Colombier tab[0].inuse = 1; 6203ff48bf5SDavid du Colombier tab[0].mode = 0666; 6213ff48bf5SDavid du Colombier 6223ff48bf5SDavid du Colombier postmountsrv(&fs, srvname, mtpt, MBEFORE); 6233ff48bf5SDavid du Colombier exits(nil); 6243ff48bf5SDavid du Colombier } 625