⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 swap_pag.c

📁 open bsd vm device design
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1990 University of Utah. * Copyright (c) 1991, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * the Systems Programming Group of the University of Utah Computer * Science Department. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: Utah $Hdr: swap_pager.c 1.4 91/04/30$ * *	@(#)swap_pager.c	8.9 (Berkeley) 3/21/94 *//* * Quick hack to page to dedicated partition(s). * TODO: *	Add multiprocessor locks *	Deal with async writes in a better fashion */#include <sys/param.h>#include <sys/systm.h>#include <sys/proc.h>#include <sys/buf.h>#include <sys/map.h>#include <sys/vnode.h>#include <sys/malloc.h>#include <miscfs/specfs/specdev.h>#include <vm/vm.h>#include <vm/vm_page.h>#include <vm/vm_pageout.h>#include <vm/swap_pager.h>#define NSWSIZES	16	/* size of swtab */#define MAXDADDRS	64	/* max # of disk addrs for fixed allocations */#ifndef NPENDINGIO#define NPENDINGIO	64	/* max # of pending cleans */#endif#ifdef DEBUGint	swpagerdebug = 0x100;#define	SDB_FOLLOW	0x001#define SDB_INIT	0x002#define SDB_ALLOC	0x004#define SDB_IO		0x008#define SDB_WRITE	0x010#define SDB_FAIL	0x020#define SDB_ALLOCBLK	0x040#define SDB_FULL	0x080#define SDB_ANOM	0x100#define SDB_ANOMPANIC	0x200#define SDB_CLUSTER	0x400#define SDB_PARANOIA	0x800#endifTAILQ_HEAD(swpclean, swpagerclean);struct swpagerclean {	TAILQ_ENTRY(swpagerclean)	spc_list;	int				spc_flags;	struct buf			*spc_bp;	sw_pager_t			spc_swp;	vm_offset_t			spc_kva;	vm_page_t			spc_m;	int				spc_npages;} swcleanlist[NPENDINGIO];typedef struct swpagerclean *swp_clean_t;/* spc_flags values */#define SPC_FREE	0x00#define SPC_BUSY	0x01#define SPC_DONE	0x02#define SPC_ERROR	0x04struct swtab {	vm_size_t st_osize;	/* size of object (bytes) */	int	  st_bsize;	/* vs. size of swap block (DEV_BSIZE units) */#ifdef DEBUG	u_long	  st_inuse;	/* number in this range in use */	u_long	  st_usecnt;	/* total used of this size */#endif} swtab[NSWSIZES+1];#ifdef DEBUGint		swap_pager_poip;	/* pageouts in progress */int		swap_pager_piip;	/* pageins in progress */#endifint		swap_pager_maxcluster;	/* maximum cluster size */int		swap_pager_npendingio;	/* number of pager clean structs */struct swpclean	swap_pager_inuse;	/* list of pending page cleans */struct swpclean	swap_pager_free;	/* list of free pager clean structs */struct pagerlst	swap_pager_list;	/* list of "named" anon regions */static void 		swap_pager_init __P((void));static vm_pager_t	swap_pager_alloc			    __P((caddr_t, vm_size_t, vm_prot_t, vm_offset_t));static void		swap_pager_clean __P((int));#ifdef DEBUGstatic void		swap_pager_clean_check __P((vm_page_t *, int, int));#endifstatic void		swap_pager_cluster			    __P((vm_pager_t, vm_offset_t,				 vm_offset_t *, vm_offset_t *));static void		swap_pager_dealloc __P((vm_pager_t));static int		swap_pager_getpage			    __P((vm_pager_t, vm_page_t *, int, boolean_t));static boolean_t	swap_pager_haspage __P((vm_pager_t, vm_offset_t));static int		swap_pager_io __P((sw_pager_t, vm_page_t *, int, int));static void		swap_pager_iodone __P((struct buf *));static int		swap_pager_putpage			    __P((vm_pager_t, vm_page_t *, int, boolean_t));struct pagerops swappagerops = {	swap_pager_init,	swap_pager_alloc,	swap_pager_dealloc,	swap_pager_getpage,	swap_pager_putpage,	swap_pager_haspage,	swap_pager_cluster};static voidswap_pager_init(){	register swp_clean_t spc;	register int i, bsize;	extern int dmmin, dmmax;	int maxbsize;#ifdef DEBUG	if (swpagerdebug & (SDB_FOLLOW|SDB_INIT))		printf("swpg_init()\n");#endif	dfltpagerops = &swappagerops;	TAILQ_INIT(&swap_pager_list);	/*	 * Allocate async IO structures.	 *	 * XXX it would be nice if we could do this dynamically based on	 * the value of nswbuf (since we are ultimately limited by that)	 * but neither nswbuf or malloc has been initialized yet.  So the	 * structs are statically allocated above.	 */	swap_pager_npendingio = NPENDINGIO;	/*	 * Initialize clean lists	 */	TAILQ_INIT(&swap_pager_inuse);	TAILQ_INIT(&swap_pager_free);	for (i = 0, spc = swcleanlist; i < swap_pager_npendingio; i++, spc++) {		TAILQ_INSERT_TAIL(&swap_pager_free, spc, spc_list);		spc->spc_flags = SPC_FREE;	}	/*	 * Calculate the swap allocation constants.	 */        if (dmmin == 0) {                dmmin = DMMIN;		if (dmmin < CLBYTES/DEV_BSIZE)			dmmin = CLBYTES/DEV_BSIZE;	}        if (dmmax == 0)                dmmax = DMMAX;	/*	 * Fill in our table of object size vs. allocation size	 */	bsize = btodb(PAGE_SIZE);	if (bsize < dmmin)		bsize = dmmin;	maxbsize = btodb(sizeof(sw_bm_t) * NBBY * PAGE_SIZE);	if (maxbsize > dmmax)		maxbsize = dmmax;	for (i = 0; i < NSWSIZES; i++) {		swtab[i].st_osize = (vm_size_t) (MAXDADDRS * dbtob(bsize));		swtab[i].st_bsize = bsize;		if (bsize <= btodb(MAXPHYS))			swap_pager_maxcluster = dbtob(bsize);#ifdef DEBUG		if (swpagerdebug & SDB_INIT)			printf("swpg_init: ix %d, size %x, bsize %x\n",			       i, swtab[i].st_osize, swtab[i].st_bsize);#endif		if (bsize >= maxbsize)			break;		bsize *= 2;	}	swtab[i].st_osize = 0;	swtab[i].st_bsize = bsize;}/* * Allocate a pager structure and associated resources. * Note that if we are called from the pageout daemon (handle == NULL) * we should not wait for memory as it could resulting in deadlock. */static vm_pager_tswap_pager_alloc(handle, size, prot, foff)	caddr_t handle;	register vm_size_t size;	vm_prot_t prot;	vm_offset_t foff;{	register vm_pager_t pager;	register sw_pager_t swp;	struct swtab *swt;	int waitok;#ifdef DEBUG	if (swpagerdebug & (SDB_FOLLOW|SDB_ALLOC))		printf("swpg_alloc(%x, %x, %x)\n", handle, size, prot);#endif	/*	 * If this is a "named" anonymous region, look it up and	 * return the appropriate pager if it exists.	 */	if (handle) {		pager = vm_pager_lookup(&swap_pager_list, handle);		if (pager != NULL) {			/*			 * Use vm_object_lookup to gain a reference			 * to the object and also to remove from the			 * object cache.			 */			if (vm_object_lookup(pager) == NULL)				panic("swap_pager_alloc: bad object");			return(pager);		}	}	/*	 * Pager doesn't exist, allocate swap management resources	 * and initialize.	 */	waitok = handle ? M_WAITOK : M_NOWAIT;	pager = (vm_pager_t)malloc(sizeof *pager, M_VMPAGER, waitok);	if (pager == NULL)		return(NULL);	swp = (sw_pager_t)malloc(sizeof *swp, M_VMPGDATA, waitok);	if (swp == NULL) {#ifdef DEBUG		if (swpagerdebug & SDB_FAIL)			printf("swpg_alloc: swpager malloc failed\n");#endif		free((caddr_t)pager, M_VMPAGER);		return(NULL);	}	size = round_page(size);	for (swt = swtab; swt->st_osize; swt++)		if (size <= swt->st_osize)			break;#ifdef DEBUG	swt->st_inuse++;	swt->st_usecnt++;#endif	swp->sw_osize = size;	swp->sw_bsize = swt->st_bsize;	swp->sw_nblocks = (btodb(size) + swp->sw_bsize - 1) / swp->sw_bsize;	swp->sw_blocks = (sw_blk_t)		malloc(swp->sw_nblocks*sizeof(*swp->sw_blocks),		       M_VMPGDATA, M_NOWAIT);	if (swp->sw_blocks == NULL) {		free((caddr_t)swp, M_VMPGDATA);		free((caddr_t)pager, M_VMPAGER);#ifdef DEBUG		if (swpagerdebug & SDB_FAIL)			printf("swpg_alloc: sw_blocks malloc failed\n");		swt->st_inuse--;		swt->st_usecnt--;#endif		return(FALSE);	}	bzero((caddr_t)swp->sw_blocks,	      swp->sw_nblocks * sizeof(*swp->sw_blocks));	swp->sw_poip = 0;	if (handle) {		vm_object_t object;		swp->sw_flags = SW_NAMED;		TAILQ_INSERT_TAIL(&swap_pager_list, pager, pg_list);		/*		 * Consistant with other pagers: return with object		 * referenced.  Can't do this with handle == NULL		 * since it might be the pageout daemon calling.		 */		object = vm_object_allocate(size);		vm_object_enter(object, pager);		vm_object_setpager(object, pager, 0, FALSE);	} else {		swp->sw_flags = 0;		pager->pg_list.tqe_next = NULL;		pager->pg_list.tqe_prev = NULL;	}	pager->pg_handle = handle;	pager->pg_ops = &swappagerops;	pager->pg_type = PG_SWAP;	pager->pg_flags = PG_CLUSTERPUT;	pager->pg_data = swp;#ifdef DEBUG	if (swpagerdebug & SDB_ALLOC)		printf("swpg_alloc: pg_data %x, %x of %x at %x\n",		       swp, swp->sw_nblocks, swp->sw_bsize, swp->sw_blocks);#endif	return(pager);}static voidswap_pager_dealloc(pager)	vm_pager_t pager;{	register int i;	register sw_blk_t bp;	register sw_pager_t swp;	struct swtab *swt;	int s;#ifdef DEBUG	/* save panic time state */	if ((swpagerdebug & SDB_ANOMPANIC) && panicstr)		return;	if (swpagerdebug & (SDB_FOLLOW|SDB_ALLOC))		printf("swpg_dealloc(%x)\n", pager);#endif	/*	 * Remove from list right away so lookups will fail if we	 * block for pageout completion.	 */	swp = (sw_pager_t) pager->pg_data;	if (swp->sw_flags & SW_NAMED) {		TAILQ_REMOVE(&swap_pager_list, pager, pg_list);		swp->sw_flags &= ~SW_NAMED;	}#ifdef DEBUG	for (swt = swtab; swt->st_osize; swt++)		if (swp->sw_osize <= swt->st_osize)			break;	swt->st_inuse--;#endif	/*	 * Wait for all pageouts to finish and remove	 * all entries from cleaning list.	 */	s = splbio();	while (swp->sw_poip) {		swp->sw_flags |= SW_WANTED;		(void) tsleep(swp, PVM, "swpgdealloc", 0);	}	splx(s);	swap_pager_clean(B_WRITE);	/*	 * Free left over swap blocks	 */	for (i = 0, bp = swp->sw_blocks; i < swp->sw_nblocks; i++, bp++)		if (bp->swb_block) {#ifdef DEBUG			if (swpagerdebug & (SDB_ALLOCBLK|SDB_FULL))				printf("swpg_dealloc: blk %x\n",				       bp->swb_block);#endif			rmfree(swapmap, swp->sw_bsize, bp->swb_block);		}	/*	 * Free swap management resources	 */	free((caddr_t)swp->sw_blocks, M_VMPGDATA);	free((caddr_t)swp, M_VMPGDATA);	free((caddr_t)pager, M_VMPAGER);}static intswap_pager_getpage(pager, mlist, npages, sync)	vm_pager_t pager;	vm_page_t *mlist;	int npages;	boolean_t sync;{#ifdef DEBUG	if (swpagerdebug & SDB_FOLLOW)		printf("swpg_getpage(%x, %x, %x, %x)\n",		       pager, mlist, npages, sync);#endif	return(swap_pager_io((sw_pager_t)pager->pg_data,			     mlist, npages, B_READ));}static intswap_pager_putpage(pager, mlist, npages, sync)	vm_pager_t pager;	vm_page_t *mlist;	int npages;	boolean_t sync;{	int flags;#ifdef DEBUG	if (swpagerdebug & SDB_FOLLOW)		printf("swpg_putpage(%x, %x, %x, %x)\n",		       pager, mlist, npages, sync);#endif	if (pager == NULL) {		swap_pager_clean(B_WRITE);		return (VM_PAGER_OK);		/* ??? */	}	flags = B_WRITE;	if (!sync)		flags |= B_ASYNC;	return(swap_pager_io((sw_pager_t)pager->pg_data,			     mlist, npages, flags));}static boolean_tswap_pager_haspage(pager, offset)	vm_pager_t pager;	vm_offset_t offset;{	register sw_pager_t swp;	register sw_blk_t swb;	int ix;#ifdef DEBUG	if (swpagerdebug & (SDB_FOLLOW|SDB_ALLOCBLK))		printf("swpg_haspage(%x, %x) ", pager, offset);#endif	swp = (sw_pager_t) pager->pg_data;	ix = offset / dbtob(swp->sw_bsize);	if (swp->sw_blocks == NULL || ix >= swp->sw_nblocks) {#ifdef DEBUG		if (swpagerdebug & (SDB_FAIL|SDB_FOLLOW|SDB_ALLOCBLK))			printf("swpg_haspage: %x bad offset %x, ix %x\n",			       swp->sw_blocks, offset, ix);#endif		return(FALSE);	}	swb = &swp->sw_blocks[ix];	if (swb->swb_block)		ix = atop(offset % dbtob(swp->sw_bsize));#ifdef DEBUG	if (swpagerdebug & SDB_ALLOCBLK)		printf("%x blk %x+%x ", swp->sw_blocks, swb->swb_block, ix);	if (swpagerdebug & (SDB_FOLLOW|SDB_ALLOCBLK))		printf("-> %c\n",		       "FT"[swb->swb_block && (swb->swb_mask & (1 << ix))]);#endif	if (swb->swb_block && (swb->swb_mask & (1 << ix)))		return(TRUE);	return(FALSE);}static voidswap_pager_cluster(pager, offset, loffset, hoffset)	vm_pager_t	pager;	vm_offset_t	offset;	vm_offset_t	*loffset;	vm_offset_t	*hoffset;{	sw_pager_t swp;	register int bsize;	vm_offset_t loff, hoff;#ifdef DEBUG	if (swpagerdebug & (SDB_FOLLOW|SDB_CLUSTER))		printf("swpg_cluster(%x, %x) ", pager, offset);#endif	swp = (sw_pager_t) pager->pg_data;	bsize = dbtob(swp->sw_bsize);	if (bsize > swap_pager_maxcluster)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -