xref: /csrg-svn/sys/vm/vm_swap.c (revision 43376)
123460Smckusick /*
237729Smckusick  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
337729Smckusick  * All rights reserved.
423460Smckusick  *
537729Smckusick  * Redistribution and use in source and binary forms are permitted
637729Smckusick  * provided that the above copyright notice and this paragraph are
737729Smckusick  * duplicated in all such forms and that any documentation,
837729Smckusick  * advertising materials, and other materials related to such
937729Smckusick  * distribution and use acknowledge that the software was developed
1037729Smckusick  * by the University of California, Berkeley.  The name of the
1137729Smckusick  * University may not be used to endorse or promote products derived
1237729Smckusick  * from this software without specific prior written permission.
1337729Smckusick  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1437729Smckusick  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1537729Smckusick  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1637729Smckusick  *
17*43376Smckusick  *	@(#)vm_swap.c	7.12 (Berkeley) 06/21/90
1823460Smckusick  */
191404Sbill 
2017107Sbloom #include "param.h"
2117107Sbloom #include "systm.h"
2217107Sbloom #include "buf.h"
2317107Sbloom #include "conf.h"
24*43376Smckusick #include "syscontext.h"
2537729Smckusick #include "vnode.h"
2640652Smckusick #include "specdev.h"
2717107Sbloom #include "map.h"
2817107Sbloom #include "file.h"
291404Sbill 
301404Sbill /*
311404Sbill  * Indirect driver for multi-controller paging.
321404Sbill  */
331404Sbill swstrategy(bp)
341404Sbill 	register struct buf *bp;
351404Sbill {
3630750Skarels 	int sz, off, seg, index;
3730750Skarels 	register struct swdevt *sp;
3839894Smckusick 	struct vnode *vp;
391404Sbill 
407435Sroot #ifdef GENERIC
417435Sroot 	/*
427435Sroot 	 * A mini-root gets copied into the front of the swap
437435Sroot 	 * and we run over top of the swap area just long
447435Sroot 	 * enough for us to do a mkfs and restor of the real
457435Sroot 	 * root (sure beats rewriting standalone restor).
467435Sroot 	 */
4711051Ssam #define	MINIROOTSIZE	4096
487435Sroot 	if (rootdev == dumpdev)
497435Sroot 		bp->b_blkno += MINIROOTSIZE;
507435Sroot #endif
519010Sroot 	sz = howmany(bp->b_bcount, DEV_BSIZE);
5212490Ssam 	if (bp->b_blkno+sz > nswap) {
531404Sbill 		bp->b_flags |= B_ERROR;
5430750Skarels 		biodone(bp);
551404Sbill 		return;
561404Sbill 	}
5712490Ssam 	if (nswdev > 1) {
5812490Ssam 		off = bp->b_blkno % dmmax;
5912490Ssam 		if (off+sz > dmmax) {
6012490Ssam 			bp->b_flags |= B_ERROR;
6130750Skarels 			biodone(bp);
6212490Ssam 			return;
6312490Ssam 		}
6412490Ssam 		seg = bp->b_blkno / dmmax;
6530750Skarels 		index = seg % nswdev;
6612490Ssam 		seg /= nswdev;
6712490Ssam 		bp->b_blkno = seg*dmmax + off;
6812490Ssam 	} else
6930750Skarels 		index = 0;
7030750Skarels 	sp = &swdevt[index];
7139894Smckusick 	if ((bp->b_dev = sp->sw_dev) == 0)
721404Sbill 		panic("swstrategy");
7339304Smckusick 	if (sp->sw_vp == NULL) {
7439304Smckusick 		bp->b_error |= B_ERROR;
7539304Smckusick 		biodone(bp);
7639304Smckusick 		return;
7739304Smckusick 	}
7839806Smckusick 	VHOLD(sp->sw_vp);
7939880Smckusick 	if ((bp->b_flags & B_READ) == 0) {
8039894Smckusick 		if (vp = bp->b_vp) {
8139894Smckusick 			vp->v_numoutput--;
8239894Smckusick 			if ((vp->v_flag & VBWAIT) && vp->v_numoutput <= 0) {
8339894Smckusick 				vp->v_flag &= ~VBWAIT;
8439894Smckusick 				wakeup((caddr_t)&vp->v_numoutput);
8539894Smckusick 			}
8639880Smckusick 		}
8739880Smckusick 		sp->sw_vp->v_numoutput++;
8839880Smckusick 	}
8939894Smckusick 	if (bp->b_vp != NULL)
9039894Smckusick 		brelvp(bp);
9137729Smckusick 	bp->b_vp = sp->sw_vp;
9237729Smckusick 	VOP_STRATEGY(bp);
931404Sbill }
941404Sbill 
951404Sbill /*
961404Sbill  * System call swapon(name) enables swapping on device name,
971404Sbill  * which must be in the swdevsw.  Return EBUSY
981404Sbill  * if already swapping on this device.
991404Sbill  */
100*43376Smckusick /* ARGSUSED */
101*43376Smckusick swapon(p, uap, retval)
102*43376Smckusick 	struct proc *p;
103*43376Smckusick 	struct args {
104*43376Smckusick 		char	*name;
105*43376Smckusick 	} *uap;
106*43376Smckusick 	int *retval;
1071404Sbill {
10837729Smckusick 	register struct vnode *vp;
1091404Sbill 	register struct swdevt *sp;
11016695Smckusick 	register struct nameidata *ndp = &u.u_nd;
111*43376Smckusick 	dev_t dev;
112*43376Smckusick 	int error;
1131404Sbill 
114*43376Smckusick 	if (error = suser(u.u_cred, &u.u_acflag))
115*43376Smckusick 		RETURN (error);
11616695Smckusick 	ndp->ni_nameiop = LOOKUP | FOLLOW;
11716695Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
11816695Smckusick 	ndp->ni_dirp = uap->name;
119*43376Smckusick 	if (error = namei(ndp))
120*43376Smckusick 		RETURN (error);
12137729Smckusick 	vp = ndp->ni_vp;
12237729Smckusick 	if (vp->v_type != VBLK) {
12337729Smckusick 		vrele(vp);
124*43376Smckusick 		RETURN (ENOTBLK);
1251404Sbill 	}
12637729Smckusick 	dev = (dev_t)vp->v_rdev;
1271404Sbill 	if (major(dev) >= nblkdev) {
12837729Smckusick 		vrele(vp);
129*43376Smckusick 		RETURN (ENXIO);
1301404Sbill 	}
13117879Sbloom 	for (sp = &swdevt[0]; sp->sw_dev; sp++)
1321404Sbill 		if (sp->sw_dev == dev) {
1331404Sbill 			if (sp->sw_freed) {
13437729Smckusick 				vrele(vp);
135*43376Smckusick 				RETURN (EBUSY);
1361404Sbill 			}
13737729Smckusick 			sp->sw_vp = vp;
138*43376Smckusick 			if (error = swfree(sp - swdevt)) {
13937729Smckusick 				vrele(vp);
140*43376Smckusick 				RETURN (error);
14137729Smckusick 			}
142*43376Smckusick 			RETURN (0);
1431404Sbill 		}
14437729Smckusick 	vrele(vp);
145*43376Smckusick 	RETURN (EINVAL);
1461404Sbill }
1471404Sbill 
1481404Sbill /*
1491404Sbill  * Swfree(index) frees the index'th portion of the swap map.
1501404Sbill  * Each of the nswdev devices provides 1/nswdev'th of the swap
15112490Ssam  * space, which is laid out with blocks of dmmax pages circularly
1521404Sbill  * among the devices.
1531404Sbill  */
1541404Sbill swfree(index)
1551404Sbill 	int index;
1561404Sbill {
15730750Skarels 	register struct swdevt *sp;
1581404Sbill 	register swblk_t vsbase;
1598772Sroot 	register long blk;
16037729Smckusick 	struct vnode *vp;
16112490Ssam 	register swblk_t dvbase;
16212490Ssam 	register int nblks;
16330750Skarels 	int error;
1641404Sbill 
16530750Skarels 	sp = &swdevt[index];
16637729Smckusick 	vp = sp->sw_vp;
16737729Smckusick 	if (error = VOP_OPEN(vp, FREAD|FWRITE, u.u_cred))
16830750Skarels 		return (error);
16930750Skarels 	sp->sw_freed = 1;
17030750Skarels 	nblks = sp->sw_nblks;
17112490Ssam 	for (dvbase = 0; dvbase < nblks; dvbase += dmmax) {
17212490Ssam 		blk = nblks - dvbase;
17312490Ssam 		if ((vsbase = index*dmmax + dvbase*nswdev) >= nswap)
17412490Ssam 			panic("swfree");
17512490Ssam 		if (blk > dmmax)
17612490Ssam 			blk = dmmax;
1771404Sbill 		if (vsbase == 0) {
1781404Sbill 			/*
1791404Sbill 			 * Can't free a block starting at 0 in the swapmap
1802788Swnj 			 * but need some space for argmap so use 1/2 this
1811404Sbill 			 * hunk which needs special treatment anyways.
1821404Sbill 			 */
18330750Skarels 			argdev = sp->sw_dev;
18437729Smckusick 			if (argdev_vp)
18537729Smckusick 				vrele(argdev_vp);
18638349Smckusick 			VREF(vp);
18737729Smckusick 			argdev_vp = vp;
1888961Sroot 			rminit(argmap, (long)(blk/2-ctod(CLSIZE)),
1898961Sroot 			    (long)ctod(CLSIZE), "argmap", ARGMAPSIZE);
1902788Swnj 			/*
1912788Swnj 			 * First of all chunks... initialize the swapmap
1922788Swnj 			 * the second half of the hunk.
1932788Swnj 			 */
19437729Smckusick 			rminit(swapmap, (long)(blk/2), (long)(blk/2),
1958794Sroot 			    "swap", nswapmap);
19630750Skarels 		} else if (dvbase == 0) {
19730750Skarels 			/*
19830750Skarels 			 * Don't use the first cluster of the device
19930750Skarels 			 * in case it starts with a label or boot block.
20030750Skarels 			 */
20130750Skarels 			rmfree(swapmap, blk - ctod(CLSIZE),
20230750Skarels 			    vsbase + ctod(CLSIZE));
2031404Sbill 		} else
2042788Swnj 			rmfree(swapmap, blk, vsbase);
2051404Sbill 	}
20630750Skarels 	return (0);
2071404Sbill }
208