Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/gnot/devmnt.c

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


## diffname gnot/devmnt.c 1990/03091
## diff -e /dev/null /n/bootesdump/1990/03091/sys/src/9/68020/devmnt.c
0a
#include	"u.h"
#include	"lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"errno.h"

#include	"devtab.h"

#include	"fcall.h"

/*
 * Easy version: multiple sessions but no intra-session multiplexing, copy the data
 */

typedef struct Mnt	Mnt;
struct Mnt
{
	Ref;			/* for number of chans, incl. mntpt but not msg */
	QLock;			/* for access */
	ulong	mntid;		/* serial # */
	Chan	*msg;		/* for reading and writing messages */
	Chan	*mntpt;		/* channel in user's name space */
};

#define	BUFSIZE	(MAXFDATA+500) 	/* BUG */
typedef struct Mntbuf Mntbuf;
struct Mntbuf
{
	Mntbuf	*next;
	char	buf[BUFSIZE];
};

struct
{
	Lock;
	Mntbuf	*free;
}mntbufalloc;

typedef struct Mnthdr Mnthdr;
struct Mnthdr		/* next only meaningful when buffer isn't being used */
{
	Mnthdr	*next;
	Fcall	thdr;
	Fcall	rhdr;
};

struct
{
	Lock;
	Mnthdr	*free;
}mnthdralloc;

struct
{
	Lock;
	long	id;
}mntid;

Mnt	*mnt;
void	mntxmit(Mnt*, Mnthdr*);

Mntbuf*
mballoc(void)
{
	Mntbuf *mb;

loop:
	lock(&mntbufalloc);
	if(mb = mntbufalloc.free){		/* assign = */
		mntbufalloc.free = mb->next;
		unlock(&mntbufalloc);
		return mb;
	}
	unlock(&mntbufalloc);
	print("no mntbufs\n");
	if(u == 0)
		panic("mballoc");
	u->p->state = Wakeme;
	alarm(1000, wakeme, u->p);
	sched();
	goto loop;
}

void
mbfree(Mntbuf *mb)
{
	lock(&mntbufalloc);
	mb->next = mntbufalloc.free;
	mntbufalloc.free = mb;
	unlock(&mntbufalloc);
}

Mnthdr*
mhalloc(void)
{
	Mnthdr *mh;

loop:
	lock(&mnthdralloc);
	if(mh = mnthdralloc.free){		/* assign = */
		mnthdralloc.free = mh->next;
		unlock(&mnthdralloc);
		return mh;
	}
	unlock(&mnthdralloc);
	print("no mnthdrs\n");
	if(u == 0)
		panic("mballoc");
	u->p->state = Wakeme;
	alarm(1000, wakeme, u->p);
	sched();
	goto loop;
}

void
mhfree(Mnthdr *mh)
{
	lock(&mnthdralloc);
	mh->next = mnthdralloc.free;
	mnthdralloc.free = mh;
	unlock(&mnthdralloc);
}

Mnt*
mntdev(int dev, int noerr)
{
	Mnt *m;
	int i;

	for(m=mnt,i=0; i<conf.nmntdev; i++,m++)		/* use a hash table some day */
		if(m->mntid == dev){
			if(m->msg == 0)
				break;
			return m;
		}
	if(noerr)
		return 0;
	error(0, Eshutdown);
}

void
mntreset(void)
{
	int i;
	Mntbuf *mb;
	Mnthdr *mh;

	mnt = ialloc(conf.nmntdev*sizeof(Mnt), 0);

	mb = ialloc(conf.nmntbuf*sizeof(Mntbuf), 0);
	for(i=0; i<conf.nmntbuf-1; i++)
		mb[i].next = &mb[i+1];
	mb[i].next = 0;
	mntbufalloc.free = mb;

	mh = ialloc(conf.nmnthdr*sizeof(Mnthdr), 0);
	for(i=0; i<conf.nmnthdr-1; i++)
		mh[i].next = &mh[i+1];
	mh[i].next = 0;
	mnthdralloc.free = mh;
}

void
mntinit(void)
{
}

Chan*
mntattach(char *spec)
{
	int i;
	Mnt *m;
	Mnthdr *mh;
	Chan *c, *cm;
	struct bogus{
		Chan	*chan;
		char	*spec;
	}bogus;

	bogus = *((struct bogus *)spec);
	spec = bogus.spec;

	m = mnt;
	for(i=0; i<conf.nmntdev; i++,m++){
		lock(m);
		if(m->ref == 0)
			goto Found;
		unlock(m);
	}
	error(0, Enomntdev);
    Found:
	m->ref = 1;
	unlock(m);
	lock(&mntid);
	m->mntid = ++mntid.id;
	unlock(&mntid);
	c = devattach('M', spec);
	c->dev = m->mntid;
	m->mntpt = c;
	cm = bogus.chan;
	m->msg = cm;
	incref(cm);
	mh = mhalloc();
	if(waserror()){
		mhfree(mh);
		close(c);
		nexterror();
	}
	mh->thdr.type = Tattach;
	mh->thdr.fid = c->fid;
	memcpy(mh->thdr.uname, u->p->pgrp->user, NAMELEN);
	strcpy(mh->thdr.aname, spec);
	mntxmit(m, mh);
	c->qid = mh->rhdr.qid;
	c->mchan = m->msg;
	c->mqid = c->qid;
	mhfree(mh);
	poperror();
	return c;
}

Chan*
mntclone(Chan *c, Chan *nc)
{
	Mnt *m;
	Mnthdr *mh;
	int new;

	new = 0;
	if(nc == 0){
		nc = newchan();
		new = 1;
		if(waserror()){
			close(nc);
			nexterror();
		}
	}
	m = mntdev(c->dev, 0);
	mh = mhalloc();
	if(waserror()){
		mhfree(mh);
		nexterror();
	}
	mh->thdr.type = Tclone;
	mh->thdr.fid = c->fid;
	mh->thdr.newfid = nc->fid;
	mntxmit(m, mh);
	nc->type = c->type;
	nc->dev = c->dev;
	nc->qid = c->qid;
	nc->mode = c->mode;
	nc->flag = c->flag;
	nc->offset = c->offset;
	nc->mnt = c->mnt;
	nc->mchan = c->mchan;
	nc->mqid = c->qid;
	if(new)
		poperror();
	mhfree(mh);
	poperror();
	incref(m);
	return nc;
}

int	 
mntwalk(Chan *c, char *name)
{
	Mnt *m;
	Mnthdr *mh;
	int found;

	found = 1;
	m = mntdev(c->dev, 0);
	mh = mhalloc();
	mh->thdr.type = Twalk;
	mh->thdr.fid = c->fid;
	strcpy(mh->thdr.name, name);
	if(waserror()){	/* BUG: can check type of error? */
		found = 0;
		goto Out;
	}
	mntxmit(m, mh);
	c->qid = mh->rhdr.qid;
	poperror();
    Out:
	mhfree(mh);
	return found;
}

void	 
mntstat(Chan *c, char *dp)
{
	Mnt *m;
	Mnthdr *mh;

	m = mntdev(c->dev, 0);
	mh = mhalloc();
	if(waserror()){
		mhfree(mh);
		nexterror();
	}
	mh->thdr.type = Tstat;
	mh->thdr.fid = c->fid;
	mntxmit(m, mh);
	memcpy(dp, mh->rhdr.stat, DIRLEN);
	dp[DIRLEN-4] = devchar[c->type];
	dp[DIRLEN-3] = 0;
	dp[DIRLEN-2] = c->dev;
	dp[DIRLEN-1] = c->dev>>8;
	mhfree(mh);
	poperror();
}

Chan*
mntopen(Chan *c, int omode)
{
	Mnt *m;
	Mnthdr *mh;

	m = mntdev(c->dev, 0);
	mh = mhalloc();
	if(waserror()){
		mhfree(mh);
		nexterror();
	}
	mh->thdr.type = Topen;
	mh->thdr.fid = c->fid;
	mh->thdr.mode = omode;
	mntxmit(m, mh);
	c->qid = mh->rhdr.qid;
	mhfree(mh);
	poperror();
	c->offset = 0;
	c->mode = openmode(omode);
	c->flag |= COPEN;
	return c;
}

void	 
mntcreate(Chan *c, char *name, int omode, ulong perm)
{
	Mnt *m;
	Mnthdr *mh;

	m = mntdev(c->dev, 0);
	mh = mhalloc();
	if(waserror()){
		mhfree(mh);
		nexterror();
	}
	mh->thdr.type = Tcreate;
	mh->thdr.fid = c->fid;
	strcpy(mh->thdr.name, name);
	mh->thdr.mode = omode;
	mh->thdr.perm = perm;
	mntxmit(m, mh);
	c->qid = mh->rhdr.qid;
	mhfree(mh);
	poperror();
	c->flag |= COPEN;
	c->mode = openmode(omode);
	c->qid = mh->rhdr.qid;
}

void	 
mntclose(Chan *c)
{
	Mnt *m;
	Mnthdr *mh;

	m = mntdev(c->dev, 0);
	mh = mhalloc();
	if(waserror()){
		mhfree(mh);
		nexterror();
	}
	mh->thdr.type = Tclunk;
	mh->thdr.fid = c->fid;
	mntxmit(m, mh);
	mhfree(mh);
	if(c == m->mntpt)
		m->mntpt = 0;
	if(decref(m) == 0){		/* BUG: need to hang up all pending i/o */
		qlock(m);
		close(m->msg);
		m->msg = 0;
		qunlock(m);
	}
	poperror();
}

long
mntreadwrite(Chan *c, void *vbuf, long n, int type)
{
	Mnt *m;
	Mnthdr *mh;
	long nt, nr, count, offset;
	char *buf;

	buf = vbuf;
	count = 0;
	offset = c->offset;
	m = mntdev(c->dev, 0);
	mh = mhalloc();
	if(waserror()){
		mhfree(mh);
		nexterror();
	}
	mh->thdr.type = type;
	mh->thdr.fid = c->fid;
    Loop:
	nt = n;
	if(nt > MAXFDATA)
		nt = MAXFDATA;
	mh->thdr.offset = offset;
	mh->thdr.count = nt;
	mh->thdr.data = buf;
	mntxmit(m, mh);
	nr = mh->rhdr.count;
	offset += nr;
	count += nr;
	buf += nr;
	n -= nr;
	if(n && nr==nt)
		goto Loop;
	mhfree(mh);
	poperror();
	return count;
}

long	 
mntread(Chan *c, void *buf, long n)
{
	long i;
	uchar *b;

	n = mntreadwrite(c, buf, n, Tread);
	if(c->qid & CHDIR){
		b = (uchar*)buf;
		for(i=n-DIRLEN; i>=0; i-=DIRLEN){
			b[DIRLEN-4] = devchar[c->type];
			b[DIRLEN-3] = 0;
			b[DIRLEN-2] = c->dev;
			b[DIRLEN-1] = c->dev>>8;
			b += DIRLEN;
		}
	}
	return n;
}

long	 
mntwrite(Chan *c, void *buf, long n)
{
	return mntreadwrite(c, buf, n, Twrite);
}

void	 
mntremove(Chan *c)
{
	Mnt *m;
	Mnthdr *mh;

	m = mntdev(c->dev, 0);
	mh = mhalloc();
	if(waserror()){
		mhfree(mh);
		nexterror();
	}
	mh->thdr.type = Tremove;
	mh->thdr.fid = c->fid;
	mntxmit(m, mh);
	mhfree(mh);
	poperror();
}

void
mntwstat(Chan *c, char *dp)
{
	Mnt *m;
	Mnthdr *mh;

	m = mntdev(c->dev, 0);
	mh = mhalloc();
	if(waserror()){
		mhfree(mh);
		nexterror();
	}
	mh->thdr.type = Twstat;
	mh->thdr.fid = c->fid;
	memcpy(mh->thdr.stat, dp, DIRLEN);
	mntxmit(m, mh);
	mhfree(mh);
	poperror();
}

void	 
mnterrstr(Error *e, char *buf)
{
	Mnt *m;
	Mnthdr *mh;
	char *def="mounted device shut down";

	m = mntdev(e->dev, 1);
	if(m == 0){
		strcpy(buf, def);
		return;
	}
	mh = mhalloc();
	if(waserror()){
		strcpy(buf, def);
		mhfree(mh);
		nexterror();
	}
	mh->thdr.type = Terrstr;
	mh->thdr.fid = 0;
	mh->thdr.err = e->code;
	mntxmit(m, mh);
	strcpy(buf, (char*)mh->rhdr.ename);
	mhfree(mh);
	poperror();
}

void	 
mntuserstr(Error *e, char *buf)
{
	Mnt *m;
	Mnthdr *mh;
	char *def="mounted device shut down";

	m = mntdev(e->dev, 1);
	if(m == 0){
		strcpy(buf, def);
		return;
	}
	mh = mhalloc();
	if(waserror()){
		strcpy(buf, def);
		mhfree(mh);
		nexterror();
	}
	mh->thdr.type = Tuserstr;
	mh->thdr.fid = 0;
	mh->thdr.uid = e->code;
	mntxmit(m, mh);
	strcpy(buf, (char*)mh->rhdr.uname);
	mhfree(mh);
	poperror();
}

void
mntxmit(Mnt *m, Mnthdr *mh)
{
	ulong n;
	Mntbuf *mbr, *mbw;
	Chan *mntpt, *msg;
	int isbit;

	mbr = mballoc();
	mbw = mballoc();
	if(waserror()){
		mbfree(mbr);
		mbfree(mbw);
		nexterror();
	}
	n = convS2M(&mh->thdr, mbw->buf);
	isbit = 0;
	if(devchar[m->msg->type] == 'b')
		isbit = 1;
	/*
	 * Avoid qlock for bit, to maximize parallelism
	 */
	if(isbit){
		lock(&m->use);		/* spin rather than sleep */
		if((msg = m->msg) == 0){
			unlock(&m->use);
			error(0, Eshutdown);
		}
		incref(msg);
		unlock(&m->use);
	}else{
		qlock(m);
		if((msg = m->msg) == 0){
			qunlock(m);
			error(0, Eshutdown);
		}
		qlock(msg);
	}
	if(waserror()){
		if(isbit)
			close(msg);
		else{
			qunlock(m);
			qunlock(msg);
		}
		nexterror();
	}
	if((*devtab[msg->type].write)(msg, mbw->buf, n) != n){
		pprint("short write in mntxmit\n");
		error(0, Egreg);
	}

	/*
	 * Read response
	 */
	n = (*devtab[msg->type].read)(msg, mbr->buf, BUFSIZE);
	if(isbit)
		close(msg);
	else{
		qunlock(m);
		qunlock(msg);
	}
	poperror();

	if(convM2S(mbr->buf, &mh->rhdr, n) == 0){
		pprint("format error in mntxmit\n");
		error(0, Egreg);
	}

	/*
	 * Various checks
	 */
	if(mh->rhdr.type != mh->thdr.type+1){
		pprint("type mismatch %d %d\n", mh->rhdr.type, mh->thdr.type+1);
		error(0, Egreg);
	}
	if(mh->rhdr.fid != mh->thdr.fid){
		pprint("fid mismatch %d %d type %d\n", mh->rhdr.fid, mh->thdr.fid, mh->rhdr.type);
		error(0, Egreg);
	}
	if(mh->rhdr.err){
		mntpt = m->mntpt;	/* unsafe, but Errors are unsafe anyway */
		if(mntpt)
			error(mntpt, mh->rhdr.err);
		error(0, Eshutdown);
	}
	/*
	 * Copy out on read
	 */
	if(mh->thdr.type == Tread)
		memcpy(mh->thdr.data, mh->rhdr.data, mh->rhdr.count);
	mbfree(mbr);
	mbfree(mbw);
	poperror();
}
.
## diffname gnot/devmnt.c 1990/0312
## diff -e /n/bootesdump/1990/03091/sys/src/9/68020/devmnt.c /n/bootesdump/1990/0312/sys/src/9/68020/devmnt.c
469a
	decref(m);
.
384a
print("close mount table %d\n", m->mntid);
.
## diffname gnot/devmnt.c 1990/0324
## diff -e /n/bootesdump/1990/0312/sys/src/9/68020/devmnt.c /n/bootesdump/1990/0324/sys/src/9/68020/devmnt.c
570c
	if(devchar[m->msg->type] == '3')
.
## diffname gnot/devmnt.c 1990/0504
## diff -e /n/bootesdump/1990/0324/sys/src/9/68020/devmnt.c /n/bootesdump/1990/0504/sys/src/9/68020/devmnt.c
385d
## diffname gnot/devmnt.c 1990/0511
## diff -e /n/bootesdump/1990/0504/sys/src/9/68020/devmnt.c /n/bootesdump/1990/0511/sys/src/9/68020/devmnt.c
613a
	if((*devtab[msg->type].write)(msg, mbw->buf, n) != n){
		pprint("short write in mntxmit\n");
		error(0, Egreg);
	}

	/*
	 * Read response
	 */
	n = (*devtab[msg->type].read)(msg, mbr->buf, BUFSIZE);
	qunlock(m);
	qunlock(msg);
.
612a
		nexterror();
.
611a
		error(0, Eshutdown);
	}
	qlock(msg);
	if(waserror()){
		qunlock(m);
.
608,610c
	close(msg);
	poperror();

	if(convM2S(mbr->buf, &mh->rhdr, n) == 0){
		pprint("format error in mntxmit\n");
		error(0, Egreg);
	}

	/*
	 * Various checks
	 */
	if(mh->rhdr.type != mh->thdr.type+1){
		pprint("type mismatch %d %d\n", mh->rhdr.type, mh->thdr.type+1);
		error(0, Egreg);
	}
	if(mh->rhdr.fid != mh->thdr.fid){
		pprint("fid mismatch %d %d type %d\n", mh->rhdr.fid, mh->thdr.fid, mh->rhdr.type);
		error(0, Egreg);
	}
	if(mh->rhdr.err){
		mntpt = m->mntpt;	/* unsafe, but Errors are unsafe anyway */
		if(mntpt)
			error(mntpt, mh->rhdr.err);
		error(0, Eshutdown);
	}

	/*
	 * Copy out on read
	 */
	if(mh->thdr.type == Tread)
		memcpy(mh->thdr.data, mh->rhdr.data, mh->rhdr.count);
	mbfree(mbr);
	mbfree(mbw);
	poperror();
	return;

    Normal:
	qlock(m);
	if((msg = m->msg) == 0){
.
591,596c
		close(msg);
.
589a
	incref(msg);
	unlock(&m->use);
.
582,588c
		error(0, Eshutdown);
.
574,580c
	if(devchar[m->msg->type] != '3')
		goto Normal;
	lock(&m->use);		/* spin rather than sleep */
	if((msg = m->msg) == 0){
.
572c
	 * Bit3 does its own multiplexing.  (Well, the file server does.)
	 * The code is different enough that it's broken out separately here.
.
568,570d
558d
## diffname gnot/devmnt.c 1990/05313
## diff -e /n/bootesdump/1990/0511/sys/src/9/68020/devmnt.c /n/bootesdump/1990/05313/sys/src/9/68020/devmnt.c
659,669c
    Respond:
	mqfree(q);
	poperror();
.
645,656c
	if(q->reader == 0){		/* i will read */
		q->reader = u->p;
    Read:
		qunlock(q);
		qlocked = 0;
		n = (*devtab[q->msg->type].read)(q->msg, mbr->buf, BUFSIZE);
		if(convM2S(mbr->buf, &mh->rhdr, n) == 0){
			print("format error in mntxmit\n");
			mnterrdequeue(q, mh);
			error(0, Ebadmsg);
		}
		/*
		 * Response might not be mine
		 */
		qlock(q);
		qlocked = 1;
		if(mh->rhdr.fid == mh->thdr.fid
		&& mh->rhdr.type == mh->thdr.type+1){	/* it's mine */
			q->reader = 0;
			if(w = q->writer){	/* advance a writer to reader */
				q->reader = w->p;
				q->writer = w->next;
				wakeup(&w->r);
			}
			qunlock(q);
			qlocked = 0;
			goto Respond;
		}
		/*
		 * Hand response to correct recipient
		 */
if(q->writer == 0) print("response with empty queue\n");
		for(ow=0,w=q->writer; w; ow=w,w=w->next)
			if(mh->rhdr.fid == w->thdr.fid
			&& mh->rhdr.type == w->thdr.type+1){
				Mntbuf *t;
				t = mbr;
				mbr = w->mbr;
				w->mbr = t;
				memcpy(&w->rhdr, &mh->rhdr, sizeof mh->rhdr);
				/* take recipient from queue */
				if(ow == 0)
					q->writer = w->next;
				else
					ow->next = w->next;
				wakeup(&w->r);
				goto Read;
			}
		goto Read;
	}else{
		mh->mbr = mbr;
		mh->p = u->p;
		/* put self in queue */
		mh->next = q->writer;
		q->writer = mh;
		qunlock(q);
		qlocked = 0;
		if(waserror()){		/* interrupted sleep */
			print("interrupted i/o\n");
			mnterrdequeue(q, mh);
			nexterror();
		}
		sleep(&mh->r, return0, 0);
		poperror();
		qlock(q);
		qlocked = 1;
		if(q->reader == u->p)	/* i got promoted */
			goto Read;
		mbr = mh->mbr;		/* pick up my buffer */
		qunlock(q);
		qlocked = 0;
		goto Respond;
.
641,643c
	if((*devtab[q->msg->type].write)(q->msg, mbw->buf, n) != n){
		print("short write in mntxmit\n");
		error(0, Eshortmsg);
.
637,638c
		if(qlocked)
			qunlock(q);
		mqfree(q);
.
634,635c
	incref(q);
	qlock(q);
	qlocked = 1;
.
630,632c
#endif
	q = m->q;
	if(q == 0)
.
609,610c
		print("fid mismatch %d %d type %d\n", mh->rhdr.fid, mh->thdr.fid, mh->rhdr.type);
		error(0, Ebadmsg);
.
605,606c
		print("type mismatch %d %d\n", mh->rhdr.type, mh->thdr.type+1);
		error(0, Ebadmsg);
.
597,598c
		print("format error in mntxmit\n");
		error(0, Ebadmsg);
.
585,586c
		print("short write in mntxmit\n");
		error(0, Eshortmsg);
.
566a
#ifdef	bit3
.
557c
	Mnthdr *w, *ow;
	Chan *mntpt;
	MntQ *q;
	int qlocked;
.
552a
mnterrdequeue(MntQ *q, Mnthdr *mh)		/* queue is unlocked */
{
	Mnthdr *w;

	qlock(q);
	/* take self from queue if necessary */
	if(q->reader == u->p){	/* advance a writer to reader */
		w = q->writer;
		if(w){
			q->reader = w->p;
			q->writer = w->next;
			wakeup(&w->r);
		}else{
			q->reader = 0;
			q->writer = 0;
		}
	}else{
		w = q->writer;
		if(w == mh)
			q->writer = w->next;
		else{
			while(w){
				if(w->next == mh){
					w->next = mh->next;
					break;
				}
				w = w->next;
			}
		}
	}
	qunlock(q);

}
void
.
461,475c
	mntclunk(c, Tremove);
.
392a
void
mntclose(Chan *c)
{
	mntclunk(c, Tclunk);
}

.
384,389c
	lock(m);
	if(--m->ref == 0){		/* BUG: need to hang up all pending i/o */
		q = m->q;
		m->q = 0;
		m->mntid = 0;
		unlock(m);		/* mqfree can take time */
		mqfree(q);
	}else
		unlock(m);
	if(waserr)
		nexterror();
.
380c
	waserr = 0;
	if(waserror())		/* gotta clean up as if there wasn't */
		waserr = 1;
	else
		mntxmit(m, mh);
.
374,378c
	mh->thdr.type = t;
.
370a
	MntQ *q;
	int waserr;
int ne = u->nerrlab;
.
367c
mntclunk(Chan *c, int t)
.
261a
	if(new)
		poperror();
.
258,259d
216c
	c->mchan = m->q->msg;
.
206a
		mqfree(q);
.
203a

    out:
.
202c

	/*
	 * Look for queue to same msg channel
	 */
	q = mntqalloc.arena;
	for(i=0; i<conf.nmntdev; i++,q++)
		if(q->msg==cm){
			lock(q);
			if(q->ref && q->msg==cm){
				m->q = q;
				q->ref++;
				unlock(q);
				goto out;
			}
			unlock(q);
		}
	m->q = mqalloc();
	m->q->msg = cm;
.
191a

.
174a
	MntQ *q;
.
173c
	Mnt *m, *mm;
.
161a

	mq = ialloc(conf.nmntdev*sizeof(MntQ), 0);
	for(i=0; i<conf.nmntdev-1; i++)
		mq[i].next = &mq[i+1];
	mq[i].next = 0;
	mntqalloc.arena = mq;
	mntqalloc.free = mq;
.
147a
	MntQ *mq;
.
133c
			if(m->q == 0)
.
124a
MntQ*
mqalloc(void)
{
	MntQ *q;

	lock(&mntqalloc);
	if(q = mntqalloc.free){		/* assign = */
		mntqalloc.free = q->next;
		unlock(&mntqalloc);
		lock(q);
		q->ref = 1;
		q->writer = 0;
		q->reader = 0;
		unlock(q);
		return q;
	}
	unlock(&mntqalloc);
	panic("no mntqs\n");			/* there MUST be enough */
}

void
mqfree(MntQ *mq)
{
	Chan *msg = 0;

	lock(mq);
	if(--mq->ref == 0){
		msg = mq->msg;
		mq->msg = 0;
		lock(&mntqalloc);
		mq->next = mntqalloc.free;
		mntqalloc.free = mq;
		unlock(&mntqalloc);
	}
	unlock(mq);
	if(msg)		/* after locks are down */
		close(msg);
}

.
109c
		panic("mhalloc");
.
56a
	MntQ	*arena;
	MntQ	*free;
}mntqalloc;

struct
{
	Lock;
.
45a
	Rendez	r;
	Proc	*p;
	Mntbuf	*mbr;
.
43c
	Mnthdr	*next;	/* in free list or writers list */
.
40,41c
struct Mnthdr
.
25a
struct MntQ
{
	Ref;
	QLock;			/* for access */
	MntQ	*next;		/* for allocation */
	Chan	*msg;		/* for reading and writing messages */
	Proc	*reader;	/* process reading response */
	Mnthdr	*writer;	/* queue of headers of written messages */
};

.
23a
	MntQ	*q;
.
22d
20d
16a
typedef struct Mnthdr	Mnthdr;
typedef struct MntQ	MntQ;

.
12,14d
## diffname gnot/devmnt.c 1990/0604
## diff -e /n/bootesdump/1990/05313/sys/src/9/68020/devmnt.c /n/bootesdump/1990/0604/sys/src/9/68020/devmnt.c
756,758d
717,718c
	n = (*devtab[q->msg->type].read)(q->msg, mbr->buf, BUFSIZE);
	mqfree(q);
.
709c
	if((*devtab[q->msg->type].write)(q->msg, mbw->buf, n) != n){
.
706c
		mqfree(q);
.
698,704c

	incref(q);
.
696c
	if(devchar[q->msg->type] != '3')
.
691c
	q = m->q;
	if(q == 0)
		error(0, Eshutdown);
#ifdef	BIT3
.
## diffname gnot/devmnt.c 1990/0605
## diff -e /n/bootesdump/1990/0604/sys/src/9/68020/devmnt.c /n/bootesdump/1990/0605/sys/src/9/68020/devmnt.c
656a
print("err: writer\n");
.
646a
print("err: reader\n");
.
169a
print("mqfree\n");
.
## diffname gnot/devmnt.c 1990/0617
## diff -e /n/bootesdump/1990/0605/sys/src/9/68020/devmnt.c /n/bootesdump/1990/0617/sys/src/9/68020/devmnt.c
828c
			print("%lux interrupted i/o %d %d\n", u->p, mh->thdr.type, mh->thdr.fid);
.
801c
if(q->writer == 0) print("response with empty queue %d %d %d: %d %d\n", mh->rhdr.type, mh->rhdr.err, mh->rhdr.fid, mh->thdr.type, mh->thdr.fid);
.
777c
			print("%lux %lux %lux %d format error in mntxmit %s\n", u->p, q->reader, q->writer, n, u->p->text);
.
659d
648d
290a
	qunlock(&mntqalloc);
.
286,288c
	m->q = mqalloc(cm);
.
274a
	qlock(&mntqalloc);
.
170c
print("mqfree %lux %lux\n", mq->reader, mq->writer);
.
159d
156d
153a
		q->msg = msg;
		unlock(q);
		incref(msg);
.
151d
148d
144c
mqalloc(Chan *msg)	/* mntqalloc is qlocked */
.
67a
	QLock;
.
## diffname gnot/devmnt.c 1990/0619
## diff -e /n/bootesdump/1990/0617/sys/src/9/68020/devmnt.c /n/bootesdump/1990/0619/sys/src/9/68020/devmnt.c
856c
	mbfree(mh->mbr);
.
836d
826c
			print("interrupted i/o\n");
.
818d
804,805c
				t = mh->mbr;
				mh->mbr = w->mbr;
.
799c
		if(q->writer==0) print("response with empty queue\n");
.
773,775c
		n = (*devtab[q->msg->type].read)(q->msg, mh->mbr->buf, BUFSIZE);
		if(convM2S(mh->mbr->buf, &mh->rhdr, n) == 0){
			print("format error in mntxmit\n");
.
748c
	mbfree(mh->mbr);
.
720c
	if(convM2S(mh->mbr->buf, &mh->rhdr, n) == 0){
.
716c
	n = (*devtab[q->msg->type].read)(q->msg, mh->mbr->buf, BUFSIZE);
.
687c
		mbfree(mh->mbr);
.
684c
	mh->mbr = mballoc();
.
678c
	Mntbuf *mbw;
.
170d
## diffname gnot/devmnt.c 1990/0620
## diff -e /n/bootesdump/1990/0619/sys/src/9/68020/devmnt.c /n/bootesdump/1990/0620/sys/src/9/68020/devmnt.c
824d
798d
774d
## diffname gnot/devmnt.c 1990/0703
## diff -e /n/bootesdump/1990/0620/sys/src/9/68020/devmnt.c /n/bootesdump/1990/0703/sys/src/9/68020/devmnt.c
849a
	}
.
848c
	if(mh->thdr.type == Tread){
		if(mh->rhdr.count > mh->thdr.count)
			error(0, Ebadcnt);
.
772a
		poperror();
.
771a
		if(waserror()){
			mnterrdequeue(q, mh);
			nexterror();
		}
.
## diffname gnot/devmnt.c 1990/0707
## diff -e /n/bootesdump/1990/0703/sys/src/9/68020/devmnt.c /n/bootesdump/1990/0707/sys/src/9/68020/devmnt.c
861a

mntdump()
{
	int i;
	MntQ *q;
	Mnthdr *h;
	Proc *p;

	for(i=0; i<conf.nmntdev; i++){
		q = &mntqalloc.arena[i];
		if(!q->msg)
			continue;
		p = q->reader;
		print("q rdr %d wrtr ", p? p->pid : 0);
		for(h=q->writer; h; h=h->next)
			print("(%lux %lux %d)", h, &h->r, (p=h->p)? p->pid : 0);
		print("\n");
	}
}
.
## diffname gnot/devmnt.c 1990/0717
## diff -e /n/bootesdump/1990/0707/sys/src/9/68020/devmnt.c /n/bootesdump/1990/0717/sys/src/9/68020/devmnt.c
830c
		sleep(&mh->r, mntreadreply, mh);
.
814a
				w->readreply = 1;
.
792a
				w->readreply = 1;
.
762a
	mh->readreply = 0;
.
672a
int
mntreadreply(void *a)
{
	return ((Mnthdr *)a)->readreply;
}
.
56a
	int	readreply;	/* true if we are reader or our reply has come */
.
## diffname gnot/devmnt.c 1990/0725
## diff -e /n/bootesdump/1990/0717/sys/src/9/68020/devmnt.c /n/bootesdump/1990/0725/sys/src/9/68020/devmnt.c
294d
## diffname gnot/devmnt.c 1990/0726
## diff -e /n/bootesdump/1990/0725/sys/src/9/68020/devmnt.c /n/bootesdump/1990/0726/sys/src/9/68020/devmnt.c
293a
		mqfree(q);
.
## diffname gnot/devmnt.c 1990/0728
## diff -e /n/bootesdump/1990/0726/sys/src/9/68020/devmnt.c /n/bootesdump/1990/0728/sys/src/9/68020/devmnt.c
294d
## diffname gnot/devmnt.c 1990/11211
## diff -e /n/bootesdump/1990/0728/sys/src/9/68020/devmnt.c /n/bootesdump/1990/11211/sys/src/9/68020/devmnt.c
863c
			error(Ebadcnt);
.
852,856c
	if(mh->rhdr.type == Rerror){
		if(m->mntpt)
			errors(mh->rhdr.ename);
		error(Eshutdown);
.
810,811c
			if(mh->rhdr.tag == w->thdr.tag){
.
793,794c
		if(mh->rhdr.tag == mh->thdr.tag){	/* it's mine */
.
786c
			error(Ebadmsg);
.
771c
		error(Eshortmsg);
.
740,745d
738c
		error(Ebadmsg);
.
734c
		error(Ebadmsg);
.
731a
	if(mh->rhdr.tag != mh->thdr.tag){
		print("tag mismatch %d %d\n", mh->rhdr.tag, mh->thdr.tag);
		error(Ebadmsg);
	}
	if(mh->rhdr.type == Rerror){
		if(m->mntpt)
			errors(mh->rhdr.ename);
		error(Eshutdown);
	}
.
726c
		error(Ebadmsg);
.
714c
		error(Eshortmsg);
.
698c
		error(Eshutdown);
.
684d
677a

.
672a

.
585,638d
540c
	if(c->qid.path & CHDIR){
.
300c
	strcpy(mh->thdr.aname, bogus.spec);
	strcpy(mh->thdr.auth, bogus.auth);
.
266c
	c = devattach('M', bogus.spec);
.
258c
	error(Enomntdev);
.
248,249c
	bogus = *((struct bogus *)crud);
.
245a
		char	*auth;
.
236c
mntattach(char *crud)
.
219a
	mh[i].thdr.tag = i;
.
218a
		mh[i].thdr.tag = i;
	}
.
217c
	for(i=0; i<conf.nmnthdr-1; i++){
.
197c
	error(Eshutdown);
.
12d
## diffname gnot/devmnt.c 1990/1123
## diff -e /n/bootesdump/1990/11211/sys/src/9/68020/devmnt.c /n/bootesdump/1990/1123/sys/src/9/68020/devmnt.c
781a
		mh->prev = 0;
		mh->writing = 1;
		if(q->writer)
			q->writer->prev = mh;
.
761,776c
		if(tag<0 || tag>=conf.nmnthdr){
			print("unknown tag %d\n", tag);
			goto Read;
		}
		w = &mnthdralloc.arena[tag];
		if(!w->writing){
			print("reply not writing\n");
			goto Read;
		}
		t = mh->mbr;
		mh->mbr = w->mbr;
		w->mbr = t;
		memcpy(&w->rhdr, &mh->rhdr, sizeof mh->rhdr);
		mntwunlink(q, w);
		w->readreply = 1;
		wakeup(&w->r);
.
750a
				if(q->writer)
					q->writer->prev = 0;
.
746c
		tag = mh->rhdr.tag;
		if(tag == mh->thdr.tag){	/* it's mine */
.
636c
	int qlocked, tag;
.
633c
	Mntbuf *mbw, *t;
.
605,618c
	}else
		mntwunlink(q, mh);
.
599a
			q->writer->prev = 0;
.
590a
	if(w->next)
		w->next->prev = w->prev;
	if(w->prev)
		w->prev->next = w->next;
	else{
		q->writer = w->next;
		if(q->writer)
			q->writer->prev = 0;
	}
	w->writing = 0;
}

void
mnterrdequeue(MntQ *q, Mnthdr *mh)	/* queue is unlocked */
{
.
589c
mntwunlink(MntQ *q, Mnthdr *w)		/* queue is locked and w is a writer */
.
221a
	mnthdralloc.arena = mh;
.
61a
	Mnthdr	*arena;
.
50c
	Mnthdr	*next;		/* in free list or writers list */
	Mnthdr	*prev;		/* in writers list only */
	int	writing;	/* flag: in writers list */
.
## diffname gnot/devmnt.c 1990/1124
## diff -e /n/bootesdump/1990/1123/sys/src/9/68020/devmnt.c /n/bootesdump/1990/1124/sys/src/9/68020/devmnt.c
833c
	poperror();		/* 1 */
.
821a
	}else if(mh->rhdr.type != mh->thdr.type+1){
		print("bad type %d not %d in mntxmit\n", mh->rhdr.type, mh->thdr.type+1);
		error(Ebadmsg);
.
817c
	poperror();		/* 2 */
.
809a
		mh->active = 0;
.
801c
			mnterrdequeue(m, mh);
.
794d
780d
777,778c
		if(w->flushing || !w->active)	/* nothing to do; mntflush will clean up */
.
764a
			mh->active = 0;
.
759,761d
757a
				mntwunlink(q, w);
.
746c
			print("bad reply message\n");
			mnterrdequeue(m, mh);
.
744c
		poperror();		/* 3 */
.
739,740c
		if(waserror()){		/* 3 */
			mnterrdequeue(m, mh);
.
729a
	mh->active = 1;
.
723c
	if(waserror()){		/* 2 */
.
715c
	poperror();		/* 1 */
.
680c
	poperror();		/* 2 */
.
666c
	if(waserror()){		/* 2 */
.
648c
	if(waserror()){			/* 1 */
.
644c
	int qlocked, tag, written;
.
628c
	mntflush(m, mh);
.
618,619d
616a
			mntwunlink(q, w);
.
611a
	mh->flushing = 1;
	q = m->q;
.
610a
	MntQ *q;
.
609a
	Mnthdr *mh;

	if(omh->thdr.type == Tflush)
		return;

	mh = mhalloc();
	if(waserror()){
		omh->flushing = 0;
		mhfree(mh);
		return;		/* no more errors please */
	}
	mh->thdr.type = Tflush;
	mh->thdr.oldtag = omh->thdr.tag;
	mntxmit(m, mh);
	omh->flushing = 0;
	mhfree(mh);
	poperror();
}

void
mnterrdequeue(Mnt *m, Mnthdr *mh)	/* queue is unlocked */
{
.
608c
mntflush(Mnt *m, Mnthdr *omh)	/* queue is unlocked */
.
606a
/*
 * m->q is unlocked.  Send Tflush message to flush omh->tag.
 * Cut off all errors.   Caller will free omh
 */
.
604d
140a
	if(mh->flushing)
		return;
	mh->active = 0;
.
124a
		mh->flushing = 0;
.
52c
	short	active;
	short	flushing;	/* a Tflush has been sent */
.
## diffname gnot/devmnt.c 1990/1126
## diff -e /n/bootesdump/1990/1124/sys/src/9/68020/devmnt.c /n/bootesdump/1990/1126/sys/src/9/68020/devmnt.c
472d
## diffname gnot/devmnt.c 1990/1127
## diff -e /n/bootesdump/1990/1126/sys/src/9/68020/devmnt.c /n/bootesdump/1990/1127/sys/src/9/68020/devmnt.c
811,813c
		w->mbr = mh->mbr;
		mh->mbr = 0;
.
774a
		mh->mbr = mballoc();
.
708a
	mh->mbr = mballoc();
.
680c
		if(mh->mbr)
			mbfree(mh->mbr);
.
677c
	mh->mbr = 0;
.
672c
	Mntbuf *mbw;
.
## diffname gnot/devmnt.c 1990/1210 # deleted
## diff -e /n/bootesdump/1990/1127/sys/src/9/68020/devmnt.c /n/bootesdump/1990/1210/sys/src/9/68020/devmnt.c
1,888d

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].