Plan 9 from Bell Labs’s /usr/web/sources/contrib/quanstro/root/sys/src/cmd/aoedbfs/aoedbfs.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#include <u.h>
#include <libc.h>
#include <auth.h>
#include <fcall.h>
#include <thread.h>
#include <9p.h>

Srv fs;

typedef struct{
	int	id;
	int	fd;
}Node;

enum{
	Xctl	= 1,
	Xfpregs,
	Xkregs,
	Xmem,
	Xproc,
	Xregs,
	Xsegment,
	Xtext,
	Xstatus,

};

struct{
	char 	*s;
	ulong	id;
	ulong	mode;
}tab[] = {
	"ctl",		Xctl,		0222,
	"fpregs",	Xfpregs,	0666,
	"kregs",	Xkregs,		0666,
	"mem",		Xmem,		0666,
	"proc",		Xproc,		0444,
	"regs",		Xregs,		0666,
	"text",		Xtext,		0444,
	"segment",	Xsegment,	0444,
	"status",	Xstatus,	0444,
};

#define dprint(...)		if(debug) fprint(2, _VA_ARGS_)

int	textfd = -1;
int	srvfd;
int 	debug = 0;
char*	textfile = 	"/usr/bwc/VS3/vs.nm";
char	srvname[32];
char*	procname = 	"1";
Channel	*rchan;
int	shelf = -1;

void
killall(Srv*)
{
	bind("#p", "/proc", MREPL);
	threadexitsall("done");
}

void
fsopen(Req *r)
{
	char buf[ERRMAX];
	Node *np;

	np = r->fid->file->aux;
	if (np)
	switch(np->id){
	case Xtext:
		close(textfd);
		textfd = open(textfile, OREAD);
		if(textfd < 0) {
			snprint(buf, sizeof buf, "text: %r");
			respond(r, buf);
			return;
		}
		break;
	}		
	respond(r, nil);
}

void
fsread(Req *r)
{
	int i, n;
	char buf[512];
	Node *np;

	np = r->fid->file->aux;
	switch(np->id){
	case Xfpregs:
	case Xproc:
	case Xkregs:
		respond(r, "Egreg");
		break;
	case Xregs:
	case Xmem:
	case Xsegment:
		if(sendp(rchan, r) != 1){
			snprint(buf, sizeof buf, "aoedbfs sendp: %r");
			respond(r, buf);
			return;
		}
		break;
	case Xstatus:
		n = sprint(buf, "%-28s%-28s%-28s", "remote", "system", "New");
		for(i = 0; i < 9; i++)
			n += sprint(buf+n, "%-12d", 0);
		readstr(r, buf);
		respond(r, nil);
		break;
	case Xtext:
		n = pread(textfd, r->ofcall.data, r->ifcall.count, r->ifcall.offset);
		if(n < 0) {
			rerrstr(buf, sizeof buf);
			respond(r, buf);
			break;
		}
		r->ofcall.count = n;
		respond(r, nil);
		break;
	default:
		respond(r, "unknown read");
	}
}

void
fswrite(Req *r)
{
	char buf[ERRMAX];
	Node *np;

	np = r->fid->file->aux;
	switch(np->id){
	case Xctl:
	case Xkregs:
	case Xmem:
	case Xsegment:
		if(sendp(rchan, r) != 1) {
			snprint(buf, sizeof buf, "aoedbfs sendp: %r");
			respond(r, buf);
		}
		break;
	default:
		respond(r, "Egreg");
		break;
	}
}

enum{
	Rbsize	= 8192,
};
uchar	aoebuf[Rbsize];
uvlong	aoeoff = -1;
int	aoelen;
int	aoefd = -1;

int
tailio(long (*io)(int, void*, long, vlong), int fd, void *buf, ulong l, uvlong byte)
{
	int r;
	ulong rem;

	rem = byte&(Rbsize-1);
	if(l+rem > Rbsize)
		l = Rbsize-rem;
	if(aoeoff == byte && aoefd == fd)
		r = aoelen;
	else{
		r = pread(fd, aoebuf, Rbsize, byte-rem);
		if(r < 0){
			aoeoff = -1;
			return -1;
		}
		aoeoff = byte-rem;
		aoelen = r;
		aoefd = fd;
	}
	if(l+rem >= r)
		l = r-rem;
	else if(io == pwrite)
		return -1;

	if(io == pwrite){
		memmove(aoebuf+rem, buf, l);
		r = io(fd, aoebuf, r, byte-rem);
		if(r != aoelen)
			return -1;
	}else
		memmove(buf, aoebuf+rem, l);
	return l;
}

static int
byteio(long (d)(int, void*, long, vlong), int fd, char *buf, ulong l, uvlong byte)
{
	int r;
	ulong l0;

	l0 = l;
loop:
	if(l == 0)
		return l0-l;
	if((r = tailio(d, fd, buf, l, byte)) < 0)
		return -1;
	byte += r;
	buf += r;
	l -= r;
	if(byte%Rbsize)
		return l0-l;

	while(l >= Rbsize){
		if((r = d(fd, buf, Rbsize, byte)) < 0)
			return -1;
		byte += r;
		buf += r;
		l -= r;
		if(r < Rbsize)
			return l0-l;
	}
	goto loop;
}

char*
xctl(Req *r)
{
	char *e;

	e = nil;
	if(strncmp(r->ifcall.data, "kill", 4) == 0
	|| strncmp(r->ifcall.data, "exit", 4) == 0){
		respond(r, nil);
		yield();
		bind("#p", "/proc", MREPL);
		threadexitsall("done");
	}else if(strncmp(r->ifcall.data, "close", 5)
	&& strncmp(r->ifcall.data, "open", 4))
		e = "permission denied";
	return e;
}

void
servaoe(void *)
{
	int n;
	char *e, buf[ERRMAX];
	long (*io)(int, void*, long, vlong);
	Req *r;
	Node *np;

	while(r = recvp(rchan)){
		np = r->fid->file->aux;
		e = nil;
		if(np->id == Xctl){
			e = xctl(r);
			goto rpt;
		}
		if(r->type == Twrite)
			io = pwrite;
		else //(r->type == Tread)
			io = pread;
		n = byteio(io, np->fd, r->ofcall.data, r->ifcall.count, r->ifcall.offset);
		if(n < 0){
			snprint(buf, sizeof buf, "%r");
			e = buf;
		} else if(n == r->ifcall.offset || io == pread)
			r->ofcall.count = n;
	rpt:
		respond(r, e);
	}
	sysfatal("recv: %r");
}

Srv fs = {
	.open=	fsopen,
	.read=	fsread,
	.write=	fswrite,
	.end=	killall,
};

void
setslot(char *path, int slot)
{
	File *f;
	int fd;
	Node *np;
	Dir *d;
	char buf[32], pbuf[32];

	incref(fs.tree->root);
	snprint(pbuf, sizeof pbuf, path, procname);
	f = walkfile(fs.tree->root, pbuf);
	if (f == nil)
		sysfatal("Can't walk %s: %r", pbuf);
	snprint(buf, sizeof buf, "/dev/aoe/%d.%d/data", shelf, slot);
	fd = open(buf, ORDWR);
	if (fd < 0)
		sysfatal("setslot: open: %r");
	if(!(d = dirfstat(fd)))
		sysfatal("dirfstat: %r");
	f->length = d->length;
	free(d);
	np = f->aux;
	np->fd = fd;
	closefile(f);
}

void
usage(void)
{
	fprint(2, "usage: aoedbfs [-d] [-p procnum] [-t textfile] shelf\n");
	exits("usage");
}

void
threadmain(int argc, char **argv)
{
	int i, p[2];
	File *dir;
	Node *np;

	rfork(RFNOTEG);
	ARGBEGIN{
	case 'D':
		chatty9p++;
		break;
	case 'd':
		debug = 1;
		break;
	case 'p':
		procname = EARGF(usage());
		break;
	case 't':
		textfile = EARGF(usage());
		break;
	default:
		usage();
	}ARGEND;

	switch(argc){
	case 1:
		shelf = atoi(*argv);
		break;
	default:
		usage();
	}

	fmtinstall('H', encodefmt);
	quotefmtinstall();
	rchan = chancreate(sizeof(Req*), 10);
	if(pipe(p) < 0)
		sysfatal("pipe: %r");

	fmtinstall('F', fcallfmt);
	srvfd = p[1];
	proccreate(servaoe, nil, 8*8192);

	fs.tree = alloctree("aoedbfs", "aoedbfs", DMDIR|0555, nil);
	dir = createfile(fs.tree->root, procname, "aoedbfs", DMDIR|0555, 0);
	for(i=0; i<nelem(tab); i++) {
		np = malloc(sizeof *np);
		np->id = tab[i].id;
		np->fd = -1;
		closefile(createfile(dir, tab[i].s, "aoedbfs", tab[i].mode, np));
	}
	closefile(dir);
	setslot("%s/regs", 252);
	setslot("%s/mem", 253);
	setslot("%s/segment", 254);
	snprint(srvname, sizeof srvname, "aoedbfs.%d", getpid());
	threadpostmountsrv(&fs, srvname, "/proc", MBEFORE);
	threadexits(0);
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.