|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
33: * @(#)vm_swap.c 7.18 (Berkeley) 5/6/91
34: */
35:
36: #include "param.h"
37: #include "systm.h"
38: #include "buf.h"
39: #include "conf.h"
40: #include "proc.h"
41: #include "namei.h"
42: #include "dmap.h" /* XXX */
43: #include "vnode.h"
44: #include "specdev.h"
45: #include "map.h"
46: #include "file.h"
47:
48: /*
49: * Indirect driver for multi-controller paging.
50: */
51:
52: int nswap, nswdev;
53:
54: /*
55: * Set up swap devices.
56: * Initialize linked list of free swap
57: * headers. These do not actually point
58: * to buffers, but rather to pages that
59: * are being swapped in and out.
60: */
61: swapinit()
62: {
63: register int i;
64: register struct buf *sp = swbuf;
65: struct swdevt *swp;
66: int error;
67:
68: /*
69: * Count swap devices, and adjust total swap space available.
70: * Some of this space will not be available until a swapon()
71: * system is issued, usually when the system goes multi-user.
72: */
73: nswdev = 0;
74: nswap = 0;
75: for (swp = swdevt; swp->sw_dev; swp++) {
76: nswdev++;
77: if (swp->sw_nblks > nswap)
78: nswap = swp->sw_nblks;
79: }
80: if (nswdev == 0)
81: panic("swapinit");
82: if (nswdev > 1)
83: nswap = ((nswap + dmmax - 1) / dmmax) * dmmax;
84: nswap *= nswdev;
85: if (bdevvp(swdevt[0].sw_dev, &swdevt[0].sw_vp))
86: panic("swapvp");
87: if (error = swfree(&proc0, 0)) {
88: printf("swfree errno %d\n", error); /* XXX */
89: panic("swapinit swfree 0");
90: }
91:
92: /*
93: * Now set up swap buffer headers.
94: */
95: bswlist.av_forw = sp;
96: for (i = 0; i < nswbuf - 1; i++, sp++)
97: sp->av_forw = sp + 1;
98: sp->av_forw = NULL;
99: }
100:
101: swstrategy(bp)
102: register struct buf *bp;
103: {
104: int sz, off, seg, index;
105: register struct swdevt *sp;
106: struct vnode *vp;
107:
108: #ifdef GENERIC
109: /*
110: * A mini-root gets copied into the front of the swap
111: * and we run over top of the swap area just long
112: * enough for us to do a mkfs and restor of the real
113: * root (sure beats rewriting standalone restor).
114: */
115: #define MINIROOTSIZE 4096
116: if (rootdev == dumpdev)
117: bp->b_blkno += MINIROOTSIZE;
118: #endif
119: sz = howmany(bp->b_bcount, DEV_BSIZE);
120: if (bp->b_blkno + sz > nswap) {
121: bp->b_flags |= B_ERROR;
122: biodone(bp);
123: return;
124: }
125: if (nswdev > 1) {
126: off = bp->b_blkno % dmmax;
127: if (off+sz > dmmax) {
128: bp->b_flags |= B_ERROR;
129: biodone(bp);
130: return;
131: }
132: seg = bp->b_blkno / dmmax;
133: index = seg % nswdev;
134: seg /= nswdev;
135: bp->b_blkno = seg*dmmax + off;
136: } else
137: index = 0;
138: sp = &swdevt[index];
139: if ((bp->b_dev = sp->sw_dev) == 0)
140: panic("swstrategy");
141: if (sp->sw_vp == NULL) {
142: bp->b_error |= B_ERROR;
143: biodone(bp);
144: return;
145: }
146: VHOLD(sp->sw_vp);
147: if ((bp->b_flags & B_READ) == 0) {
148: if (vp = bp->b_vp) {
149: vp->v_numoutput--;
150: if ((vp->v_flag & VBWAIT) && vp->v_numoutput <= 0) {
151: vp->v_flag &= ~VBWAIT;
152: wakeup((caddr_t)&vp->v_numoutput);
153: }
154: }
155: sp->sw_vp->v_numoutput++;
156: }
157: if (bp->b_vp != NULL)
158: brelvp(bp);
159: bp->b_vp = sp->sw_vp;
160: VOP_STRATEGY(bp);
161: }
162:
163: /*
164: * System call swapon(name) enables swapping on device name,
165: * which must be in the swdevsw. Return EBUSY
166: * if already swapping on this device.
167: */
168: /* ARGSUSED */
169: swapon(p, uap, retval)
170: struct proc *p;
171: struct args {
172: char *name;
173: } *uap;
174: int *retval;
175: {
176: register struct vnode *vp;
177: register struct swdevt *sp;
178: register struct nameidata *ndp;
179: dev_t dev;
180: int error;
181: struct nameidata nd;
182:
183: if (error = suser(p->p_ucred, &p->p_acflag))
184: return (error);
185: ndp = &nd;
186: ndp->ni_nameiop = LOOKUP | FOLLOW;
187: ndp->ni_segflg = UIO_USERSPACE;
188: ndp->ni_dirp = uap->name;
189: if (error = namei(ndp, p))
190: return (error);
191: vp = ndp->ni_vp;
192: if (vp->v_type != VBLK) {
193: vrele(vp);
194: return (ENOTBLK);
195: }
196: dev = (dev_t)vp->v_rdev;
197: if (major(dev) >= nblkdev) {
198: vrele(vp);
199: return (ENXIO);
200: }
201: for (sp = &swdevt[0]; sp->sw_dev; sp++)
202: if (sp->sw_dev == dev) {
203: if (sp->sw_freed) {
204: vrele(vp);
205: return (EBUSY);
206: }
207: sp->sw_vp = vp;
208: if (error = swfree(p, sp - swdevt)) {
209: vrele(vp);
210: return (error);
211: }
212: return (0);
213: }
214: vrele(vp);
215: return (EINVAL);
216: }
217:
218: /*
219: * Swfree(index) frees the index'th portion of the swap map.
220: * Each of the nswdev devices provides 1/nswdev'th of the swap
221: * space, which is laid out with blocks of dmmax pages circularly
222: * among the devices.
223: */
224: swfree(p, index)
225: struct proc *p;
226: int index;
227: {
228: register struct swdevt *sp;
229: register swblk_t vsbase;
230: register long blk;
231: struct vnode *vp;
232: register swblk_t dvbase;
233: register int nblks;
234: int error;
235:
236: sp = &swdevt[index];
237: vp = sp->sw_vp;
238: if (error = VOP_OPEN(vp, FREAD|FWRITE, p->p_ucred, p))
239: return (error);
240: sp->sw_freed = 1;
241: nblks = sp->sw_nblks;
242: for (dvbase = 0; dvbase < nblks; dvbase += dmmax) {
243: blk = nblks - dvbase;
244: if ((vsbase = index*dmmax + dvbase*nswdev) >= nswap)
245: panic("swfree");
246: if (blk > dmmax)
247: blk = dmmax;
248: if (vsbase == 0) {
249: /*
250: * First of all chunks... initialize the swapmap
251: * the second half of the hunk.
252: */
253: rminit(swapmap, (long)(blk/2), (long)(blk/2),
254: "swap", nswapmap);
255: } else if (dvbase == 0) {
256: /*
257: * Don't use the first cluster of the device
258: * in case it starts with a label or boot block.
259: */
260: rmfree(swapmap, blk - ctod(CLSIZE),
261: vsbase + ctod(CLSIZE));
262: } else
263: rmfree(swapmap, blk, vsbase);
264: }
265: return (0);
266: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.