shithub: drawterm

Download patch

ref: 823eea4c3d7da44cd4b2a27aa53cc16c7c67680b
parent: c6f547e1a46ebbf7a290427fe3a0b66932d671a0
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Oct 3 13:58:44 EDT 2021

chan: minimize differences with 9front...

--- a/kern/chan.c
+++ b/kern/chan.c
@@ -441,6 +441,12 @@
 		c = nc;
 	}
 
+	if(c->umh != nil){	//BUG
+		print("cunique umh != nil from %#p\n", getcallerpc(&c));
+		putmhead(c->umh);
+		c->umh = nil;
+	}
+
 	return c;
 }
 
@@ -512,61 +518,81 @@
 void
 putmhead(Mhead *m)
 {
-	if(m != nil && decref(&m->ref) == 0){
-		assert(m->mount == nil);
-		cclose(m->from);
-		free(m);
-	}
+	if(m == nil)
+		return;
+	if(decref(&m->ref))
+		return;
+	assert(m->mount == nil);
+	cclose(m->from);
+	free(m);
 }
 
 int
-cmount(Chan **newp, Chan *old, int flag, char *spec)
+cmount(Chan *new, Chan *old, int flag, char *spec)
 {
-	int order, flg;
-	Chan *new;
+	int order;
 	Mhead *m, **l, *mh;
-	Mount *nm, *f, *um, **h;
+	Mount *nm, *f, *um;
 	Pgrp *pg;
 
-	if(QTDIR & (old->qid.type^(*newp)->qid.type))
-		error(Emount);
-
 	if(old->umh != nil)
-		print("cmount: unexpected umh, caller %#p\n", getcallerpc(&newp));
+		print("cmount: unexpected umh, caller %#p\n", getcallerpc(&new));
 
+	if(QTDIR & (old->qid.type^new->qid.type))
+		error(Emount);
+
 	order = flag&MORDER;
 
 	if((old->qid.type&QTDIR) == 0 && order != MREPL)
 		error(Emount);
 
-	new = *newp;
+	nm = newmount(new, flag, spec);
 	mh = new->umh;
+	if(mh != nil) {
+		rlock(&mh->lock);
+		if(waserror()) {
+			runlock(&mh->lock);
+			mountfree(nm);
+			nexterror();
+		}
+		um = mh->mount;
+		if(um != nil){
+			/*
+			 * Not allowed to bind when the old directory is itself a union. 
+			 * (Maybe it should be allowed, but I don't see what the semantics
+			 * would be.)
+			 *
+			 * We need to check mh->mount->next to tell unions apart from
+			 * simple mount points, so that things like
+			 *	mount -c fd /root
+			 *	bind -c /root /
+			 * work.  
+			 * 
+			 * The check of mount->mflag allows things like
+			 *	mount fd /root
+			 *	bind -c /root /
+			 * 
+			 * This is far more complicated than it should be, but I don't
+			 * see an easier way at the moment.
+			 */
+			if((flag&MCREATE) != 0 && (um->next != nil || (um->mflag&MCREATE) == 0))
+				error(Emount);
 
-	/*
-	 * Not allowed to bind when the old directory is itself a union. 
-	 * (Maybe it should be allowed, but I don't see what the semantics
-	 * would be.)
-	 *
-	 * We need to check mh->mount->next to tell unions apart from
-	 * simple mount points, so that things like
-	 *	mount -c fd /root
-	 *	bind -c /root /
-	 * work.  
-	 * 
-	 * The check of mount->mflag allows things like
-	 *	mount fd /root
-	 *	bind -c /root /
-	 * 
-	 * This is far more complicated than it should be, but I don't
-	 * see an easier way at the moment.
-	 */
-	if((flag&MCREATE) != 0 && mh != nil && mh->mount != nil
-	&& (mh->mount->next != nil || (mh->mount->mflag&MCREATE) == 0))
-		error(Emount);
+			/*
+			 *  copy a union when binding it onto a directory
+			 */
+			f = nm;
+			for(um = um->next; um != nil; um = um->next){
+				f->next = newmount(um->to, order==MREPL? MAFTER: order, um->spec);
+				f = f->next;
+			}
+		}
+		runlock(&mh->lock);
+		poperror();
+	}
 
 	pg = up->pgrp;
 	wlock(&pg->ns);
-
 	l = &MOUNTH(pg, old->qid);
 	for(m = *l; m != nil; m = m->hash){
 		if(eqchan(m->from, old, 1))
@@ -573,7 +599,6 @@
 			break;
 		l = &m->hash;
 	}
-
 	if(m == nil){
 		/*
 		 *  nothing mounted here yet.  create a mount
@@ -580,8 +605,6 @@
 		 *  head and add to the hash table.
 		 */
 		m = newmhead(old);
-		*l = m;
-
 		/*
 		 *  if this is a union mount, add the old
 		 *  node to the mount chain.
@@ -588,52 +611,31 @@
 		 */
 		if(order != MREPL)
 			m->mount = newmount(old, 0, nil);
+		*l = m;
 	}
 	wlock(&m->lock);
-	if(waserror()){
-		wunlock(&m->lock);
-		nexterror();
-	}
-	wunlock(&pg->ns);
-
-	nm = newmount(new, flag, spec);
-	if(mh != nil && mh->mount != nil){
-		/*
-		 *  copy a union when binding it onto a directory
-		 */
-		flg = order;
-		if(order == MREPL)
-			flg = MAFTER;
-		h = &nm->next;
-		um = mh->mount;
-		for(um = um->next; um != nil; um = um->next){
-			f = newmount(um->to, flg, um->spec);
-			*h = f;
-			h = &f->next;
-		}
-	}
-
-	if(m->mount != nil && order == MREPL){
-		mountfree(m->mount);
-		m->mount = nil;
-	}
-
-	if(flag & MCREATE)
-		nm->mflag |= MCREATE;
-
-	if(m->mount != nil && order == MAFTER){
-		for(f = m->mount; f->next != nil; f = f->next)
+	um = m->mount;
+	if(um != nil && order == MAFTER){
+		for(f = um; f->next != nil; f = f->next)
 			;
 		f->next = nm;
-	}else{
-		for(f = nm; f->next != nil; f = f->next)
-			;
-		f->next = m->mount;
+		um = nil;
+	} else {
+		if(order != MREPL){
+			for(f = nm; f->next != nil; f = f->next)
+				;
+			f->next = um;
+			um = nil;
+		}
 		m->mount = nm;
 	}
+	order = nm->mountid;
 	wunlock(&m->lock);
-	poperror();
-	return nm->mountid;
+	wunlock(&pg->ns);
+
+	mountfree(um);
+
+	return order;
 }
 
 void
@@ -736,13 +738,13 @@
 	rlock(&pg->ns);
 	for(m = MOUNTH(pg, qid); m != nil; m = m->hash){
 		if(eqchantdqid(m->from, type, dev, qid, 1)){
-			rlock(&m->lock);
-			runlock(&pg->ns);
 			if(mp != nil)
 				incref(&m->ref);
+			rlock(&m->lock);
 			to = m->mount->to;
 			incref(&to->ref);
 			runlock(&m->lock);
+			runlock(&pg->ns);
 			if(mp != nil){
 				putmhead(*mp);
 				*mp = m;
@@ -957,7 +959,7 @@
 				n = wq->nqid;
 				nc = wq->clone;
 			}else{		/* stopped early, at a mount point */
-				didmount = 1;
+				assert(didmount);
 				if(wq->clone != nil){
 					cclose(wq->clone);
 					wq->clone = nil;
@@ -979,11 +981,6 @@
 	}
 	putmhead(mh);
 	c = cunique(c);
-	if(c->umh != nil){	//BUG
-		print("walk umh\n");
-		putmhead(c->umh);
-		c->umh = nil;
-	}
 
 	pathclose(c->path);
 	c->path = path;
@@ -1293,8 +1290,13 @@
 		m = nil;
 		if(!nomount)
 			domount(&c, &m, nil);
-		putmhead(c->umh);
+		if(waserror()){
+			putmhead(m);
+			nexterror();
+		}
+		c = cunique(c);
 		c->umh = m;
+		poperror();
 		break;
 
 	case Aaccess:
@@ -1311,9 +1313,13 @@
 		m = nil;
 		if(!nomount)
 			domount(&c, &m, &path);
-
+		if(waserror()){
+			putmhead(m);
+			nexterror();
+		}
 		/* our own copy to open or remove */
 		c = cunique(c);
+		poperror();
 
 		/* now it's our copy anyway, we can put the name back */
 		pathclose(c->path);
@@ -1331,16 +1337,17 @@
 
 		case Aopen:
 		case Acreate:
-			if(c->umh != nil){
-				print("cunique umh Open\n");
-				putmhead(c->umh);
-				c->umh = nil;
-			}
 			/* only save the mount head if it's a multiple element union */
-			if(m != nil && m->mount != nil && m->mount->next != nil)
-				c->umh = m;
-			else
-				putmhead(m);
+			if(m != nil) {
+				rlock(&m->lock);
+				if(m->mount != nil && m->mount->next != nil) {
+					c->umh = m;
+					runlock(&m->lock);
+				} else {
+					runlock(&m->lock);
+					putmhead(m);
+				}
+			}
 
 			/* save registers else error() in open has wrong value of c saved */
 			saveregisters();
--- a/kern/devmnt.c
+++ b/kern/devmnt.c
@@ -301,6 +301,9 @@
 	Mnt *m;
 	Mntrpc *r;
 
+	if(ac != nil && ac->mchan != c)
+		error(Ebadusefd);
+
 	m = c->mux;
 	if(m == nil){
 		mntversion(c, nil, 0, 0);
--- a/kern/fns.h
+++ b/kern/fns.h
@@ -25,7 +25,7 @@
 void		closepgrp(Pgrp*);
 void		closergrp(Rgrp*);
 void		cmderror(Cmdbuf*, char*);
-int		cmount(Chan**, Chan*, int, char*);
+int		cmount(Chan*, Chan*, int, char*);
 Block*		concatblock(Block*);
 Block*		copyblock(Block*, int);
 void		cunmount(Chan*, Chan*);
@@ -101,6 +101,7 @@
 Chan*		mntauth(Chan*, char*);
 void		mntdump(void);
 long		mntversion(Chan*, char*, int, int);
+Chan*		mntattach(Chan*, Chan*, char*, int);
 void		mountfree(Mount*);
 void		muxclose(Mnt*);
 Chan*		namec(char*, int, int, ulong);
--- a/kern/sysfile.c
+++ b/kern/sysfile.c
@@ -293,7 +293,7 @@
 }
 
 static void
-closefd(int fd, int flag)
+fdclose(int fd, int flag)
 {
 	int i;
 	Chan *c;
@@ -325,7 +325,7 @@
 _sysclose(int fd)
 {
 	fdtochan(fd, -1, 0, 0);
-	closefd(fd, 0);
+	fdclose(fd, 0);
 
 	return 0;
 }
@@ -636,24 +636,23 @@
 	return 0;
 }
 
-long
-bindmount(int ismount, int fd, int afd, char* arg0, char* arg1, ulong flag, char* spec)
+static int
+bindmount(int ismount, int fd, int afd, char* arg0, char* arg1, int flag, char* spec)
 {
 	int ret;
 	Chan *c0, *c1, *ac, *bc;
-	struct{
-		Chan	*chan;
-		Chan	*authchan;
-		char	*spec;
-		int	flags;
-	}bogus;
 
 	if((flag&~MMASK) || (flag&MORDER)==(MBEFORE|MAFTER))
 		error(Ebadarg);
 
-	bogus.flags = flag & MCACHE;
-
 	if(ismount){
+		validaddr((uintptr)spec, 1, 0);
+		spec = validnamedup(spec, 1);
+		if(waserror()){
+			free(spec);
+			nexterror();
+		}
+
 		if(up->pgrp->noattach)
 			error(Enoattach);
 
@@ -660,7 +659,7 @@
 		ac = nil;
 		bc = fdtochan(fd, ORDWR, 0, 1);
 		if(waserror()) {
-			if(ac)
+			if(ac != nil)
 				cclose(ac);
 			cclose(bc);
 			nexterror();
@@ -669,26 +668,14 @@
 		if(afd >= 0)
 			ac = fdtochan(afd, ORDWR, 0, 1);
 
-		bogus.chan = bc;
-		bogus.authchan = ac;
-
-		validaddr((ulong)spec, 1, 0);
-		bogus.spec = spec;
-		if(waserror())
-			error(Ebadspec);
-		validname(spec, 1);
-		poperror();
-
-		ret = devno('M', 0);
-		c0 = devtab[ret]->attach((char*)&bogus);
-
-		poperror();
-		if(ac)
+		c0 = mntattach(bc, ac, spec, flag&MCACHE);
+		poperror();	/* ac bc */
+		if(ac != nil)
 			cclose(ac);
 		cclose(bc);
 	}else{
-		bogus.spec = 0;
-		validaddr((ulong)arg0, 1, 0);
+		spec = nil;
+		validaddr((uintptr)arg0, 1, 0);
 		c0 = namec(arg0, Abind, 0, 0);
 	}
 
@@ -697,7 +684,7 @@
 		nexterror();
 	}
 
-	validaddr((ulong)arg1, 1, 0);
+	validaddr((uintptr)arg1, 1, 0);
 	c1 = namec(arg1, Amount, 0, 0);
 	if(waserror()){
 		cclose(c1);
@@ -704,15 +691,17 @@
 		nexterror();
 	}
 
-	ret = cmount(&c0, c1, flag, bogus.spec);
+	ret = cmount(c0, c1, flag, spec);
 
 	poperror();
 	cclose(c1);
 	poperror();
 	cclose(c0);
-	if(ismount)
-		closefd(fd, 0);
-
+	if(ismount){
+		fdclose(fd, 0);
+		poperror();
+		free(spec);
+	}
 	return ret;
 }