diff options
author | Artur Grabowski <art@cvs.openbsd.org> | 1999-08-23 08:13:26 +0000 |
---|---|---|
committer | Artur Grabowski <art@cvs.openbsd.org> | 1999-08-23 08:13:26 +0000 |
commit | 5e018d13123ba2850afd208f355a0577361e19d2 (patch) | |
tree | 88d1b9ad76f66ffad16bab3cc37857968ca274ac /sys/uvm/uvm_swap.c | |
parent | 238f8e71e72bda976d468ba8817e92e5248e25d3 (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.c | 124 |
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); |