ref: 4f6fa04fe60dde3f55e4f07589d0373e0fe841c9
parent: 882ec4ba3d42f15e630119e1f43e5400123539b5
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Nov 30 17:00:03 EST 2025
kernel: get rid of mountid and quadratic algorithms in pgrpcpy() and devproc/readns1() Ori discovered that the 64-bit Mount.mountid was handled incorrectly in devproc's readns1() as Chan.nrock is 32-bit integer. Instead of sorting the Mount entries by 64-bit mountid using pgrpinsert(), always maintain orderd linked list in Pgrp.mntorder. For pgrpcpy(), we also add a Mount *norder "forward" pointer, which we temporarily stuff new Mount's into the original pgrp Mount's. A the end, we re-insert all the new mounts using pgrpinsert(). Pgrpinsert() is now O(1) as it just needs to append to the list (and we keep a tail link pointer). Add Mhead *umh into Mount struct and devproc's readns1() becomes trivial. The 64-bit mountid is not needed anymore, so remove as well as the nextmount() generator.
--- a/sys/src/9/port/chan.c
+++ b/sys/src/9/port/chan.c
@@ -742,11 +742,18 @@
putmhead(m);
nexterror();
}
- m->mount = newmount(old, 0, nil);
+ f = newmount(old, 0, nil);
+ f->umh = m;
+ m->mount = f;
+ pgrpinsert(pg, f);
poperror();
}
*l = m;
}
+ for(f = nm; f != nil; f = f->next){+ f->umh = m;
+ pgrpinsert(pg, f);
+ }
wlock(&m->lock);
um = m->mount;
if(um != nil && order == MAFTER){@@ -764,6 +771,8 @@
m->mount = nm;
}
wunlock(&m->lock);
+ for(f = um; f != nil; f = f->next)
+ pgrpremove(pg, f);
wunlock(&pg->ns);
poperror();
@@ -807,10 +816,12 @@
}
wlock(&m->lock);
- f = m->mount;
if(mounted == nil){- *l = m->hash;
+ for(f = m->mount; f != nil; f = f->next)
+ pgrpremove(pg, f);
+ f = m->mount;
m->mount = nil;
+ *l = m->hash;
wunlock(&m->lock);
wunlock(&pg->ns);
mountfree(f);
@@ -817,9 +828,11 @@
putmhead(m);
return;
}
- for(p = &m->mount; f != nil; f = f->next){+ p = &m->mount;
+ for(f = m->mount; f != nil; f = f->next){if(eqchan(f->to, mounted, 1) ||
(f->to->mchan != nil && eqchan(f->to->mchan, mounted, 1))){+ pgrpremove(pg, f);
*p = f->next;
f->next = nil;
if(m->mount == nil){--- a/sys/src/9/port/devproc.c
+++ b/sys/src/9/port/devproc.c
@@ -642,9 +642,7 @@
readns1(Chan *c, Proc *p, char *buf, int nbuf)
{Pgrp *pg;
- Mount *t, *cm;
- Mhead *f, *mh;
- ulong minid, bestmid;
+ Mount *f;
char flag[10], *srv;
int i;
@@ -652,49 +650,35 @@
if(pg == nil || p->dot == nil || p->pid != PID(c->qid))
error(Eprocdied);
- bestmid = ~0;
- minid = c->nrock;
- if(minid == bestmid)
+ if(c->nrock < 0)
return 0;
rlock(&pg->ns);
- mh = nil;
- cm = nil;
- for(i = 0; i < MNTHASH; i++) {- for(f = pg->mnthash[i]; f != nil; f = f->hash) {- rlock(&f->lock);
- for(t = f->mount; t != nil; t = t->next) {- if(t->mountid >= minid && t->mountid < bestmid) {- bestmid = t->mountid;
- cm = t;
- mh = f;
- }
- }
- runlock(&f->lock);
- }
+ i = 0;
+ for(f = pg->mntorder; f != nil; f = f->order) {+ if(i++ >= c->nrock)
+ break;
}
- if(bestmid == ~0) {- c->nrock = bestmid;
+ if(f == nil) {+ c->nrock = -1;
i = snprint(buf, nbuf, "cd %q\n", p->dot->path->s);
} else {- c->nrock = bestmid+1;
-
- int2flag(cm->mflag, flag);
- if(strcmp(cm->to->path->s, "#M") == 0){- srv = cm->to->mchan->srvname;
+ c->nrock = i;
+ int2flag(f->mflag, flag);
+ if(strcmp(f->to->path->s, "#M") == 0){+ srv = f->to->mchan->srvname;
if(srv == nil)
- srv = cm->to->mchan->path->s;
- i = snprint(buf, nbuf, *cm->spec?
+ srv = f->to->mchan->path->s;
+ i = snprint(buf, nbuf, *f->spec?
"mount %s %q %q %q\n": "mount %s %q %q\n", flag,
- srv, mh->from->path->s, cm->spec);
+ srv, f->umh->from->path->s, f->spec);
}else{i = snprint(buf, nbuf, "bind %s %q %q\n", flag,
- cm->to->path->s, mh->from->path->s);
+ f->to->path->s, f->umh->from->path->s);
}
}
-
runlock(&pg->ns);
return i;
--- a/sys/src/9/port/pgrp.c
+++ b/sys/src/9/port/pgrp.c
@@ -9,19 +9,6 @@
Whinesecs = 10, /* frequency of out-of-resources printing */
};
-uvlong
-nextmount(void)
-{- static uvlong next = 0;
- static Lock lk;
- uvlong n;
-
- lock(&lk);
- n = ++next;
- unlock(&lk);
- return n;
-}
-
Pgrp*
newpgrp(void)
{@@ -31,6 +18,7 @@
if(p == nil)
error(Enomem);
p->ref = 1;
+ p->mntordertail = &p->mntorder;
return p;
}
@@ -77,41 +65,44 @@
free(p);
}
-static void
-pgrpinsert(Mount **order, Mount *m)
+void
+pgrpinsert(Pgrp *pg, Mount *m)
{- Mount *f;
-
m->order = nil;
- for(f = *order; f != nil; f = f->order) {- if(m->mountid < f->mountid) {- m->order = f;
- *order = m;
+ *pg->mntordertail = m;
+ pg->mntordertail = &m->order;
+}
+
+void
+pgrpremove(Pgrp *pg, Mount *m)
+{+ Mount *f, **l = &pg->mntorder;
+
+ for(f = pg->mntorder; f != nil; f = f->order) {+ if(f == m){+ if((*l = f->order) == nil)
+ pg->mntordertail = l;
+ f->order = nil;
return;
}
- order = &f->order;
+ l = &f->order;
}
- *order = m;
}
-/*
- * pgrpcpy MUST preserve the mountid allocation order of the parent group
- */
void
pgrpcpy(Pgrp *to, Pgrp *from)
{- Mount *n, *m, **link, *order;
+ Mount *n, *m, **link;
Mhead *f, **l, *mh;
int i;
wlock(&to->ns);
- rlock(&from->ns);
+ wlock(&from->ns); /* must wlock to protect from->mntorder->norder */
if(waserror()){- runlock(&from->ns);
+ wunlock(&from->ns);
wunlock(&to->ns);
nexterror();
}
- order = nil;
for(i = 0; i < MNTHASH; i++) {l = &to->mnthash[i];
for(f = from->mnthash[i]; f != nil; f = f->hash) {@@ -125,28 +116,23 @@
l = &mh->hash;
link = &mh->mount;
for(m = f->mount; m != nil; m = m->next) {- n = malloc(sizeof(Mount)+strlen(m->spec)+1);
- if(n == nil)
- error(Enomem);
- n->mountid = m->mountid;
- n->mflag = m->mflag;
- n->to = m->to;
- incref(n->to);
- strcpy(n->spec, m->spec);
- pgrpinsert(&order, n);
+ n = newmount(m->to, m->mflag, m->spec);
+ n->umh = mh;
*link = n;
link = &n->next;
+ m->norder = n; /* for from->mntorder loop below */
}
runlock(&f->lock);
poperror();
}
}
- /*
- * Allocate mount ids in the same sequence as the parent group
- */
- for(m = order; m != nil; m = m->order)
- m->mountid = nextmount();
- runlock(&from->ns);
+ /* add mounts in original mntorder */
+ for(m = from->mntorder; m != nil; m = m->order){+ n = m->norder;
+ m->norder = nil;
+ pgrpinsert(to, n);
+ }
+ wunlock(&from->ns);
wunlock(&to->ns);
poperror();
}
@@ -272,7 +258,6 @@
error(Enomem);
m->to = to;
incref(to);
- m->mountid = nextmount();
m->mflag = flag;
strcpy(m->spec, spec);
setmalloctag(m, getcallerpc(&to));
--- a/sys/src/9/port/portdat.h
+++ b/sys/src/9/port/portdat.h
@@ -260,11 +260,12 @@
struct Mount
{- uvlong mountid;
- int mflag;
- Mount* next;
- Mount* order;
+ Mount* order; /* Pgrp.mntorder chain */
+ Mount* norder; /* forward pointer for pgrpcpy() */
+ Mount* next; /* Mhead.mount chain */
+ Mhead* umh; /* the union we belong to */
Chan* to; /* channel replacing channel */
+ int mflag;
char spec[];
};
@@ -281,10 +282,9 @@
{Rendez;
- ulong vers;
-
vlong off;
vlong seq;
+ ulong vers;
uint i;
Mntrpc *r[8];
@@ -513,6 +513,8 @@
Ref;
RWLock ns; /* Namespace n read/one write lock */
u64int notallowed[4]; /* Room for 256 devices */
+ Mount *mntorder; /* Ordered list of mounts */
+ Mount **mntordertail;
Mhead *mnthash[MNTHASH];
};
--- a/sys/src/9/port/portfns.h
+++ b/sys/src/9/port/portfns.h
@@ -245,6 +245,8 @@
ulong perfticks(void);
_Noreturn void pexit(char*, int);
void pgrpcpy(Pgrp*, Pgrp*);
+void pgrpinsert(Pgrp*, Mount *);
+void pgrpremove(Pgrp*, Mount *);
ulong pidalloc(Proc*);
#define waserror() setlabel(&up->errlab[up->nerrlab++])
#define poperror() up->nerrlab--
--
⑨