xref: /original-bsd/sys/vm/vm_swap.c (revision 460057e1)
1 /*	vm_swap.c	4.5	82/03/12	*/
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 
12 struct	buf rswbuf;
13 /*
14  * Indirect driver for multi-controller paging.
15  */
16 swstrategy(bp)
17 	register struct buf *bp;
18 {
19 	int sz, off, seg;
20 	dev_t dev;
21 
22 	sz = (bp->b_bcount+511)/512;
23 	off = bp->b_blkno % DMMAX;
24 	if (bp->b_blkno+sz > nswap || off+sz > DMMAX) {
25 		bp->b_flags |= B_ERROR;
26 		iodone(bp);
27 		return;
28 	}
29 	seg = bp->b_blkno / DMMAX;
30 	dev = swdevt[seg % nswdev].sw_dev;
31 	seg /= nswdev;
32 	bp->b_blkno = seg*DMMAX + off;
33 	bp->b_dev = dev;
34 	if (dev == 0)
35 		panic("swstrategy");
36 	(*bdevsw[major(dev)].d_strategy)(bp);
37 }
38 
39 swread(dev)
40 {
41 
42 	physio(swstrategy, &rswbuf, dev, B_READ, minphys);
43 }
44 
45 swwrite(dev)
46 {
47 
48 	physio(swstrategy, &rswbuf, dev, B_WRITE, minphys);
49 }
50 
51 /*
52  * System call swapon(name) enables swapping on device name,
53  * which must be in the swdevsw.  Return EBUSY
54  * if already swapping on this device.
55  */
56 vswapon()
57 {
58 	register struct inode *ip;
59 	dev_t dev;
60 	register struct swdevt *sp;
61 
62 	ip = namei(uchar, 0, 1);
63 	if (ip == NULL)
64 		return;
65 	if ((ip->i_mode&IFMT) != IFBLK) {
66 		u.u_error = ENOTBLK;
67 		iput(ip);
68 		return;
69 	}
70 	dev = (dev_t)ip->i_un.i_rdev;
71 	iput(ip);
72 	if (major(dev) >= nblkdev) {
73 		u.u_error = ENXIO;
74 		return;
75 	}
76 	/*
77 	 * Search starting at second table entry,
78 	 * since first (primary swap area) is freed at boot.
79 	 */
80 	for (sp = &swdevt[1]; sp->sw_dev; sp++)
81 		if (sp->sw_dev == dev) {
82 			if (sp->sw_freed) {
83 				u.u_error = EBUSY;
84 				return;
85 			}
86 			swfree(sp - swdevt);
87 			return;
88 		}
89 	u.u_error = ENODEV;
90 }
91 
92 /*
93  * Swfree(index) frees the index'th portion of the swap map.
94  * Each of the nswdev devices provides 1/nswdev'th of the swap
95  * space, which is laid out with blocks of DMMAX pages circularly
96  * among the devices.
97  */
98 swfree(index)
99 	int index;
100 {
101 	register swblk_t vsbase;
102 	register int blk;
103 
104 	swdevt[index].sw_freed = 1;
105 	for (vsbase = index*DMMAX; vsbase < nswap; vsbase += nswdev*DMMAX) {
106 		blk = nswap - vsbase;
107 		if (blk > DMMAX)
108 			blk = DMMAX;
109 		if (vsbase == 0) {
110 			/*
111 			 * Can't free a block starting at 0 in the swapmap
112 			 * but need some space for argmap so use 1/2 this
113 			 * hunk which needs special treatment anyways.
114 			 */
115 			argdev = swdevt[0].sw_dev;
116 			rminit(argmap, blk/2-CLSIZE, CLSIZE,
117 			    "argmap", ARGMAPSIZE);
118 			/*
119 			 * First of all chunks... initialize the swapmap
120 			 * the second half of the hunk.
121 			 */
122 			rminit(swapmap, blk/2, blk/2, "swap", nswapmap);
123 		} else
124 			rmfree(swapmap, blk, vsbase);
125 	}
126 }
127