summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/src/9/port/swap.c45
1 files changed, 23 insertions, 22 deletions
diff --git a/sys/src/9/port/swap.c b/sys/src/9/port/swap.c
index b8e0631ff..c51417520 100644
--- a/sys/src/9/port/swap.c
+++ b/sys/src/9/port/swap.c
@@ -49,7 +49,7 @@ swapinit(void)
swapimage.notext = 1;
}
-uintptr
+static uintptr
newswap(void)
{
uchar *look;
@@ -64,7 +64,8 @@ newswap(void)
if(look == 0)
panic("inconsistent swap");
- *look = 1;
+ *look = 2; /* ref for pte + io transaction */
+
swapalloc.last = look;
swapalloc.free--;
unlock(&swapalloc);
@@ -324,12 +325,14 @@ pagepte(int type, Page **pg)
case SG_STACK:
case SG_SHARED:
/*
- * get a new swap address and clear any pages
- * referring to it from the cache
+ * get a new swap address with swapcount 2, one for the pte
+ * and one extra ref for us while we write the page to disk
*/
daddr = newswap();
if(daddr == ~0)
break;
+
+ /* clear any pages referring to it from the cache */
cachedel(&swapimage, daddr);
lock(outp);
@@ -338,12 +341,6 @@ pagepte(int type, Page **pg)
uncachepage(outp);
/*
- * incr the reference count to make sure it sticks around while
- * being written
- */
- outp->ref++;
-
- /*
* enter it into the cache so that a fault happening
* during the write will grab the page from the cache
* rather than one partially written to the disk
@@ -396,23 +393,27 @@ executeio(void)
if(ioptr > conf.nswppo)
panic("executeio: ioptr %d > %d", ioptr, conf.nswppo);
out = iolist[i];
- k = kmap(out);
- kaddr = (char*)VA(k);
- if(waserror())
- panic("executeio: page out I/O error");
+ /* only write when swap address still referenced */
+ if(swapcount(out->daddr) > 1){
+ k = kmap(out);
+ kaddr = (char*)VA(k);
+
+ if(waserror())
+ panic("executeio: page out I/O error");
- n = devtab[c->type]->write(c, kaddr, BY2PG, out->daddr);
- if(n != BY2PG)
- nexterror();
+ n = devtab[c->type]->write(c, kaddr, BY2PG, out->daddr);
+ if(n != BY2PG)
+ nexterror();
+
+ kunmap(k);
+ poperror();
+ }
- kunmap(k);
- poperror();
+ /* drop our extra swap reference */
+ putswap((Page*)out->daddr);
/* Free up the page after I/O */
- lock(out);
- out->ref--;
- unlock(out);
putpage(out);
}
ioptr = 0;