~kris/9p

9hist

da82c9cfc4fe4ed2623d3221482d10c86a19673d — David du Colombier 25 years ago 8ce307a
Plan 9 from Bell Labs 2001-06-01
6 files changed, 163 insertions(+), 126 deletions(-)

M bitsy/devsac.c
M bitsy/fns.h
M bitsy/main.c
M port/chan.c
M port/devloopback.c
M port/devmnt.c
M bitsy/devsac.c => bitsy/devsac.c +72 -64
@@ 99,13 99,13 @@ static Sac root;
static Cache cache[CacheSize];
static ulong cacheage;

static void	sacdir(Chan *, SacDir*, char*);
static int	sacdir(Chan *, SacDir*, uchar*, int);
static ulong	getl(void *p);
static Sac	*saccpy(Sac *s);
static Sac *saclookup(Sac *s, char *name);
static int sacdirread(Chan *, char *p, long off, long cnt);
static void loadblock(void *buf, uchar *offset, int blocksize);
static void sacfree(Sac*);
static Sac	*saclookup(Sac *s, char *name);
static int	sacdirread(Chan *, uchar *p, long off, long cnt);
static void	loadblock(void *buf, uchar *offset, int blocksize);
static void	sacfree(Sac*);

static void
pathtoqid(ulong path, Qid *q)


@@ 119,6 119,17 @@ pathtoqid(ulong path, Qid *q)
}

static void
omodetomode(ulong om, ulong *m)
{
	ulong nm;

	nm = om & ~(CHDIR|CHAPPEND|CHEXCL|CHMOUNT);
	if(om & CHDIR)
		nm |= DMDIR;
	*m = nm;
}

static void
sacinit(void)
{
	SacHeader *hdr;


@@ 152,7 163,6 @@ sacattach(char* spec)
{
	Chan *c;
	int dev;
	int opath;

	dev = atoi(spec);
	if(dev != 0)


@@ 163,29 173,19 @@ sacattach(char* spec)
		error("devsac: bad magic");

	c = devattach('C', spec);
	path = getl(root.qid);
	pathtoqid(path, &c->qid;
	pathtoqid(getl(root.qid), &c->qid);
	c->dev = dev;
	c->aux = saccpy(&root);
	return c;
}

static Chan*
sacclone(Chan *c, Chan *nc)
{
	nc = devclone(c, nc);
	nc->aux = saccpy(c->aux);
	return nc;
}

static Walkqid*
sacwalk(Chan *c, Chan *nc, char **name, int nname)
{
	Sac *sac;
	int i, j, alloc;
	int j, alloc;
	Walkqid *wq;
	char *n;
	Dir dir;

	if(nname > 0)
		isdir(c);


@@ 200,26 200,35 @@ sacwalk(Chan *c, Chan *nc, char **name, int nname)
	}
	if(nc == nil){
		nc = devclone(c);
		nc->type = 0;	/* device doesn't know about this channel yet */
		alloc = 1;
	}
	wq->clone = nc;

	for(j=0; j<nname; j++){
		isdir(nc);

		if(name[0]=='.' && name[1]==0)
			return 1;
		n = name[j];
		if(strcmp(n, ".") == 0){
			wq->qid[wq->nqid++] = nc->qid;
			continue;
		}
		sac = nc->aux;
		sac = saclookup(sac, name);
		sac = saclookup(sac, n);
		if(sac == nil) {
			if(j == 0)
				error(Enonexist);
			strncpy(up->error, Enonexist, NAMELEN);
			return 0;
			break;
		}
		nc->aux = sac;
		pathtoqid(getl(sac->qid), &nc->qid);
	}
	return 1;
	poperror();
	if(wq->nqid < nname){
		if(alloc)
			cclose(wq->clone);
		wq->clone = nil;
	}
	return wq;
}

static Chan*


@@ 260,12 269,8 @@ sacread(Chan *c, void *a, long n, vlong voff)

	buf = a;
	cnt = n;
	if(c->qid.path & CHDIR){
		cnt = (cnt/DIRLEN)*DIRLEN;
		if(off%DIRLEN)
			error("i/o error");
		return sacdirread(c, buf, off, cnt);
	}
	if(c->qid.type & QTDIR)
		return sacdirread(c, a, off, cnt);
	sac = c->aux;
	length = getl(sac->length);
	if(off >= length)


@@ 311,11 316,13 @@ sacclose(Chan* c)
	sacfree(sac);
}


static void
sacstat(Chan *c, char *db)
static int
sacstat(Chan *c, uchar *db, int n)
{
	sacdir(c, c->aux, db);
	n = sacdir(c, c->aux, db, n);
	if(n == 0)
		error(Ebadarg);
	return n;
}

static Sac*


@@ 361,24 368,23 @@ sacfree(Sac *s)
	free(s);
}

static void
sacdir(Chan *c, SacDir *s, char *buf)
static int
sacdir(Chan *c, SacDir *s, uchar *db, int n)
{
	Dir dir;

	memmove(dir.name, s->name, NAMELEN);
	dir.qid = (Qid){getl(s->qid), 0};
	dir.mode = getl(s->mode);
	dir.name = s->name;
	dir.uid = s->uid;
	dir.gid = s->gid;
	dir.muid = s->uid;
	pathtoqid(getl(s->qid), &dir.qid);
	omodetomode(getl(s->mode), &dir.mode);
	dir.length = getl(s->length);
	if(dir.mode &CHDIR)
		dir.length *= DIRLEN;
	memmove(dir.uid, s->uid, NAMELEN);
	memmove(dir.gid, s->gid, NAMELEN);
	dir.atime = getl(s->atime);
	dir.mtime = getl(s->mtime);
	dir.type = devtab[c->type]->dc;
	dir.dev = c->dev;
	convD2M(&dir, buf);
	return convD2M(&dir, db, n);
}

static void


@@ 457,41 463,44 @@ sacparent(Sac *s)
	return s;
}

/* n**2 alg to read a directory */
static int
sacdirread(Chan *c, char *p, long off, long cnt)
sacdirread(Chan *c, uchar *p, long off, long cnt)
{
	uchar *blocks;
	SacDir *buf;
	int iblock, per, i, j, n, ndir;
	int per, i, j, n, ndir;
	long sofar;
	Sac *s;

	s = c->aux;
	blocks = data + getl(s->blocks);
	per = blocksize/sizeof(SacDir);
	ndir = getl(s->length);
	off /= DIRLEN;
	cnt /= DIRLEN;
	if(off >= ndir)
		return 0;
	if(cnt > ndir-off)
		cnt = ndir-off;
	iblock = -1;
	buf = malloc(per*sizeof(SacDir));
	for(i=off; i<off+cnt; i++) {
		j = i/per;
		if(j != iblock) {

	buf = malloc(blocksize);
	sofar = 0;
	for(j = 0; j < ndir; j++) {
		i = j%per;
		if(i == 0) {
			n = per;
			if(n > ndir-j*per)
				n = ndir-j*per;
			loadblock(buf, blocks + j*OffsetSize, n*sizeof(SacDir));
			iblock = j;
		}
		j *= per;
		sacdir(c, buf+i-j, p);
		p += DIRLEN;
		n = sacdir(c, buf+i, p, cnt - sofar);
		if(n == 0)
			break;
		if(off > 0)
			off -= n;
		else {
			p += n;
			sofar += n;
		}
	}
	free(buf);
	return cnt*DIRLEN;

	return sofar;
}

static Sac*


@@ 551,7 560,6 @@ Dev sacdevtab = {
	devreset,
	sacinit,
	sacattach,
	sacclone,
	sacwalk,
	sacstat,
	sacopen,

M bitsy/fns.h => bitsy/fns.h +2 -1
@@ 39,6 39,7 @@ ulong	inl(ulong);
void	intrenable(int, int, void (*)(Ureg*, void*), void*, char*);
int	iprint(char*, ...);
void	irpower(int);
#define	kmapinval()
void	lcdpower(int);
void	links(void);
void*	mapmem(ulong, int, int);


@@ 75,7 76,7 @@ void	putpid(ulong);
void	qpanic(char *, ...);
void	rs232power(int);
void	uartspecial(Uart*, int, Queue**, Queue**, int (*)(Queue*, int));
void	sa1100_uartsetup(int);
void	sa1110_uartsetup(int);
void	screeninit(void);
int	screenprint(char*, ...);			/* debugging */
void	serialµcputs(uchar *str, int n);

M bitsy/main.c => bitsy/main.c +1 -1
@@ 35,7 35,7 @@ main(void)
	mmuinit();
	machinit();
	trapinit();
	sa1100_uartsetup(1);
	sa1110_uartsetup(1);
	rs232power(1);
	dmainit();
	screeninit();

M port/chan.c => port/chan.c +58 -20
@@ 6,12 6,12 @@
#include	"../port/error.h"

int chandebug=0;		/* toggled by sysr1 */
QLock chanprint;		/* probably asking for trouble (deadlocks) -rsc */

/* transition BUG */
int client9p = 2;
int kernel9p = 2;


int domount(Chan**, Mhead**);
Ref mheadcounter;



@@ 45,13 45,26 @@ dumpmount(void)		/* DEBUGGING */
				f->from->qid.vers, devtab[f->from->type]->dc,
				f->from->dev);
			for(t = f->mount; t; t = t->next)
				print("\t%p: %s (umh %p)\n", t, t->to->name->s, t->to->umh);
				print("\t%p: %s (umh %p) (path %.8llux dev %C %lud)\n", t, t->to->name->s, t->to->umh, t->to->qid.path, devtab[t->to->type]->dc, t->to->dev);
		}
	}
	poperror();
	runlock(&pg->ns);
}


char*
c2name(Chan *c)		/* DEBUGGING */
{
	if(c == nil)
		return "<nil chan>";
	if(c->name == nil)
		return "<nil name>";
	if(c->name->s == nil)
		return "<nil name.s>";
	return c->name->s;
}

enum
{
	CNAMESLOP	= 20


@@ 225,7 238,6 @@ newchan(void)
		c->link = chanalloc.list;
		chanalloc.list = c;
		unlock(&chanalloc);
if(chandebug) print("newchan %d\n", c->fid);
	}

	/* if you get an error before associating with a dev,


@@ 676,6 688,11 @@ undomount(Chan *c, Cname *name)
	he = &pg->mnthash[MNTHASH];
	for(h = pg->mnthash; h < he; h++) {
		for(f = *h; f; f = f->hash) {
			if(strcmp(f->from->name->s, name->s) != 0)
				continue;
if(chandebug)
print("[%lud]\tundomount found head %s; need chan (path %.8llux dev %C %lud)\n",
	up->pid, name->s, c->qid.path, devtab[c->type]->dc, c->dev);
			for(t = f->mount; t; t = t->next) {
				if(eqchan(c, t->to, 1)) {
					/*


@@ 690,6 707,8 @@ undomount(Chan *c, Cname *name)
					incref(nc);
					cclose(c);
					c = nc;
if(chandebug)
print("[%lud]\tundomount found %s\n", up->pid, c2name(c));
					break;
				}
			}


@@ 722,10 741,12 @@ walk(Chan **cp, char **names, int nnames, int nomount)
	mh = nil;

if(chandebug){
print("walk");
qlock(&chanprint);
print("[%lud] walk %s to ", up->pid, c2name(c));
for(i=0; i<nnames; i++)
	print(" %s", names[i]);
	print("%s%s", i?"/":"", names[i]);
print("\n");
qunlock(&chanprint);
}

	/*


@@ 755,9 776,13 @@ print("\n");
		}

if(chandebug){
print("\ttry chan: qid %.8llux devchar %C dev %lud ->\n", c->qid.path, devtab[c->type]->dc, c->dev);
qlock(&chanprint);
print("[%lud]\twalk from %s (path %.8llux dev %C %lud) to ", 
	up->pid, c2name(c), c->qid.path, devtab[c->type]->dc, c->dev);
for(i=0; i<ntry; i++)
	print(" %s", names[i]);
	print("%s%s", i?"/":"", names[i]);
print("\n");
qunlock(&chanprint);
}
		if(!dotdot && !nomount)
			domount(&c, &mh);


@@ 766,12 791,11 @@ for(i=0; i<ntry; i++)
		dev = c->dev;

		if((wq = devtab[type]->walk(c, nil, names, ntry)) == nil){
if(chandebug) print("walk failed.");
if(chandebug) print("[%lud]\twalk failed.\n", up->pid);
			/* try a union mount, if any */
			if(mh == nil || nomount){
			Giveup:
if(chandebug) print("give up\n");
//delay(2000);
if(chandebug) print("[%lud]\tgive up\n", up->pid);
				cclose(c);
				cnameclose(cname);
				return -1;


@@ 784,7 808,9 @@ if(chandebug) print("give up\n");
			}
			for(f = mh->mount; f; f = f->next)
{
if(chandebug) print("\ttry chan: qid %.8llux devchar %C dev %lud ->\n", c->qid.path, devtab[c->type]->dc, c->dev);
if(chandebug)
 print("[%lud]\twalk from %s (path %.8llux dev %C %lud)\n", 
  up->pid, c2name(c), c->qid.path, devtab[c->type]->dc, c->dev);
				if((wq = devtab[f->to->type]->walk(f->to, nil, names, ntry)) != nil)
					break;
}


@@ 802,34 828,49 @@ if(chandebug) print("\ttry chan: qid %.8llux devchar %C dev %lud ->\n", c->qid.p
		if(dotdot) {
			assert(wq->nqid == 1);
			assert(wq->clone != nil);
if(chandebug) print("undo wq->clone->name %s cname %s...", wq->clone->name->s, cname->s);

			cname = addelem(cname, "..");
if(chandebug)
print("[%lud]\tundo wq->clone %s cname %s\n", up->pid, c2name(wq->clone), cname?cname->s:"<nil name>");
			nc = undomount(wq->clone, cname);
if(chandebug) print("undidmount nc %s...", nc->name->s);
if(chandebug)
print("[%lud]\tundo returned %s\n", up->pid, c2name(nc));
			n = 1;
		} else {
			nc = nil;
if(chandebug) print("find.");
			if(!nomount)
				for(i=0; i<wq->nqid && i<nnames-1; i++)
					if(findmount(&nc, &nmh, type, dev, wq->qid[i]))
						break;
			if(nc == nil){	/* no mount points along path */
if(chandebug)
print("[%lud]\tno mount points along path\n", up->pid);
				if(wq->clone == nil){
					cclose(c);
					cnameclose(cname);
					free(wq);
if(chandebug) print("fail\n");
					return -1;
				}
				n = wq->nqid;
				nc = wq->clone;
			}else{		/* stopped early, at a mount point */
if(chandebug){int j;
qlock(&chanprint);
print("[%lud]\tfound mount point: ", up->pid);
for(j=0; j<=i; j++)
	print("%s%s", j?"/":"", names[j]);
print(" becomes ");
print("%s\n", c2name(nc));
qunlock(&chanprint);
}
				if(wq->clone != nil){
					cclose(wq->clone);
					wq->clone = nil;
				}
				n = i+1;
			}
			for(i=0; i<n; i++)
				cname = addelem(cname, names[i]);
		}

		cclose(c);


@@ 837,12 878,8 @@ if(chandebug) print("fail\n");
		putmhead(mh);
		mh = nmh;

		for(i=0; i<n; i++)
			cname = addelem(cname, names[i]);

		names += n;
		nnames -= n;
//print("nc %s nnames %d devchar %C qid %.8llux\n", cname->s, nnames, devtab[c->type]->dc, c->qid.path);
		free(wq);
	}



@@ 860,7 897,8 @@ if(c->umh != nil){

	cclose(*cp);
	*cp = c;
if(chandebug) print("success\n");
if(chandebug)
print("[%lud]\twalk succeeds; name %s chan (path %.8llux dev %C %lud)\n", up->pid, c2name(c), c->qid.path, devtab[c->type]->dc, c->dev);
	return 0;
}


M port/devloopback.c => port/devloopback.c +14 -17
@@ 185,21 185,6 @@ loopbackattach(char *spec)
	return c;
}

static Chan*
loopbackclone(Chan *c, Chan *nc)
{
	Loop *lb;

	lb = c->aux;
	nc = devclone(c, nc);
	qlock(lb);
	lb->ref++;
	if((c->flag & COPEN) && TYPE(c->qid.path) == Qdata)
		lb->link[ID(c->qid.path)].ref++;
	qunlock(lb);
	return nc;
}

static int
loopbackgen(Chan *c, char*, Dirtab*, int, int i, Dir *dp)
{


@@ 247,7 232,7 @@ loopbackgen(Chan *c, char*, Dirtab*, int, int i, Dir *dp)
		if(i >= nelem(loopportdir))
			return -1;
		tab = &loopportdir[i];
		mkqid(&qid, QID(ID(c->qid.path), tab->qid.path), 0, QTDIR);
		mkqid(&qid, QID(ID(c->qid.path), tab->qid.path), 0, QTFILE);
		devdir(c, qid, tab->name, tab->length, eve, tab->perm, dp);
		return 1;
	default:


@@ 273,7 258,19 @@ loopbackgen(Chan *c, char*, Dirtab*, int, int i, Dir *dp)
static Walkqid*
loopbackwalk(Chan *c, Chan *nc, char **name, int nname)
{
	return devwalk(c, nc, name, nname, nil, 0, loopbackgen);
	Walkqid *wq;
	Loop *lb;

	wq = devwalk(c, nc, name, nname, nil, 0, loopbackgen);
	if(wq != nil && wq->clone != nil && wq->clone != c){
		lb = c->aux;
		qlock(lb);
		lb->ref++;
		if((c->flag & COPEN) && TYPE(c->qid.path) == Qdata)
			lb->link[ID(c->qid.path)].ref++;
		qunlock(lb);
	}
	return wq;
}

static int

M port/devmnt.c => port/devmnt.c +16 -23
@@ 80,7 80,7 @@ static Chan*
mntattach(char *muxattach)
{
	Mnt *m;
	Chan *c, *mc;
	Chan *c;
	struct bogus{
		Chan	*chan;
		char	*spec;


@@ 155,23 155,6 @@ mntattach(char *muxattach)
	mattach(m, c, bogus.spec);
	poperror();

	/*
	 * Detect a recursive mount for a mount point served by exportfs.
	 * If QTDIR is clear in the returned qid, the foreign server is
	 * requesting the mount point be folded into the connection
	 * to the exportfs. In this case the remote mount driver does
	 * the multiplexing.
	 */
	mc = m->c;
	if(mc->type == devno('M', 0) && (c->qid.type&QTDIR) == 0) {
		mclose(m, c);
		c->qid.type |= QTDIR;
		c->mntptr = mc->mntptr;
		c->mchan = c->mntptr->c;
		c->mqid = c->qid;
		incref(c->mntptr);
	}

	if(bogus.flags & MCACHE)
		c->flag |= CCACHE;



@@ 227,8 210,8 @@ mntwalk(Chan *c, Chan *nc, char **name, int nname)
	Mnt *m;
	Mntrpc *r;
	Walkqid *wq;
extern int chandebug;
if(chandebug){

if(0){
	print("mntwalk ");
	for(i=0; i<nname; i++)
		print("%s/", name[i]);


@@ 678,12 661,22 @@ mountio(Mnt *m, Mntrpc *r)
}

int
mntreadn(Chan *c, uchar *buf, int n)
mntreadn(Chan *c, uchar *buf, int n, int uninterruptable)
{
	int m, dm;

	for(m=0; m<n; m+=dm){
		if(uninterruptable)
			if(waserror()){
				/* user DEL may stop assembly; wait for full 9P msg. */
				if(strstr(up->error, "interrupt") == nil)
					nexterror();
				dm = 0;
				continue;
			}
		dm = devtab[c->type]->read(c, buf, n-m, 0);
		if(uninterruptable)
			poperror();
		if(dm <= 0)
			return 0;
		buf += dm;


@@ 703,7 696,7 @@ mntrpcread(Mnt *m, Mntrpc *r)
	r->reply.type = 0;
	r->reply.tag = 0;
	/* read size, then read exactly the right number of bytes */
	n = mntreadn(m->c, r->rpc, BIT32SZ);
	n = mntreadn(m->c, r->rpc, BIT32SZ, 0);
	if(n != BIT32SZ){
		if(n > 0)
			print("devmnt expected BIT32SZ got %d\n", n);


@@ 714,7 707,7 @@ mntrpcread(Mnt *m, Mntrpc *r)
		print("devmnt: len %d max messagesize %ld\n", len, m->c->iounit);
		return -1;
	}
	n += mntreadn(m->c, r->rpc+BIT32SZ, len-BIT32SZ);
	n += mntreadn(m->c, r->rpc+BIT32SZ, len-BIT32SZ, 1);
	if(n != len){
		print("devmnt: length %d expected %d\n", n, len);
		return -1;