devsegment: cleanups
- return distinct error message when attempting to create Globalseg with physseg name - copy directory name to up->genbuf so it stays valid after we unlock(&glogalseglock) - cleanup wstat() handling, allow changing uid - make sure global segment size is below SEGMAXSIZE - move isoverlap() check from globalsegattach() into segattach() - remove Proc* argument from globalsegattach(), segattach() and isoverlap() - make Physseg.attr and segattach attr parameter an int for consistency
This commit is contained in:
parent
f846721035
commit
1057a859b8
5 changed files with 62 additions and 61 deletions
|
@ -34,8 +34,8 @@ static Globalseg *globalseg[100];
|
|||
static Lock globalseglock;
|
||||
|
||||
|
||||
Segment* (*_globalsegattach)(Proc*, char*);
|
||||
static Segment* globalsegattach(Proc *p, char *name);
|
||||
Segment* (*_globalsegattach)(char*);
|
||||
static Segment* globalsegattach(char *name);
|
||||
|
||||
static Segment* fixedseg(uintptr va, ulong len);
|
||||
|
||||
|
@ -64,7 +64,7 @@ getgseg(Chan *c)
|
|||
static void
|
||||
putgseg(Globalseg *g)
|
||||
{
|
||||
if(decref(g) > 0)
|
||||
if(g == nil || decref(g))
|
||||
return;
|
||||
if(g->s != nil)
|
||||
putseg(g->s);
|
||||
|
@ -103,9 +103,9 @@ segmentgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp)
|
|||
q.vers = 0;
|
||||
q.path = PATH(s, Qsegdir);
|
||||
q.type = QTDIR;
|
||||
devdir(c, q, g->name, 0, g->uid, DMDIR|0777, dp);
|
||||
kstrcpy(up->genbuf, g->name, sizeof up->genbuf);
|
||||
devdir(c, q, up->genbuf, 0, g->uid, DMDIR|0777, dp);
|
||||
unlock(&globalseglock);
|
||||
|
||||
break;
|
||||
case Qsegdir:
|
||||
if(s == DEVDOTDOT){
|
||||
|
@ -183,16 +183,6 @@ segmentopen(Chan *c, int omode)
|
|||
error(Eisdir);
|
||||
break;
|
||||
case Qctl:
|
||||
g = getgseg(c);
|
||||
if(waserror()){
|
||||
putgseg(g);
|
||||
nexterror();
|
||||
}
|
||||
devpermcheck(g->uid, g->perm, omode);
|
||||
c->aux = g;
|
||||
poperror();
|
||||
c->flag |= COPEN;
|
||||
break;
|
||||
case Qdata:
|
||||
g = getgseg(c);
|
||||
if(waserror()){
|
||||
|
@ -200,27 +190,31 @@ segmentopen(Chan *c, int omode)
|
|||
nexterror();
|
||||
}
|
||||
devpermcheck(g->uid, g->perm, omode);
|
||||
if(g->s == nil)
|
||||
if(TYPE(c) == Qdata && g->s == nil)
|
||||
error("segment not yet allocated");
|
||||
c->aux = g;
|
||||
poperror();
|
||||
c->flag |= COPEN;
|
||||
break;
|
||||
default:
|
||||
panic("segmentopen");
|
||||
}
|
||||
c->mode = openmode(omode);
|
||||
c->offset = 0;
|
||||
c->flag |= COPEN;
|
||||
return c;
|
||||
}
|
||||
|
||||
static void
|
||||
segmentclose(Chan *c)
|
||||
{
|
||||
if(TYPE(c) == Qtopdir)
|
||||
return;
|
||||
if(c->flag & COPEN)
|
||||
putgseg(c->aux);
|
||||
switch(TYPE(c)){
|
||||
case Qctl:
|
||||
case Qdata:
|
||||
if(c->flag & COPEN){
|
||||
putgseg(c->aux);
|
||||
c->aux = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Chan*
|
||||
|
@ -232,8 +226,11 @@ segmentcreate(Chan *c, char *name, int omode, ulong perm)
|
|||
if(TYPE(c) != Qtopdir)
|
||||
error(Eperm);
|
||||
|
||||
if(strlen(name) >= sizeof(up->genbuf))
|
||||
error(Etoolong);
|
||||
|
||||
if(findphysseg(name) != nil)
|
||||
error(Eexist);
|
||||
error("name collision with physical segment");
|
||||
|
||||
if((perm & DMDIR) == 0)
|
||||
error(Ebadarg);
|
||||
|
@ -249,10 +246,8 @@ segmentcreate(Chan *c, char *name, int omode, ulong perm)
|
|||
if(g == nil){
|
||||
if(xfree < 0)
|
||||
xfree = x;
|
||||
} else {
|
||||
if(strcmp(g->name, name) == 0)
|
||||
error(Eexist);
|
||||
}
|
||||
} else if(strcmp(g->name, name) == 0)
|
||||
error(Eexist);
|
||||
}
|
||||
if(xfree < 0)
|
||||
error("too many global segments");
|
||||
|
@ -269,7 +264,6 @@ segmentcreate(Chan *c, char *name, int omode, ulong perm)
|
|||
c->qid.type = QTDIR;
|
||||
c->qid.vers = 0;
|
||||
c->mode = openmode(omode);
|
||||
c->mode = OWRITE;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
@ -330,13 +324,15 @@ segmentwrite(Chan *c, void *a, long n, vlong voff)
|
|||
va = va&~(BY2PG-1);
|
||||
if(va == 0 || top > USTKTOP || top <= va)
|
||||
error(Ebadarg);
|
||||
len = (top - va) / BY2PG;
|
||||
len = top - va;
|
||||
if(len > SEGMAXSIZE)
|
||||
error(Enovmem);
|
||||
if(cb->nf >= 4 && strcmp(cb->f[3], "fixed") == 0){
|
||||
if(!iseve())
|
||||
error(Eperm);
|
||||
g->s = fixedseg(va, len);
|
||||
g->s = fixedseg(va, len/BY2PG);
|
||||
} else
|
||||
g->s = newseg(SG_SHARED, va, len);
|
||||
g->s = newseg(SG_SHARED, va, len/BY2PG);
|
||||
} else
|
||||
error(Ebadctl);
|
||||
free(cb);
|
||||
|
@ -359,22 +355,27 @@ segmentwstat(Chan *c, uchar *dp, int n)
|
|||
if(c->qid.type == QTDIR)
|
||||
error(Eperm);
|
||||
|
||||
d = nil;
|
||||
g = getgseg(c);
|
||||
if(waserror()){
|
||||
free(d);
|
||||
putgseg(g);
|
||||
nexterror();
|
||||
}
|
||||
|
||||
if(strcmp(g->uid, up->user) && !iseve())
|
||||
error(Eperm);
|
||||
d = smalloc(sizeof(Dir)+n);
|
||||
n = convM2D(dp, n, &d[0], (char*)&d[1]);
|
||||
g->perm = d->mode & 0777;
|
||||
|
||||
if(n == 0)
|
||||
error(Eshortstat);
|
||||
if(!emptystr(d->uid))
|
||||
kstrdup(&g->uid, d->uid);
|
||||
if(d->mode != ~0UL)
|
||||
g->perm = d->mode&0777;
|
||||
free(d);
|
||||
putgseg(g);
|
||||
poperror();
|
||||
|
||||
free(d);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
@ -399,13 +400,12 @@ segmentremove(Chan *c)
|
|||
* called by segattach()
|
||||
*/
|
||||
static Segment*
|
||||
globalsegattach(Proc *p, char *name)
|
||||
globalsegattach(char *name)
|
||||
{
|
||||
int x;
|
||||
Globalseg *g;
|
||||
Segment *s;
|
||||
|
||||
g = nil;
|
||||
if(waserror()){
|
||||
unlock(&globalseglock);
|
||||
nexterror();
|
||||
|
@ -414,19 +414,16 @@ globalsegattach(Proc *p, char *name)
|
|||
for(x = 0; x < nelem(globalseg); x++){
|
||||
g = globalseg[x];
|
||||
if(g != nil && strcmp(g->name, name) == 0)
|
||||
break;
|
||||
}
|
||||
if(x == nelem(globalseg)){
|
||||
unlock(&globalseglock);
|
||||
poperror();
|
||||
return nil;
|
||||
goto Found;
|
||||
}
|
||||
unlock(&globalseglock);
|
||||
poperror();
|
||||
return nil;
|
||||
Found:
|
||||
devpermcheck(g->uid, g->perm, ORDWR);
|
||||
s = g->s;
|
||||
if(s == nil)
|
||||
error("global segment not assigned a virtual address");
|
||||
if(isoverlap(p, s->base, s->top - s->base) != nil)
|
||||
error("overlaps existing segment");
|
||||
incref(s);
|
||||
unlock(&globalseglock);
|
||||
poperror();
|
||||
|
|
|
@ -389,7 +389,7 @@ enum
|
|||
|
||||
struct Physseg
|
||||
{
|
||||
ulong attr; /* Segment attributes */
|
||||
int attr; /* Segment attributes */
|
||||
char *name; /* Attach name */
|
||||
uintptr pa; /* Physical address */
|
||||
uintptr size; /* Maximum segment size in bytes */
|
||||
|
|
|
@ -140,7 +140,7 @@ int iprint(char*, ...);
|
|||
void isdir(Chan*);
|
||||
int iseve(void);
|
||||
int islo(void);
|
||||
Segment* isoverlap(Proc*, uintptr, uintptr);
|
||||
Segment* isoverlap(uintptr, uintptr);
|
||||
Physseg* findphysseg(char*);
|
||||
void ixsummary(void);
|
||||
void kickpager(void);
|
||||
|
@ -309,7 +309,7 @@ void scheddump(void);
|
|||
void schedinit(void);
|
||||
void (*screenputs)(char*, int);
|
||||
long seconds(void);
|
||||
uintptr segattach(Proc*, ulong, char *, uintptr, uintptr);
|
||||
uintptr segattach(int, char *, uintptr, uintptr);
|
||||
void segclock(uintptr);
|
||||
long segio(Segio*, Segment*, void*, long, vlong, int);
|
||||
void segpage(Segment*, Page*);
|
||||
|
|
|
@ -27,7 +27,7 @@ static struct Imagealloc
|
|||
QLock ireclaim; /* mutex on reclaiming free images */
|
||||
}imagealloc;
|
||||
|
||||
Segment* (*_globalsegattach)(Proc*, char*);
|
||||
Segment* (*_globalsegattach)(char*);
|
||||
|
||||
void
|
||||
initseg(void)
|
||||
|
@ -533,7 +533,7 @@ mfreeseg(Segment *s, uintptr start, ulong pages)
|
|||
}
|
||||
|
||||
Segment*
|
||||
isoverlap(Proc *p, uintptr va, uintptr len)
|
||||
isoverlap(uintptr va, uintptr len)
|
||||
{
|
||||
int i;
|
||||
Segment *ns;
|
||||
|
@ -541,7 +541,7 @@ isoverlap(Proc *p, uintptr va, uintptr len)
|
|||
|
||||
newtop = va+len;
|
||||
for(i = 0; i < NSEG; i++) {
|
||||
ns = p->seg[i];
|
||||
ns = up->seg[i];
|
||||
if(ns == nil)
|
||||
continue;
|
||||
if((newtop > ns->base && newtop <= ns->top) ||
|
||||
|
@ -590,7 +590,7 @@ findphysseg(char *name)
|
|||
}
|
||||
|
||||
uintptr
|
||||
segattach(Proc *p, ulong attr, char *name, uintptr va, uintptr len)
|
||||
segattach(int attr, char *name, uintptr va, uintptr len)
|
||||
{
|
||||
int sno;
|
||||
Segment *s, *os;
|
||||
|
@ -600,7 +600,7 @@ segattach(Proc *p, ulong attr, char *name, uintptr va, uintptr len)
|
|||
error(Ebadarg);
|
||||
|
||||
for(sno = 0; sno < NSEG; sno++)
|
||||
if(p->seg[sno] == nil && sno != ESEG)
|
||||
if(up->seg[sno] == nil && sno != ESEG)
|
||||
break;
|
||||
|
||||
if(sno == NSEG)
|
||||
|
@ -611,9 +611,13 @@ segattach(Proc *p, ulong attr, char *name, uintptr va, uintptr len)
|
|||
* same name
|
||||
*/
|
||||
if(_globalsegattach != nil){
|
||||
s = (*_globalsegattach)(p, name);
|
||||
s = (*_globalsegattach)(name);
|
||||
if(s != nil){
|
||||
p->seg[sno] = s;
|
||||
if(isoverlap(s->base, s->top - s->base) != nil){
|
||||
putseg(s);
|
||||
error(Esoverlap);
|
||||
}
|
||||
up->seg[sno] = s;
|
||||
return s->base;
|
||||
}
|
||||
}
|
||||
|
@ -634,7 +638,7 @@ segattach(Proc *p, ulong attr, char *name, uintptr va, uintptr len)
|
|||
* map the zero page.
|
||||
*/
|
||||
if(va == 0) {
|
||||
for (os = p->seg[SSEG]; os != nil; os = isoverlap(p, va, len)) {
|
||||
for (os = up->seg[SSEG]; os != nil; os = isoverlap(va, len)) {
|
||||
va = os->base;
|
||||
if(len >= va)
|
||||
error(Enovmem);
|
||||
|
@ -646,7 +650,7 @@ segattach(Proc *p, ulong attr, char *name, uintptr va, uintptr len)
|
|||
if(va == 0 || (va+len) > USTKTOP || (va+len) < va)
|
||||
error(Ebadarg);
|
||||
|
||||
if(isoverlap(p, va, len) != nil)
|
||||
if(isoverlap(va, len) != nil)
|
||||
error(Esoverlap);
|
||||
|
||||
ps = findphysseg(name);
|
||||
|
@ -661,7 +665,7 @@ segattach(Proc *p, ulong attr, char *name, uintptr va, uintptr len)
|
|||
|
||||
s = newseg(attr, va, len/BY2PG);
|
||||
s->pseg = ps;
|
||||
p->seg[sno] = s;
|
||||
up->seg[sno] = s;
|
||||
|
||||
return va;
|
||||
}
|
||||
|
|
|
@ -429,7 +429,7 @@ sysexec(va_list list)
|
|||
tstk = s->base;
|
||||
if(tstk <= USTKSIZE)
|
||||
error(Enovmem);
|
||||
} while((s = isoverlap(up, tstk-USTKSIZE, USTKSIZE)) != nil);
|
||||
} while((s = isoverlap(tstk-USTKSIZE, USTKSIZE)) != nil);
|
||||
up->seg[ESEG] = newseg(SG_STACK, tstk-USTKSIZE, USTKSIZE/BY2PG);
|
||||
|
||||
/*
|
||||
|
@ -785,12 +785,12 @@ syssegbrk(va_list list)
|
|||
uintptr
|
||||
syssegattach(va_list list)
|
||||
{
|
||||
ulong attr;
|
||||
int attr;
|
||||
char *name;
|
||||
uintptr va;
|
||||
ulong len;
|
||||
|
||||
attr = va_arg(list, ulong);
|
||||
attr = va_arg(list, int);
|
||||
name = va_arg(list, char*);
|
||||
va = va_arg(list, uintptr);
|
||||
len = va_arg(list, ulong);
|
||||
|
@ -800,7 +800,7 @@ syssegattach(va_list list)
|
|||
free(name);
|
||||
nexterror();
|
||||
}
|
||||
va = segattach(up, attr, name, va, len);
|
||||
va = segattach(attr, name, va, len);
|
||||
free(name);
|
||||
poperror();
|
||||
return va;
|
||||
|
|
Loading…
Reference in a new issue