xref: /original-bsd/sys/vm/vm_swap.c (revision 92d3de31)
1 /*	vm_swap.c	4.16	83/02/13	*/
2 
3 #include "../h/param.h"
4 #include "../h/systm.h"
5 #include "../h/buf.h"
6 #include "../h/conf.h"
7 #include "../h/dir.h"
8 #include "../h/user.h"
9 #include "../h/inode.h"
10 #include "../h/map.h"
11 #include "../h/uio.h"
12 #include "../h/file.h"
13 #include "../h/nami.h"
14 
15 struct	buf rswbuf;
16 /*
17  * Indirect driver for multi-controller paging.
18  */
19 swstrategy(bp)
20 	register struct buf *bp;
21 {
22 	int sz, off, seg;
23 	dev_t dev;
24 
25 #ifdef GENERIC
26 	/*
27 	 * A mini-root gets copied into the front of the swap
28 	 * and we run over top of the swap area just long
29 	 * enough for us to do a mkfs and restor of the real
30 	 * root (sure beats rewriting standalone restor).
31 	 */
32 #define	MINIROOTSIZE	4096
33 	if (rootdev == dumpdev)
34 		bp->b_blkno += MINIROOTSIZE;
35 #endif
36 	sz = howmany(bp->b_bcount, DEV_BSIZE);
37 	off = bp->b_blkno % DMMAX;
38 	if (bp->b_blkno+sz > nswap || off+sz > DMMAX) {
39 		bp->b_flags |= B_ERROR;
40 		iodone(bp);
41 		return;
42 	}
43 	seg = bp->b_blkno / DMMAX;
44 	dev = swdevt[seg % nswdev].sw_dev;
45 	seg /= nswdev;
46 	bp->b_blkno = seg*DMMAX + off;
47 	bp->b_dev = dev;
48 	if (dev == 0)
49 		panic("swstrategy");
50 	(*bdevsw[major(dev)].d_strategy)(bp);
51 }
52 
53 swread(dev, uio)
54 	dev_t dev;
55 	struct uio *uio;
56 {
57 
58 	return (physio(swstrategy, &rswbuf, dev, B_READ, minphys, uio));
59 }
60 
61 swwrite(dev, uio)
62 	dev_t dev;
63 	struct uio *uio;
64 {
65 
66 	return (physio(swstrategy, &rswbuf, dev, B_WRITE, minphys, uio));
67 }
68 
69 /*
70  * System call swapon(name) enables swapping on device name,
71  * which must be in the swdevsw.  Return EBUSY
72  * if already swapping on this device.
73  */
74 oswapon()
75 {
76 	register struct inode *ip;
77 	dev_t dev;
78 	register struct swdevt *sp;
79 
80 	ip = namei(uchar, LOOKUP, 1);
81 	if (ip == NULL)
82 		return;
83 	if ((ip->i_mode&IFMT) != IFBLK) {
84 		u.u_error = ENOTBLK;
85 		iput(ip);
86 		return;
87 	}
88 	dev = (dev_t)ip->i_rdev;
89 	iput(ip);
90 	if (major(dev) >= nblkdev) {
91 		u.u_error = ENXIO;
92 		return;
93 	}
94 	/*
95 	 * Search starting at second table entry,
96 	 * since first (primary swap area) is freed at boot.
97 	 */
98 	for (sp = &swdevt[1]; sp->sw_dev; sp++)
99 		if (sp->sw_dev == dev) {
100 			if (sp->sw_freed) {
101 				u.u_error = EBUSY;
102 				return;
103 			}
104 			swfree(sp - swdevt);
105 			return;
106 		}
107 	u.u_error = ENODEV;
108 }
109 
110 /*
111  * Swfree(index) frees the index'th portion of the swap map.
112  * Each of the nswdev devices provides 1/nswdev'th of the swap
113  * space, which is laid out with blocks of DMMAX pages circularly
114  * among the devices.
115  */
116 swfree(index)
117 	int index;
118 {
119 	register swblk_t vsbase;
120 	register long blk;
121 	dev_t dev;
122 
123 	dev = swdevt[index].sw_dev;
124 	(*bdevsw[major(dev)].d_open)(dev, FREAD|FWRITE);
125 	swdevt[index].sw_freed = 1;
126 	for (vsbase = index*DMMAX; vsbase < nswap; vsbase += nswdev*DMMAX) {
127 		blk = nswap - vsbase;
128 		if (blk > DMMAX)
129 			blk = DMMAX;
130 		if (vsbase == 0) {
131 			/*
132 			 * Can't free a block starting at 0 in the swapmap
133 			 * but need some space for argmap so use 1/2 this
134 			 * hunk which needs special treatment anyways.
135 			 */
136 			argdev = swdevt[0].sw_dev;
137 			rminit(argmap, (long)(blk/2-ctod(CLSIZE)),
138 			    (long)ctod(CLSIZE), "argmap", ARGMAPSIZE);
139 			/*
140 			 * First of all chunks... initialize the swapmap
141 			 * the second half of the hunk.
142 			 */
143 			rminit(swapmap, (long)blk/2, (long)blk/2,
144 			    "swap", nswapmap);
145 		} else
146 			rmfree(swapmap, blk, vsbase);
147 	}
148 }
149