void
pgrpinsert(Mount **order, Mount *m)
{
Mount *f;
m->order = nil;
if(*order == nil) {
*order = m;
return;
}
for(f = *order; f != nil; f = f->order) {
if(m->mountid < f->mountid) {
m->order = f;
*order = m;
return;
}
order = &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;
Mhead *f, **tom, **l, *mh;
int i;
wlock(&to->ns);
rlock(&from->ns);
order = nil;
tom = to->mnthash;
for(i = 0; i < MNTHASH; i++) {
l = tom++;
for(f = from->mnthash[i]; f != nil; f = f->hash) {
rlock(&f->lock);
mh = newmhead(f->from);
*l = mh;
l = &mh->hash;
link = &mh->mount;
for(m = f->mount; m != nil; m = m->next) {
n = smalloc(sizeof(Mount));
n->mountid = m->mountid;
n->mflag = m->mflag;
n->to = m->to;
incref(n->to);
if(m->spec != nil)
kstrdup(&n->spec, m->spec);
pgrpinsert(&order, n);
*link = n;
link = &n->next;
}
runlock(&f->lock);
}
}
/*
* Allocate mount ids in the same sequence as the parent group
*/
for(m = order; m != nil; m = m->order)
m->mountid = incref(&mountid);
runlock(&from->ns);
wunlock(&to->ns);
}
Fgrp*
dupfgrp(Fgrp *f)
{
Fgrp *new;
Chan *c;
int i;
/*
* If we get into trouble, forceclosefgrp
* will bail us out.
*/
up->closingfgrp = f;
for(i = 0; i <= f->maxfd; i++)
if((c = f->fd[i]) != nil){
f->fd[i] = nil;
cclose(c);
}
up->closingfgrp = nil;
free(f->fd);
free(f);
}
/*
* Called from interrupted() because up is in the middle
* of closefgrp and just got a kill ctl message.
* This usually means that up has wedged because
* of some kind of deadly embrace with mntclose
* trying to talk to itself. To break free, hand the
* unclosed channels to the close queue. Once they
* are finished, the blocked cclose that we've
* interrupted will finish by itself.
*/
void
forceclosefgrp(void)
{
int i;
Chan *c;
Fgrp *f;