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

1990/0604/port/devmnt.c (diff list | history)

1990/0513/sys/src/9/port/devmnt.c:9,281990/0604/sys/src/9/port/devmnt.c:9,37 (short | long | prev | next)
1990/0227    
 
#include	"fcall.h" 
 
/* 
 * Easy version: multiple sessions but no intra-session multiplexing, copy the data 
 */ 
 
typedef struct Mnt	Mnt; 
1990/0604    
typedef struct Mnthdr	Mnthdr; 
typedef struct MntQ	MntQ; 
 
1990/0227    
struct Mnt 
{ 
	Ref;			/* for number of chans, incl. mntpt but not msg */ 
1990/0324    
	QLock;			/* for access */ 
1990/0303    
	ulong	mntid;		/* serial # */ 
1990/0227    
	Chan	*msg;		/* for reading and writing messages */ 
	Chan	*mntpt;		/* channel in user's name space */ 
1990/0604    
	MntQ	*q; 
1990/0227    
}; 
 
1990/0604    
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/0227    
#define	BUFSIZE	(MAXFDATA+500) 	/* BUG */ 
typedef struct Mntbuf Mntbuf; 
struct Mntbuf 
1990/0513/sys/src/9/port/devmnt.c:37,481990/0604/sys/src/9/port/devmnt.c:46,59
1990/0227    
	Mntbuf	*free; 
}mntbufalloc; 
 
typedef struct Mnthdr Mnthdr; 
struct Mnthdr		/* next only meaningful when buffer isn't being used */ 
1990/0604    
struct Mnthdr 
1990/0227    
{ 
	Mnthdr	*next; 
1990/0604    
	Mnthdr	*next;	/* in free list or writers list */ 
1990/0227    
	Fcall	thdr; 
	Fcall	rhdr; 
1990/0604    
	Rendez	r; 
	Proc	*p; 
	Mntbuf	*mbr; 
1990/0227    
}; 
 
struct 
1990/0513/sys/src/9/port/devmnt.c:54,591990/0604/sys/src/9/port/devmnt.c:65,77
1990/0303    
struct 
{ 
	Lock; 
1990/0604    
	MntQ	*arena; 
	MntQ	*free; 
}mntqalloc; 
 
struct 
{ 
	Lock; 
1990/0303    
	long	id; 
}mntid; 
 
1990/0513/sys/src/9/port/devmnt.c:106,1121990/0604/sys/src/9/port/devmnt.c:124,130
1990/0227    
	unlock(&mnthdralloc); 
	print("no mnthdrs\n"); 
	if(u == 0) 
		panic("mballoc"); 
1990/0604    
		panic("mhalloc"); 
1990/0227    
	u->p->state = Wakeme; 
	alarm(1000, wakeme, u->p); 
	sched(); 
1990/0513/sys/src/9/port/devmnt.c:122,1271990/0604/sys/src/9/port/devmnt.c:140,184
1990/0227    
	unlock(&mnthdralloc); 
} 
 
1990/0604    
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/0227    
Mnt* 
mntdev(int dev, int noerr) 
{ 
1990/0513/sys/src/9/port/devmnt.c:130,1361990/0604/sys/src/9/port/devmnt.c:187,193
1990/0227    
 
1990/0303    
	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/0604    
			if(m->q == 0) 
1990/0303    
				break; 
			return m; 
		} 
1990/0513/sys/src/9/port/devmnt.c:145,1501990/0604/sys/src/9/port/devmnt.c:202,208
1990/0227    
	int i; 
	Mntbuf *mb; 
	Mnthdr *mh; 
1990/0604    
	MntQ *mq; 
1990/0227    
 
	mnt = ialloc(conf.nmntdev*sizeof(Mnt), 0); 
 
1990/0513/sys/src/9/port/devmnt.c:159,1641990/0604/sys/src/9/port/devmnt.c:217,229
1990/0227    
		mh[i].next = &mh[i+1]; 
	mh[i].next = 0; 
	mnthdralloc.free = mh; 
1990/0604    
 
	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/0227    
} 
 
void 
1990/0513/sys/src/9/port/devmnt.c:170,1771990/0604/sys/src/9/port/devmnt.c:235,243
1990/0227    
mntattach(char *spec) 
{ 
	int i; 
	Mnt *m; 
1990/0604    
	Mnt *m, *mm; 
1990/0227    
	Mnthdr *mh; 
1990/0604    
	MntQ *q; 
1990/0227    
	Chan *c, *cm; 
	struct bogus{ 
		Chan	*chan; 
1990/0513/sys/src/9/port/devmnt.c:189,1941990/0604/sys/src/9/port/devmnt.c:255,261
1990/0227    
		unlock(m); 
	} 
	error(0, Enomntdev); 
1990/0604    
 
1990/0227    
    Found: 
	m->ref = 1; 
	unlock(m); 
1990/0513/sys/src/9/port/devmnt.c:199,2091990/0604/sys/src/9/port/devmnt.c:266,296
1990/0303    
	c->dev = m->mntid; 
1990/0227    
	m->mntpt = c; 
	cm = bogus.chan; 
	m->msg = cm; 
1990/0604    
 
	/* 
	 * 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/0227    
	incref(cm); 
1990/0604    
 
    out: 
1990/0227    
	mh = mhalloc(); 
	if(waserror()){ 
		mhfree(mh); 
1990/0604    
		mqfree(q); 
1990/0227    
		close(c); 
		nexterror(); 
	} 
1990/0513/sys/src/9/port/devmnt.c:213,2191990/0604/sys/src/9/port/devmnt.c:300,306
1990/0227    
	strcpy(mh->thdr.aname, spec); 
	mntxmit(m, mh); 
	c->qid = mh->rhdr.qid; 
1990/0303    
	c->mchan = m->msg; 
1990/0604    
	c->mchan = m->q->msg; 
1990/0303    
	c->mqid = c->qid; 
1990/0227    
	mhfree(mh); 
	poperror(); 
1990/0513/sys/src/9/port/devmnt.c:364,3951990/0604/sys/src/9/port/devmnt.c:451,496
1990/0227    
} 
 
void	  
mntclose(Chan *c) 
1990/0604    
mntclunk(Chan *c, int t) 
1990/0227    
{ 
	Mnt *m; 
	Mnthdr *mh; 
1990/0604    
	MntQ *q; 
	int waserr; 
int ne = u->nerrlab; 
1990/0227    
 
	m = mntdev(c->dev, 0); 
	mh = mhalloc(); 
	if(waserror()){ 
		mhfree(mh); 
		nexterror(); 
	} 
	mh->thdr.type = Tclunk; 
1990/0604    
	mh->thdr.type = t; 
1990/0227    
	mh->thdr.fid = c->fid; 
	mntxmit(m, mh); 
1990/0604    
	waserr = 0; 
	if(waserror())		/* gotta clean up as if there wasn't */ 
		waserr = 1; 
	else 
		mntxmit(m, mh); 
1990/0227    
	mhfree(mh); 
	if(c == m->mntpt) 
		m->mntpt = 0; 
	if(decref(m) == 0){		/* BUG: need to hang up all pending i/o */ 
1990/0324    
		qlock(m); 
1990/0227    
		close(m->msg); 
		m->msg = 0; 
1990/0324    
		qunlock(m); 
1990/0227    
	} 
1990/0604    
	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/0227    
	poperror(); 
} 
 
1990/0604    
void 
mntclose(Chan *c) 
{ 
	mntclunk(c, Tclunk); 
} 
 
1990/0227    
long 
mntreadwrite(Chan *c, void *vbuf, long n, int type) 
{ 
1990/0513/sys/src/9/port/devmnt.c:458,4781990/0604/sys/src/9/port/devmnt.c:559,565
1990/0227    
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/0227    
	mh->thdr.type = Tremove; 
	mh->thdr.fid = c->fid; 
	mntxmit(m, mh); 
	mhfree(mh); 
	poperror(); 
1990/0604    
	mntclunk(c, Tremove); 
1990/0227    
} 
 
void 
1990/0513/sys/src/9/port/devmnt.c:550,5601990/0604/sys/src/9/port/devmnt.c:637,684
1990/0227    
} 
 
void 
1990/0604    
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/0227    
mntxmit(Mnt *m, Mnthdr *mh) 
{ 
	ulong n; 
	Mntbuf *mbr, *mbw; 
1990/03081    
	Chan *mntpt, *msg; 
1990/0604    
	Mnthdr *w, *ow; 
	Chan *mntpt; 
	MntQ *q; 
	int qlocked; 
1990/0227    
 
	mbr = mballoc(); 
	mbw = mballoc(); 
1990/0513/sys/src/9/port/devmnt.c:564,6011990/0604/sys/src/9/port/devmnt.c:688,724
1990/0227    
		nexterror(); 
	} 
	n = convS2M(&mh->thdr, mbw->buf); 
1990/0604    
	q = m->q; 
	if(q == 0) 
		error(0, Eshutdown); 
#ifdef	BIT3 
1990/03081    
	/* 
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/03081    
	 */ 
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/0324    
		unlock(&m->use); 
1990/0511    
		error(0, Eshutdown); 
1990/03081    
	} 
1990/0511    
	incref(msg); 
	unlock(&m->use); 
1990/0604    
 
	incref(q); 
1990/0227    
	if(waserror()){ 
1990/0511    
		close(msg); 
1990/0604    
		mqfree(q); 
1990/0227    
		nexterror(); 
	} 
1990/03081    
	if((*devtab[msg->type].write)(msg, mbw->buf, n) != n){ 
1990/0227    
		pprint("short write in mntxmit\n"); 
		error(0, Egreg); 
1990/0604    
	if((*devtab[q->msg->type].write)(q->msg, mbw->buf, n) != n){ 
		print("short write in mntxmit\n"); 
		error(0, Eshortmsg); 
1990/0227    
	} 
 
	/* 
	 * Read response 
	 */ 
1990/03081    
	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){ 
		pprint("format error in mntxmit\n"); 
		error(0, Egreg); 
1990/0604    
		print("format error in mntxmit\n"); 
		error(0, Ebadmsg); 
1990/0511    
	} 
 
	/* 
1990/0513/sys/src/9/port/devmnt.c:602,6131990/0604/sys/src/9/port/devmnt.c:725,736
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/0604    
		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/0604    
		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/0513/sys/src/9/port/devmnt.c:627,6721990/0604/sys/src/9/port/devmnt.c:750,846
1990/0511    
	return; 
 
    Normal: 
	qlock(m); 
	if((msg = m->msg) == 0){ 
1990/0324    
		qunlock(m); 
1990/0511    
		error(0, Eshutdown); 
	} 
	qlock(msg); 
1990/0604    
#endif 
	incref(q); 
	qlock(q); 
	qlocked = 1; 
1990/0511    
	if(waserror()){ 
		qunlock(m); 
1990/03081    
		qunlock(msg); 
1990/0604    
		if(qlocked) 
			qunlock(q); 
		mqfree(q); 
1990/0511    
		nexterror(); 
1990/03081    
	} 
1990/0511    
	if((*devtab[msg->type].write)(msg, mbw->buf, n) != n){ 
		pprint("short write in mntxmit\n"); 
		error(0, Egreg); 
1990/0604    
	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/0227    
	poperror(); 
                 
	if(convM2S(mbr->buf, &mh->rhdr, n) == 0){ 
		pprint("format error in mntxmit\n"); 
		error(0, Egreg); 
1990/0604    
	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/0227    
	} 
 
	/* 
	 * 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/0604    
    Respond: 
	mqfree(q); 
	poperror(); 
1990/0227    
	if(mh->rhdr.err){ 
		mntpt = m->mntpt;	/* unsafe, but Errors are unsafe anyway */ 
		if(mntpt) 


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