xref: /plan9/sys/src/cmd/aux/disksim.c (revision 81cf874224a4620dc66ce2d894718f8bb735f81d)
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