~kris/9p

9hist

fb07b2978cf423f8a9268fcebef7d7def9b6c205 — David du Colombier 24 years ago 26a1924
Plan 9 from Bell Labs 2002-01-04
7 files changed, 124 insertions(+), 58 deletions(-)

M mtx/main.c
M mtx/mmu.c
M port/chan.c
M port/dev.c
M port/devmnt.c
M port/portfns.h
M port/sysfile.c
M mtx/main.c => mtx/main.c +1 -0
@@ 137,6 137,7 @@ init0(void)
		poperror();
	}
	kproc("alarm", alarmkproc, 0);
print("touser forestalled\n");
for(;;);
	touser((void*)(USTKTOP-8));
}

M mtx/mmu.c => mtx/mmu.c +18 -5
@@ 5,8 5,21 @@
#include	"fns.h"
#include	"io.h"

void *ptab;
ulong ptabsize;
/*
 *	The page table is shared across all processes and processors
 *	(hence needs to be locked for updates on a multiprocessor).
 *	Different processes are distinguished via the VSID field in
 *	the segment registers.  As flushing the entire page table is an
 *	expensive operation, we implement an aging algorithm for
 *	mmu pids, with a background kproc to purge stale pids en mass.
 */

static struct {
	Lock;
	void		*base;		/* start of page table in kernel virtual space */
	ulong	size;			/* number of bytes in page table */
	int		slotgen;		/* used to choose which pte to alocate in pteg */
} ptab;

void
mmuinit(void)


@@ 22,9 35,9 @@ mmuinit(void)
		mem <<= 1;
	}

	ptabsize = (1<<(lhash+6));
	ptab = xspanalloc(ptabsize, 0, ptabsize);
	putsdr1(PADDR(ptab) | ((1<<(lhash-10))-1));
	ptab.size = (1<<(lhash+6));
	ptab.base = xspanalloc(ptab.size, 0, ptab.size);
	putsdr1(PADDR(ptab.base) | ((1<<(lhash-10))-1));
}

void

M port/chan.c => port/chan.c +93 -46
@@ 85,6 85,7 @@ struct Elemlist
	char	*name;	/* copy of name, so '/' can be overwritten */
	int	nelems;
	char	**elems;
	int	*off;
};

#define SEP(c) ((c) == 0 || (c) == '/')


@@ 708,12 709,14 @@ undomount(Chan *c, Cname *name)
}

/*
 * Either walks all the way or not at all.  No partial results.
 * Either walks all the way or not at all.  No partial results in *cp.
 * *nerror is the number of names to display in an error message.
 */
static char Edoesnotexist[] = "does not exist";
int
walk(Chan **cp, char **names, int nnames, int nomount)
walk(Chan **cp, char **names, int nnames, int nomount, int *nerror)
{
	int i, dotdot, n, ntry, type, dev;
	int dev, dotdot, i, n, nhave, ntry, type;
	Chan *c, *nc;
	Cname *cname;
	Mount *f;


@@ 736,13 739,21 @@ walk(Chan **cp, char **names, int nnames, int nomount)
	 * An invariant is that each time through the loop, c is on the undomount
	 * side of the mount point, and c's name is cname.
	 */
	while(nnames > 0){
		ntry = nnames;
	for(nhave=0; nhave<nnames; nhave+=n){
		if((c->qid.type&QTDIR)==0){
			if(nerror)
				*nerror = nhave;
			cnameclose(cname);
			cclose(c);
			strcpy(up->errstr, Enotdir);
			return -1;
		}
		ntry = nnames - nhave;
		if(ntry > MAXWELEM)
			ntry = MAXWELEM;
		dotdot = 0;
		for(i=0; i<nnames; i++){
			if(isdotdot(names[i])){
		for(i=0; i<ntry; i++){
			if(isdotdot(names[nhave+i])){
				if(i==0) {
					dotdot = 1;
					ntry = 1;


@@ 758,34 769,29 @@ walk(Chan **cp, char **names, int nnames, int nomount)
		type = c->type;
		dev = c->dev;

		if((wq = devtab[type]->walk(c, nil, names, ntry)) == nil){
		if((wq = devtab[type]->walk(c, nil, names+nhave, ntry)) == nil){
			/* try a union mount, if any */
			if(mh == nil || nomount){
			Giveup:
			if(mh && !nomount){
				/*
				 * mh->mount == c, so start at mh->mount->next
				 */
				rlock(&mh->lock);
				for(f = mh->mount->next; f; f = f->next)
					if((wq = devtab[f->to->type]->walk(f->to, nil, names+nhave, ntry)) != nil)
						break;
				runlock(&mh->lock);
				if(f != nil){
					type = f->to->type;
					dev = f->to->dev;
				}
			}
			if(wq == nil){
				cclose(c);
				cnameclose(cname);
				if(nerror)
					*nerror = nhave+1;
				return -1;
			}

			rlock(&mh->lock);
			if(waserror()){
				runlock(&mh->lock);
				nexterror();
			}
			/*
			 * mh->mount == c, so start at mh->mount->next
			 */
			for(f = mh->mount->next; f; f = f->next)
				if((wq = devtab[f->to->type]->walk(f->to, nil, names, ntry)) != nil)
					break;
			poperror();
			runlock(&mh->lock);

			if(wq == nil)
				goto Giveup;

			type = f->to->type;
			dev = f->to->dev;
		}

		nmh = nil;


@@ 806,6 812,15 @@ walk(Chan **cp, char **names, int nnames, int nomount)
				if(wq->clone == nil){
					cclose(c);
					cnameclose(cname);
					if(wq->nqid==0 || (wq->qid[wq->nqid-1].type&QTDIR)){
						if(nerror)
							*nerror = nhave+wq->nqid+1;
						strcpy(up->errstr, Edoesnotexist);
					}else{
						if(nerror)
							*nerror = nhave+wq->nqid;
						strcpy(up->errstr, Enotdir);
					}
					free(wq);
					return -1;
				}


@@ 819,15 834,12 @@ walk(Chan **cp, char **names, int nnames, int nomount)
				n = i+1;
			}
			for(i=0; i<n; i++)
				cname = addelem(cname, names[i]);
				cname = addelem(cname, names[nhave+i]);
		}
		cclose(c);
		c = nc;
		putmhead(mh);
		mh = nmh;

		names += n;
		nnames -= n;
		free(wq);
	}



@@ 846,6 858,8 @@ walk(Chan **cp, char **names, int nnames, int nomount)

	cclose(*cp);
	*cp = c;
	if(nerror)
		*nerror = 0;
	return 0;
}



@@ 910,6 924,7 @@ static void
growparse(Elemlist *e)
{
	char **new;
	int *inew;
	enum { Delta = 8 };

	if(e->nelems % Delta == 0){


@@ 917,6 932,10 @@ growparse(Elemlist *e)
		memmove(new, e->elems, e->nelems*sizeof(char*));
		free(e->elems);
		e->elems = new;
		inew = smalloc((e->nelems+Delta+1) * sizeof(int));
		memmove(inew, e->off, e->nelems*sizeof(int));
		free(e->off);
		e->off = inew;
	}
}



@@ 934,20 953,38 @@ parsename(char *name, Elemlist *e)
	name = e->name;
	e->nelems = 0;
	e->elems = nil;
	e->off = smalloc(sizeof(int));
	e->off[0] = 0;
	for(;;){
		name = skipslash(name);
		if(*name=='\0')
			break;
		growparse(e);
		
		e->elems[e->nelems++] = name;
		slash = utfrune(name, '/');
		if(slash == nil)
		if(slash == nil){
			e->off[e->nelems] = name+strlen(name) - e->name;
			break;
		}
		e->off[e->nelems] = slash - e->name;
		*slash++ = '\0';
		name = slash;
	}
}

void*
memrchr(void *va, int c, long n)
{
	uchar *a, *e;

	a = va;
	for(e=a+n-1; e>a; e--)
		if(*e == c)
			return e;
	return nil;
}

/*
 * Turn a name into a channel.
 * &name[0] is known to be a valid address.  It may be a kernel address.


@@ 967,7 1004,7 @@ parsename(char *name, Elemlist *e)
Chan*
namec(char *aname, int amode, int omode, ulong perm)
{
	int n, t, nomount;
	int n, prefix, len, t, nomount, npath;
	Chan *c, *cnew;
	Cname *cname;
	Elemlist e;


@@ 1034,19 1071,17 @@ namec(char *aname, int amode, int omode, ulong perm)
		name = skipslash(name);
		break;
	}
	prefix = name - aname;

	e.name = nil;
	e.elems = nil;
	e.off = nil;
	e.nelems = 0;
	if(waserror()){
		if(strcmp(up->errstr, Enonexist) == 0){
			if(strlen(aname) < ERRMAX/3 || (name=strrchr(aname, '/'))==nil || name==aname)
				snprint(up->errstr, ERRMAX, "\"%s\" does not exist", aname);
			else
				snprint(up->errstr, ERRMAX, "file \"...%s\" does not exist", name);
		}
		cclose(c);
		free(e.name);
		free(e.elems);
		free(e.off);
//dumpmount();
		nexterror();
	}


@@ 1065,8 1100,19 @@ namec(char *aname, int amode, int omode, ulong perm)
		e.nelems--;
	}

	if(walk(&c, e.elems, e.nelems, nomount) < 0)
		error(Enonexist);
	if(walk(&c, e.elems, e.nelems, nomount, &npath) < 0){
		if(npath < 0 || npath > e.nelems){
			print("namec %s walk error npath=%d\n", aname, npath);
			nexterror();
		}
		len = prefix+e.off[npath];
		strcpy(tmperrbuf, up->errstr);
		if(len < ERRMAX/3 || (name=memrchr(aname, '/', len))==nil || name==aname)
			snprint(up->errstr, ERRMAX, "\"%.*s\" %s", len, aname, tmperrbuf);
		else
			snprint(up->errstr, ERRMAX, "\"...%.*s\" %s", (int)(len-(name-aname)), name, tmperrbuf);
		nexterror();
	}

	switch(amode){
	case Aaccess:


@@ 1156,7 1202,7 @@ if(c->umh != nil){
		 * If omode&OEXCL is set, just give up.
		 */
		e.nelems++;
		if(walk(&c, e.elems+e.nelems-1, 1, nomount) == 0){
		if(walk(&c, e.elems+e.nelems-1, 1, nomount, nil) == 0){
			if(omode&OEXCL)
				error(Eexist);
			omode |= OTRUNC;


@@ 1246,7 1292,7 @@ if(c->umh != nil){
			createerr = up->errstr;
			up->errstr = tmperrbuf;
			/* note: we depend that walk does not error */
			if(walk(&c, e.elems+e.nelems-1, 1, nomount) < 0){
			if(walk(&c, e.elems+e.nelems-1, 1, nomount, nil) < 0){
				up->errstr = createerr;
				error(createerr);	/* report true error */
			}


@@ 1269,6 1315,7 @@ if(c->umh != nil){
		kstrcpy(up->genbuf, ".", sizeof up->genbuf);
	free(e.name);
	free(e.elems);
	free(e.off);

	return c;
}

M port/dev.c => port/dev.c +5 -1
@@ 147,7 147,11 @@ devwalk(Chan *c, Chan *nc, char **name, int nname, Dirtab *tab, int ntab, Devgen
	wq->clone = nc;

	for(j=0; j<nname; j++){
		isdir(nc);
		if(!(nc->qid.type&QTDIR)){
			if(j==0)
				error(Enotdir);
			goto Done;
		}
		n = name[j];
		if(strcmp(n, ".") == 0){
    Accept:

M port/devmnt.c => port/devmnt.c +1 -0
@@ 450,6 450,7 @@ mntwalk(Chan *c, Chan *nc, char **name, int nname)
		wq->qid[i] = r->reply.wqid[i];

    Return:

	poperror();
	mntfree(r);
	poperror();

M port/portfns.h => port/portfns.h +4 -4
@@ 16,7 16,7 @@ int		blocklen(Block*);
void		cachedel(Image*, ulong);
void		cachepage(Page*, Image*);
void		callwithureg(void(*)(Ureg*));
char*	c2name(Chan*);
char*		c2name(Chan*);
int		cangetc(void*);
int		canlock(Lock*);
int		canpage(Proc*);


@@ 60,7 60,7 @@ void		delay(int);
Chan*		devattach(int, char*);
Block*		devbread(Chan*, long, ulong);
long		devbwrite(Chan*, Block*, ulong);
Chan*	devclone(Chan*);
Chan*		devclone(Chan*);
int		devconfig(int, char *, DevConf *);
void		devcreate(Chan*, char*, int, ulong);
void		devdir(Chan*, Qid, char*, vlong, char*, long, Dir*);


@@ 74,7 74,7 @@ void		devpower(int);
void		devremove(Chan*);
void		devreset(void);
int		devstat(Chan*, uchar*, int, Dirtab*, int, Devgen*);
Walkqid*		devwalk(Chan*, Chan*, char**, int, Dirtab*, int, Devgen*);
Walkqid*	devwalk(Chan*, Chan*, char**, int, Dirtab*, int, Devgen*);
int		devwstat(Chan*, uchar*, int);
void		drawactive(int);
void		drawcmap(void);


@@ 336,7 336,7 @@ void		validstat(uchar*, int);
void		vcacheinval(Page*, ulong);
void*		vmemchr(void*, int, int);
Proc*		wakeup(Rendez*);
int		walk(Chan**, char**, int, int);
int		walk(Chan**, char**, int, int, int*);
void		wlock(RWlock*);
void		wunlock(RWlock*);
void*		xalloc(ulong);

M port/sysfile.c => port/sysfile.c +2 -2
@@ 197,9 197,9 @@ syspipe(ulong *arg)
		nexterror();
	}
	c[1] = cclone(c[0]);
	if(walk(&c[0], datastr+0, 1, 1) < 0)
	if(walk(&c[0], datastr+0, 1, 1, nil) < 0)
		error(Egreg);
	if(walk(&c[1], datastr+1, 1, 1) < 0)
	if(walk(&c[1], datastr+1, 1, 1, nil) < 0)
		error(Egreg);
	c[0] = d->open(c[0], ORDWR);
	c[1] = d->open(c[1], ORDWR);