swap: make sure swap address sticks arround until page is written to swap
we have to make sure the *swap address* doesnt go away, after putting the swap address in the segment pte. after we unlock the segment, the process could be killed or fault which would cause the swap address to be freed *before* we write the page to disk when it pulls the page from the cache and putswap() swap pte. keeping a reference to the page is no good. we have to hold on the swap address. this also has the advantage that we can now test if the swap address is still referenced and can avoid writing to disk.
This commit is contained in:
parent
fcfa74a1cf
commit
1b8fb4fec3
1 changed files with 23 additions and 22 deletions
|
@ -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);
|
||||
|
@ -337,12 +340,6 @@ pagepte(int type, Page **pg)
|
|||
/* forget anything that it used to cache */
|
||||
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
|
||||
|
@ -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);
|
||||
|
||||
n = devtab[c->type]->write(c, kaddr, BY2PG, out->daddr);
|
||||
if(n != BY2PG)
|
||||
nexterror();
|
||||
if(waserror())
|
||||
panic("executeio: page out I/O error");
|
||||
|
||||
kunmap(k);
|
||||
poperror();
|
||||
n = devtab[c->type]->write(c, kaddr, BY2PG, out->daddr);
|
||||
if(n != BY2PG)
|
||||
nexterror();
|
||||
|
||||
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;
|
||||
|
|
Loading…
Reference in a new issue