xref: /csrg-svn/sys/vm/vm_swap.c (revision 12359)
1*12359Ssam /*	vm_swap.c	4.17	83/05/10	*/
21404Sbill 
31404Sbill #include "../h/param.h"
41404Sbill #include "../h/systm.h"
51404Sbill #include "../h/buf.h"
61404Sbill #include "../h/conf.h"
71404Sbill #include "../h/dir.h"
81404Sbill #include "../h/user.h"
91404Sbill #include "../h/inode.h"
101404Sbill #include "../h/map.h"
117828Sroot #include "../h/uio.h"
129010Sroot #include "../h/file.h"
139170Ssam #include "../h/nami.h"
141404Sbill 
151404Sbill struct	buf rswbuf;
161404Sbill /*
171404Sbill  * Indirect driver for multi-controller paging.
181404Sbill  */
191404Sbill swstrategy(bp)
201404Sbill 	register struct buf *bp;
211404Sbill {
221404Sbill 	int sz, off, seg;
231404Sbill 	dev_t dev;
241404Sbill 
257435Sroot #ifdef GENERIC
267435Sroot 	/*
277435Sroot 	 * A mini-root gets copied into the front of the swap
287435Sroot 	 * and we run over top of the swap area just long
297435Sroot 	 * enough for us to do a mkfs and restor of the real
307435Sroot 	 * root (sure beats rewriting standalone restor).
317435Sroot 	 */
3211051Ssam #define	MINIROOTSIZE	4096
337435Sroot 	if (rootdev == dumpdev)
347435Sroot 		bp->b_blkno += MINIROOTSIZE;
357435Sroot #endif
369010Sroot 	sz = howmany(bp->b_bcount, DEV_BSIZE);
371404Sbill 	off = bp->b_blkno % DMMAX;
381404Sbill 	if (bp->b_blkno+sz > nswap || off+sz > DMMAX) {
391404Sbill 		bp->b_flags |= B_ERROR;
401404Sbill 		iodone(bp);
411404Sbill 		return;
421404Sbill 	}
431404Sbill 	seg = bp->b_blkno / DMMAX;
441404Sbill 	dev = swdevt[seg % nswdev].sw_dev;
451404Sbill 	seg /= nswdev;
461404Sbill 	bp->b_blkno = seg*DMMAX + off;
471404Sbill 	bp->b_dev = dev;
481404Sbill 	if (dev == 0)
491404Sbill 		panic("swstrategy");
501404Sbill 	(*bdevsw[major(dev)].d_strategy)(bp);
511404Sbill }
521404Sbill 
537828Sroot swread(dev, uio)
547828Sroot 	dev_t dev;
557828Sroot 	struct uio *uio;
561404Sbill {
571404Sbill 
588819Sroot 	return (physio(swstrategy, &rswbuf, dev, B_READ, minphys, uio));
591404Sbill }
601404Sbill 
617828Sroot swwrite(dev, uio)
627828Sroot 	dev_t dev;
637828Sroot 	struct uio *uio;
641404Sbill {
651404Sbill 
668819Sroot 	return (physio(swstrategy, &rswbuf, dev, B_WRITE, minphys, uio));
671404Sbill }
681404Sbill 
691404Sbill /*
701404Sbill  * System call swapon(name) enables swapping on device name,
711404Sbill  * which must be in the swdevsw.  Return EBUSY
721404Sbill  * if already swapping on this device.
731404Sbill  */
74*12359Ssam swapon()
751404Sbill {
76*12359Ssam 	struct a {
77*12359Ssam 		char	*name;
78*12359Ssam 	};
791404Sbill 	register struct inode *ip;
801404Sbill 	dev_t dev;
811404Sbill 	register struct swdevt *sp;
821404Sbill 
839170Ssam 	ip = namei(uchar, LOOKUP, 1);
841404Sbill 	if (ip == NULL)
851404Sbill 		return;
861404Sbill 	if ((ip->i_mode&IFMT) != IFBLK) {
871404Sbill 		u.u_error = ENOTBLK;
881404Sbill 		iput(ip);
891404Sbill 		return;
901404Sbill 	}
917278Swnj 	dev = (dev_t)ip->i_rdev;
921404Sbill 	iput(ip);
931404Sbill 	if (major(dev) >= nblkdev) {
941404Sbill 		u.u_error = ENXIO;
951404Sbill 		return;
961404Sbill 	}
971404Sbill 	/*
981404Sbill 	 * Search starting at second table entry,
991404Sbill 	 * since first (primary swap area) is freed at boot.
1001404Sbill 	 */
1011404Sbill 	for (sp = &swdevt[1]; sp->sw_dev; sp++)
1021404Sbill 		if (sp->sw_dev == dev) {
1031404Sbill 			if (sp->sw_freed) {
1041404Sbill 				u.u_error = EBUSY;
1051404Sbill 				return;
1061404Sbill 			}
1071404Sbill 			swfree(sp - swdevt);
1081404Sbill 			return;
1091404Sbill 		}
1101404Sbill 	u.u_error = ENODEV;
1111404Sbill }
1121404Sbill 
1131404Sbill /*
1141404Sbill  * Swfree(index) frees the index'th portion of the swap map.
1151404Sbill  * Each of the nswdev devices provides 1/nswdev'th of the swap
1161404Sbill  * space, which is laid out with blocks of DMMAX pages circularly
1171404Sbill  * among the devices.
1181404Sbill  */
1191404Sbill swfree(index)
1201404Sbill 	int index;
1211404Sbill {
1221404Sbill 	register swblk_t vsbase;
1238772Sroot 	register long blk;
1248961Sroot 	dev_t dev;
1251404Sbill 
1268961Sroot 	dev = swdevt[index].sw_dev;
1278961Sroot 	(*bdevsw[major(dev)].d_open)(dev, FREAD|FWRITE);
1281404Sbill 	swdevt[index].sw_freed = 1;
1291404Sbill 	for (vsbase = index*DMMAX; vsbase < nswap; vsbase += nswdev*DMMAX) {
1301404Sbill 		blk = nswap - vsbase;
1311404Sbill 		if (blk > DMMAX)
1321404Sbill 			blk = DMMAX;
1331404Sbill 		if (vsbase == 0) {
1341404Sbill 			/*
1351404Sbill 			 * Can't free a block starting at 0 in the swapmap
1362788Swnj 			 * but need some space for argmap so use 1/2 this
1371404Sbill 			 * hunk which needs special treatment anyways.
1381404Sbill 			 */
1391404Sbill 			argdev = swdevt[0].sw_dev;
1408961Sroot 			rminit(argmap, (long)(blk/2-ctod(CLSIZE)),
1418961Sroot 			    (long)ctod(CLSIZE), "argmap", ARGMAPSIZE);
1422788Swnj 			/*
1432788Swnj 			 * First of all chunks... initialize the swapmap
1442788Swnj 			 * the second half of the hunk.
1452788Swnj 			 */
1468794Sroot 			rminit(swapmap, (long)blk/2, (long)blk/2,
1478794Sroot 			    "swap", nswapmap);
1481404Sbill 		} else
1492788Swnj 			rmfree(swapmap, blk, vsbase);
1501404Sbill 	}
1511404Sbill }
152