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