diff options
author | dyson <dyson@FreeBSD.org> | 1998-01-17 09:17:02 +0000 |
---|---|---|
committer | dyson <dyson@FreeBSD.org> | 1998-01-17 09:17:02 +0000 |
commit | b130b30c96fd365316e5a4f21ec0965be052e78b (patch) | |
tree | 5fa8acd32fec5f8fc8f142f0696ee005c2542f64 | |
parent | de471d9a3b481d2b4870deedad64835148e99c26 (diff) | |
download | FreeBSD-src-b130b30c96fd365316e5a4f21ec0965be052e78b.zip FreeBSD-src-b130b30c96fd365316e5a4f21ec0965be052e78b.tar.gz |
Tie up some loose ends in vnode/object management. Remove an unneeded
config option in pmap. Fix a problem with faulting in pages. Clean-up
some loose ends in swap pager memory management.
The system should be much more stable, but all subtile bugs aren't fixed yet.
-rw-r--r-- | sys/amd64/amd64/pmap.c | 30 | ||||
-rw-r--r-- | sys/i386/i386/pmap.c | 30 | ||||
-rw-r--r-- | sys/kern/vfs_bio.c | 16 | ||||
-rw-r--r-- | sys/kern/vfs_export.c | 35 | ||||
-rw-r--r-- | sys/kern/vfs_subr.c | 35 | ||||
-rw-r--r-- | sys/sys/vnode.h | 5 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_vfsops.c | 5 | ||||
-rw-r--r-- | sys/vm/swap_pager.c | 39 | ||||
-rw-r--r-- | sys/vm/vm_fault.c | 92 | ||||
-rw-r--r-- | sys/vm/vm_map.c | 256 | ||||
-rw-r--r-- | sys/vm/vm_map.h | 6 | ||||
-rw-r--r-- | sys/vm/vm_object.c | 40 | ||||
-rw-r--r-- | sys/vm/vm_object.h | 4 | ||||
-rw-r--r-- | sys/vm/vm_page.c | 38 | ||||
-rw-r--r-- | sys/vm/vm_pageout.c | 27 | ||||
-rw-r--r-- | sys/vm/vnode_pager.c | 14 |
16 files changed, 346 insertions, 326 deletions
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c index fa9b6bd..d3f0ec0 100644 --- a/sys/amd64/amd64/pmap.c +++ b/sys/amd64/amd64/pmap.c @@ -39,7 +39,7 @@ * SUCH DAMAGE. * * from: @(#)pmap.c 7.7 (Berkeley) 5/12/91 - * $Id: pmap.c,v 1.175 1997/12/22 00:36:48 dyson Exp $ + * $Id: pmap.c,v 1.176 1997/12/22 10:06:09 dyson Exp $ */ /* @@ -115,8 +115,6 @@ #define PMAP_INLINE #endif -#define PTPHINT - /* * Get PDEs and PTEs for user/kernel address space */ @@ -1051,10 +1049,8 @@ _pmap_unwire_pte_hold(pmap_t pmap, vm_page_t m) { invltlb_1pg(pteva); } -#if defined(PTPHINT) if (pmap->pm_ptphint == m) pmap->pm_ptphint = NULL; -#endif /* * If the page is finally unwired, simply free it. @@ -1100,7 +1096,6 @@ pmap_unuse_pt(pmap, va, mpte) if (mpte == NULL) { ptepindex = (va >> PDRSHIFT); -#if defined(PTPHINT) if (pmap->pm_ptphint && (pmap->pm_ptphint->pindex == ptepindex)) { mpte = pmap->pm_ptphint; @@ -1108,9 +1103,6 @@ pmap_unuse_pt(pmap, va, mpte) mpte = pmap_page_lookup( pmap->pm_pteobj, ptepindex); pmap->pm_ptphint = mpte; } -#else - mpte = pmap_page_lookup( pmap->pm_pteobj, ptepindex); -#endif } return pmap_unwire_pte_hold(pmap, mpte); @@ -1244,11 +1236,9 @@ pmap_release_free_page(pmap, p) pmap_kremove((vm_offset_t) pmap->pm_pdir); } -#if defined(PTPHINT) if (pmap->pm_ptphint && (pmap->pm_ptphint->pindex == p->pindex)) pmap->pm_ptphint = NULL; -#endif vm_page_free_zero(p); splx(s); @@ -1315,12 +1305,10 @@ retry: ptepa = VM_PAGE_TO_PHYS(m); pmap->pm_pdir[ptepindex] = (pd_entry_t) (ptepa | PG_U | PG_RW | PG_V); -#if defined(PTPHINT) /* * Set the page table hint */ pmap->pm_ptphint = m; -#endif /* * Try to use the new mapping, but if we cannot, then @@ -1376,7 +1364,6 @@ pmap_allocpte(pmap, va) * hold count, and activate it. */ if (ptepa) { -#if defined(PTPHINT) /* * In order to get the page table page, try the * hint first. @@ -1388,9 +1375,6 @@ pmap_allocpte(pmap, va) m = pmap_page_lookup( pmap->pm_pteobj, ptepindex); pmap->pm_ptphint = m; } -#else - m = pmap_page_lookup( pmap->pm_pteobj, ptepindex); -#endif ++m->hold_count; return m; } @@ -2252,7 +2236,6 @@ retry: if (ptepa) { if (ptepa & PG_PS) panic("pmap_enter_quick: unexpected mapping into 4MB page"); -#if defined(PTPHINT) if (pmap->pm_ptphint && (pmap->pm_ptphint->pindex == ptepindex)) { mpte = pmap->pm_ptphint; @@ -2260,9 +2243,6 @@ retry: mpte = pmap_page_lookup( pmap->pm_pteobj, ptepindex); pmap->pm_ptphint = mpte; } -#else - mpte = pmap_page_lookup( pmap->pm_pteobj, ptepindex); -#endif if (mpte == NULL) goto retry; ++mpte->hold_count; @@ -2469,12 +2449,14 @@ retry: * of pmap_object_init_pt, except it runs at page fault time instead * of mmap time. */ -#define PFBAK 2 -#define PFFOR 2 +#define PFBAK 3 +#define PFFOR 3 #define PAGEORDER_SIZE (PFBAK+PFFOR) static int pmap_prefault_pageorder[] = { - -PAGE_SIZE, PAGE_SIZE, -2 * PAGE_SIZE, 2 * PAGE_SIZE + -PAGE_SIZE, PAGE_SIZE, + -2 * PAGE_SIZE, 2 * PAGE_SIZE, + -3 * PAGE_SIZE, 3 * PAGE_SIZE }; void diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c index fa9b6bd..d3f0ec0 100644 --- a/sys/i386/i386/pmap.c +++ b/sys/i386/i386/pmap.c @@ -39,7 +39,7 @@ * SUCH DAMAGE. * * from: @(#)pmap.c 7.7 (Berkeley) 5/12/91 - * $Id: pmap.c,v 1.175 1997/12/22 00:36:48 dyson Exp $ + * $Id: pmap.c,v 1.176 1997/12/22 10:06:09 dyson Exp $ */ /* @@ -115,8 +115,6 @@ #define PMAP_INLINE #endif -#define PTPHINT - /* * Get PDEs and PTEs for user/kernel address space */ @@ -1051,10 +1049,8 @@ _pmap_unwire_pte_hold(pmap_t pmap, vm_page_t m) { invltlb_1pg(pteva); } -#if defined(PTPHINT) if (pmap->pm_ptphint == m) pmap->pm_ptphint = NULL; -#endif /* * If the page is finally unwired, simply free it. @@ -1100,7 +1096,6 @@ pmap_unuse_pt(pmap, va, mpte) if (mpte == NULL) { ptepindex = (va >> PDRSHIFT); -#if defined(PTPHINT) if (pmap->pm_ptphint && (pmap->pm_ptphint->pindex == ptepindex)) { mpte = pmap->pm_ptphint; @@ -1108,9 +1103,6 @@ pmap_unuse_pt(pmap, va, mpte) mpte = pmap_page_lookup( pmap->pm_pteobj, ptepindex); pmap->pm_ptphint = mpte; } -#else - mpte = pmap_page_lookup( pmap->pm_pteobj, ptepindex); -#endif } return pmap_unwire_pte_hold(pmap, mpte); @@ -1244,11 +1236,9 @@ pmap_release_free_page(pmap, p) pmap_kremove((vm_offset_t) pmap->pm_pdir); } -#if defined(PTPHINT) if (pmap->pm_ptphint && (pmap->pm_ptphint->pindex == p->pindex)) pmap->pm_ptphint = NULL; -#endif vm_page_free_zero(p); splx(s); @@ -1315,12 +1305,10 @@ retry: ptepa = VM_PAGE_TO_PHYS(m); pmap->pm_pdir[ptepindex] = (pd_entry_t) (ptepa | PG_U | PG_RW | PG_V); -#if defined(PTPHINT) /* * Set the page table hint */ pmap->pm_ptphint = m; -#endif /* * Try to use the new mapping, but if we cannot, then @@ -1376,7 +1364,6 @@ pmap_allocpte(pmap, va) * hold count, and activate it. */ if (ptepa) { -#if defined(PTPHINT) /* * In order to get the page table page, try the * hint first. @@ -1388,9 +1375,6 @@ pmap_allocpte(pmap, va) m = pmap_page_lookup( pmap->pm_pteobj, ptepindex); pmap->pm_ptphint = m; } -#else - m = pmap_page_lookup( pmap->pm_pteobj, ptepindex); -#endif ++m->hold_count; return m; } @@ -2252,7 +2236,6 @@ retry: if (ptepa) { if (ptepa & PG_PS) panic("pmap_enter_quick: unexpected mapping into 4MB page"); -#if defined(PTPHINT) if (pmap->pm_ptphint && (pmap->pm_ptphint->pindex == ptepindex)) { mpte = pmap->pm_ptphint; @@ -2260,9 +2243,6 @@ retry: mpte = pmap_page_lookup( pmap->pm_pteobj, ptepindex); pmap->pm_ptphint = mpte; } -#else - mpte = pmap_page_lookup( pmap->pm_pteobj, ptepindex); -#endif if (mpte == NULL) goto retry; ++mpte->hold_count; @@ -2469,12 +2449,14 @@ retry: * of pmap_object_init_pt, except it runs at page fault time instead * of mmap time. */ -#define PFBAK 2 -#define PFFOR 2 +#define PFBAK 3 +#define PFFOR 3 #define PAGEORDER_SIZE (PFBAK+PFFOR) static int pmap_prefault_pageorder[] = { - -PAGE_SIZE, PAGE_SIZE, -2 * PAGE_SIZE, 2 * PAGE_SIZE + -PAGE_SIZE, PAGE_SIZE, + -2 * PAGE_SIZE, 2 * PAGE_SIZE, + -3 * PAGE_SIZE, 3 * PAGE_SIZE }; void diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index 5a1633a..d00bffe 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -11,7 +11,7 @@ * 2. Absolutely no warranty of function or purpose is made by the author * John S. Dyson. * - * $Id: vfs_bio.c,v 1.141 1998/01/06 05:15:55 dyson Exp $ + * $Id: vfs_bio.c,v 1.142 1998/01/12 01:46:25 dyson Exp $ */ /* @@ -793,11 +793,6 @@ vfs_vmio_release(bp) vp = bp->b_vp; vm_page_protect(m, VM_PROT_NONE); vm_page_free(m); - if (vp && VSHOULDFREE(vp) && - (vp->v_flag & (VFREE|VTBFREE)) == 0) { - TAILQ_INSERT_TAIL(&vnode_tobefree_list, vp, v_freelist); - vp->v_flag |= VTBFREE; - } } } else { /* @@ -892,7 +887,9 @@ vfs_bio_awrite(struct buf * bp) splx(s); return nwritten; } - } else if ((vp->v_flag & VOBJBUF) && (vp->v_type == VBLK) && + } +#if 0 + else if ((vp->v_flag & VOBJBUF) && (vp->v_type == VBLK) && ((size = bp->b_bufsize) >= PAGE_SIZE)) { maxcl = MAXPHYS / size; for (i = 1; i < maxcl; i++) { @@ -913,11 +910,11 @@ vfs_bio_awrite(struct buf * bp) */ if (ncl != 1) { nwritten = cluster_wbuild(vp, size, lblkno, ncl); - printf("Block cluster: (%d, %d)\n", lblkno, nwritten); splx(s); return nwritten; } } +#endif bremfree(bp); splx(s); @@ -1086,6 +1083,7 @@ trytofreespace: brelvp(bp); fillbuf: + /* we are not free, nor do we contain interesting data */ if (bp->b_rcred != NOCRED) { crfree(bp->b_rcred); @@ -1112,7 +1110,7 @@ fillbuf: bp->b_npages = 0; bp->b_dirtyoff = bp->b_dirtyend = 0; bp->b_validoff = bp->b_validend = 0; - bp->b_usecount = 4; + bp->b_usecount = 5; maxsize = (maxsize + PAGE_MASK) & ~PAGE_MASK; diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c index 8ae2ba4..3b0eb61 100644 --- a/sys/kern/vfs_export.c +++ b/sys/kern/vfs_export.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)vfs_subr.c 8.31 (Berkeley) 5/26/95 - * $Id: vfs_subr.c,v 1.122 1998/01/12 01:46:30 dyson Exp $ + * $Id: vfs_subr.c,v 1.123 1998/01/12 03:15:01 dyson Exp $ */ /* @@ -66,6 +66,7 @@ #include <vm/vm_extern.h> #include <vm/pmap.h> #include <vm/vm_map.h> +#include <vm/vm_pager.h> #include <vm/vnode_pager.h> #include <sys/sysctl.h> @@ -77,7 +78,6 @@ static void insmntque __P((struct vnode *vp, struct mount *mp)); #ifdef DDB static void printlockedvnodes __P((void)); #endif -static void vbusy __P((struct vnode *)); static void vclean __P((struct vnode *vp, int flags, struct proc *p)); static void vfree __P((struct vnode *)); static void vgonel __P((struct vnode *vp, struct proc *p)); @@ -110,7 +110,7 @@ SYSCTL_INT(_debug, OID_AUTO, wantfreevnodes, CTLFLAG_RW, &wantfreevnodes, 0, "") static u_long freevnodes = 0; SYSCTL_INT(_debug, OID_AUTO, freevnodes, CTLFLAG_RD, &freevnodes, 0, ""); -int vfs_ioopt = 2; +int vfs_ioopt = 0; SYSCTL_INT(_vfs, OID_AUTO, ioopt, CTLFLAG_RW, &vfs_ioopt, 0, ""); struct mntlist mountlist; /* mounted filesystem list */ @@ -374,8 +374,11 @@ getnewvnode(tag, mp, vops, vpp) for (vp = TAILQ_FIRST(&vnode_tobefree_list); vp; vp = nvp) { nvp = TAILQ_NEXT(vp, v_freelist); TAILQ_REMOVE(&vnode_tobefree_list, vp, v_freelist); - TAILQ_INSERT_TAIL(&vnode_tmp_list, vp, v_freelist); + TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist); vp->v_flag &= ~VTBFREE; + vp->v_flag |= VFREE; + if (vp->v_usecount) + panic("tobe free vnode isn't"); freevnodes++; } @@ -1171,9 +1174,6 @@ vclean(vp, flags, p) if ((active = vp->v_usecount)) vp->v_usecount++; - if (vp->v_object) { - vp->v_object->flags |= OBJ_DEAD; - } /* * Prevent the vnode from being recycled or brought into use while we * clean it out. @@ -1193,10 +1193,21 @@ vclean(vp, flags, p) /* * Clean out any buffers associated with the vnode. */ - if (vp->v_object) - vm_object_terminate(vp->v_object); - else - vinvalbuf(vp, V_SAVE, NOCRED, p, 0, 0); + vinvalbuf(vp, V_SAVE, NOCRED, p, 0, 0); + if (vp->v_object) { + if (vp->v_object->ref_count == 0) { + /* + * This is a normal way of shutting down the object/vnode + * association. + */ + vm_object_terminate(vp->v_object); + } else { + /* + * Woe to the process that tries to page now :-). + */ + vm_pager_deallocate(vp->v_object); + } + } /* * If purging an active vnode, it must be closed and @@ -2186,7 +2197,7 @@ vfree(vp) splx(s); } -static void +void vbusy(vp) struct vnode *vp; { diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 8ae2ba4..3b0eb61 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)vfs_subr.c 8.31 (Berkeley) 5/26/95 - * $Id: vfs_subr.c,v 1.122 1998/01/12 01:46:30 dyson Exp $ + * $Id: vfs_subr.c,v 1.123 1998/01/12 03:15:01 dyson Exp $ */ /* @@ -66,6 +66,7 @@ #include <vm/vm_extern.h> #include <vm/pmap.h> #include <vm/vm_map.h> +#include <vm/vm_pager.h> #include <vm/vnode_pager.h> #include <sys/sysctl.h> @@ -77,7 +78,6 @@ static void insmntque __P((struct vnode *vp, struct mount *mp)); #ifdef DDB static void printlockedvnodes __P((void)); #endif -static void vbusy __P((struct vnode *)); static void vclean __P((struct vnode *vp, int flags, struct proc *p)); static void vfree __P((struct vnode *)); static void vgonel __P((struct vnode *vp, struct proc *p)); @@ -110,7 +110,7 @@ SYSCTL_INT(_debug, OID_AUTO, wantfreevnodes, CTLFLAG_RW, &wantfreevnodes, 0, "") static u_long freevnodes = 0; SYSCTL_INT(_debug, OID_AUTO, freevnodes, CTLFLAG_RD, &freevnodes, 0, ""); -int vfs_ioopt = 2; +int vfs_ioopt = 0; SYSCTL_INT(_vfs, OID_AUTO, ioopt, CTLFLAG_RW, &vfs_ioopt, 0, ""); struct mntlist mountlist; /* mounted filesystem list */ @@ -374,8 +374,11 @@ getnewvnode(tag, mp, vops, vpp) for (vp = TAILQ_FIRST(&vnode_tobefree_list); vp; vp = nvp) { nvp = TAILQ_NEXT(vp, v_freelist); TAILQ_REMOVE(&vnode_tobefree_list, vp, v_freelist); - TAILQ_INSERT_TAIL(&vnode_tmp_list, vp, v_freelist); + TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist); vp->v_flag &= ~VTBFREE; + vp->v_flag |= VFREE; + if (vp->v_usecount) + panic("tobe free vnode isn't"); freevnodes++; } @@ -1171,9 +1174,6 @@ vclean(vp, flags, p) if ((active = vp->v_usecount)) vp->v_usecount++; - if (vp->v_object) { - vp->v_object->flags |= OBJ_DEAD; - } /* * Prevent the vnode from being recycled or brought into use while we * clean it out. @@ -1193,10 +1193,21 @@ vclean(vp, flags, p) /* * Clean out any buffers associated with the vnode. */ - if (vp->v_object) - vm_object_terminate(vp->v_object); - else - vinvalbuf(vp, V_SAVE, NOCRED, p, 0, 0); + vinvalbuf(vp, V_SAVE, NOCRED, p, 0, 0); + if (vp->v_object) { + if (vp->v_object->ref_count == 0) { + /* + * This is a normal way of shutting down the object/vnode + * association. + */ + vm_object_terminate(vp->v_object); + } else { + /* + * Woe to the process that tries to page now :-). + */ + vm_pager_deallocate(vp->v_object); + } + } /* * If purging an active vnode, it must be closed and @@ -2186,7 +2197,7 @@ vfree(vp) splx(s); } -static void +void vbusy(vp) struct vnode *vp; { diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index cc4fa03..c9689f0 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)vnode.h 8.7 (Berkeley) 2/4/94 - * $Id: vnode.h,v 1.63 1998/01/06 05:23:04 dyson Exp $ + * $Id: vnode.h,v 1.64 1998/01/12 01:44:08 dyson Exp $ */ #ifndef _SYS_VNODE_H_ @@ -281,7 +281,7 @@ extern void (*lease_updatetime) __P((int deltat)); !((vp)->v_object->ref_count || (vp)->v_object->resident_page_count))) #define VSHOULDBUSY(vp) \ - (((vp)->v_flag & VFREE) && \ + (((vp)->v_flag & (VFREE|VTBFREE)) && \ ((vp)->v_holdcnt || (vp)->v_usecount)) #endif /* KERNEL */ @@ -525,6 +525,7 @@ struct vnode * void vput __P((struct vnode *vp)); void vrele __P((struct vnode *vp)); void vref __P((struct vnode *vp)); +void vbusy __P((struct vnode *vp)); extern vop_t **default_vnodeop_p; diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index e78bceb..4de0f52 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)ffs_vfsops.c 8.31 (Berkeley) 5/20/95 - * $Id: ffs_vfsops.c,v 1.63 1997/12/29 00:24:28 dyson Exp $ + * $Id: ffs_vfsops.c,v 1.64 1998/01/06 05:23:41 dyson Exp $ */ #include "opt_quota.h" @@ -747,9 +747,6 @@ ffs_unmount(mp, mntflags, p) ump->um_devvp->v_specflags &= ~SI_MOUNTEDON; vinvalbuf(ump->um_devvp, V_SAVE, NOCRED, p, 0, 0); - if (ump->um_devvp->v_object) - vm_object_terminate(ump->um_devvp->v_object); - error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE, NOCRED, p); diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c index a2e6e72..5ba0224 100644 --- a/sys/vm/swap_pager.c +++ b/sys/vm/swap_pager.c @@ -39,7 +39,7 @@ * from: Utah $Hdr: swap_pager.c 1.4 91/04/30$ * * @(#)swap_pager.c 8.9 (Berkeley) 3/21/94 - * $Id: swap_pager.c,v 1.79 1997/12/02 21:07:19 phk Exp $ + * $Id: swap_pager.c,v 1.80 1997/12/24 15:05:21 dyson Exp $ */ /* @@ -477,30 +477,33 @@ swap_pager_free_swap(object) /* * Free left over swap blocks */ - s = splbio(); - for (i = 0, swb = object->un_pager.swp.swp_blocks; - i < object->un_pager.swp.swp_nblocks; i++, swb++) { + s = splvm(); + swb = object->un_pager.swp.swp_blocks; + if (!swb) + return; + + for (i = 0; i < object->un_pager.swp.swp_nblocks; i++, swb++) { for (j = 0; j < SWB_NPAGES; j++) { if (swb->swb_block[j] != SWB_EMPTY) { /* - * initially the length of the run is zero - */ + * initially the length of the run is zero + */ if (block_count == 0) { first_block = swb->swb_block[j]; block_count = btodb(PAGE_SIZE); swb->swb_block[j] = SWB_EMPTY; /* - * if the new block can be included into the current run - */ + * if the new block can be included into the current run + */ } else if (swb->swb_block[j] == first_block + block_count) { block_count += btodb(PAGE_SIZE); swb->swb_block[j] = SWB_EMPTY; /* - * terminate the previous run, and start a new one - */ + * terminate the previous run, and start a new one + */ } else { swap_pager_freeswapspace(object, first_block, - (unsigned) first_block + block_count - 1); + (unsigned) first_block + block_count - 1); first_block = swb->swb_block[j]; block_count = btodb(PAGE_SIZE); swb->swb_block[j] = SWB_EMPTY; @@ -719,6 +722,7 @@ swap_pager_dealloc(object) vm_object_t object; { int s; + sw_blk_t swb; /* * Remove from list right away so lookups will fail if we block for @@ -753,11 +757,14 @@ swap_pager_dealloc(object) printf("swap_pager_dealloc: *warning* freeing pager with %d blocks\n", object->un_pager.swp.swp_allocsize); } - /* - * Free swap management resources - */ - free(object->un_pager.swp.swp_blocks, M_VMPGDATA); - object->un_pager.swp.swp_blocks = NULL; + swb = object->un_pager.swp.swp_blocks; + if (swb) { + /* + * Free swap management resources + */ + free(swb, M_VMPGDATA); + object->un_pager.swp.swp_blocks = NULL; + } } static inline int diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index 2185e33..65dcaa5 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -66,7 +66,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_fault.c,v 1.73 1998/01/06 05:25:54 dyson Exp $ + * $Id: vm_fault.c,v 1.74 1998/01/12 01:44:25 dyson Exp $ */ /* @@ -96,8 +96,8 @@ int vm_fault_additional_pages __P((vm_page_t, int, int, vm_page_t *, int *)); -#define VM_FAULT_READ_AHEAD 4 -#define VM_FAULT_READ_BEHIND 3 +#define VM_FAULT_READ_AHEAD 8 +#define VM_FAULT_READ_BEHIND 7 #define VM_FAULT_READ (VM_FAULT_READ_AHEAD+VM_FAULT_READ_BEHIND+1) /* @@ -151,7 +151,10 @@ vm_fault(vm_map_t map, vm_offset_t vaddr, vm_prot_t fault_type, int fault_flags) #define RELEASE_PAGE(m) { \ PAGE_WAKEUP(m); \ - if (m->queue != PQ_ACTIVE) vm_page_activate(m); \ + if (m->queue != PQ_ACTIVE) { \ + vm_page_activate(m); \ + m->act_count = 0; \ + } \ } #define UNLOCK_MAP { \ @@ -168,7 +171,10 @@ vm_fault(vm_map_t map, vm_offset_t vaddr, vm_prot_t fault_type, int fault_flags) vm_object_pip_wakeup(first_object); \ } \ UNLOCK_MAP; \ - if (vp != NULL) VOP_UNLOCK(vp, 0, p); \ + if (vp != NULL) { \ + vput(vp); \ + vp = NULL; \ + } \ } #define UNLOCK_AND_DEALLOCATE { \ @@ -183,11 +189,35 @@ RetryFault:; * Find the backing store object and offset into it to begin the * search. */ - if ((result = vm_map_lookup(&map, vaddr, fault_type, &entry, &first_object, &first_pindex, &prot, &wired, &su)) != KERN_SUCCESS) { - return (result); + if ((result != KERN_PROTECTION_FAILURE) || + ((fault_flags & VM_FAULT_WIRE_MASK) != VM_FAULT_USER_WIRE)) { + return result; + } + + /* + * If we are user-wiring a r/w segment, and it is COW, then + * we need to do the COW operation. Note that we don't COW + * currently RO sections now, because it is NOT desirable + * to COW .text. We simply keep .text from ever being COW'ed + * and take the heat that one cannot debug wired .text sections. + */ + result = vm_map_lookup(&map, vaddr, + VM_PROT_READ|VM_PROT_WRITE|VM_PROT_OVERRIDE_WRITE, + &entry, &first_object, &first_pindex, &prot, &wired, &su); + if (result != KERN_SUCCESS) { + return result; + } + + /* + * If we don't COW now, on a user wire, the user will never + * be able to write to the mapping. If we don't make this + * restriction, the bookkeeping would be nearly impossible. + */ + if ((entry->protection & VM_PROT_WRITE) == 0) + entry->max_protection &= ~VM_PROT_WRITE; } if (entry->eflags & MAP_ENTRY_NOFAULT) { @@ -196,33 +226,6 @@ RetryFault:; } /* - * If we are user-wiring a r/w segment, and it is COW, then - * we need to do the COW operation. Note that we don't COW - * currently RO sections now, because it is NOT desirable - * to COW .text. We simply keep .text from ever being COW'ed - * and take the heat that one cannot debug wired .text sections. - */ - if (((fault_flags & VM_FAULT_WIRE_MASK) == VM_FAULT_USER_WIRE) && - (entry->eflags & MAP_ENTRY_NEEDS_COPY)) { - if(entry->protection & VM_PROT_WRITE) { - int tresult; - vm_map_lookup_done(map, entry); - - tresult = vm_map_lookup(&map, vaddr, VM_PROT_READ|VM_PROT_WRITE, - &entry, &first_object, &first_pindex, &prot, &wired, &su); - if (tresult != KERN_SUCCESS) - return tresult; - } else { - /* - * If we don't COW now, on a user wire, the user will never - * be able to write to the mapping. If we don't make this - * restriction, the bookkeeping would be nearly impossible. - */ - entry->max_protection &= ~VM_PROT_WRITE; - } - } - - /* * Make a reference to this object to prevent its disposal while we * are messing with it. Once we have the reference, the map is free * to be diddled. Since objects reference their shadows (and copies), @@ -284,6 +287,12 @@ RetryFault:; */ while (TRUE) { + + if (object->flags & OBJ_DEAD) { + UNLOCK_AND_DEALLOCATE; + return (KERN_PROTECTION_FAILURE); + } + m = vm_page_lookup(object, pindex); if (m != NULL) { int queue; @@ -322,14 +331,14 @@ RetryFault:; m->flags |= PG_BUSY; - if (/*m->valid && */ - ((m->valid & VM_PAGE_BITS_ALL) != VM_PAGE_BITS_ALL) && + if (((m->valid & VM_PAGE_BITS_ALL) != VM_PAGE_BITS_ALL) && m->object != kernel_object && m->object != kmem_object) { goto readrest; } break; } - if (((object->type != OBJT_DEFAULT) && (((fault_flags & VM_FAULT_WIRE_MASK) == 0) || wired)) + if (((object->type != OBJT_DEFAULT) && + (((fault_flags & VM_FAULT_WIRE_MASK) == 0) || wired)) || (object == first_object)) { if (pindex >= object->size) { @@ -341,7 +350,7 @@ RetryFault:; * Allocate a new page for this object/offset pair. */ m = vm_page_alloc(object, pindex, - (vp || object->backing_object)?VM_ALLOC_NORMAL:VM_ALLOC_ZERO); + (vp || object->backing_object)? VM_ALLOC_NORMAL: VM_ALLOC_ZERO); if (m == NULL) { UNLOCK_AND_DEALLOCATE; @@ -349,8 +358,10 @@ RetryFault:; goto RetryFault; } } + readrest: - if (object->type != OBJT_DEFAULT && (((fault_flags & VM_FAULT_WIRE_MASK) == 0) || wired)) { + if (object->type != OBJT_DEFAULT && + (((fault_flags & VM_FAULT_WIRE_MASK) == 0) || wired)) { int rv; int faultcount; int reqpage; @@ -469,7 +480,8 @@ readrest: * around having the machine panic on a kernel space * fault w/ I/O error. */ - if (((map != kernel_map) && (rv == VM_PAGER_ERROR)) || (rv == VM_PAGER_BAD)) { + if (((map != kernel_map) && (rv == VM_PAGER_ERROR)) || + (rv == VM_PAGER_BAD)) { FREE_PAGE(m); UNLOCK_AND_DEALLOCATE; return ((rv == VM_PAGER_ERROR) ? KERN_FAILURE : KERN_PROTECTION_FAILURE); diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index 67039d4..ccbf5d7 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -61,7 +61,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_map.c,v 1.104 1998/01/06 05:25:58 dyson Exp $ + * $Id: vm_map.c,v 1.105 1998/01/12 01:44:31 dyson Exp $ */ /* @@ -87,9 +87,11 @@ #include <vm/vm_page.h> #include <vm/vm_object.h> #include <vm/vm_pageout.h> +#include <vm/vm_pager.h> #include <vm/vm_kern.h> #include <vm/vm_extern.h> #include <vm/default_pager.h> +#include <vm/swap_pager.h> #include <vm/vm_zone.h> static MALLOC_DEFINE(M_VMMAP, "VM map", "VM map structures"); @@ -332,6 +334,7 @@ vm_map_entry_create(map) #define vm_map_entry_link(map, after_where, entry) \ { \ (map)->nentries++; \ + (map)->timestamp++; \ (entry)->prev = (after_where); \ (entry)->next = (after_where)->next; \ (entry)->prev->next = (entry); \ @@ -340,6 +343,7 @@ vm_map_entry_create(map) #define vm_map_entry_unlink(map, entry) \ { \ (map)->nentries--; \ + (map)->timestamp++; \ (entry)->next->prev = (entry)->prev; \ (entry)->prev->next = (entry)->next; \ } @@ -1145,23 +1149,27 @@ vm_map_madvise(map, pmap, start, end, advise) for(current = entry; (current != &map->header) && (current->start < end); current = current->next) { - vm_size_t size = current->end - current->start; + vm_size_t size; if (current->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP)) { continue; } + vm_map_clip_end(map, current, end); + size = current->end - current->start; + /* * Create an object if needed */ if (current->object.vm_object == NULL) { vm_object_t object; + if ((advise == MADV_FREE) || (advise == MADV_DONTNEED)) + continue; object = vm_object_allocate(OBJT_DEFAULT, OFF_TO_IDX(size)); current->object.vm_object = object; current->offset = 0; } - vm_map_clip_end(map, current, end); switch (advise) { case MADV_NORMAL: current->object.vm_object->behavior = OBJ_NORMAL; @@ -1181,8 +1189,7 @@ vm_map_madvise(map, pmap, start, end, advise) { vm_pindex_t pindex; int count; - size = current->end - current->start; - pindex = OFF_TO_IDX(entry->offset); + pindex = OFF_TO_IDX(current->offset); count = OFF_TO_IDX(size); /* * MADV_DONTNEED removes the page from all @@ -1197,7 +1204,6 @@ vm_map_madvise(map, pmap, start, end, advise) { vm_pindex_t pindex; int count; - size = current->end - current->start; pindex = OFF_TO_IDX(current->offset); count = OFF_TO_IDX(size); vm_object_madvise(current->object.vm_object, @@ -1213,6 +1219,7 @@ vm_map_madvise(map, pmap, start, end, advise) } } + map->timestamp++; vm_map_simplify_entry(map, entry); vm_map_unlock(map); return; @@ -1262,6 +1269,7 @@ vm_map_inherit(vm_map_t map, vm_offset_t start, vm_offset_t end, } vm_map_simplify_entry(map, temp_entry); + map->timestamp++; vm_map_unlock(map); return (KERN_SUCCESS); } @@ -1364,6 +1372,7 @@ vm_map_user_pageable(map, start, end, new_pageable) /* First we need to allow map modifications */ vm_map_set_recursive(map); vm_map_lock_downgrade(map); + map->timestamp++; rv = vm_fault_user_wire(map, entry->start, entry->end); if (rv) { @@ -1394,6 +1403,7 @@ vm_map_user_pageable(map, start, end, new_pageable) vm_map_simplify_entry(map,entry); } } + map->timestamp++; vm_map_unlock(map); return KERN_SUCCESS; } @@ -1562,6 +1572,7 @@ vm_map_pageable(map, start, end, new_pageable) entry->wired_count--; entry = entry->prev; } + map->timestamp++; vm_map_unlock(map); return (KERN_INVALID_ARGUMENT); } @@ -1630,6 +1641,7 @@ vm_map_pageable(map, start, end, new_pageable) vm_map_unlock(map); + map->timestamp++; return (KERN_SUCCESS); } @@ -2068,6 +2080,7 @@ vmspace_fork(vm1) (caddr_t) (vm1 + 1) - (caddr_t) &vm1->vm_startcopy); new_pmap = &vm2->vm_pmap; /* XXX */ new_map = &vm2->vm_map; /* XXX */ + new_map->timestamp = 1; old_entry = old_map->header.next; @@ -2224,7 +2237,7 @@ vmspace_unshare(struct proc *p) { int vm_map_lookup(vm_map_t *var_map, /* IN/OUT */ vm_offset_t vaddr, - vm_prot_t fault_type, + vm_prot_t fault_typea, vm_map_entry_t *out_entry, /* OUT */ vm_object_t *object, /* OUT */ vm_pindex_t *pindex, /* OUT */ @@ -2238,6 +2251,7 @@ vm_map_lookup(vm_map_t *var_map, /* IN/OUT */ register vm_map_t map = *var_map; register vm_prot_t prot; register boolean_t su; + vm_prot_t fault_type = fault_typea; RetryLookup:; @@ -2297,11 +2311,16 @@ RetryLookup:; */ prot = entry->protection; - if ((fault_type & VM_PROT_OVERRIDE_WRITE) == 0 || - (entry->eflags & MAP_ENTRY_COW) == 0 || - (entry->wired_count != 0)) { - if ((fault_type & (prot)) != - (fault_type & ~VM_PROT_OVERRIDE_WRITE)) + + fault_type &= (VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); + if ((fault_type & prot) != fault_type) { + RETURN(KERN_PROTECTION_FAILURE); + } + + if (entry->wired_count && + (fault_type & VM_PROT_WRITE) && + (entry->eflags & MAP_ENTRY_COW) && + (fault_typea & VM_PROT_OVERRIDE_WRITE) == 0) { RETURN(KERN_PROTECTION_FAILURE); } @@ -2462,16 +2481,16 @@ vm_map_lookup_done(map, entry) * operations. */ int -vm_uiomove(mapa, srcobject, cp, cnt, uaddra, npages) +vm_uiomove(mapa, srcobject, cp, cnta, uaddra, npages) vm_map_t mapa; vm_object_t srcobject; off_t cp; - int cnt; + int cnta; vm_offset_t uaddra; int *npages; { vm_map_t map; - vm_object_t first_object, object; + vm_object_t first_object, oldobject, object; vm_map_entry_t first_entry, entry; vm_prot_t prot; boolean_t wired, su; @@ -2480,12 +2499,14 @@ vm_uiomove(mapa, srcobject, cp, cnt, uaddra, npages) vm_pindex_t first_pindex, osize, oindex; off_t ooffset; int skipinit, allremoved; + int cnt; if (npages) *npages = 0; allremoved = 0; + cnt = cnta; while (cnt > 0) { map = mapa; uaddr = uaddra; @@ -2531,28 +2552,15 @@ vm_uiomove(mapa, srcobject, cp, cnt, uaddra, npages) * If we are changing an existing map entry, just redirect * the object, and change mappings. */ - if (first_object->type == OBJT_VNODE) { - - if (first_object != srcobject) { - - vm_object_deallocate(first_object); - srcobject->flags |= OBJ_OPT; - vm_object_reference(srcobject); - - first_entry->object.vm_object = srcobject; - first_entry->offset = cp; - - } else if (first_entry->offset != cp) { - - first_entry->offset = cp; - - } else { - - skipinit = 1; + if ((first_object->ref_count == 1) && + (first_object->size == osize) && + ((first_object->type == OBJT_DEFAULT) || + (first_object->type == OBJT_SWAP)) ) { - } + oldobject = first_object->backing_object; - if (skipinit == 0) { + if ((first_object->backing_object_offset != cp) || + (oldobject != srcobject)) { /* * Remove old window into the file */ @@ -2562,39 +2570,31 @@ vm_uiomove(mapa, srcobject, cp, cnt, uaddra, npages) } /* - * Force copy on write for mmaped regions - */ - vm_object_pmap_copy_1 (srcobject, - oindex, oindex + osize); - } - - } else if ((first_object->ref_count == 1) && - (first_object->size == osize) && - (first_object->resident_page_count == 0)) { - vm_object_t oldobject; - - oldobject = first_object->backing_object; + * Remove unneeded old pages + */ + if (first_object->resident_page_count) { + vm_object_page_remove (first_object, 0, 0, 0); + } - if ((first_object->backing_object_offset != cp) || - (oldobject != srcobject)) { /* - * Remove old window into the file - */ - if (!allremoved) { - pmap_remove (map->pmap, uaddra, uaddra + cnt); - allremoved = 1; + * Invalidate swap space + */ + if (first_object->type == OBJT_SWAP) { + swap_pager_freespace(first_object, + OFF_TO_IDX(first_object->paging_offset), + first_object->size); } /* * Force copy on write for mmaped regions */ - vm_object_pmap_copy_1 (srcobject, - oindex, oindex + osize); + vm_object_pmap_copy_1 (srcobject, oindex, oindex + osize); /* * Point the object appropriately */ if (oldobject != srcobject) { + /* * Set the object optimization hint flag */ @@ -2613,6 +2613,7 @@ vm_uiomove(mapa, srcobject, cp, cnt, uaddra, npages) TAILQ_INSERT_TAIL(&srcobject->shadow_head, first_object, shadow_list); srcobject->shadow_count++; + srcobject->flags |= OBJ_OPT; first_object->backing_object = srcobject; } @@ -2629,15 +2630,17 @@ vm_uiomove(mapa, srcobject, cp, cnt, uaddra, npages) srcobject->flags |= OBJ_OPT; vm_object_reference(srcobject); + object = srcobject; + ooffset = cp; + vm_object_shadow(&object, &ooffset, osize); + if (!allremoved) { pmap_remove (map->pmap, uaddra, uaddra + cnt); allremoved = 1; } - vm_object_pmap_copy_1 (srcobject, - oindex, oindex + osize); - vm_map_lookup_done(map, first_entry); - vm_map_lock(map); + vm_object_pmap_copy_1 (srcobject, oindex, oindex + osize); + vm_map_lock_upgrade(map); if (first_entry == &map->header) { map->first_free = &map->header; @@ -2648,8 +2651,8 @@ vm_uiomove(mapa, srcobject, cp, cnt, uaddra, npages) SAVE_HINT(map, first_entry->prev); vm_map_entry_delete(map, first_entry); - rv = vm_map_insert(map, srcobject, cp, start, end, - VM_PROT_ALL, VM_PROT_ALL, MAP_COPY_ON_WRITE | MAP_COPY_NEEDED); + rv = vm_map_insert(map, object, ooffset, start, end, + VM_PROT_ALL, VM_PROT_ALL, MAP_COPY_ON_WRITE); if (rv != KERN_SUCCESS) panic("vm_uiomove: could not insert new entry: %d", rv); @@ -2659,9 +2662,10 @@ vm_uiomove(mapa, srcobject, cp, cnt, uaddra, npages) * Map the window directly, if it is already in memory */ if (!skipinit) - pmap_object_init_pt(map->pmap, start, - srcobject, (vm_pindex_t) OFF_TO_IDX(cp), end - start, 0); + pmap_object_init_pt(map->pmap, uaddra, + srcobject, (vm_pindex_t) OFF_TO_IDX(cp), tcnt, 0); + map->timestamp++; vm_map_unlock(map); cnt -= tcnt; @@ -2689,9 +2693,8 @@ vm_freeze_page_alloc(object, pindex) return NULL; } - m->valid = VM_PAGE_BITS_ALL; + m->valid = 0; m->dirty = 0; - vm_page_deactivate(m); return m; } @@ -2708,30 +2711,20 @@ vm_freeze_copyopts(object, froma, toa) int s; vm_object_t robject, robjectn; vm_pindex_t idx, from, to; - return; - if ((vfs_ioopt == 0) || (object == NULL) || + if ((vfs_ioopt == 0) || + (object == NULL) || ((object->flags & OBJ_OPT) == 0)) return; if (object->shadow_count > object->ref_count) panic("vm_freeze_copyopts: sc > rc"); - for( robject = TAILQ_FIRST(&object->shadow_head); - robject; - robject = robjectn) { + while( robject = TAILQ_FIRST(&object->shadow_head)) { vm_pindex_t bo_pindex; - vm_pindex_t dstpindex; vm_page_t m_in, m_out; - robjectn = TAILQ_NEXT(robject, shadow_list); - bo_pindex = OFF_TO_IDX(robject->backing_object_offset); - if (bo_pindex > toa) - continue; - - if ((bo_pindex + robject->size) < froma) - continue; vm_object_reference(robject); @@ -2748,86 +2741,79 @@ vm_freeze_copyopts(object, froma, toa) } robject->paging_in_progress++; - from = froma; - if (from < bo_pindex) - from = bo_pindex; - - to = toa; - - for (idx = from; idx < to; idx++) { - dstpindex = idx - bo_pindex; - if (dstpindex >= robject->size) - break; + for (idx = 0; idx < robject->size; idx++) { - m_in = vm_page_lookup(object, idx); - if (m_in == NULL) - continue; - - if( m_in->flags & PG_BUSY) { - s = splvm(); - while (m_in && (m_in->flags & PG_BUSY)) { - m_in->flags |= PG_WANTED; - tsleep(m_in, PVM, "pwtfrz", 0); - m_in = vm_page_lookup(object, idx); - } - splx(s); - if (m_in == NULL) - continue; - } - m_in->flags |= PG_BUSY; - -retryout: - m_out = vm_page_lookup(robject, dstpindex); +m_outretry: + m_out = vm_page_lookup(robject, idx); if( m_out && (m_out->flags & PG_BUSY)) { s = splvm(); while (m_out && (m_out->flags & PG_BUSY)) { m_out->flags |= PG_WANTED; tsleep(m_out, PVM, "pwtfrz", 0); - m_out = vm_page_lookup(robject, dstpindex); + m_out = vm_page_lookup(robject, idx); } splx(s); } if (m_out == NULL) { - m_out = vm_freeze_page_alloc(robject, dstpindex); + m_out = vm_freeze_page_alloc(robject, idx); if (m_out == NULL) - goto retryout; + goto m_outretry; } if (m_out->valid == 0) { + m_out->flags |= PG_BUSY; +m_inretry: + m_in = vm_page_lookup(object, bo_pindex + idx); + if (m_in == NULL) { + int rv; + m_in = vm_freeze_page_alloc(object, bo_pindex + idx); + if (m_in == NULL) + goto m_inretry; + rv = vm_pager_get_pages(object, &m_in, 1, 0); + if (rv != VM_PAGER_OK) { + printf("vm_freeze_copyopts: cannot read page from file: %x\n", m_in->pindex); + continue; + } + } else if(m_in->busy || (m_in->flags & PG_BUSY)) { + s = splvm(); + while (m_in && (m_in->busy || (m_in->flags & PG_BUSY))) { + m_in->flags |= PG_WANTED; + tsleep(m_in, PVM, "pwtfrz", 0); + m_in = vm_page_lookup(object, bo_pindex + idx); + } + splx(s); + if (m_in == NULL) { + goto m_inretry; + } + } + + m_in->flags |= PG_BUSY; vm_page_protect(m_in, VM_PROT_NONE); - pmap_copy_page(VM_PAGE_TO_PHYS(m_in), - VM_PAGE_TO_PHYS(m_out)); + pmap_copy_page(VM_PAGE_TO_PHYS(m_in), VM_PAGE_TO_PHYS(m_out)); m_out->valid = VM_PAGE_BITS_ALL; - } - PAGE_WAKEUP(m_out); - PAGE_WAKEUP(m_in); - } - - vm_object_pip_wakeup(robject); - - if (((from - bo_pindex) == 0) && ((to - bo_pindex) == robject->size)) { - - object->shadow_count--; + m_out->dirty = VM_PAGE_BITS_ALL; - TAILQ_REMOVE(&object->shadow_head, robject, shadow_list); - robject->backing_object = NULL; - robject->backing_object_offset = 0; + vm_page_deactivate(m_out); + vm_page_deactivate(m_in); - if (object->ref_count == 1) { - if (object->shadow_count == 0) - object->flags &= ~OBJ_OPT; - vm_object_deallocate(object); - vm_object_deallocate(robject); - return; + PAGE_WAKEUP(m_out); + PAGE_WAKEUP(m_in); } - vm_object_deallocate(object); } + + object->shadow_count--; + object->ref_count--; + TAILQ_REMOVE(&object->shadow_head, robject, shadow_list); + robject->backing_object = NULL; + robject->backing_object_offset = 0; + + vm_object_pip_wakeup(robject); vm_object_deallocate(robject); } - if (object->shadow_count == 0) - object->flags &= ~OBJ_OPT; + + object->flags &= ~OBJ_OPT; } #include "opt_ddb.h" diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h index d70a2b1..1568814 100644 --- a/sys/vm/vm_map.h +++ b/sys/vm/vm_map.h @@ -61,7 +61,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_map.h,v 1.29 1997/12/19 09:03:12 dyson Exp $ + * $Id: vm_map.h,v 1.30 1998/01/06 05:26:00 dyson Exp $ */ /* @@ -126,7 +126,6 @@ struct vm_map_entry { * insertion, or removal. */ struct vm_map { - struct pmap *pmap; /* Physical map */ struct lock lock; /* Lock for map data */ struct vm_map_entry header; /* List of entries */ int nentries; /* Number of entries */ @@ -136,9 +135,10 @@ struct vm_map { int ref_count; /* Reference count */ struct simplelock ref_lock; /* Lock for ref_count field */ vm_map_entry_t hint; /* hint for quick lookups */ + unsigned int timestamp; /* Version number */ vm_map_entry_t first_free; /* First free space hint */ boolean_t entries_pageable; /* map entries pageable?? */ - unsigned int timestamp; /* Version number */ + struct pmap *pmap; /* Physical map */ #define min_offset header.start #define max_offset header.end }; diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index 33ec0a1..43bf48b 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -61,7 +61,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_object.c,v 1.105 1998/01/07 03:12:19 dyson Exp $ + * $Id: vm_object.c,v 1.106 1998/01/12 01:44:38 dyson Exp $ */ /* @@ -242,8 +242,11 @@ vm_object_reference(object) #endif object->ref_count++; - if (object->type == OBJT_VNODE) - vget((struct vnode *) object->handle, LK_NOOBJ, curproc); + if (object->type == OBJT_VNODE) { + while (vget((struct vnode *) object->handle, LK_RETRY|LK_NOOBJ, curproc)) { + printf("vm_object_reference: delay in getting object\n"); + } + } } void @@ -263,11 +266,10 @@ vm_object_vndeallocate(object) #endif object->ref_count--; - if (object->type == OBJT_VNODE) { - if (object->ref_count == 0) - vp->v_flag &= ~VTEXT; - vrele(vp); + if (object->ref_count == 0) { + vp->v_flag &= ~VTEXT; } + vrele(vp); } /* @@ -296,7 +298,7 @@ vm_object_deallocate(object) } if (object->ref_count == 0) { - panic("vm_object_deallocate: object deallocated too many times"); + panic("vm_object_deallocate: object deallocated too many times: %d", object->type); } else if (object->ref_count > 2) { object->ref_count--; return; @@ -452,17 +454,17 @@ vm_object_terminate(object) */ vm_pager_deallocate(object); - simple_lock(&vm_object_list_lock); - TAILQ_REMOVE(&vm_object_list, object, object_list); - vm_object_count--; - simple_unlock(&vm_object_list_lock); - - wakeup(object); - - /* - * Free the space for the object. - */ - zfree(obj_zone, object); + if (object->ref_count == 0) { + simple_lock(&vm_object_list_lock); + TAILQ_REMOVE(&vm_object_list, object, object_list); + vm_object_count--; + simple_unlock(&vm_object_list_lock); + /* + * Free the space for the object. + */ + zfree(obj_zone, object); + wakeup(object); + } } /* diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h index ac86c6c..c72acd9 100644 --- a/sys/vm/vm_object.h +++ b/sys/vm/vm_object.h @@ -61,7 +61,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_object.h,v 1.40 1997/12/29 00:24:55 dyson Exp $ + * $Id: vm_object.h,v 1.41 1998/01/06 05:26:07 dyson Exp $ */ /* @@ -73,7 +73,7 @@ #include <sys/queue.h> -enum obj_type { OBJT_DEFAULT, OBJT_SWAP, OBJT_VNODE, OBJT_DEVICE }; +enum obj_type { OBJT_DEFAULT, OBJT_SWAP, OBJT_VNODE, OBJT_DEVICE, OBJT_DEAD }; typedef enum obj_type objtype_t; /* diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index ff824d6..884d0fb 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)vm_page.c 7.4 (Berkeley) 5/7/91 - * $Id: vm_page.c,v 1.84 1997/12/29 00:24:58 dyson Exp $ + * $Id: vm_page.c,v 1.85 1998/01/12 01:44:41 dyson Exp $ */ /* @@ -894,18 +894,21 @@ vm_page_alloc(object, pindex, page_req) (cnt.v_free_count < cnt.v_pageout_free_min)) pagedaemon_wakeup(); - if (((page_req == VM_ALLOC_NORMAL) || (page_req == VM_ALLOC_ZERO)) && - oldobject && - ((oldobject->type == OBJT_VNODE) && - (oldobject->ref_count == 0) && - (oldobject->resident_page_count == 0))) { + s = splvm(); + if ((qtype == PQ_CACHE) && + ((page_req == VM_ALLOC_NORMAL) || (page_req == VM_ALLOC_ZERO)) && + oldobject && (oldobject->type == OBJT_VNODE) && + ((oldobject->flags & OBJ_DEAD) == 0)) { struct vnode *vp; vp = (struct vnode *) oldobject->handle; - if (VSHOULDFREE(vp)) { - vm_object_reference(oldobject); - vm_object_vndeallocate(oldobject); + if (vp && VSHOULDFREE(vp)) { + if ((vp->v_flag & (VFREE|VTBFREE|VDOOMED)) == 0) { + TAILQ_INSERT_TAIL(&vnode_tobefree_list, vp, v_freelist); + vp->v_flag |= VTBFREE; + } } } + splx(s); return (m); } @@ -970,6 +973,10 @@ static int vm_page_freechk_and_unqueue(m) vm_page_t m; { + vm_object_t oldobject; + + oldobject = m->object; + #if !defined(MAX_PERF) if (m->busy || (m->flags & PG_BUSY) || @@ -999,6 +1006,18 @@ vm_page_freechk_and_unqueue(m) cnt.v_wire_count--; } + if (oldobject && (oldobject->type == OBJT_VNODE) && + ((oldobject->flags & OBJ_DEAD) == 0)) { + struct vnode *vp; + vp = (struct vnode *) oldobject->handle; + if (vp && VSHOULDFREE(vp)) { + if ((vp->v_flag & (VTBFREE|VDOOMED|VFREE)) == 0) { + TAILQ_INSERT_TAIL(&vnode_tobefree_list, vp, v_freelist); + vp->v_flag |= VTBFREE; + } + } + } + return 1; } @@ -1068,6 +1087,7 @@ vm_page_free(m) } else { TAILQ_INSERT_HEAD(pq->pl, m, pageq); } + vm_page_free_wakeup(); splx(s); } diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c index b5669fd..391b41c 100644 --- a/sys/vm/vm_pageout.c +++ b/sys/vm/vm_pageout.c @@ -65,7 +65,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_pageout.c,v 1.106 1998/01/06 05:26:11 dyson Exp $ + * $Id: vm_pageout.c,v 1.107 1998/01/12 01:44:44 dyson Exp $ */ /* @@ -594,19 +594,24 @@ vm_pageout_map_deactivate_pages(map, desired) void vm_pageout_page_free(vm_page_t m) { - vm_object_t objref = NULL; + struct vnode *vp; + vm_object_t object; - m->flags |= PG_BUSY; - if (m->object->type == OBJT_VNODE) { - objref = m->object; - vm_object_reference(objref); + object = m->object; + vp = NULL; + + object->ref_count++; + if (object->type == OBJT_VNODE) { + vp = object->handle; + vp->v_usecount++; + if (VSHOULDBUSY(vp)) + vbusy(vp); } + m->flags |= PG_BUSY; vm_page_protect(m, VM_PROT_NONE); PAGE_WAKEUP(m); vm_page_free(m); - if (objref) { - vm_object_vndeallocate(objref); - } + vm_object_deallocate(object); } /* @@ -776,10 +781,10 @@ rescan0: continue; } - if (object->type == OBJT_VNODE) { + if (object->type == OBJT_VNODE && (object->flags & OBJ_DEAD) == 0) { vp = object->handle; if (VOP_ISLOCKED(vp) || - vget(vp, LK_EXCLUSIVE, curproc)) { + vget(vp, LK_EXCLUSIVE|LK_NOOBJ, curproc)) { if ((m->queue == PQ_INACTIVE) && (m->hold_count == 0) && (m->busy == 0) && diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c index f3ed776..aec5c55 100644 --- a/sys/vm/vnode_pager.c +++ b/sys/vm/vnode_pager.c @@ -38,7 +38,7 @@ * SUCH DAMAGE. * * from: @(#)vnode_pager.c 7.5 (Berkeley) 4/20/91 - * $Id: vnode_pager.c,v 1.78 1997/12/29 00:25:11 dyson Exp $ + * $Id: vnode_pager.c,v 1.79 1998/01/06 05:26:17 dyson Exp $ */ /* @@ -178,7 +178,6 @@ vnode_pager_dealloc(object) splx(s); } - object->flags |= OBJ_DEAD; object->handle = NULL; object->type = OBJT_DEFAULT; vp->v_object = NULL; @@ -200,6 +199,9 @@ vnode_pager_haspage(object, pindex, before, after) int bsize; int pagesperblock, blocksperpage; + if ((vp == NULL) || (vp->v_flag & VDOOMED)) + return FALSE; + /* * If filesystem no longer mounted or offset beyond end of file we do * not have the page. @@ -892,9 +894,13 @@ vnode_pager_lock(object) for (; object != NULL; object = object->backing_object) { if (object->type != OBJT_VNODE) continue; + if (object->flags & OBJ_DEAD) + return NULL; - vn_lock(object->handle, - LK_NOPAUSE | LK_SHARED | LK_RETRY | LK_CANRECURSE, p); + while (vget(object->handle, + LK_NOPAUSE | LK_SHARED | LK_RETRY | LK_CANRECURSE, p)) { + printf("vnode_pager_lock: retrying\n"); + } return object->handle; } return NULL; |