M port/error.h => port/error.h +1 -0
@@ 46,6 46,7 @@ extern char Enetunreach[]; /* network unreachable */
extern char Eintr[]; /* interrupted */
extern char Eneedservice[]; /* service required for tcp/udp/il calls */
extern char Enomem[]; /* kernel allocate failed */
+extern char Enoswap[]; /* swap space full */
extern char Esfnotcached[]; /* subfont not cached */
extern char Esoverlap[]; /* segments overlap */
extern char Emouseset[]; /* mouse type already set */
M port/fault.c => port/fault.c +14 -7
@@ 38,13 38,13 @@ fault(ulong addr, int read)
}
static void
-faulterror(char *s)
+faulterror(char *s, int freemem)
{
if(up->nerrlab) {
postnote(up, 1, s, NDebug);
error(s);
}
- pexit(s, 0);
+ pexit(s, freemem);
}
int
@@ 125,6 125,13 @@ fixfault(Segment *s, ulong addr, int read, int doputmmu)
ref = lkp->ref;
if(ref > 1) {
unlock(lkp);
+
+ if(swapfull()){
+ qunlock(&s->lk);
+ pprint("swap space full\n");
+ faulterror(Enoswap, 1);
+ }
+
new = newpage(0, &s, addr);
if(s == 0)
return -1;
@@ 134,7 141,7 @@ fixfault(Segment *s, ulong addr, int read, int doputmmu)
}
else {
/* save a copy of the original for the image cache */
- if(lkp->image)
+ if(lkp->image && !swapfull())
duppage(lkp);
unlock(lkp);
@@ 214,7 221,7 @@ retry:
continue;
kunmap(k);
putpage(new);
- faulterror("sys: demand load I/O error");
+ faulterror("sys: demand load I/O error", 0);
}
ask = s->flen-soff;
@@ 223,7 230,7 @@ retry:
n = devtab[c->type]->read(c, kaddr, ask, daddr);
if(n != ask)
- faulterror(Eioload);
+ faulterror(Eioload, 0);
if(ask < BY2PG)
memset(kaddr+ask, 0, BY2PG-ask);
@@ 250,12 257,12 @@ retry:
putpage(new);
qlock(&s->lk);
qunlock(&s->lk);
- faulterror("sys: page in I/O error");
+ faulterror("sys: page in I/O error", 0);
}
n = devtab[c->type]->read(c, kaddr, BY2PG, daddr);
if(n != BY2PG)
- faulterror(Eioload);
+ faulterror(Eioload, 0);
poperror();
kunmap(k);
M port/portfns.h => port/portfns.h +1 -0
@@ 295,6 295,7 @@ void splx(int);
void splxpc(int);
void srvrecover(Chan*, Chan*);
int swapcount(ulong);
+int swapfull(void);
void swapinit(void);
Block* trimblock(Block*, int, int);
void tsleep(Rendez*, int (*)(void*), void*, int);
M port/segment.c => port/segment.c +23 -0
@@ 53,6 53,9 @@ newseg(int type, ulong base, ulong size)
if(size > (SEGMAPSIZE*PTEPERTAB))
error(Enovmem);
+ if(swapfull())
+ error(Enoswap);
+
s = smalloc(sizeof(Segment));
s->ref = 1;
s->type = type;
@@ 157,7 160,12 @@ dupseg(Segment **seg, int segno, int share)
case SG_STACK:
qlock(&s->lk);
+ if(waserror()){
+ qunlock(&s->lk);
+ nexterror();
+ }
n = newseg(s->type, s->base, s->size);
+ poperror();
break;
case SG_BSS: /* Just copy on write */
@@ 169,7 177,12 @@ dupseg(Segment **seg, int segno, int share)
qunlock(&s->lk);
return s;
}
+ if(waserror()){
+ qunlock(&s->lk);
+ nexterror();
+ }
n = newseg(s->type, s->base, s->size);
+ poperror();
break;
case SG_DATA: /* Copy on write plus demand load info */
@@ 183,7 196,12 @@ dupseg(Segment **seg, int segno, int share)
qunlock(&s->lk);
return s;
}
+ if(waserror()){
+ qunlock(&s->lk);
+ nexterror();
+ }
n = newseg(s->type, s->base, s->size);
+ poperror();
incref(s->image);
n->image = s->image;
@@ 438,6 456,11 @@ ibrk(ulong addr, int seg)
return 0;
}
+ if(swapfull()){
+ qunlock(&s->lk);
+ error(Enoswap);
+ }
+
for(i = 0; i < NSEG; i++) {
ns = up->seg[i];
if(ns == 0 || ns == s)
M port/swap.c => port/swap.c +13 -2
@@ 38,8 38,11 @@ newswap(void)
uchar *look;
lock(&swapalloc);
- if(swapalloc.free == 0)
- panic("out of swap space");
+
+ if(swapalloc.free == 0){
+ unlock(&swapalloc);
+ return ~0;
+ }
look = memchr(swapalloc.last, 0, swapalloc.top-swapalloc.last);
if(look == 0)
@@ 285,6 288,8 @@ pagepte(int type, Page **pg)
* referring to it from the cache
*/
daddr = newswap();
+ if(daddr == ~0)
+ break;
cachedel(&swapimage, daddr);
lock(outp);
@@ 396,3 401,9 @@ setswapchan(Chan *c)
swapimage.c = c;
}
+
+int
+swapfull(void)
+{
+ return swapalloc.free < conf.nswap/10;
+}