summaryrefslogtreecommitdiff
path: root/sys/uvm/uvm_swap.c
diff options
context:
space:
mode:
authorArtur Grabowski <art@cvs.openbsd.org>1999-08-23 08:13:26 +0000
committerArtur Grabowski <art@cvs.openbsd.org>1999-08-23 08:13:26 +0000
commit5e018d13123ba2850afd208f355a0577361e19d2 (patch)
tree88d1b9ad76f66ffad16bab3cc37857968ca274ac /sys/uvm/uvm_swap.c
parent238f8e71e72bda976d468ba8817e92e5248e25d3 (diff)
sync with NetBSD from 1999.05.24 (there is a reason for this date)
Mostly cleanups, but also a few improvements to pagedaemon for better handling of low memory and/or low swap conditions.
Diffstat (limited to 'sys/uvm/uvm_swap.c')
-rw-r--r--sys/uvm/uvm_swap.c124
1 files changed, 70 insertions, 54 deletions
diff --git a/sys/uvm/uvm_swap.c b/sys/uvm/uvm_swap.c
index 6c0b22c5ae3..21f768a78c4 100644
--- a/sys/uvm/uvm_swap.c
+++ b/sys/uvm/uvm_swap.c
@@ -1,5 +1,4 @@
-/* $OpenBSD: uvm_swap.c,v 1.8 1999/07/08 00:54:28 deraadt Exp $ */
-/* $NetBSD: uvm_swap.c,v 1.23 1998/12/26 06:25:59 marc Exp $ */
+/* $NetBSD: uvm_swap.c,v 1.26 1999/03/26 17:34:16 chs Exp $ */
/*
* Copyright (c) 1995, 1996, 1997 Matthew R. Green
@@ -85,7 +84,7 @@
* - swap_syscall_lock (sleep lock): this lock serializes the swapctl
* system call and prevents the swap priority list from changing
* while we are in the middle of a system call (e.g. SWAP_STATS).
- * - swap_data_lock (simple_lock): this lock protects all swap data
+ * - uvm.swap_data_lock (simple_lock): this lock protects all swap data
* structures including the priority list, the swapdev structures,
* and the swapmap extent.
* - swap_buf_lock (simple_lock): this lock protects the free swapbuf
@@ -236,7 +235,6 @@ static struct swap_priority swap_priority;
/* locks */
lock_data_t swap_syscall_lock;
-static simple_lock_data_t swap_data_lock;
/*
* prototypes
@@ -287,7 +285,7 @@ uvm_swap_init()
LIST_INIT(&swap_priority);
uvmexp.nswapdev = 0;
lockinit(&swap_syscall_lock, PVM, "swapsys", 0, 0);
- simple_lock_init(&swap_data_lock);
+ simple_lock_init(&uvm.swap_data_lock);
if (bdevvp(swapdev, &swapdev_vp))
panic("uvm_swap_init: can't get vnode for swap device");
@@ -347,7 +345,7 @@ uvm_swap_init()
/*
* swaplist_insert: insert swap device "sdp" into the global list
*
- * => caller must hold both swap_syscall_lock and swap_data_lock
+ * => caller must hold both swap_syscall_lock and uvm.swap_data_lock
* => caller must provide a newly malloc'd swappri structure (we will
* FREE it if we don't need it... this it to prevent malloc blocking
* here while adding swap)
@@ -407,7 +405,7 @@ swaplist_insert(sdp, newspp, priority)
* swaplist_find: find and optionally remove a swap device from the
* global list.
*
- * => caller must hold both swap_syscall_lock and swap_data_lock
+ * => caller must hold both swap_syscall_lock and uvm.swap_data_lock
* => we return the swapdev we found (and removed)
*/
static struct swapdev *
@@ -443,7 +441,7 @@ swaplist_find(vp, remove)
* swaplist_trim: scan priority list for empty priority entries and kill
* them.
*
- * => caller must hold both swap_syscall_lock and swap_data_lock
+ * => caller must hold both swap_syscall_lock and uvm.swap_data_lock
*/
static void
swaplist_trim()
@@ -463,7 +461,7 @@ swaplist_trim()
* swapdrum_add: add a "swapdev"'s blocks into /dev/drum's area.
*
* => caller must hold swap_syscall_lock
- * => swap_data_lock should be unlocked (we may sleep)
+ * => uvm.swap_data_lock should be unlocked (we may sleep)
*/
static void
swapdrum_add(sdp, npages)
@@ -485,7 +483,7 @@ swapdrum_add(sdp, npages)
* to the "swapdev" that maps that section of the drum.
*
* => each swapdev takes one big contig chunk of the drum
- * => caller must hold swap_data_lock
+ * => caller must hold uvm.swap_data_lock
*/
static struct swapdev *
swapdrum_getsdp(pgno)
@@ -506,6 +504,7 @@ swapdrum_getsdp(pgno)
return NULL;
}
+
/*
* sys_swapctl: main entry point for swapctl(2) system call
* [with two helper functions: swap_on and swap_off]
@@ -558,7 +557,7 @@ sys_swapctl(p, v, retval)
*
* note that the swap_priority list can't change as long
* as we are holding the swap_syscall_lock. we don't want
- * to grab the swap_data_lock because we may fault&sleep during
+ * to grab the uvm.swap_data_lock because we may fault&sleep during
* copyout() and we don't want to be holding that lock then!
*/
if (SCARG(uap, cmd) == SWAP_STATS
@@ -662,6 +661,15 @@ sys_swapctl(p, v, retval)
error = 0; /* assume no error */
switch(SCARG(uap, cmd)) {
+ case SWAP_DUMPDEV:
+ if (vp->v_type != VBLK) {
+ error = ENOTBLK;
+ goto out;
+ }
+ dumpdev = vp->v_rdev;
+
+ break;
+
case SWAP_CTL:
/*
* get new priority, remove old entry (if any) and then
@@ -671,14 +679,14 @@ sys_swapctl(p, v, retval)
priority = SCARG(uap, misc);
spp = (struct swappri *)
malloc(sizeof *spp, M_VMSWAP, M_WAITOK);
- simple_lock(&swap_data_lock);
+ simple_lock(&uvm.swap_data_lock);
if ((sdp = swaplist_find(vp, 1)) == NULL) {
error = ENOENT;
} else {
swaplist_insert(sdp, spp, priority);
swaplist_trim();
}
- simple_unlock(&swap_data_lock);
+ simple_unlock(&uvm.swap_data_lock);
if (error)
free(spp, M_VMSWAP);
break;
@@ -691,10 +699,10 @@ sys_swapctl(p, v, retval)
* it.
*/
priority = SCARG(uap, misc);
- simple_lock(&swap_data_lock);
+ simple_lock(&uvm.swap_data_lock);
if ((sdp = swaplist_find(vp, 0)) != NULL) {
error = EBUSY;
- simple_unlock(&swap_data_lock);
+ simple_unlock(&uvm.swap_data_lock);
break;
}
sdp = (struct swapdev *)
@@ -713,7 +721,7 @@ sys_swapctl(p, v, retval)
sdp->swd_cred = crdup(p->p_ucred);
#endif
swaplist_insert(sdp, spp, priority);
- simple_unlock(&swap_data_lock);
+ simple_unlock(&uvm.swap_data_lock);
sdp->swd_pathlen = len;
sdp->swd_path = malloc(sdp->swd_pathlen, M_VMSWAP, M_WAITOK);
@@ -726,10 +734,10 @@ sys_swapctl(p, v, retval)
* if swap_on is a success, it will clear the SWF_FAKE flag
*/
if ((error = swap_on(p, sdp)) != 0) {
- simple_lock(&swap_data_lock);
+ simple_lock(&uvm.swap_data_lock);
(void) swaplist_find(vp, 1); /* kill fake entry */
swaplist_trim();
- simple_unlock(&swap_data_lock);
+ simple_unlock(&uvm.swap_data_lock);
#ifdef SWAP_TO_FILES
if (vp->v_type == VREG)
crfree(sdp->swd_cred);
@@ -752,9 +760,9 @@ sys_swapctl(p, v, retval)
/*
* find the entry of interest and ensure it is enabled.
*/
- simple_lock(&swap_data_lock);
+ simple_lock(&uvm.swap_data_lock);
if ((sdp = swaplist_find(vp, 0)) == NULL) {
- simple_unlock(&swap_data_lock);
+ simple_unlock(&uvm.swap_data_lock);
error = ENXIO;
break;
}
@@ -763,7 +771,7 @@ sys_swapctl(p, v, retval)
* can't stop swapping from it (again).
*/
if ((sdp->swd_flags & (SWF_INUSE|SWF_ENABLE)) == 0) {
- simple_unlock(&swap_data_lock);
+ simple_unlock(&uvm.swap_data_lock);
error = EBUSY;
break;
}
@@ -779,7 +787,7 @@ sys_swapctl(p, v, retval)
error = ENXIO;
break;
}
- simple_unlock(&swap_data_lock);
+ simple_unlock(&uvm.swap_data_lock);
free((caddr_t)sdp, M_VMSWAP);
#else
error = EINVAL;
@@ -810,7 +818,7 @@ out:
*
* => we avoid the start of the disk (to protect disk labels)
* => we also avoid the miniroot, if we are swapping to root.
- * => caller should leave swap_data_lock unlocked, we may lock it
+ * => caller should leave uvm.swap_data_lock unlocked, we may lock it
* if needed.
*/
static int
@@ -953,9 +961,11 @@ swap_on(p, sdp)
if (extent_alloc_region(sdp->swd_ex, 0, addr, EX_WAITOK))
panic("disklabel region");
sdp->swd_npginuse += addr;
+ simple_lock(&uvm.swap_data_lock);
uvmexp.swpginuse += addr;
+ uvmexp.swpgonly += addr;
+ simple_unlock(&uvm.swap_data_lock);
}
-
/*
* if the vnode we are swapping to is the root vnode
@@ -979,8 +989,11 @@ swap_on(p, sdp)
rootpages, EX_WAITOK))
panic("swap_on: unable to preserve miniroot");
+ simple_lock(&uvm.swap_data_lock);
sdp->swd_npginuse += (rootpages - addr);
uvmexp.swpginuse += (rootpages - addr);
+ uvmexp.swpgonly += (rootpages - addr);
+ simple_unlock(&uvm.swap_data_lock);
printf("Preserved %d pages of miniroot ", rootpages);
printf("leaving %d pages of swap\n", size - rootpages);
@@ -989,12 +1002,12 @@ swap_on(p, sdp)
/*
* now add the new swapdev to the drum and enable.
*/
- simple_lock(&swap_data_lock);
+ simple_lock(&uvm.swap_data_lock);
swapdrum_add(sdp, npages);
sdp->swd_npages = npages;
sdp->swd_flags &= ~SWF_FAKE; /* going live */
sdp->swd_flags |= (SWF_INUSE|SWF_ENABLE);
- simple_unlock(&swap_data_lock);
+ simple_unlock(&uvm.swap_data_lock);
uvmexp.swpages += npages;
/*
@@ -1147,8 +1160,7 @@ swstrategy(bp)
{
struct swapdev *sdp;
struct vnode *vp;
- int pageno;
- int bn;
+ int s, pageno, bn;
UVMHIST_FUNC("swstrategy"); UVMHIST_CALLED(pdhist);
/*
@@ -1157,9 +1169,9 @@ swstrategy(bp)
* in it (i.e. the blocks we are doing I/O on).
*/
pageno = dbtob(bp->b_blkno) >> PAGE_SHIFT;
- simple_lock(&swap_data_lock);
+ simple_lock(&uvm.swap_data_lock);
sdp = swapdrum_getsdp(pageno);
- simple_unlock(&swap_data_lock);
+ simple_unlock(&uvm.swap_data_lock);
if (sdp == NULL) {
bp->b_error = EINVAL;
bp->b_flags |= B_ERROR;
@@ -1195,6 +1207,7 @@ swstrategy(bp)
* must convert "bp" from an I/O on /dev/drum to an I/O
* on the swapdev (sdp).
*/
+ s = splbio();
bp->b_blkno = bn; /* swapdev block number */
vp = sdp->swd_vp; /* swapdev vnode pointer */
bp->b_dev = sdp->swd_dev; /* swapdev dev_t */
@@ -1205,10 +1218,8 @@ swstrategy(bp)
* drum's v_numoutput counter to the swapdevs.
*/
if ((bp->b_flags & B_READ) == 0) {
- int s = splbio();
vwakeup(bp); /* kills one 'v_numoutput' on drum */
vp->v_numoutput++; /* put it on swapdev */
- splx(s);
}
/*
@@ -1222,6 +1233,7 @@ swstrategy(bp)
* finally plug in swapdev vnode and start I/O
*/
bp->b_vp = vp;
+ splx(s);
VOP_STRATEGY(bp);
return;
#ifdef SWAP_TO_FILES
@@ -1550,7 +1562,7 @@ sw_reg_iodone(bp)
* allocate in a priority we "rotate" the circle queue.
* => space can be freed with uvm_swap_free
* => we return the page slot number in /dev/drum (0 == invalid slot)
- * => we lock swap_data_lock
+ * => we lock uvm.swap_data_lock
* => XXXMRG: "LESSOK" INTERFACE NEEDED TO EXTENT SYSTEM
*/
int
@@ -1572,7 +1584,7 @@ uvm_swap_alloc(nslots, lessok)
/*
* lock data lock, convert slots into blocks, and enter loop
*/
- simple_lock(&swap_data_lock);
+ simple_lock(&uvm.swap_data_lock);
ReTry: /* XXXMRG */
for (spp = swap_priority.lh_first; spp != NULL;
@@ -1598,23 +1610,11 @@ ReTry: /* XXXMRG */
CIRCLEQ_INSERT_TAIL(&spp->spi_swapdev, sdp, swd_next);
sdp->swd_npginuse += *nslots;
uvmexp.swpginuse += *nslots;
- simple_unlock(&swap_data_lock);
+ simple_unlock(&uvm.swap_data_lock);
/* done! return drum slot number */
UVMHIST_LOG(pdhist,
"success! returning %d slots starting at %d",
*nslots, result + sdp->swd_drumoffset, 0, 0);
-#if 0
-{
- struct swapdev *sdp2;
-
- sdp2 = swapdrum_getsdp(result + sdp->swd_drumoffset);
- if (sdp2 == NULL) {
-printf("uvm_swap_alloc: nslots=%d, dev=%x, drumoff=%d, result=%ld",
- *nslots, sdp->swd_dev, sdp->swd_drumoffset, result);
-panic("uvm_swap_alloc: allocating unmapped swap block!");
- }
-}
-#endif
return(result + sdp->swd_drumoffset);
}
}
@@ -1626,7 +1626,7 @@ panic("uvm_swap_alloc: allocating unmapped swap block!");
}
/* XXXMRG: END HACK */
- simple_unlock(&swap_data_lock);
+ simple_unlock(&uvm.swap_data_lock);
return 0; /* failed */
}
@@ -1634,7 +1634,7 @@ panic("uvm_swap_alloc: allocating unmapped swap block!");
* uvm_swap_free: free swap slots
*
* => this can be all or part of an allocation made by uvm_swap_alloc
- * => we lock swap_data_lock
+ * => we lock uvm.swap_data_lock
*/
void
uvm_swap_free(startslot, nslots)
@@ -1651,7 +1651,7 @@ uvm_swap_free(startslot, nslots)
* in the extent, and return. must hold pri lock to do
* lookup and access the extent.
*/
- simple_lock(&swap_data_lock);
+ simple_lock(&uvm.swap_data_lock);
sdp = swapdrum_getsdp(startslot);
#ifdef DIAGNOSTIC
@@ -1674,7 +1674,7 @@ uvm_swap_free(startslot, nslots)
if (sdp->swd_npginuse < 0)
panic("uvm_swap_free: inuse < 0");
#endif
- simple_unlock(&swap_data_lock);
+ simple_unlock(&uvm.swap_data_lock);
}
/*
@@ -1721,9 +1721,25 @@ uvm_swap_get(page, swslot, flags)
printf("uvm_swap_get: ASYNC get requested?\n");
#endif
+ /*
+ * this page is (about to be) no longer only in swap.
+ */
+ simple_lock(&uvm.swap_data_lock);
+ uvmexp.swpgonly--;
+ simple_unlock(&uvm.swap_data_lock);
+
result = uvm_swap_io(&page, swslot, 1, B_READ |
((flags & PGO_SYNCIO) ? 0 : B_ASYNC));
+ if (result != VM_PAGER_OK && result != VM_PAGER_PEND) {
+ /*
+ * oops, the read failed so it really is still only in swap.
+ */
+ simple_lock(&uvm.swap_data_lock);
+ uvmexp.swpgonly++;
+ simple_unlock(&uvm.swap_data_lock);
+ }
+
return (result);
}
@@ -1789,8 +1805,10 @@ uvm_swap_io(pps, startslot, npages, flags)
bp->b_vnbufs.le_next = NOLIST;
bp->b_data = (caddr_t)kva;
bp->b_blkno = startblk;
+ s = splbio();
VHOLD(swapdev_vp);
bp->b_vp = swapdev_vp;
+ splx(s);
/* XXXCDC: isn't swapdev_vp always a VCHR? */
/* XXXMRG: probably -- this is obviously something inherited... */
if (swapdev_vp->v_type == VBLK)
@@ -1848,7 +1866,6 @@ uvm_swap_io(pps, startslot, npages, flags)
* now dispose of the swap buffer
*/
s = splbio();
- bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS|B_PAGET|B_UAREA|B_DIRTY|B_NOCACHE);
if (bp->b_vp)
brelvp(bp);
@@ -1883,9 +1900,8 @@ uvm_swap_bufdone(bp)
#endif
/*
- * drop buffers reference to the vnode and its flags.
+ * drop the buffer's reference to the vnode.
*/
- bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS|B_PAGET|B_UAREA|B_DIRTY|B_NOCACHE);
if (bp->b_vp)
brelvp(bp);