In ibrk and segattach there are two different expressions which check for expanding or newly created segments overlapping an existing segment. Neither version was general enough to catch all possible cases. This patch also includes a minimal correction for a bug reported in 9fans by cinap_lenrek on 2014-06-08 (Re: duppage) which can lead to resource starvation & deadlock: duppage() causes the freelist to be shuffled differently. without stuffing cached pages at the freelist tail, the tail accumulates a uncached "stopper" page which breaks the invariant of imagereclaim which just scans from the tail backwards as long as the pages are cached. imagereclaim does not move the pages to the head after uncaching them! so by default imagereclaim prevents the cached pages before the ones it reclaimed from being reclaimed ever. Reference: /n/sources/patch/segment-overlap Date: Tue Apr 19 13:16:06 CES 2016 Signed-off-by: miller@hamnavoe.com --- /sys/src/9/port/segment.c Tue Apr 19 13:06:56 2016 +++ /sys/src/9/port/segment.c Tue Apr 19 13:06:53 2016 @@ -344,6 +344,8 @@ if(p->ref == 0) { n++; uncachepage(p); + pageunchain(p); + pagechainhead(p); } unlock(p); } @@ -484,7 +486,7 @@ ns = up->seg[i]; if(ns == 0 || ns == s) continue; - if(newtop >= ns->base && newtop < ns->top) { + if(newtop > ns->base && s->base < ns->top) { qunlock(&s->lk); error(Esoverlap); } @@ -586,8 +588,7 @@ ns = p->seg[i]; if(ns == 0) continue; - if((newtop > ns->base && newtop <= ns->top) || - (va >= ns->base && va < ns->top)) + if(newtop > ns->base && va < ns->top) return ns; } return nil; --- /sys/src/9/port/page.c Tue Apr 19 13:07:02 2016 +++ /sys/src/9/port/page.c Tue Apr 19 13:06:59 2016 @@ -64,7 +64,7 @@ print("%ldM swap\n", vkb/1024); } -static void +void pageunchain(Page *p) { if(canlock(&palloc)) --- /sys/src/9/port/portfns.h Tue Apr 19 13:07:07 2016 +++ /sys/src/9/port/portfns.h Tue Apr 19 13:07:04 2016 @@ -215,6 +215,7 @@ void pageinit(void); ulong pagenumber(Page*); void pagersummary(void); +void pageunchain(Page *p); void panic(char*, ...); Cmdbuf* parsecmd(char *a, int n); void pathclose(Path*);