plan 9 kernel history: overview | file list | diff list

gnot/devmnt.c (diff list | history)

1990/03091/sys/src/9/gnot/devmnt.c:382,3871990/0312/sys/src/9/gnot/devmnt.c:382,388 (short | long)
1990/03091    
	if(c == m->mntpt) 
		m->mntpt = 0; 
	if(decref(m) == 0){		/* BUG: need to hang up all pending i/o */ 
1990/0312    
print("close mount table %d\n", m->mntid); 
1990/03091    
		qlock(m); 
		close(m->msg); 
		m->msg = 0; 
1990/03091/sys/src/9/gnot/devmnt.c:467,4721990/0312/sys/src/9/gnot/devmnt.c:468,474
1990/03091    
		mhfree(mh); 
		nexterror(); 
	} 
1990/0312    
	decref(m); 
1990/03091    
	mh->thdr.type = Tremove; 
	mh->thdr.fid = c->fid; 
	mntxmit(m, mh); 
1990/0312/sys/src/9/gnot/devmnt.c:567,5731990/0324/sys/src/9/gnot/devmnt.c:567,573 (short | long)
1990/03091    
	} 
	n = convS2M(&mh->thdr, mbw->buf); 
	isbit = 0; 
	if(devchar[m->msg->type] == 'b') 
1990/0324    
	if(devchar[m->msg->type] == '3') 
1990/03091    
		isbit = 1; 
	/* 
	 * Avoid qlock for bit, to maximize parallelism 
1990/0324/sys/src/9/gnot/devmnt.c:382,3881990/0504/sys/src/9/gnot/devmnt.c:382,387 (short | long)
1990/03091    
	if(c == m->mntpt) 
		m->mntpt = 0; 
	if(decref(m) == 0){		/* BUG: need to hang up all pending i/o */ 
1990/0312    
print("close mount table %d\n", m->mntid); 
1990/03091    
		qlock(m); 
		close(m->msg); 
		m->msg = 0; 
1990/0504/sys/src/9/gnot/devmnt.c:555,5611990/0511/sys/src/9/gnot/devmnt.c:555,560 (short | long)
1990/03091    
	ulong n; 
	Mntbuf *mbr, *mbw; 
	Chan *mntpt, *msg; 
	int isbit; 
 
	mbr = mballoc(); 
	mbw = mballoc(); 
1990/0504/sys/src/9/gnot/devmnt.c:565,5991990/0511/sys/src/9/gnot/devmnt.c:564,584
1990/03091    
		nexterror(); 
	} 
	n = convS2M(&mh->thdr, mbw->buf); 
	isbit = 0; 
1990/0324    
	if(devchar[m->msg->type] == '3') 
1990/03091    
		isbit = 1; 
	/* 
	 * Avoid qlock for bit, to maximize parallelism 
1990/0511    
	 * Bit3 does its own multiplexing.  (Well, the file server does.) 
	 * The code is different enough that it's broken out separately here. 
1990/03091    
	 */ 
	if(isbit){ 
		lock(&m->use);		/* spin rather than sleep */ 
		if((msg = m->msg) == 0){ 
			unlock(&m->use); 
			error(0, Eshutdown); 
		} 
		incref(msg); 
1990/0511    
	if(devchar[m->msg->type] != '3') 
		goto Normal; 
	lock(&m->use);		/* spin rather than sleep */ 
	if((msg = m->msg) == 0){ 
1990/03091    
		unlock(&m->use); 
	}else{ 
		qlock(m); 
		if((msg = m->msg) == 0){ 
			qunlock(m); 
			error(0, Eshutdown); 
		} 
		qlock(msg); 
1990/0511    
		error(0, Eshutdown); 
1990/03091    
	} 
1990/0511    
	incref(msg); 
	unlock(&m->use); 
1990/03091    
	if(waserror()){ 
		if(isbit) 
			close(msg); 
		else{ 
			qunlock(m); 
			qunlock(msg); 
		} 
1990/0511    
		close(msg); 
1990/03091    
		nexterror(); 
	} 
	if((*devtab[msg->type].write)(msg, mbw->buf, n) != n){ 
1990/0504/sys/src/9/gnot/devmnt.c:605,6161990/0511/sys/src/9/gnot/devmnt.c:590,654
1990/03091    
	 * Read response 
	 */ 
	n = (*devtab[msg->type].read)(msg, mbr->buf, BUFSIZE); 
	if(isbit) 
		close(msg); 
	else{ 
1990/0511    
	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){ 
1990/03091    
		qunlock(m); 
1990/0511    
		error(0, Eshutdown); 
	} 
	qlock(msg); 
	if(waserror()){ 
		qunlock(m); 
1990/03091    
		qunlock(msg); 
1990/0511    
		nexterror(); 
1990/03091    
	} 
1990/0511    
	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); 
1990/03091    
	poperror(); 
 
	if(convM2S(mbr->buf, &mh->rhdr, n) == 0){ 
1990/0511/sys/src/9/gnot/devmnt.c:9,281990/05313/sys/src/9/gnot/devmnt.c:9,37 (short | long)
1990/03091    
 
#include	"fcall.h" 
 
/* 
 * Easy version: multiple sessions but no intra-session multiplexing, copy the data 
 */ 
 
typedef struct Mnt	Mnt; 
1990/05313    
typedef struct Mnthdr	Mnthdr; 
typedef struct MntQ	MntQ; 
 
1990/03091    
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 */ 
1990/05313    
	MntQ	*q; 
1990/03091    
}; 
 
1990/05313    
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 */ 
}; 
 
1990/03091    
#define	BUFSIZE	(MAXFDATA+500) 	/* BUG */ 
typedef struct Mntbuf Mntbuf; 
struct Mntbuf 
1990/0511/sys/src/9/gnot/devmnt.c:37,481990/05313/sys/src/9/gnot/devmnt.c:46,59
1990/03091    
	Mntbuf	*free; 
}mntbufalloc; 
 
typedef struct Mnthdr Mnthdr; 
struct Mnthdr		/* next only meaningful when buffer isn't being used */ 
1990/05313    
struct Mnthdr 
1990/03091    
{ 
	Mnthdr	*next; 
1990/05313    
	Mnthdr	*next;	/* in free list or writers list */ 
1990/03091    
	Fcall	thdr; 
	Fcall	rhdr; 
1990/05313    
	Rendez	r; 
	Proc	*p; 
	Mntbuf	*mbr; 
1990/03091    
}; 
 
struct 
1990/0511/sys/src/9/gnot/devmnt.c:54,591990/05313/sys/src/9/gnot/devmnt.c:65,77
1990/03091    
struct 
{ 
	Lock; 
1990/05313    
	MntQ	*arena; 
	MntQ	*free; 
}mntqalloc; 
 
struct 
{ 
	Lock; 
1990/03091    
	long	id; 
}mntid; 
 
1990/0511/sys/src/9/gnot/devmnt.c:106,1121990/05313/sys/src/9/gnot/devmnt.c:124,130
1990/03091    
	unlock(&mnthdralloc); 
	print("no mnthdrs\n"); 
	if(u == 0) 
		panic("mballoc"); 
1990/05313    
		panic("mhalloc"); 
1990/03091    
	u->p->state = Wakeme; 
	alarm(1000, wakeme, u->p); 
	sched(); 
1990/0511/sys/src/9/gnot/devmnt.c:122,1271990/05313/sys/src/9/gnot/devmnt.c:140,184
1990/03091    
	unlock(&mnthdralloc); 
} 
 
1990/05313    
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); 
} 
 
1990/03091    
Mnt* 
mntdev(int dev, int noerr) 
{ 
1990/0511/sys/src/9/gnot/devmnt.c:130,1361990/05313/sys/src/9/gnot/devmnt.c:187,193
1990/03091    
 
	for(m=mnt,i=0; i<conf.nmntdev; i++,m++)		/* use a hash table some day */ 
		if(m->mntid == dev){ 
			if(m->msg == 0) 
1990/05313    
			if(m->q == 0) 
1990/03091    
				break; 
			return m; 
		} 
1990/0511/sys/src/9/gnot/devmnt.c:145,1501990/05313/sys/src/9/gnot/devmnt.c:202,208
1990/03091    
	int i; 
	Mntbuf *mb; 
	Mnthdr *mh; 
1990/05313    
	MntQ *mq; 
1990/03091    
 
	mnt = ialloc(conf.nmntdev*sizeof(Mnt), 0); 
 
1990/0511/sys/src/9/gnot/devmnt.c:159,1641990/05313/sys/src/9/gnot/devmnt.c:217,229
1990/03091    
		mh[i].next = &mh[i+1]; 
	mh[i].next = 0; 
	mnthdralloc.free = mh; 
1990/05313    
 
	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; 
1990/03091    
} 
 
void 
1990/0511/sys/src/9/gnot/devmnt.c:170,1771990/05313/sys/src/9/gnot/devmnt.c:235,243
1990/03091    
mntattach(char *spec) 
{ 
	int i; 
	Mnt *m; 
1990/05313    
	Mnt *m, *mm; 
1990/03091    
	Mnthdr *mh; 
1990/05313    
	MntQ *q; 
1990/03091    
	Chan *c, *cm; 
	struct bogus{ 
		Chan	*chan; 
1990/0511/sys/src/9/gnot/devmnt.c:189,1941990/05313/sys/src/9/gnot/devmnt.c:255,261
1990/03091    
		unlock(m); 
	} 
	error(0, Enomntdev); 
1990/05313    
 
1990/03091    
    Found: 
	m->ref = 1; 
	unlock(m); 
1990/0511/sys/src/9/gnot/devmnt.c:199,2091990/05313/sys/src/9/gnot/devmnt.c:266,296
1990/03091    
	c->dev = m->mntid; 
	m->mntpt = c; 
	cm = bogus.chan; 
	m->msg = cm; 
1990/05313    
 
	/* 
	 * 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; 
1990/03091    
	incref(cm); 
1990/05313    
 
    out: 
1990/03091    
	mh = mhalloc(); 
	if(waserror()){ 
		mhfree(mh); 
1990/05313    
		mqfree(q); 
1990/03091    
		close(c); 
		nexterror(); 
	} 
1990/0511/sys/src/9/gnot/devmnt.c:213,2191990/05313/sys/src/9/gnot/devmnt.c:300,306
1990/03091    
	strcpy(mh->thdr.aname, spec); 
	mntxmit(m, mh); 
	c->qid = mh->rhdr.qid; 
	c->mchan = m->msg; 
1990/05313    
	c->mchan = m->q->msg; 
1990/03091    
	c->mqid = c->qid; 
	mhfree(mh); 
	poperror(); 
1990/0511/sys/src/9/gnot/devmnt.c:255,2641990/05313/sys/src/9/gnot/devmnt.c:342,351
1990/03091    
	nc->mnt = c->mnt; 
	nc->mchan = c->mchan; 
	nc->mqid = c->qid; 
	if(new) 
		poperror(); 
	mhfree(mh); 
	poperror(); 
1990/05313    
	if(new) 
		poperror(); 
1990/03091    
	incref(m); 
	return nc; 
} 
1990/0511/sys/src/9/gnot/devmnt.c:364,3951990/05313/sys/src/9/gnot/devmnt.c:451,496
1990/03091    
} 
 
void	  
mntclose(Chan *c) 
1990/05313    
mntclunk(Chan *c, int t) 
1990/03091    
{ 
	Mnt *m; 
	Mnthdr *mh; 
1990/05313    
	MntQ *q; 
	int waserr; 
int ne = u->nerrlab; 
1990/03091    
 
	m = mntdev(c->dev, 0); 
	mh = mhalloc(); 
	if(waserror()){ 
		mhfree(mh); 
		nexterror(); 
	} 
	mh->thdr.type = Tclunk; 
1990/05313    
	mh->thdr.type = t; 
1990/03091    
	mh->thdr.fid = c->fid; 
	mntxmit(m, mh); 
1990/05313    
	waserr = 0; 
	if(waserror())		/* gotta clean up as if there wasn't */ 
		waserr = 1; 
	else 
		mntxmit(m, mh); 
1990/03091    
	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); 
	} 
1990/05313    
	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(); 
1990/03091    
	poperror(); 
} 
 
1990/05313    
void 
mntclose(Chan *c) 
{ 
	mntclunk(c, Tclunk); 
} 
 
1990/03091    
long 
mntreadwrite(Chan *c, void *vbuf, long n, int type) 
{ 
1990/0511/sys/src/9/gnot/devmnt.c:458,4781990/05313/sys/src/9/gnot/devmnt.c:559,565
1990/03091    
void	  
mntremove(Chan *c) 
{ 
	Mnt *m; 
	Mnthdr *mh; 
                 
	m = mntdev(c->dev, 0); 
	mh = mhalloc(); 
	if(waserror()){ 
		mhfree(mh); 
		nexterror(); 
	} 
1990/0312    
	decref(m); 
1990/03091    
	mh->thdr.type = Tremove; 
	mh->thdr.fid = c->fid; 
	mntxmit(m, mh); 
	mhfree(mh); 
	poperror(); 
1990/05313    
	mntclunk(c, Tremove); 
1990/03091    
} 
 
void 
1990/0511/sys/src/9/gnot/devmnt.c:550,5601990/05313/sys/src/9/gnot/devmnt.c:637,684
1990/03091    
} 
 
void 
1990/05313    
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 
1990/03091    
mntxmit(Mnt *m, Mnthdr *mh) 
{ 
	ulong n; 
	Mntbuf *mbr, *mbw; 
	Chan *mntpt, *msg; 
1990/05313    
	Mnthdr *w, *ow; 
	Chan *mntpt; 
	MntQ *q; 
	int qlocked; 
1990/03091    
 
	mbr = mballoc(); 
	mbw = mballoc(); 
1990/0511/sys/src/9/gnot/devmnt.c:564,5691990/05313/sys/src/9/gnot/devmnt.c:688,694
1990/03091    
		nexterror(); 
	} 
	n = convS2M(&mh->thdr, mbw->buf); 
1990/05313    
#ifdef	bit3 
1990/03091    
	/* 
1990/0511    
	 * Bit3 does its own multiplexing.  (Well, the file server does.) 
	 * The code is different enough that it's broken out separately here. 
1990/0511/sys/src/9/gnot/devmnt.c:582,5891990/05313/sys/src/9/gnot/devmnt.c:707,714
1990/03091    
		nexterror(); 
	} 
	if((*devtab[msg->type].write)(msg, mbw->buf, n) != n){ 
		pprint("short write in mntxmit\n"); 
		error(0, Egreg); 
1990/05313    
		print("short write in mntxmit\n"); 
		error(0, Eshortmsg); 
1990/03091    
	} 
 
	/* 
1990/0511/sys/src/9/gnot/devmnt.c:594,6011990/05313/sys/src/9/gnot/devmnt.c:719,726
1990/0511    
	poperror(); 
 
	if(convM2S(mbr->buf, &mh->rhdr, n) == 0){ 
		pprint("format error in mntxmit\n"); 
		error(0, Egreg); 
1990/05313    
		print("format error in mntxmit\n"); 
		error(0, Ebadmsg); 
1990/0511    
	} 
 
	/* 
1990/0511/sys/src/9/gnot/devmnt.c:602,6131990/05313/sys/src/9/gnot/devmnt.c:727,738
1990/0511    
	 * 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); 
1990/05313    
		print("type mismatch %d %d\n", mh->rhdr.type, mh->thdr.type+1); 
		error(0, Ebadmsg); 
1990/0511    
	} 
	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); 
1990/05313    
		print("fid mismatch %d %d type %d\n", mh->rhdr.fid, mh->thdr.fid, mh->rhdr.type); 
		error(0, Ebadmsg); 
1990/0511    
	} 
	if(mh->rhdr.err){ 
		mntpt = m->mntpt;	/* unsafe, but Errors are unsafe anyway */ 
1990/0511/sys/src/9/gnot/devmnt.c:627,6721990/05313/sys/src/9/gnot/devmnt.c:752,851
1990/0511    
	return; 
 
    Normal: 
	qlock(m); 
	if((msg = m->msg) == 0){ 
1990/03091    
		qunlock(m); 
1990/05313    
#endif 
	q = m->q; 
	if(q == 0) 
1990/0511    
		error(0, Eshutdown); 
	} 
	qlock(msg); 
1990/05313    
	incref(q); 
	qlock(q); 
	qlocked = 1; 
1990/0511    
	if(waserror()){ 
		qunlock(m); 
1990/03091    
		qunlock(msg); 
1990/05313    
		if(qlocked) 
			qunlock(q); 
		mqfree(q); 
1990/0511    
		nexterror(); 
1990/03091    
	} 
1990/0511    
	if((*devtab[msg->type].write)(msg, mbw->buf, n) != n){ 
		pprint("short write in mntxmit\n"); 
		error(0, Egreg); 
1990/05313    
	if((*devtab[q->msg->type].write)(q->msg, mbw->buf, n) != n){ 
		print("short write in mntxmit\n"); 
		error(0, Eshortmsg); 
1990/0511    
	} 
                 
	/* 
	 * Read response 
	 */ 
	n = (*devtab[msg->type].read)(msg, mbr->buf, BUFSIZE); 
	qunlock(m); 
	qunlock(msg); 
1990/03091    
	poperror(); 
                 
	if(convM2S(mbr->buf, &mh->rhdr, n) == 0){ 
		pprint("format error in mntxmit\n"); 
		error(0, Egreg); 
1990/05313    
	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; 
1990/03091    
	} 
 
	/* 
	 * 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); 
	} 
1990/05313    
    Respond: 
	mqfree(q); 
	poperror(); 
1990/03091    
	if(mh->rhdr.err){ 
		mntpt = m->mntpt;	/* unsafe, but Errors are unsafe anyway */ 
		if(mntpt) 
1990/05313/sys/src/9/gnot/devmnt.c:688,7121990/0604/sys/src/9/gnot/devmnt.c:688,710 (short | long)
1990/03091    
		nexterror(); 
	} 
	n = convS2M(&mh->thdr, mbw->buf); 
1990/05313    
#ifdef	bit3 
1990/0604    
	q = m->q; 
	if(q == 0) 
		error(0, Eshutdown); 
#ifdef	BIT3 
1990/03091    
	/* 
1990/0511    
	 * Bit3 does its own multiplexing.  (Well, the file server does.) 
	 * The code is different enough that it's broken out separately here. 
1990/03091    
	 */ 
1990/0511    
	if(devchar[m->msg->type] != '3') 
1990/0604    
	if(devchar[q->msg->type] != '3') 
1990/0511    
		goto Normal; 
	lock(&m->use);		/* spin rather than sleep */ 
	if((msg = m->msg) == 0){ 
1990/03091    
		unlock(&m->use); 
1990/0511    
		error(0, Eshutdown); 
1990/03091    
	} 
1990/0511    
	incref(msg); 
	unlock(&m->use); 
1990/0604    
 
	incref(q); 
1990/03091    
	if(waserror()){ 
1990/0511    
		close(msg); 
1990/0604    
		mqfree(q); 
1990/03091    
		nexterror(); 
	} 
	if((*devtab[msg->type].write)(msg, mbw->buf, n) != n){ 
1990/0604    
	if((*devtab[q->msg->type].write)(q->msg, mbw->buf, n) != n){ 
1990/05313    
		print("short write in mntxmit\n"); 
		error(0, Eshortmsg); 
1990/03091    
	} 
1990/05313/sys/src/9/gnot/devmnt.c:714,7211990/0604/sys/src/9/gnot/devmnt.c:712,719
1990/03091    
	/* 
	 * Read response 
	 */ 
	n = (*devtab[msg->type].read)(msg, mbr->buf, BUFSIZE); 
1990/0511    
	close(msg); 
1990/0604    
	n = (*devtab[q->msg->type].read)(q->msg, mbr->buf, BUFSIZE); 
	mqfree(q); 
1990/0511    
	poperror(); 
 
	if(convM2S(mbr->buf, &mh->rhdr, n) == 0){ 
1990/05313/sys/src/9/gnot/devmnt.c:753,7611990/0604/sys/src/9/gnot/devmnt.c:751,756
1990/0511    
 
    Normal: 
1990/05313    
#endif 
	q = m->q; 
	if(q == 0) 
1990/0511    
		error(0, Eshutdown); 
1990/05313    
	incref(q); 
	qlock(q); 
	qlocked = 1; 
1990/0604/sys/src/9/gnot/devmnt.c:167,1721990/0605/sys/src/9/gnot/devmnt.c:167,173 (short | long)
1990/05313    
 
	lock(mq); 
	if(--mq->ref == 0){ 
1990/0605    
print("mqfree\n"); 
1990/05313    
		msg = mq->msg; 
		mq->msg = 0; 
		lock(&mntqalloc); 
1990/0604/sys/src/9/gnot/devmnt.c:644,6491990/0605/sys/src/9/gnot/devmnt.c:645,651
1990/05313    
	qlock(q); 
	/* take self from queue if necessary */ 
	if(q->reader == u->p){	/* advance a writer to reader */ 
1990/0605    
print("err: reader\n"); 
1990/05313    
		w = q->writer; 
		if(w){ 
			q->reader = w->p; 
1990/0604/sys/src/9/gnot/devmnt.c:654,6591990/0605/sys/src/9/gnot/devmnt.c:656,662
1990/05313    
			q->writer = 0; 
		} 
	}else{ 
1990/0605    
print("err: writer\n"); 
1990/05313    
		w = q->writer; 
		if(w == mh) 
			q->writer = w->next; 
1990/0605/sys/src/9/gnot/devmnt.c:65,701990/0617/sys/src/9/gnot/devmnt.c:65,71 (short | long)
1990/03091    
struct 
{ 
	Lock; 
1990/0617    
	QLock; 
1990/05313    
	MntQ	*arena; 
	MntQ	*free; 
}mntqalloc; 
1990/0605/sys/src/9/gnot/devmnt.c:141,1621990/0617/sys/src/9/gnot/devmnt.c:142,162
1990/03091    
} 
 
1990/05313    
MntQ* 
mqalloc(void) 
1990/0617    
mqalloc(Chan *msg)	/* mntqalloc is qlocked */ 
1990/05313    
{ 
	MntQ *q; 
 
	lock(&mntqalloc); 
	if(q = mntqalloc.free){		/* assign = */ 
		mntqalloc.free = q->next; 
		unlock(&mntqalloc); 
		lock(q); 
		q->ref = 1; 
1990/0617    
		q->msg = msg; 
		unlock(q); 
		incref(msg); 
1990/05313    
		q->writer = 0; 
		q->reader = 0; 
		unlock(q); 
		return q; 
	} 
	unlock(&mntqalloc); 
	panic("no mntqs\n");			/* there MUST be enough */ 
} 
 
1990/0605/sys/src/9/gnot/devmnt.c:167,1731990/0617/sys/src/9/gnot/devmnt.c:167,173
1990/05313    
 
	lock(mq); 
	if(--mq->ref == 0){ 
1990/0605    
print("mqfree\n"); 
1990/0617    
print("mqfree %lux %lux\n", mq->reader, mq->writer); 
1990/05313    
		msg = mq->msg; 
		mq->msg = 0; 
		lock(&mntqalloc); 
1990/0605/sys/src/9/gnot/devmnt.c:272,2771990/0617/sys/src/9/gnot/devmnt.c:272,278
1990/05313    
	 * Look for queue to same msg channel 
	 */ 
	q = mntqalloc.arena; 
1990/0617    
	qlock(&mntqalloc); 
1990/05313    
	for(i=0; i<conf.nmntdev; i++,q++) 
		if(q->msg==cm){ 
			lock(q); 
1990/0605/sys/src/9/gnot/devmnt.c:283,2931990/0617/sys/src/9/gnot/devmnt.c:284,293
1990/05313    
			} 
			unlock(q); 
		} 
	m->q = mqalloc(); 
	m->q->msg = cm; 
1990/03091    
	incref(cm); 
1990/0617    
	m->q = mqalloc(cm); 
1990/05313    
 
    out: 
1990/0617    
	qunlock(&mntqalloc); 
1990/03091    
	mh = mhalloc(); 
	if(waserror()){ 
		mhfree(mh); 
1990/0605/sys/src/9/gnot/devmnt.c:645,6511990/0617/sys/src/9/gnot/devmnt.c:645,650
1990/05313    
	qlock(q); 
	/* take self from queue if necessary */ 
	if(q->reader == u->p){	/* advance a writer to reader */ 
1990/0605    
print("err: reader\n"); 
1990/05313    
		w = q->writer; 
		if(w){ 
			q->reader = w->p; 
1990/0605/sys/src/9/gnot/devmnt.c:656,6621990/0617/sys/src/9/gnot/devmnt.c:655,660
1990/05313    
			q->writer = 0; 
		} 
	}else{ 
1990/0605    
print("err: writer\n"); 
1990/05313    
		w = q->writer; 
		if(w == mh) 
			q->writer = w->next; 
1990/0605/sys/src/9/gnot/devmnt.c:774,7801990/0617/sys/src/9/gnot/devmnt.c:772,778
1990/05313    
		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"); 
1990/0617    
			print("%lux %lux %lux %d format error in mntxmit %s\n", u->p, q->reader, q->writer, n, u->p->text); 
1990/05313    
			mnterrdequeue(q, mh); 
			error(0, Ebadmsg); 
		} 
1990/0605/sys/src/9/gnot/devmnt.c:798,8041990/0617/sys/src/9/gnot/devmnt.c:796,802
1990/05313    
		/* 
		 * Hand response to correct recipient 
		 */ 
if(q->writer == 0) print("response with empty queue\n"); 
1990/0617    
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); 
1990/05313    
		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){ 
1990/0605/sys/src/9/gnot/devmnt.c:825,8311990/0617/sys/src/9/gnot/devmnt.c:823,829
1990/05313    
		qunlock(q); 
		qlocked = 0; 
		if(waserror()){		/* interrupted sleep */ 
			print("interrupted i/o\n"); 
1990/0617    
			print("%lux interrupted i/o %d %d\n", u->p, mh->thdr.type, mh->thdr.fid); 
1990/05313    
			mnterrdequeue(q, mh); 
			nexterror(); 
		} 
1990/0617/sys/src/9/gnot/devmnt.c:167,1731990/0619/sys/src/9/gnot/devmnt.c:167,172 (short | long)
1990/05313    
 
	lock(mq); 
	if(--mq->ref == 0){ 
1990/0617    
print("mqfree %lux %lux\n", mq->reader, mq->writer); 
1990/05313    
		msg = mq->msg; 
		mq->msg = 0; 
		lock(&mntqalloc); 
1990/0617/sys/src/9/gnot/devmnt.c:675,6901990/0619/sys/src/9/gnot/devmnt.c:674,689
1990/03091    
mntxmit(Mnt *m, Mnthdr *mh) 
{ 
	ulong n; 
	Mntbuf *mbr, *mbw; 
1990/0619    
	Mntbuf *mbw; 
1990/05313    
	Mnthdr *w, *ow; 
	Chan *mntpt; 
	MntQ *q; 
	int qlocked; 
1990/03091    
 
	mbr = mballoc(); 
1990/0619    
	mh->mbr = mballoc(); 
1990/03091    
	mbw = mballoc(); 
	if(waserror()){ 
		mbfree(mbr); 
1990/0619    
		mbfree(mh->mbr); 
1990/03091    
		mbfree(mbw); 
		nexterror(); 
	} 
1990/0617/sys/src/9/gnot/devmnt.c:713,7231990/0619/sys/src/9/gnot/devmnt.c:712,722
1990/03091    
	/* 
	 * Read response 
	 */ 
1990/0604    
	n = (*devtab[q->msg->type].read)(q->msg, mbr->buf, BUFSIZE); 
1990/0619    
	n = (*devtab[q->msg->type].read)(q->msg, mh->mbr->buf, BUFSIZE); 
1990/0604    
	mqfree(q); 
1990/0511    
	poperror(); 
 
	if(convM2S(mbr->buf, &mh->rhdr, n) == 0){ 
1990/0619    
	if(convM2S(mh->mbr->buf, &mh->rhdr, n) == 0){ 
1990/05313    
		print("format error in mntxmit\n"); 
		error(0, Ebadmsg); 
1990/0511    
	} 
1990/0617/sys/src/9/gnot/devmnt.c:745,7511990/0619/sys/src/9/gnot/devmnt.c:744,750
1990/0511    
	 */ 
	if(mh->thdr.type == Tread) 
		memcpy(mh->thdr.data, mh->rhdr.data, mh->rhdr.count); 
	mbfree(mbr); 
1990/0619    
	mbfree(mh->mbr); 
1990/0511    
	mbfree(mbw); 
	poperror(); 
	return; 
1990/0617/sys/src/9/gnot/devmnt.c:770,7781990/0619/sys/src/9/gnot/devmnt.c:769,777
1990/05313    
    Read: 
		qunlock(q); 
		qlocked = 0; 
		n = (*devtab[q->msg->type].read)(q->msg, mbr->buf, BUFSIZE); 
		if(convM2S(mbr->buf, &mh->rhdr, n) == 0){ 
1990/0617    
			print("%lux %lux %lux %d format error in mntxmit %s\n", u->p, q->reader, q->writer, n, u->p->text); 
1990/0619    
		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"); 
1990/05313    
			mnterrdequeue(q, mh); 
			error(0, Ebadmsg); 
		} 
1990/0617/sys/src/9/gnot/devmnt.c:796,8081990/0619/sys/src/9/gnot/devmnt.c:795,807
1990/05313    
		/* 
		 * Hand response to correct recipient 
		 */ 
1990/0617    
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); 
1990/0619    
		if(q->writer==0) print("response with empty queue\n"); 
1990/05313    
		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; 
1990/0619    
				t = mh->mbr; 
				mh->mbr = w->mbr; 
1990/05313    
				w->mbr = t; 
				memcpy(&w->rhdr, &mh->rhdr, sizeof mh->rhdr); 
				/* take recipient from queue */ 
1990/0617/sys/src/9/gnot/devmnt.c:815,8211990/0619/sys/src/9/gnot/devmnt.c:814,819
1990/05313    
			} 
		goto Read; 
	}else{ 
		mh->mbr = mbr; 
		mh->p = u->p; 
		/* put self in queue */ 
		mh->next = q->writer; 
1990/0617/sys/src/9/gnot/devmnt.c:823,8291990/0619/sys/src/9/gnot/devmnt.c:821,827
1990/05313    
		qunlock(q); 
		qlocked = 0; 
		if(waserror()){		/* interrupted sleep */ 
1990/0617    
			print("%lux interrupted i/o %d %d\n", u->p, mh->thdr.type, mh->thdr.fid); 
1990/0619    
			print("interrupted i/o\n"); 
1990/05313    
			mnterrdequeue(q, mh); 
			nexterror(); 
		} 
1990/0617/sys/src/9/gnot/devmnt.c:833,8391990/0619/sys/src/9/gnot/devmnt.c:831,836
1990/05313    
		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; 
1990/0617/sys/src/9/gnot/devmnt.c:853,8591990/0619/sys/src/9/gnot/devmnt.c:850,856
1990/03091    
	 */ 
	if(mh->thdr.type == Tread) 
		memcpy(mh->thdr.data, mh->rhdr.data, mh->rhdr.count); 
	mbfree(mbr); 
1990/0619    
	mbfree(mh->mbr); 
1990/03091    
	mbfree(mbw); 
	poperror(); 
} 
1990/0619/sys/src/9/gnot/devmnt.c:771,7771990/0620/sys/src/9/gnot/devmnt.c:771,776 (short | long)
1990/05313    
		qlocked = 0; 
1990/0619    
		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"); 
1990/05313    
			mnterrdequeue(q, mh); 
			error(0, Ebadmsg); 
		} 
1990/0619/sys/src/9/gnot/devmnt.c:795,8011990/0620/sys/src/9/gnot/devmnt.c:794,799
1990/05313    
		/* 
		 * Hand response to correct recipient 
		 */ 
1990/0619    
		if(q->writer==0) print("response with empty queue\n"); 
1990/05313    
		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){ 
1990/0619/sys/src/9/gnot/devmnt.c:821,8271990/0620/sys/src/9/gnot/devmnt.c:819,824
1990/05313    
		qunlock(q); 
		qlocked = 0; 
		if(waserror()){		/* interrupted sleep */ 
1990/0619    
			print("interrupted i/o\n"); 
1990/05313    
			mnterrdequeue(q, mh); 
			nexterror(); 
		} 
1990/0620/sys/src/9/gnot/devmnt.c:769,7751990/0703/sys/src/9/gnot/devmnt.c:769,780 (short | long)
1990/05313    
    Read: 
		qunlock(q); 
		qlocked = 0; 
1990/0703    
		if(waserror()){ 
			mnterrdequeue(q, mh); 
			nexterror(); 
		} 
1990/0619    
		n = (*devtab[q->msg->type].read)(q->msg, mh->mbr->buf, BUFSIZE); 
1990/0703    
		poperror(); 
1990/0619    
		if(convM2S(mh->mbr->buf, &mh->rhdr, n) == 0){ 
1990/05313    
			mnterrdequeue(q, mh); 
			error(0, Ebadmsg); 
1990/0620/sys/src/9/gnot/devmnt.c:845,8521990/0703/sys/src/9/gnot/devmnt.c:850,860
1990/03091    
	/* 
	 * Copy out on read 
	 */ 
	if(mh->thdr.type == Tread) 
1990/0703    
	if(mh->thdr.type == Tread){ 
		if(mh->rhdr.count > mh->thdr.count) 
			error(0, Ebadcnt); 
1990/03091    
		memcpy(mh->thdr.data, mh->rhdr.data, mh->rhdr.count); 
1990/0703    
	} 
1990/0619    
	mbfree(mh->mbr); 
1990/03091    
	mbfree(mbw); 
	poperror(); 
1990/0703/sys/src/9/gnot/devmnt.c:859,8611990/0707/sys/src/9/gnot/devmnt.c:859,880 (short | long)
1990/03091    
	mbfree(mbw); 
	poperror(); 
} 
1990/0707    
 
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"); 
	} 
} 
1990/0707/sys/src/9/gnot/devmnt.c:54,591990/0717/sys/src/9/gnot/devmnt.c:54,60 (short | long)
1990/05313    
	Rendez	r; 
	Proc	*p; 
	Mntbuf	*mbr; 
1990/0717    
	int	readreply;	/* true if we are reader or our reply has come */ 
1990/03091    
}; 
 
struct 
1990/0707/sys/src/9/gnot/devmnt.c:670,6751990/0717/sys/src/9/gnot/devmnt.c:671,681
1990/05313    
	qunlock(q); 
 
} 
1990/0717    
int 
mntreadreply(void *a) 
{ 
	return ((Mnthdr *)a)->readreply; 
} 
1990/05313    
void 
1990/03091    
mntxmit(Mnt *m, Mnthdr *mh) 
{ 
1990/0707/sys/src/9/gnot/devmnt.c:760,7651990/0717/sys/src/9/gnot/devmnt.c:766,772
1990/05313    
		mqfree(q); 
1990/0511    
		nexterror(); 
1990/03091    
	} 
1990/0717    
	mh->readreply = 0; 
1990/05313    
	if((*devtab[q->msg->type].write)(q->msg, mbw->buf, n) != n){ 
		print("short write in mntxmit\n"); 
		error(0, Eshortmsg); 
1990/0707/sys/src/9/gnot/devmnt.c:790,7951990/0717/sys/src/9/gnot/devmnt.c:797,803
1990/05313    
			if(w = q->writer){	/* advance a writer to reader */ 
				q->reader = w->p; 
				q->writer = w->next; 
1990/0717    
				w->readreply = 1; 
1990/05313    
				wakeup(&w->r); 
			} 
			qunlock(q); 
1990/0707/sys/src/9/gnot/devmnt.c:812,8171990/0717/sys/src/9/gnot/devmnt.c:820,826
1990/05313    
					q->writer = w->next; 
				else 
					ow->next = w->next; 
1990/0717    
				w->readreply = 1; 
1990/05313    
				wakeup(&w->r); 
				goto Read; 
			} 
1990/0707/sys/src/9/gnot/devmnt.c:827,8331990/0717/sys/src/9/gnot/devmnt.c:836,842
1990/05313    
			mnterrdequeue(q, mh); 
			nexterror(); 
		} 
		sleep(&mh->r, return0, 0); 
1990/0717    
		sleep(&mh->r, mntreadreply, mh); 
1990/05313    
		poperror(); 
		qlock(q); 
		qlocked = 1; 
1990/0717/sys/src/9/gnot/devmnt.c:291,2971990/0725/sys/src/9/gnot/devmnt.c:291,296 (short | long)
1990/03091    
	mh = mhalloc(); 
	if(waserror()){ 
		mhfree(mh); 
1990/05313    
		mqfree(q); 
1990/03091    
		close(c); 
		nexterror(); 
	} 
1990/0725/sys/src/9/gnot/devmnt.c:291,2961990/0726/sys/src/9/gnot/devmnt.c:291,297 (short | long)
1990/03091    
	mh = mhalloc(); 
	if(waserror()){ 
		mhfree(mh); 
1990/0726    
		mqfree(q); 
1990/03091    
		close(c); 
		nexterror(); 
	} 
1990/0726/sys/src/9/gnot/devmnt.c:291,2971990/0728/sys/src/9/gnot/devmnt.c:291,296 (short | long)
1990/03091    
	mh = mhalloc(); 
	if(waserror()){ 
		mhfree(mh); 
1990/0726    
		mqfree(q); 
1990/03091    
		close(c); 
		nexterror(); 
	} 
1990/0728/sys/src/9/gnot/devmnt.c:9,151990/11211/sys/src/9/gnot/devmnt.c:9,14 (short | long)
1990/03091    
 
#include	"fcall.h" 
 
                 
typedef struct Mnt	Mnt; 
1990/05313    
typedef struct Mnthdr	Mnthdr; 
typedef struct MntQ	MntQ; 
1990/0728/sys/src/9/gnot/devmnt.c:194,2001990/11211/sys/src/9/gnot/devmnt.c:193,199
1990/03091    
		} 
	if(noerr) 
		return 0; 
	error(0, Eshutdown); 
1990/11211    
	error(Eshutdown); 
1990/03091    
} 
 
void 
1990/0728/sys/src/9/gnot/devmnt.c:214,2221990/11211/sys/src/9/gnot/devmnt.c:213,224
1990/03091    
	mntbufalloc.free = mb; 
 
	mh = ialloc(conf.nmnthdr*sizeof(Mnthdr), 0); 
	for(i=0; i<conf.nmnthdr-1; i++) 
1990/11211    
	for(i=0; i<conf.nmnthdr-1; i++){ 
1990/03091    
		mh[i].next = &mh[i+1]; 
1990/11211    
		mh[i].thdr.tag = i; 
	} 
1990/03091    
	mh[i].next = 0; 
1990/11211    
	mh[i].thdr.tag = i; 
1990/03091    
	mnthdralloc.free = mh; 
1990/05313    
 
	mq = ialloc(conf.nmntdev*sizeof(MntQ), 0); 
1990/0728/sys/src/9/gnot/devmnt.c:233,2391990/11211/sys/src/9/gnot/devmnt.c:235,241
1990/03091    
} 
 
Chan* 
mntattach(char *spec) 
1990/11211    
mntattach(char *crud) 
1990/03091    
{ 
	int i; 
1990/05313    
	Mnt *m, *mm; 
1990/0728/sys/src/9/gnot/devmnt.c:243,2521990/11211/sys/src/9/gnot/devmnt.c:245,254
1990/03091    
	struct bogus{ 
		Chan	*chan; 
		char	*spec; 
1990/11211    
		char	*auth; 
1990/03091    
	}bogus; 
 
	bogus = *((struct bogus *)spec); 
	spec = bogus.spec; 
1990/11211    
	bogus = *((struct bogus *)crud); 
1990/03091    
 
	m = mnt; 
	for(i=0; i<conf.nmntdev; i++,m++){ 
1990/0728/sys/src/9/gnot/devmnt.c:255,2611990/11211/sys/src/9/gnot/devmnt.c:257,263
1990/03091    
			goto Found; 
		unlock(m); 
	} 
	error(0, Enomntdev); 
1990/11211    
	error(Enomntdev); 
1990/05313    
 
1990/03091    
    Found: 
	m->ref = 1; 
1990/0728/sys/src/9/gnot/devmnt.c:263,2691990/11211/sys/src/9/gnot/devmnt.c:265,271
1990/03091    
	lock(&mntid); 
	m->mntid = ++mntid.id; 
	unlock(&mntid); 
	c = devattach('M', spec); 
1990/11211    
	c = devattach('M', bogus.spec); 
1990/03091    
	c->dev = m->mntid; 
	m->mntpt = c; 
	cm = bogus.chan; 
1990/0728/sys/src/9/gnot/devmnt.c:297,3031990/11211/sys/src/9/gnot/devmnt.c:299,306
1990/03091    
	mh->thdr.type = Tattach; 
	mh->thdr.fid = c->fid; 
	memcpy(mh->thdr.uname, u->p->pgrp->user, NAMELEN); 
	strcpy(mh->thdr.aname, spec); 
1990/11211    
	strcpy(mh->thdr.aname, bogus.spec); 
	strcpy(mh->thdr.auth, bogus.auth); 
1990/03091    
	mntxmit(m, mh); 
	c->qid = mh->rhdr.qid; 
1990/05313    
	c->mchan = m->q->msg; 
1990/0728/sys/src/9/gnot/devmnt.c:537,5431990/11211/sys/src/9/gnot/devmnt.c:540,546
1990/03091    
	uchar *b; 
 
	n = mntreadwrite(c, buf, n, Tread); 
	if(c->qid & CHDIR){ 
1990/11211    
	if(c->qid.path & CHDIR){ 
1990/03091    
		b = (uchar*)buf; 
		for(i=n-DIRLEN; i>=0; i-=DIRLEN){ 
			b[DIRLEN-4] = devchar[c->type]; 
1990/0728/sys/src/9/gnot/devmnt.c:582,6411990/11211/sys/src/9/gnot/devmnt.c:585,590
1990/03091    
	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 
1990/05313    
mnterrdequeue(MntQ *q, Mnthdr *mh)		/* queue is unlocked */ 
{ 
1990/0728/sys/src/9/gnot/devmnt.c:670,6801990/11211/sys/src/9/gnot/devmnt.c:619,631
1990/05313    
	qunlock(q); 
 
} 
1990/11211    
 
1990/0717    
int 
mntreadreply(void *a) 
{ 
	return ((Mnthdr *)a)->readreply; 
} 
1990/11211    
 
1990/05313    
void 
1990/03091    
mntxmit(Mnt *m, Mnthdr *mh) 
{ 
1990/0728/sys/src/9/gnot/devmnt.c:681,6871990/11211/sys/src/9/gnot/devmnt.c:632,637
1990/03091    
	ulong n; 
1990/0619    
	Mntbuf *mbw; 
1990/05313    
	Mnthdr *w, *ow; 
	Chan *mntpt; 
	MntQ *q; 
	int qlocked; 
1990/03091    
 
1990/0728/sys/src/9/gnot/devmnt.c:695,7011990/11211/sys/src/9/gnot/devmnt.c:645,651
1990/03091    
	n = convS2M(&mh->thdr, mbw->buf); 
1990/0604    
	q = m->q; 
	if(q == 0) 
		error(0, Eshutdown); 
1990/11211    
		error(Eshutdown); 
1990/0604    
#ifdef	BIT3 
1990/03091    
	/* 
1990/0511    
	 * Bit3 does its own multiplexing.  (Well, the file server does.) 
1990/0728/sys/src/9/gnot/devmnt.c:711,7171990/11211/sys/src/9/gnot/devmnt.c:661,667
1990/03091    
	} 
1990/0604    
	if((*devtab[q->msg->type].write)(q->msg, mbw->buf, n) != n){ 
1990/05313    
		print("short write in mntxmit\n"); 
		error(0, Eshortmsg); 
1990/11211    
		error(Eshortmsg); 
1990/03091    
	} 
 
	/* 
1990/0728/sys/src/9/gnot/devmnt.c:723,7481990/11211/sys/src/9/gnot/devmnt.c:673,701
1990/0511    
 
1990/0619    
	if(convM2S(mh->mbr->buf, &mh->rhdr, n) == 0){ 
1990/05313    
		print("format error in mntxmit\n"); 
		error(0, Ebadmsg); 
1990/11211    
		error(Ebadmsg); 
1990/0511    
	} 
 
	/* 
	 * Various checks 
	 */ 
1990/11211    
	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); 
	} 
1990/0511    
	if(mh->rhdr.type != mh->thdr.type+1){ 
1990/05313    
		print("type mismatch %d %d\n", mh->rhdr.type, mh->thdr.type+1); 
		error(0, Ebadmsg); 
1990/11211    
		error(Ebadmsg); 
1990/0511    
	} 
	if(mh->rhdr.fid != mh->thdr.fid){ 
1990/05313    
		print("fid mismatch %d %d type %d\n", mh->rhdr.fid, mh->thdr.fid, mh->rhdr.type); 
		error(0, Ebadmsg); 
1990/11211    
		error(Ebadmsg); 
1990/0511    
	} 
	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 
1990/0728/sys/src/9/gnot/devmnt.c:768,7741990/11211/sys/src/9/gnot/devmnt.c:721,727
1990/0717    
	mh->readreply = 0; 
1990/05313    
	if((*devtab[q->msg->type].write)(q->msg, mbw->buf, n) != n){ 
		print("short write in mntxmit\n"); 
		error(0, Eshortmsg); 
1990/11211    
		error(Eshortmsg); 
1990/0511    
	} 
1990/05313    
	if(q->reader == 0){		/* i will read */ 
		q->reader = u->p; 
1990/0728/sys/src/9/gnot/devmnt.c:783,7891990/11211/sys/src/9/gnot/devmnt.c:736,742
1990/0703    
		poperror(); 
1990/0619    
		if(convM2S(mh->mbr->buf, &mh->rhdr, n) == 0){ 
1990/05313    
			mnterrdequeue(q, mh); 
			error(0, Ebadmsg); 
1990/11211    
			error(Ebadmsg); 
1990/05313    
		} 
		/* 
		 * Response might not be mine 
1990/0728/sys/src/9/gnot/devmnt.c:790,7971990/11211/sys/src/9/gnot/devmnt.c:743,749
1990/05313    
		 */ 
		qlock(q); 
		qlocked = 1; 
		if(mh->rhdr.fid == mh->thdr.fid 
		&& mh->rhdr.type == mh->thdr.type+1){	/* it's mine */ 
1990/11211    
		if(mh->rhdr.tag == mh->thdr.tag){	/* it's mine */ 
1990/05313    
			q->reader = 0; 
			if(w = q->writer){	/* advance a writer to reader */ 
				q->reader = w->p; 
1990/0728/sys/src/9/gnot/devmnt.c:807,8141990/11211/sys/src/9/gnot/devmnt.c:759,765
1990/05313    
		 * Hand response to correct recipient 
		 */ 
		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){ 
1990/11211    
			if(mh->rhdr.tag == w->thdr.tag){ 
1990/05313    
				Mntbuf *t; 
1990/0619    
				t = mh->mbr; 
				mh->mbr = w->mbr; 
1990/0728/sys/src/9/gnot/devmnt.c:849,8591990/11211/sys/src/9/gnot/devmnt.c:800,809
1990/05313    
    Respond: 
	mqfree(q); 
	poperror(); 
1990/03091    
	if(mh->rhdr.err){ 
		mntpt = m->mntpt;	/* unsafe, but Errors are unsafe anyway */ 
		if(mntpt) 
			error(mntpt, mh->rhdr.err); 
		error(0, Eshutdown); 
1990/11211    
	if(mh->rhdr.type == Rerror){ 
		if(m->mntpt) 
			errors(mh->rhdr.ename); 
		error(Eshutdown); 
1990/03091    
	} 
	/* 
	 * Copy out on read 
1990/0728/sys/src/9/gnot/devmnt.c:860,8661990/11211/sys/src/9/gnot/devmnt.c:810,816
1990/03091    
	 */ 
1990/0703    
	if(mh->thdr.type == Tread){ 
		if(mh->rhdr.count > mh->thdr.count) 
			error(0, Ebadcnt); 
1990/11211    
			error(Ebadcnt); 
1990/03091    
		memcpy(mh->thdr.data, mh->rhdr.data, mh->rhdr.count); 
1990/0703    
	} 
1990/0619    
	mbfree(mh->mbr); 
1990/11211/sys/src/9/gnot/devmnt.c:47,531990/1123/sys/src/9/gnot/devmnt.c:47,55 (short | long)
1990/03091    
 
1990/05313    
struct Mnthdr 
1990/03091    
{ 
1990/05313    
	Mnthdr	*next;	/* in free list or writers list */ 
1990/1123    
	Mnthdr	*next;		/* in free list or writers list */ 
	Mnthdr	*prev;		/* in writers list only */ 
	int	writing;	/* flag: in writers list */ 
1990/03091    
	Fcall	thdr; 
	Fcall	rhdr; 
1990/05313    
	Rendez	r; 
1990/11211/sys/src/9/gnot/devmnt.c:59,641990/1123/sys/src/9/gnot/devmnt.c:61,67
1990/03091    
struct 
{ 
	Lock; 
1990/1123    
	Mnthdr	*arena; 
1990/03091    
	Mnthdr	*free; 
}mnthdralloc; 
 
1990/11211/sys/src/9/gnot/devmnt.c:219,2241990/1123/sys/src/9/gnot/devmnt.c:222,228
1990/11211    
	} 
1990/03091    
	mh[i].next = 0; 
1990/11211    
	mh[i].thdr.tag = i; 
1990/1123    
	mnthdralloc.arena = mh; 
1990/03091    
	mnthdralloc.free = mh; 
1990/05313    
 
	mq = ialloc(conf.nmntdev*sizeof(MntQ), 0); 
1990/11211/sys/src/9/gnot/devmnt.c:586,5931990/1123/sys/src/9/gnot/devmnt.c:590,612
1990/03091    
} 
 
void 
1990/05313    
mnterrdequeue(MntQ *q, Mnthdr *mh)		/* queue is unlocked */ 
1990/1123    
mntwunlink(MntQ *q, Mnthdr *w)		/* queue is locked and w is a writer */ 
1990/05313    
{ 
1990/1123    
	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 */ 
{ 
1990/05313    
	Mnthdr *w; 
 
	qlock(q); 
1990/11211/sys/src/9/gnot/devmnt.c:597,6211990/1123/sys/src/9/gnot/devmnt.c:616,629
1990/05313    
		if(w){ 
			q->reader = w->p; 
			q->writer = w->next; 
1990/1123    
			q->writer->prev = 0; 
1990/05313    
			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; 
			} 
		} 
	} 
1990/1123    
	}else 
		mntwunlink(q, mh); 
1990/05313    
	qunlock(q); 
 
} 
1990/11211/sys/src/9/gnot/devmnt.c:630,6391990/1123/sys/src/9/gnot/devmnt.c:638,647
1990/03091    
mntxmit(Mnt *m, Mnthdr *mh) 
{ 
	ulong n; 
1990/0619    
	Mntbuf *mbw; 
1990/1123    
	Mntbuf *mbw, *t; 
1990/05313    
	Mnthdr *w, *ow; 
	MntQ *q; 
	int qlocked; 
1990/1123    
	int qlocked, tag; 
1990/03091    
 
1990/0619    
	mh->mbr = mballoc(); 
1990/03091    
	mbw = mballoc(); 
1990/11211/sys/src/9/gnot/devmnt.c:743,7531990/1123/sys/src/9/gnot/devmnt.c:751,764
1990/05313    
		 */ 
		qlock(q); 
		qlocked = 1; 
1990/11211    
		if(mh->rhdr.tag == mh->thdr.tag){	/* it's mine */ 
1990/1123    
		tag = mh->rhdr.tag; 
		if(tag == mh->thdr.tag){	/* it's mine */ 
1990/05313    
			q->reader = 0; 
			if(w = q->writer){	/* advance a writer to reader */ 
				q->reader = w->p; 
				q->writer = w->next; 
1990/1123    
				if(q->writer) 
					q->writer->prev = 0; 
1990/0717    
				w->readreply = 1; 
1990/05313    
				wakeup(&w->r); 
			} 
1990/11211/sys/src/9/gnot/devmnt.c:758,7841990/1123/sys/src/9/gnot/devmnt.c:769,799
1990/05313    
		/* 
		 * Hand response to correct recipient 
		 */ 
		for(ow=0,w=q->writer; w; ow=w,w=w->next) 
1990/11211    
			if(mh->rhdr.tag == w->thdr.tag){ 
1990/05313    
				Mntbuf *t; 
1990/0619    
				t = mh->mbr; 
				mh->mbr = w->mbr; 
1990/05313    
				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; 
1990/0717    
				w->readreply = 1; 
1990/05313    
				wakeup(&w->r); 
				goto Read; 
			} 
1990/1123    
		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); 
1990/05313    
		goto Read; 
	}else{ 
		mh->p = u->p; 
		/* put self in queue */ 
		mh->next = q->writer; 
1990/1123    
		mh->prev = 0; 
		mh->writing = 1; 
		if(q->writer) 
			q->writer->prev = mh; 
1990/05313    
		q->writer = mh; 
		qunlock(q); 
		qlocked = 0; 
1990/1123/sys/src/9/gnot/devmnt.c:49,551990/1124/sys/src/9/gnot/devmnt.c:49,56 (short | long)
1990/03091    
{ 
1990/1123    
	Mnthdr	*next;		/* in free list or writers list */ 
	Mnthdr	*prev;		/* in writers list only */ 
	int	writing;	/* flag: in writers list */ 
1990/1124    
	short	active; 
	short	flushing;	/* a Tflush has been sent */ 
1990/03091    
	Fcall	thdr; 
	Fcall	rhdr; 
1990/05313    
	Rendez	r; 
1990/1123/sys/src/9/gnot/devmnt.c:122,1271990/1124/sys/src/9/gnot/devmnt.c:123,129
1990/03091    
	lock(&mnthdralloc); 
	if(mh = mnthdralloc.free){		/* assign = */ 
		mnthdralloc.free = mh->next; 
1990/1124    
		mh->flushing = 0; 
1990/03091    
		unlock(&mnthdralloc); 
		return mh; 
	} 
1990/1123/sys/src/9/gnot/devmnt.c:138,1431990/1124/sys/src/9/gnot/devmnt.c:140,148
1990/03091    
void 
mhfree(Mnthdr *mh) 
{ 
1990/1124    
	if(mh->flushing) 
		return; 
	mh->active = 0; 
1990/03091    
	lock(&mnthdralloc); 
	mh->next = mnthdralloc.free; 
	mnthdralloc.free = mh; 
1990/1123/sys/src/9/gnot/devmnt.c:601,6221990/1124/sys/src/9/gnot/devmnt.c:606,654
1990/1123    
		if(q->writer) 
			q->writer->prev = 0; 
	} 
	w->writing = 0; 
} 
 
1990/1124    
/* 
 * m->q is unlocked.  Send Tflush message to flush omh->tag. 
 * Cut off all errors.   Caller will free omh 
 */ 
1990/1123    
void 
mnterrdequeue(MntQ *q, Mnthdr *mh)	/* queue is unlocked */ 
1990/1124    
mntflush(Mnt *m, Mnthdr *omh)	/* queue is unlocked */ 
1990/1123    
{ 
1990/1124    
	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 */ 
{ 
1990/05313    
	Mnthdr *w; 
1990/1124    
	MntQ *q; 
1990/05313    
 
1990/1124    
	mh->flushing = 1; 
	q = m->q; 
1990/05313    
	qlock(q); 
	/* take self from queue if necessary */ 
	if(q->reader == u->p){	/* advance a writer to reader */ 
		w = q->writer; 
		if(w){ 
1990/1124    
			mntwunlink(q, w); 
1990/05313    
			q->reader = w->p; 
			q->writer = w->next; 
1990/1123    
			q->writer->prev = 0; 
1990/05313    
			wakeup(&w->r); 
		}else{ 
			q->reader = 0; 
1990/1123/sys/src/9/gnot/devmnt.c:625,6311990/1124/sys/src/9/gnot/devmnt.c:657,663
1990/1123    
	}else 
		mntwunlink(q, mh); 
1990/05313    
	qunlock(q); 
                 
1990/1124    
	mntflush(m, mh); 
1990/05313    
} 
1990/11211    
 
1990/0717    
int 
1990/1123/sys/src/9/gnot/devmnt.c:641,6511990/1124/sys/src/9/gnot/devmnt.c:673,683
1990/1123    
	Mntbuf *mbw, *t; 
1990/05313    
	Mnthdr *w, *ow; 
	MntQ *q; 
1990/1123    
	int qlocked, tag; 
1990/1124    
	int qlocked, tag, written; 
1990/03091    
 
1990/0619    
	mh->mbr = mballoc(); 
1990/03091    
	mbw = mballoc(); 
	if(waserror()){ 
1990/1124    
	if(waserror()){			/* 1 */ 
1990/0619    
		mbfree(mh->mbr); 
1990/03091    
		mbfree(mbw); 
		nexterror(); 
1990/1123/sys/src/9/gnot/devmnt.c:663,6691990/1124/sys/src/9/gnot/devmnt.c:695,701
1990/0511    
		goto Normal; 
1990/0604    
 
	incref(q); 
1990/03091    
	if(waserror()){ 
1990/1124    
	if(waserror()){		/* 2 */ 
1990/0604    
		mqfree(q); 
1990/03091    
		nexterror(); 
	} 
1990/1123/sys/src/9/gnot/devmnt.c:677,6831990/1124/sys/src/9/gnot/devmnt.c:709,715
1990/03091    
	 */ 
1990/0619    
	n = (*devtab[q->msg->type].read)(q->msg, mh->mbr->buf, BUFSIZE); 
1990/0604    
	mqfree(q); 
1990/0511    
	poperror(); 
1990/1124    
	poperror();		/* 2 */ 
1990/0511    
 
1990/0619    
	if(convM2S(mh->mbr->buf, &mh->rhdr, n) == 0){ 
1990/05313    
		print("format error in mntxmit\n"); 
1990/1123/sys/src/9/gnot/devmnt.c:712,7181990/1124/sys/src/9/gnot/devmnt.c:744,750
1990/0511    
		memcpy(mh->thdr.data, mh->rhdr.data, mh->rhdr.count); 
1990/0619    
	mbfree(mh->mbr); 
1990/0511    
	mbfree(mbw); 
	poperror(); 
1990/1124    
	poperror();		/* 1 */ 
1990/0511    
	return; 
 
    Normal: 
1990/1123/sys/src/9/gnot/devmnt.c:720,7261990/1124/sys/src/9/gnot/devmnt.c:752,758
1990/05313    
	incref(q); 
	qlock(q); 
	qlocked = 1; 
1990/0511    
	if(waserror()){ 
1990/1124    
	if(waserror()){		/* 2 */ 
1990/05313    
		if(qlocked) 
			qunlock(q); 
		mqfree(q); 
1990/1123/sys/src/9/gnot/devmnt.c:727,7321990/1124/sys/src/9/gnot/devmnt.c:759,765
1990/0511    
		nexterror(); 
1990/03091    
	} 
1990/0717    
	mh->readreply = 0; 
1990/1124    
	mh->active = 1; 
1990/05313    
	if((*devtab[q->msg->type].write)(q->msg, mbw->buf, n) != n){ 
		print("short write in mntxmit\n"); 
1990/11211    
		error(Eshortmsg); 
1990/1123/sys/src/9/gnot/devmnt.c:736,7491990/1124/sys/src/9/gnot/devmnt.c:769,783
1990/05313    
    Read: 
		qunlock(q); 
		qlocked = 0; 
1990/0703    
		if(waserror()){ 
			mnterrdequeue(q, mh); 
1990/1124    
		if(waserror()){		/* 3 */ 
			mnterrdequeue(m, mh); 
1990/0703    
			nexterror(); 
		} 
1990/0619    
		n = (*devtab[q->msg->type].read)(q->msg, mh->mbr->buf, BUFSIZE); 
1990/0703    
		poperror(); 
1990/1124    
		poperror();		/* 3 */ 
1990/0619    
		if(convM2S(mh->mbr->buf, &mh->rhdr, n) == 0){ 
1990/05313    
			mnterrdequeue(q, mh); 
1990/1124    
			print("bad reply message\n"); 
			mnterrdequeue(m, mh); 
1990/11211    
			error(Ebadmsg); 
1990/05313    
		} 
		/* 
1990/1123/sys/src/9/gnot/devmnt.c:755,7671990/1124/sys/src/9/gnot/devmnt.c:789,800
1990/1123    
		if(tag == mh->thdr.tag){	/* it's mine */ 
1990/05313    
			q->reader = 0; 
			if(w = q->writer){	/* advance a writer to reader */ 
1990/1124    
				mntwunlink(q, w); 
1990/05313    
				q->reader = w->p; 
				q->writer = w->next; 
1990/1123    
				if(q->writer) 
					q->writer->prev = 0; 
1990/0717    
				w->readreply = 1; 
1990/05313    
				wakeup(&w->r); 
			} 
1990/1124    
			mh->active = 0; 
1990/05313    
			qunlock(q); 
			qlocked = 0; 
			goto Respond; 
1990/1123/sys/src/9/gnot/devmnt.c:774,7831990/1124/sys/src/9/gnot/devmnt.c:807,814
1990/1123    
			goto Read; 
		} 
		w = &mnthdralloc.arena[tag]; 
		if(!w->writing){ 
			print("reply not writing\n"); 
1990/1124    
		if(w->flushing || !w->active)	/* nothing to do; mntflush will clean up */ 
1990/1123    
			goto Read; 
		} 
		t = mh->mbr; 
		mh->mbr = w->mbr; 
		w->mbr = t; 
1990/1123/sys/src/9/gnot/devmnt.c:791,7971990/1124/sys/src/9/gnot/devmnt.c:822,827
1990/05313    
		/* put self in queue */ 
		mh->next = q->writer; 
1990/1123    
		mh->prev = 0; 
		mh->writing = 1; 
		if(q->writer) 
			q->writer->prev = mh; 
1990/05313    
		q->writer = mh; 
1990/1123/sys/src/9/gnot/devmnt.c:798,8041990/1124/sys/src/9/gnot/devmnt.c:828,834
1990/05313    
		qunlock(q); 
		qlocked = 0; 
		if(waserror()){		/* interrupted sleep */ 
			mnterrdequeue(q, mh); 
1990/1124    
			mnterrdequeue(m, mh); 
1990/05313    
			nexterror(); 
		} 
1990/0717    
		sleep(&mh->r, mntreadreply, mh); 
1990/1123/sys/src/9/gnot/devmnt.c:807,8121990/1124/sys/src/9/gnot/devmnt.c:837,843
1990/05313    
		qlocked = 1; 
		if(q->reader == u->p)	/* i got promoted */ 
			goto Read; 
1990/1124    
		mh->active = 0; 
1990/05313    
		qunlock(q); 
		qlocked = 0; 
		goto Respond; 
1990/1123/sys/src/9/gnot/devmnt.c:814,8241990/1124/sys/src/9/gnot/devmnt.c:845,858
1990/03091    
 
1990/05313    
    Respond: 
	mqfree(q); 
	poperror(); 
1990/1124    
	poperror();		/* 2 */ 
1990/11211    
	if(mh->rhdr.type == Rerror){ 
		if(m->mntpt) 
			errors(mh->rhdr.ename); 
		error(Eshutdown); 
1990/1124    
	}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); 
1990/03091    
	} 
	/* 
	 * Copy out on read 
1990/1123/sys/src/9/gnot/devmnt.c:830,8361990/1124/sys/src/9/gnot/devmnt.c:864,870
1990/0703    
	} 
1990/0619    
	mbfree(mh->mbr); 
1990/03091    
	mbfree(mbw); 
	poperror(); 
1990/1124    
	poperror();		/* 1 */ 
1990/03091    
} 
1990/0707    
 
mntdump() 
1990/1124/sys/src/9/gnot/devmnt.c:469,4751990/1126/sys/src/9/gnot/devmnt.c:469,474 (short | long)
1990/03091    
	Mnthdr *mh; 
1990/05313    
	MntQ *q; 
	int waserr; 
int ne = u->nerrlab; 
1990/03091    
 
	m = mntdev(c->dev, 0); 
	mh = mhalloc(); 
1990/1126/sys/src/9/gnot/devmnt.c:669,6831990/1127/sys/src/9/gnot/devmnt.c:669,684 (short | long)
1990/03091    
mntxmit(Mnt *m, Mnthdr *mh) 
{ 
	ulong n; 
1990/1123    
	Mntbuf *mbw, *t; 
1990/1127    
	Mntbuf *mbw; 
1990/05313    
	Mnthdr *w, *ow; 
	MntQ *q; 
1990/1124    
	int qlocked, tag, written; 
1990/03091    
 
1990/0619    
	mh->mbr = mballoc(); 
1990/1127    
	mh->mbr = 0; 
1990/03091    
	mbw = mballoc(); 
1990/1124    
	if(waserror()){			/* 1 */ 
1990/0619    
		mbfree(mh->mbr); 
1990/1127    
		if(mh->mbr) 
			mbfree(mh->mbr); 
1990/03091    
		mbfree(mbw); 
		nexterror(); 
	} 
1990/1126/sys/src/9/gnot/devmnt.c:706,7111990/1127/sys/src/9/gnot/devmnt.c:707,713
1990/03091    
	/* 
	 * Read response 
	 */ 
1990/1127    
	mh->mbr = mballoc(); 
1990/0619    
	n = (*devtab[q->msg->type].read)(q->msg, mh->mbr->buf, BUFSIZE); 
1990/0604    
	mqfree(q); 
1990/1124    
	poperror();		/* 2 */ 
1990/1126/sys/src/9/gnot/devmnt.c:772,7771990/1127/sys/src/9/gnot/devmnt.c:774,780
1990/1124    
			mnterrdequeue(m, mh); 
1990/0703    
			nexterror(); 
		} 
1990/1127    
		mh->mbr = mballoc(); 
1990/0619    
		n = (*devtab[q->msg->type].read)(q->msg, mh->mbr->buf, BUFSIZE); 
1990/1124    
		poperror();		/* 3 */ 
1990/0619    
		if(convM2S(mh->mbr->buf, &mh->rhdr, n) == 0){ 
1990/1126/sys/src/9/gnot/devmnt.c:808,8161990/1127/sys/src/9/gnot/devmnt.c:811,818
1990/1123    
		w = &mnthdralloc.arena[tag]; 
1990/1124    
		if(w->flushing || !w->active)	/* nothing to do; mntflush will clean up */ 
1990/1123    
			goto Read; 
		t = mh->mbr; 
		mh->mbr = w->mbr; 
		w->mbr = t; 
1990/1127    
		w->mbr = mh->mbr; 
		mh->mbr = 0; 
1990/1123    
		memcpy(&w->rhdr, &mh->rhdr, sizeof mh->rhdr); 
		mntwunlink(q, w); 
		w->readreply = 1; 
1990/1127/sys/src/9/gnot/devmnt.c:1,8881990/1210/sys/src/9/gnot/devmnt.c:0 (short | long)
Deleted.
rsc Mon Mar 7 10:21:41 2005
1990/03091    
#include	"u.h" 
#include	"lib.h" 
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"errno.h" 
                 
#include	"devtab.h" 
                 
#include	"fcall.h" 
                 
typedef struct Mnt	Mnt; 
1990/05313    
typedef struct Mnthdr	Mnthdr; 
typedef struct MntQ	MntQ; 
                 
1990/03091    
struct Mnt 
{ 
	Ref;			/* for number of chans, incl. mntpt but not msg */ 
	ulong	mntid;		/* serial # */ 
	Chan	*mntpt;		/* channel in user's name space */ 
1990/05313    
	MntQ	*q; 
1990/03091    
}; 
                 
1990/05313    
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 */ 
}; 
                 
1990/03091    
#define	BUFSIZE	(MAXFDATA+500) 	/* BUG */ 
typedef struct Mntbuf Mntbuf; 
struct Mntbuf 
{ 
	Mntbuf	*next; 
	char	buf[BUFSIZE]; 
}; 
                 
struct 
{ 
	Lock; 
	Mntbuf	*free; 
}mntbufalloc; 
                 
1990/05313    
struct Mnthdr 
1990/03091    
{ 
1990/1123    
	Mnthdr	*next;		/* in free list or writers list */ 
	Mnthdr	*prev;		/* in writers list only */ 
1990/1124    
	short	active; 
	short	flushing;	/* a Tflush has been sent */ 
1990/03091    
	Fcall	thdr; 
	Fcall	rhdr; 
1990/05313    
	Rendez	r; 
	Proc	*p; 
	Mntbuf	*mbr; 
1990/0717    
	int	readreply;	/* true if we are reader or our reply has come */ 
1990/03091    
}; 
                 
struct 
{ 
	Lock; 
1990/1123    
	Mnthdr	*arena; 
1990/03091    
	Mnthdr	*free; 
}mnthdralloc; 
                 
struct 
{ 
	Lock; 
1990/0617    
	QLock; 
1990/05313    
	MntQ	*arena; 
	MntQ	*free; 
}mntqalloc; 
                 
struct 
{ 
	Lock; 
1990/03091    
	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; 
1990/1124    
		mh->flushing = 0; 
1990/03091    
		unlock(&mnthdralloc); 
		return mh; 
	} 
	unlock(&mnthdralloc); 
	print("no mnthdrs\n"); 
	if(u == 0) 
1990/05313    
		panic("mhalloc"); 
1990/03091    
	u->p->state = Wakeme; 
	alarm(1000, wakeme, u->p); 
	sched(); 
	goto loop; 
} 
                 
void 
mhfree(Mnthdr *mh) 
{ 
1990/1124    
	if(mh->flushing) 
		return; 
	mh->active = 0; 
1990/03091    
	lock(&mnthdralloc); 
	mh->next = mnthdralloc.free; 
	mnthdralloc.free = mh; 
	unlock(&mnthdralloc); 
} 
                 
1990/05313    
MntQ* 
1990/0617    
mqalloc(Chan *msg)	/* mntqalloc is qlocked */ 
1990/05313    
{ 
	MntQ *q; 
                 
	if(q = mntqalloc.free){		/* assign = */ 
		mntqalloc.free = q->next; 
		lock(q); 
		q->ref = 1; 
1990/0617    
		q->msg = msg; 
		unlock(q); 
		incref(msg); 
1990/05313    
		q->writer = 0; 
		q->reader = 0; 
		return q; 
	} 
	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); 
} 
                 
1990/03091    
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){ 
1990/05313    
			if(m->q == 0) 
1990/03091    
				break; 
			return m; 
		} 
	if(noerr) 
		return 0; 
1990/11211    
	error(Eshutdown); 
1990/03091    
} 
                 
void 
mntreset(void) 
{ 
	int i; 
	Mntbuf *mb; 
	Mnthdr *mh; 
1990/05313    
	MntQ *mq; 
1990/03091    
                 
	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); 
1990/11211    
	for(i=0; i<conf.nmnthdr-1; i++){ 
1990/03091    
		mh[i].next = &mh[i+1]; 
1990/11211    
		mh[i].thdr.tag = i; 
	} 
1990/03091    
	mh[i].next = 0; 
1990/11211    
	mh[i].thdr.tag = i; 
1990/1123    
	mnthdralloc.arena = mh; 
1990/03091    
	mnthdralloc.free = mh; 
1990/05313    
                 
	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; 
1990/03091    
} 
                 
void 
mntinit(void) 
{ 
} 
                 
Chan* 
1990/11211    
mntattach(char *crud) 
1990/03091    
{ 
	int i; 
1990/05313    
	Mnt *m, *mm; 
1990/03091    
	Mnthdr *mh; 
1990/05313    
	MntQ *q; 
1990/03091    
	Chan *c, *cm; 
	struct bogus{ 
		Chan	*chan; 
		char	*spec; 
1990/11211    
		char	*auth; 
1990/03091    
	}bogus; 
                 
1990/11211    
	bogus = *((struct bogus *)crud); 
1990/03091    
                 
	m = mnt; 
	for(i=0; i<conf.nmntdev; i++,m++){ 
		lock(m); 
		if(m->ref == 0) 
			goto Found; 
		unlock(m); 
	} 
1990/11211    
	error(Enomntdev); 
1990/05313    
                 
1990/03091    
    Found: 
	m->ref = 1; 
	unlock(m); 
	lock(&mntid); 
	m->mntid = ++mntid.id; 
	unlock(&mntid); 
1990/11211    
	c = devattach('M', bogus.spec); 
1990/03091    
	c->dev = m->mntid; 
	m->mntpt = c; 
	cm = bogus.chan; 
1990/05313    
                 
	/* 
	 * Look for queue to same msg channel 
	 */ 
	q = mntqalloc.arena; 
1990/0617    
	qlock(&mntqalloc); 
1990/05313    
	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); 
		} 
1990/0617    
	m->q = mqalloc(cm); 
1990/05313    
                 
    out: 
1990/0617    
	qunlock(&mntqalloc); 
1990/03091    
	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); 
1990/11211    
	strcpy(mh->thdr.aname, bogus.spec); 
	strcpy(mh->thdr.auth, bogus.auth); 
1990/03091    
	mntxmit(m, mh); 
	c->qid = mh->rhdr.qid; 
1990/05313    
	c->mchan = m->q->msg; 
1990/03091    
	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; 
	mhfree(mh); 
	poperror(); 
1990/05313    
	if(new) 
		poperror(); 
1990/03091    
	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	  
1990/05313    
mntclunk(Chan *c, int t) 
1990/03091    
{ 
	Mnt *m; 
	Mnthdr *mh; 
1990/05313    
	MntQ *q; 
	int waserr; 
1990/03091    
                 
	m = mntdev(c->dev, 0); 
	mh = mhalloc(); 
1990/05313    
	mh->thdr.type = t; 
1990/03091    
	mh->thdr.fid = c->fid; 
1990/05313    
	waserr = 0; 
	if(waserror())		/* gotta clean up as if there wasn't */ 
		waserr = 1; 
	else 
		mntxmit(m, mh); 
1990/03091    
	mhfree(mh); 
	if(c == m->mntpt) 
		m->mntpt = 0; 
1990/05313    
	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(); 
1990/03091    
	poperror(); 
} 
                 
1990/05313    
void 
mntclose(Chan *c) 
{ 
	mntclunk(c, Tclunk); 
} 
                 
1990/03091    
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); 
1990/11211    
	if(c->qid.path & CHDIR){ 
1990/03091    
		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) 
{ 
1990/05313    
	mntclunk(c, Tremove); 
1990/03091    
} 
                 
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 
1990/1123    
mntwunlink(MntQ *q, Mnthdr *w)		/* queue is locked and w is a writer */ 
1990/05313    
{ 
1990/1123    
	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; 
	} 
} 
                 
1990/1124    
/* 
 * m->q is unlocked.  Send Tflush message to flush omh->tag. 
 * Cut off all errors.   Caller will free omh 
 */ 
1990/1123    
void 
1990/1124    
mntflush(Mnt *m, Mnthdr *omh)	/* queue is unlocked */ 
1990/1123    
{ 
1990/1124    
	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 */ 
{ 
1990/05313    
	Mnthdr *w; 
1990/1124    
	MntQ *q; 
1990/05313    
                 
1990/1124    
	mh->flushing = 1; 
	q = m->q; 
1990/05313    
	qlock(q); 
	/* take self from queue if necessary */ 
	if(q->reader == u->p){	/* advance a writer to reader */ 
		w = q->writer; 
		if(w){ 
1990/1124    
			mntwunlink(q, w); 
1990/05313    
			q->reader = w->p; 
			wakeup(&w->r); 
		}else{ 
			q->reader = 0; 
			q->writer = 0; 
		} 
1990/1123    
	}else 
		mntwunlink(q, mh); 
1990/05313    
	qunlock(q); 
1990/1124    
	mntflush(m, mh); 
1990/05313    
} 
1990/11211    
                 
1990/0717    
int 
mntreadreply(void *a) 
{ 
	return ((Mnthdr *)a)->readreply; 
} 
1990/11211    
                 
1990/05313    
void 
1990/03091    
mntxmit(Mnt *m, Mnthdr *mh) 
{ 
	ulong n; 
1990/1127    
	Mntbuf *mbw; 
1990/05313    
	Mnthdr *w, *ow; 
	MntQ *q; 
1990/1124    
	int qlocked, tag, written; 
1990/03091    
                 
1990/1127    
	mh->mbr = 0; 
1990/03091    
	mbw = mballoc(); 
1990/1124    
	if(waserror()){			/* 1 */ 
1990/1127    
		if(mh->mbr) 
			mbfree(mh->mbr); 
1990/03091    
		mbfree(mbw); 
		nexterror(); 
	} 
	n = convS2M(&mh->thdr, mbw->buf); 
1990/0604    
	q = m->q; 
	if(q == 0) 
1990/11211    
		error(Eshutdown); 
1990/0604    
#ifdef	BIT3 
1990/03091    
	/* 
1990/0511    
	 * Bit3 does its own multiplexing.  (Well, the file server does.) 
	 * The code is different enough that it's broken out separately here. 
1990/03091    
	 */ 
1990/0604    
	if(devchar[q->msg->type] != '3') 
1990/0511    
		goto Normal; 
1990/0604    
                 
	incref(q); 
1990/1124    
	if(waserror()){		/* 2 */ 
1990/0604    
		mqfree(q); 
1990/03091    
		nexterror(); 
	} 
1990/0604    
	if((*devtab[q->msg->type].write)(q->msg, mbw->buf, n) != n){ 
1990/05313    
		print("short write in mntxmit\n"); 
1990/11211    
		error(Eshortmsg); 
1990/03091    
	} 
                 
	/* 
	 * Read response 
	 */ 
1990/1127    
	mh->mbr = mballoc(); 
1990/0619    
	n = (*devtab[q->msg->type].read)(q->msg, mh->mbr->buf, BUFSIZE); 
1990/0604    
	mqfree(q); 
1990/1124    
	poperror();		/* 2 */ 
1990/0511    
                 
1990/0619    
	if(convM2S(mh->mbr->buf, &mh->rhdr, n) == 0){ 
1990/05313    
		print("format error in mntxmit\n"); 
1990/11211    
		error(Ebadmsg); 
1990/0511    
	} 
                 
	/* 
	 * Various checks 
	 */ 
1990/11211    
	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); 
	} 
1990/0511    
	if(mh->rhdr.type != mh->thdr.type+1){ 
1990/05313    
		print("type mismatch %d %d\n", mh->rhdr.type, mh->thdr.type+1); 
1990/11211    
		error(Ebadmsg); 
1990/0511    
	} 
	if(mh->rhdr.fid != mh->thdr.fid){ 
1990/05313    
		print("fid mismatch %d %d type %d\n", mh->rhdr.fid, mh->thdr.fid, mh->rhdr.type); 
1990/11211    
		error(Ebadmsg); 
1990/0511    
	} 
                 
	/* 
	 * Copy out on read 
	 */ 
	if(mh->thdr.type == Tread) 
		memcpy(mh->thdr.data, mh->rhdr.data, mh->rhdr.count); 
1990/0619    
	mbfree(mh->mbr); 
1990/0511    
	mbfree(mbw); 
1990/1124    
	poperror();		/* 1 */ 
1990/0511    
	return; 
                 
    Normal: 
1990/05313    
#endif 
	incref(q); 
	qlock(q); 
	qlocked = 1; 
1990/1124    
	if(waserror()){		/* 2 */ 
1990/05313    
		if(qlocked) 
			qunlock(q); 
		mqfree(q); 
1990/0511    
		nexterror(); 
1990/03091    
	} 
1990/0717    
	mh->readreply = 0; 
1990/1124    
	mh->active = 1; 
1990/05313    
	if((*devtab[q->msg->type].write)(q->msg, mbw->buf, n) != n){ 
		print("short write in mntxmit\n"); 
1990/11211    
		error(Eshortmsg); 
1990/0511    
	} 
1990/05313    
	if(q->reader == 0){		/* i will read */ 
		q->reader = u->p; 
    Read: 
		qunlock(q); 
		qlocked = 0; 
1990/1124    
		if(waserror()){		/* 3 */ 
			mnterrdequeue(m, mh); 
1990/0703    
			nexterror(); 
		} 
1990/1127    
		mh->mbr = mballoc(); 
1990/0619    
		n = (*devtab[q->msg->type].read)(q->msg, mh->mbr->buf, BUFSIZE); 
1990/1124    
		poperror();		/* 3 */ 
1990/0619    
		if(convM2S(mh->mbr->buf, &mh->rhdr, n) == 0){ 
1990/1124    
			print("bad reply message\n"); 
			mnterrdequeue(m, mh); 
1990/11211    
			error(Ebadmsg); 
1990/05313    
		} 
		/* 
		 * Response might not be mine 
		 */ 
		qlock(q); 
		qlocked = 1; 
1990/1123    
		tag = mh->rhdr.tag; 
		if(tag == mh->thdr.tag){	/* it's mine */ 
1990/05313    
			q->reader = 0; 
			if(w = q->writer){	/* advance a writer to reader */ 
1990/1124    
				mntwunlink(q, w); 
1990/05313    
				q->reader = w->p; 
1990/0717    
				w->readreply = 1; 
1990/05313    
				wakeup(&w->r); 
			} 
1990/1124    
			mh->active = 0; 
1990/05313    
			qunlock(q); 
			qlocked = 0; 
			goto Respond; 
		} 
		/* 
		 * Hand response to correct recipient 
		 */ 
1990/1123    
		if(tag<0 || tag>=conf.nmnthdr){ 
			print("unknown tag %d\n", tag); 
			goto Read; 
		} 
		w = &mnthdralloc.arena[tag]; 
1990/1124    
		if(w->flushing || !w->active)	/* nothing to do; mntflush will clean up */ 
1990/1123    
			goto Read; 
1990/1127    
		w->mbr = mh->mbr; 
		mh->mbr = 0; 
1990/1123    
		memcpy(&w->rhdr, &mh->rhdr, sizeof mh->rhdr); 
		mntwunlink(q, w); 
		w->readreply = 1; 
		wakeup(&w->r); 
1990/05313    
		goto Read; 
	}else{ 
		mh->p = u->p; 
		/* put self in queue */ 
		mh->next = q->writer; 
1990/1123    
		mh->prev = 0; 
		if(q->writer) 
			q->writer->prev = mh; 
1990/05313    
		q->writer = mh; 
		qunlock(q); 
		qlocked = 0; 
		if(waserror()){		/* interrupted sleep */ 
1990/1124    
			mnterrdequeue(m, mh); 
1990/05313    
			nexterror(); 
		} 
1990/0717    
		sleep(&mh->r, mntreadreply, mh); 
1990/05313    
		poperror(); 
		qlock(q); 
		qlocked = 1; 
		if(q->reader == u->p)	/* i got promoted */ 
			goto Read; 
1990/1124    
		mh->active = 0; 
1990/05313    
		qunlock(q); 
		qlocked = 0; 
		goto Respond; 
1990/03091    
	} 
                 
1990/05313    
    Respond: 
	mqfree(q); 
1990/1124    
	poperror();		/* 2 */ 
1990/11211    
	if(mh->rhdr.type == Rerror){ 
		if(m->mntpt) 
			errors(mh->rhdr.ename); 
		error(Eshutdown); 
1990/1124    
	}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); 
1990/03091    
	} 
	/* 
	 * Copy out on read 
	 */ 
1990/0703    
	if(mh->thdr.type == Tread){ 
		if(mh->rhdr.count > mh->thdr.count) 
1990/11211    
			error(Ebadcnt); 
1990/03091    
		memcpy(mh->thdr.data, mh->rhdr.data, mh->rhdr.count); 
1990/0703    
	} 
1990/0619    
	mbfree(mh->mbr); 
1990/03091    
	mbfree(mbw); 
1990/1124    
	poperror();		/* 1 */ 
1990/03091    
} 
1990/0707    
                 
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"); 
	} 
} 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)