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;
}