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*
ctlstring(void)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
addpart(char * name,vlong start,vlong end)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
delpart(char * s)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
ctlwrite(Req * r)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*
allocblk(vlong addr)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*
getblock(vlong addr,int alloc)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
dirty(vlong addr,uchar * buf)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
rootgen(int off,Dir * d,void *)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
dirgen(int off,Dir * d,void *)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*
evommem(void * a,void * b,ulong n)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
isnonzero(void * v,ulong n)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
rdwrpart(Req * r)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 }
4333ff48bf5SDavid du Colombier /* full and right fringe blocks */
4343ff48bf5SDavid du Colombier while(tot < count){
435*bbd061d4SDavid du Colombier blk = getblock(offset+tot, r->ifcall.type==Twrite && nonzero);
4363ff48bf5SDavid du Colombier n = BLKSZ;
43711e1fb05SDavid du Colombier if(n > count-tot)
43811e1fb05SDavid du Colombier n = count-tot;
439*bbd061d4SDavid du Colombier if(r->ifcall.type != Twrite || blk != zero)
4403ff48bf5SDavid du Colombier (*move)(dat+tot, blk, n);
44111e1fb05SDavid du Colombier if(r->ifcall.type == Twrite)
44211e1fb05SDavid du Colombier dirty(offset+tot, blk);
4433ff48bf5SDavid du Colombier tot += n;
4443ff48bf5SDavid du Colombier }
4453ff48bf5SDavid du Colombier r->ofcall.count = tot;
4463ff48bf5SDavid du Colombier respond(r, nil);
4473ff48bf5SDavid du Colombier return 0;
4483ff48bf5SDavid du Colombier }
4493ff48bf5SDavid du Colombier
4503ff48bf5SDavid du Colombier void
fsread(Req * r)4513ff48bf5SDavid du Colombier fsread(Req *r)
4523ff48bf5SDavid du Colombier {
4533ff48bf5SDavid du Colombier char *s;
4543ff48bf5SDavid du Colombier
4553ff48bf5SDavid du Colombier switch((int)r->fid->qid.path){
4563ff48bf5SDavid du Colombier case Qroot:
4573ff48bf5SDavid du Colombier dirread9p(r, rootgen, nil);
4583ff48bf5SDavid du Colombier respond(r, nil);
4593ff48bf5SDavid du Colombier break;
4603ff48bf5SDavid du Colombier
4613ff48bf5SDavid du Colombier case Qdir:
4623ff48bf5SDavid du Colombier dirread9p(r, dirgen, nil);
4633ff48bf5SDavid du Colombier respond(r, nil);
4643ff48bf5SDavid du Colombier break;
4653ff48bf5SDavid du Colombier
4663ff48bf5SDavid du Colombier case Qctl:
4673ff48bf5SDavid du Colombier s = ctlstring();
4683ff48bf5SDavid du Colombier readstr(r, s);
4693ff48bf5SDavid du Colombier free(s);
4703ff48bf5SDavid du Colombier respond(r, nil);
4713ff48bf5SDavid du Colombier break;
4723ff48bf5SDavid du Colombier
4733ff48bf5SDavid du Colombier default:
4743ff48bf5SDavid du Colombier rdwrpart(r);
4753ff48bf5SDavid du Colombier break;
4763ff48bf5SDavid du Colombier }
4773ff48bf5SDavid du Colombier }
4783ff48bf5SDavid du Colombier
4793ff48bf5SDavid du Colombier void
fswrite(Req * r)4803ff48bf5SDavid du Colombier fswrite(Req *r)
4813ff48bf5SDavid du Colombier {
4823ff48bf5SDavid du Colombier switch((int)r->fid->qid.path){
4833ff48bf5SDavid du Colombier case Qroot:
4843ff48bf5SDavid du Colombier case Qdir:
4853ff48bf5SDavid du Colombier respond(r, "write to a directory?");
4863ff48bf5SDavid du Colombier break;
4873ff48bf5SDavid du Colombier
4883ff48bf5SDavid du Colombier case Qctl:
4893ff48bf5SDavid du Colombier ctlwrite(r);
4903ff48bf5SDavid du Colombier break;
4913ff48bf5SDavid du Colombier
4923ff48bf5SDavid du Colombier default:
4933ff48bf5SDavid du Colombier rdwrpart(r);
4943ff48bf5SDavid du Colombier break;
4953ff48bf5SDavid du Colombier }
4963ff48bf5SDavid du Colombier }
4973ff48bf5SDavid du Colombier
4983ff48bf5SDavid du Colombier void
fsopen(Req * r)4993ff48bf5SDavid du Colombier fsopen(Req *r)
5003ff48bf5SDavid du Colombier {
5013ff48bf5SDavid du Colombier if(r->ifcall.mode&ORCLOSE)
5023ff48bf5SDavid du Colombier respond(r, "cannot open ORCLOSE");
5033ff48bf5SDavid du Colombier
5043ff48bf5SDavid du Colombier switch((int)r->fid->qid.path){
5053ff48bf5SDavid du Colombier case Qroot:
5063ff48bf5SDavid du Colombier case Qdir:
5073ff48bf5SDavid du Colombier if(r->ifcall.mode != OREAD){
5083ff48bf5SDavid du Colombier respond(r, "bad mode for directory open");
5093ff48bf5SDavid du Colombier return;
5103ff48bf5SDavid du Colombier }
5113ff48bf5SDavid du Colombier }
5123ff48bf5SDavid du Colombier
5133ff48bf5SDavid du Colombier respond(r, nil);
5143ff48bf5SDavid du Colombier }
5153ff48bf5SDavid du Colombier
5163ff48bf5SDavid du Colombier void
fsstat(Req * r)5173ff48bf5SDavid du Colombier fsstat(Req *r)
5183ff48bf5SDavid du Colombier {
5193ff48bf5SDavid du Colombier int q;
5203ff48bf5SDavid du Colombier Dir *d;
5213ff48bf5SDavid du Colombier Part *p;
5223ff48bf5SDavid du Colombier
5233ff48bf5SDavid du Colombier d = &r->d;
5243ff48bf5SDavid du Colombier memset(d, 0, sizeof *d);
5253ff48bf5SDavid du Colombier d->qid = r->fid->qid;
5263ff48bf5SDavid du Colombier d->atime = d->mtime = time0;
5273ff48bf5SDavid du Colombier q = r->fid->qid.path;
5283ff48bf5SDavid du Colombier switch(q){
5293ff48bf5SDavid du Colombier case Qroot:
5303ff48bf5SDavid du Colombier d->name = estrdup9p("/");
5313ff48bf5SDavid du Colombier d->mode = DMDIR|0777;
5323ff48bf5SDavid du Colombier break;
5333ff48bf5SDavid du Colombier
5343ff48bf5SDavid du Colombier case Qdir:
5353ff48bf5SDavid du Colombier d->name = estrdup9p(sdname);
5363ff48bf5SDavid du Colombier d->mode = DMDIR|0777;
5373ff48bf5SDavid du Colombier break;
5383ff48bf5SDavid du Colombier
5393ff48bf5SDavid du Colombier default:
5403ff48bf5SDavid du Colombier q -= Qpart;
5413ff48bf5SDavid du Colombier if(q < 0 || q > nelem(tab) || tab[q].inuse==0 || r->fid->qid.vers != tab[q].vers){
5423ff48bf5SDavid du Colombier respond(r, "partition no longer exists");
5433ff48bf5SDavid du Colombier return;
5443ff48bf5SDavid du Colombier }
5453ff48bf5SDavid du Colombier p = &tab[q];
5463ff48bf5SDavid du Colombier d->name = estrdup9p(p->name);
5473ff48bf5SDavid du Colombier d->length = p->length * sectsize;
5483ff48bf5SDavid du Colombier d->mode = p->mode;
5493ff48bf5SDavid du Colombier break;
5503ff48bf5SDavid du Colombier }
5513ff48bf5SDavid du Colombier
5523ff48bf5SDavid du Colombier d->uid = estrdup9p("disksim");
5533ff48bf5SDavid du Colombier d->gid = estrdup9p("disksim");
5543ff48bf5SDavid du Colombier d->muid = estrdup9p("");
5553ff48bf5SDavid du Colombier respond(r, nil);
5563ff48bf5SDavid du Colombier }
5573ff48bf5SDavid du Colombier
5583ff48bf5SDavid du Colombier void
fsattach(Req * r)5593ff48bf5SDavid du Colombier fsattach(Req *r)
5603ff48bf5SDavid du Colombier {
5613ff48bf5SDavid du Colombier char *spec;
5623ff48bf5SDavid du Colombier
5633ff48bf5SDavid du Colombier spec = r->ifcall.aname;
5643ff48bf5SDavid du Colombier if(spec && spec[0]){
5653ff48bf5SDavid du Colombier respond(r, "invalid attach specifier");
5663ff48bf5SDavid du Colombier return;
5673ff48bf5SDavid du Colombier }
5683ff48bf5SDavid du Colombier r->ofcall.qid = (Qid){Qroot, 0, QTDIR};
5693ff48bf5SDavid du Colombier r->fid->qid = r->ofcall.qid;
5703ff48bf5SDavid du Colombier respond(r, nil);
5713ff48bf5SDavid du Colombier }
5723ff48bf5SDavid du Colombier
5733ff48bf5SDavid du Colombier char*
fswalk1(Fid * fid,char * name,Qid * qid)5743ff48bf5SDavid du Colombier fswalk1(Fid *fid, char *name, Qid *qid)
5753ff48bf5SDavid du Colombier {
5763ff48bf5SDavid du Colombier int i;
5773ff48bf5SDavid du Colombier switch((int)fid->qid.path){
5783ff48bf5SDavid du Colombier case Qroot:
5793ff48bf5SDavid du Colombier if(strcmp(name, sdname) == 0){
5803ff48bf5SDavid du Colombier fid->qid.path = Qdir;
5813ff48bf5SDavid du Colombier fid->qid.type = QTDIR;
5823ff48bf5SDavid du Colombier *qid = fid->qid;
5833ff48bf5SDavid du Colombier return nil;
5843ff48bf5SDavid du Colombier }
5853ff48bf5SDavid du Colombier break;
5863ff48bf5SDavid du Colombier case Qdir:
5873ff48bf5SDavid du Colombier if(strcmp(name, "ctl") == 0){
5883ff48bf5SDavid du Colombier fid->qid.path = Qctl;
5893ff48bf5SDavid du Colombier fid->qid.vers = 0;
5903ff48bf5SDavid du Colombier fid->qid.type = 0;
5913ff48bf5SDavid du Colombier *qid = fid->qid;
5923ff48bf5SDavid du Colombier return nil;
5933ff48bf5SDavid du Colombier }
5943ff48bf5SDavid du Colombier for(i=0; i<nelem(tab); i++){
5953ff48bf5SDavid du Colombier if(tab[i].inuse && strcmp(tab[i].name, name) == 0){
5963ff48bf5SDavid du Colombier fid->qid.path = i+Qpart;
5973ff48bf5SDavid du Colombier fid->qid.vers = tab[i].vers;
5983ff48bf5SDavid du Colombier fid->qid.type = 0;
5993ff48bf5SDavid du Colombier *qid = fid->qid;
6003ff48bf5SDavid du Colombier return nil;
6013ff48bf5SDavid du Colombier }
6023ff48bf5SDavid du Colombier }
6033ff48bf5SDavid du Colombier break;
6043ff48bf5SDavid du Colombier }
6053ff48bf5SDavid du Colombier return "file not found";
6063ff48bf5SDavid du Colombier }
6073ff48bf5SDavid du Colombier
6083ff48bf5SDavid du Colombier Srv fs = {
6093ff48bf5SDavid du Colombier .attach= fsattach,
6103ff48bf5SDavid du Colombier .open= fsopen,
6113ff48bf5SDavid du Colombier .read= fsread,
6123ff48bf5SDavid du Colombier .write= fswrite,
6133ff48bf5SDavid du Colombier .stat= fsstat,
6143ff48bf5SDavid du Colombier .walk1= fswalk1,
6153ff48bf5SDavid du Colombier };
6163ff48bf5SDavid du Colombier
6173ff48bf5SDavid du Colombier char *mtpt = "/dev";
6183ff48bf5SDavid du Colombier char *srvname;
6193ff48bf5SDavid du Colombier
6203ff48bf5SDavid du Colombier void
usage(void)6213ff48bf5SDavid du Colombier usage(void)
6223ff48bf5SDavid du Colombier {
62311e1fb05SDavid du Colombier fprint(2, "usage: aux/disksim [-D] [-f file] [-s srvname] [-m mtpt] [sdXX]\n");
6243ff48bf5SDavid du Colombier fprint(2, "\tdefault mtpt is /dev\n");
6253ff48bf5SDavid du Colombier exits("usage");
6263ff48bf5SDavid du Colombier }
6273ff48bf5SDavid du Colombier
6283ff48bf5SDavid du Colombier void
main(int argc,char ** argv)6293ff48bf5SDavid du Colombier main(int argc, char **argv)
6303ff48bf5SDavid du Colombier {
63111e1fb05SDavid du Colombier char *file;
63211e1fb05SDavid du Colombier
63311e1fb05SDavid du Colombier file = nil;
6343ff48bf5SDavid du Colombier quotefmtinstall();
6353ff48bf5SDavid du Colombier time0 = time(0);
6363ff48bf5SDavid du Colombier if(NPTR != BLKSZ/sizeof(void*))
6373ff48bf5SDavid du Colombier sysfatal("unexpected pointer size");
6383ff48bf5SDavid du Colombier
6393ff48bf5SDavid du Colombier ARGBEGIN{
6403ff48bf5SDavid du Colombier case 'D':
6413ff48bf5SDavid du Colombier chatty9p++;
6423ff48bf5SDavid du Colombier break;
64311e1fb05SDavid du Colombier case 'f':
64411e1fb05SDavid du Colombier file = EARGF(usage());
64511e1fb05SDavid du Colombier break;
64611e1fb05SDavid du Colombier case 'r':
64711e1fb05SDavid du Colombier rdonly = 1;
64811e1fb05SDavid du Colombier break;
6493ff48bf5SDavid du Colombier case 's':
6503ff48bf5SDavid du Colombier srvname = EARGF(usage());
6513ff48bf5SDavid du Colombier break;
6523ff48bf5SDavid du Colombier case 'm':
6533ff48bf5SDavid du Colombier mtpt = EARGF(usage());
6543ff48bf5SDavid du Colombier break;
6553ff48bf5SDavid du Colombier default:
6563ff48bf5SDavid du Colombier usage();
6573ff48bf5SDavid du Colombier }ARGEND
6583ff48bf5SDavid du Colombier
6593ff48bf5SDavid du Colombier if(argc > 1)
6603ff48bf5SDavid du Colombier usage();
6613ff48bf5SDavid du Colombier if(argc == 1)
6623ff48bf5SDavid du Colombier sdname = argv[0];
6633ff48bf5SDavid du Colombier
66411e1fb05SDavid du Colombier if(file){
66511e1fb05SDavid du Colombier if((fd = open(file, rdonly ? OREAD : ORDWR)) < 0)
66611e1fb05SDavid du Colombier sysfatal("open %s: %r", file);
66711e1fb05SDavid du Colombier }
66811e1fb05SDavid du Colombier
6693ff48bf5SDavid du Colombier inquiry = estrdup9p(inquiry);
6703ff48bf5SDavid du Colombier tab[0].name = estrdup9p("data");
6713ff48bf5SDavid du Colombier tab[0].inuse = 1;
6723ff48bf5SDavid du Colombier tab[0].mode = 0666;
6733ff48bf5SDavid du Colombier
6743ff48bf5SDavid du Colombier postmountsrv(&fs, srvname, mtpt, MBEFORE);
6753ff48bf5SDavid du Colombier exits(nil);
6763ff48bf5SDavid du Colombier }
677