Commit | Line | Data |
---|---|---|
da7c5cc6 | 1 | /* |
c4ec2128 KM |
2 | * Copyright (c) 1982, 1986, 1989 Regents of the University of California. |
3 | * All rights reserved. | |
da7c5cc6 | 4 | * |
dbf0c423 | 5 | * %sccs.include.redist.c% |
c4ec2128 | 6 | * |
6e5182e0 | 7 | * @(#)vm_swap.c 7.23 (Berkeley) %G% |
da7c5cc6 | 8 | */ |
013037be | 9 | |
3266719e KB |
10 | #include <sys/param.h> |
11 | #include <sys/systm.h> | |
12 | #include <sys/buf.h> | |
13 | #include <sys/conf.h> | |
14 | #include <sys/proc.h> | |
15 | #include <sys/namei.h> | |
16 | #include <sys/dmap.h> /* XXX */ | |
17 | #include <sys/vnode.h> | |
18 | #include <sys/specdev.h> | |
19 | #include <sys/map.h> | |
20 | #include <sys/file.h> | |
ec67a3ce | 21 | #include "stat.h" |
013037be | 22 | |
013037be BJ |
23 | /* |
24 | * Indirect driver for multi-controller paging. | |
25 | */ | |
be2fd2c3 | 26 | |
fc703211 MK |
27 | int nswap, nswdev; |
28 | ||
be2fd2c3 MK |
29 | /* |
30 | * Set up swap devices. | |
31 | * Initialize linked list of free swap | |
32 | * headers. These do not actually point | |
33 | * to buffers, but rather to pages that | |
34 | * are being swapped in and out. | |
35 | */ | |
3266719e | 36 | void |
be2fd2c3 MK |
37 | swapinit() |
38 | { | |
39 | register int i; | |
40 | register struct buf *sp = swbuf; | |
baaa1646 | 41 | register struct proc *p = &proc0; /* XXX */ |
be2fd2c3 MK |
42 | struct swdevt *swp; |
43 | int error; | |
44 | ||
45 | /* | |
46 | * Count swap devices, and adjust total swap space available. | |
47 | * Some of this space will not be available until a swapon() | |
48 | * system is issued, usually when the system goes multi-user. | |
49 | */ | |
50 | nswdev = 0; | |
51 | nswap = 0; | |
52 | for (swp = swdevt; swp->sw_dev; swp++) { | |
53 | nswdev++; | |
54 | if (swp->sw_nblks > nswap) | |
55 | nswap = swp->sw_nblks; | |
56 | } | |
57 | if (nswdev == 0) | |
58 | panic("swapinit"); | |
59 | if (nswdev > 1) | |
60 | nswap = ((nswap + dmmax - 1) / dmmax) * dmmax; | |
61 | nswap *= nswdev; | |
62 | if (bdevvp(swdevt[0].sw_dev, &swdevt[0].sw_vp)) | |
63 | panic("swapvp"); | |
baaa1646 | 64 | if (error = swfree(p, 0)) { |
be2fd2c3 MK |
65 | printf("swfree errno %d\n", error); /* XXX */ |
66 | panic("swapinit swfree 0"); | |
67 | } | |
68 | ||
69 | /* | |
70 | * Now set up swap buffer headers. | |
71 | */ | |
72 | bswlist.av_forw = sp; | |
baaa1646 | 73 | for (i = 0; i < nswbuf - 1; i++, sp++) { |
be2fd2c3 | 74 | sp->av_forw = sp + 1; |
baaa1646 KM |
75 | sp->b_rcred = sp->b_wcred = p->p_ucred; |
76 | } | |
77 | sp->b_rcred = sp->b_wcred = p->p_ucred; | |
be2fd2c3 MK |
78 | sp->av_forw = NULL; |
79 | } | |
80 | ||
3266719e | 81 | void |
013037be BJ |
82 | swstrategy(bp) |
83 | register struct buf *bp; | |
84 | { | |
ec67a3ce MK |
85 | int sz, off, seg, index; |
86 | register struct swdevt *sp; | |
013037be | 87 | |
b9ee5d20 BJ |
88 | #ifdef GENERIC |
89 | /* | |
90 | * A mini-root gets copied into the front of the swap | |
91 | * and we run over top of the swap area just long | |
92 | * enough for us to do a mkfs and restor of the real | |
93 | * root (sure beats rewriting standalone restor). | |
94 | */ | |
8c5046eb | 95 | #define MINIROOTSIZE 4096 |
b9ee5d20 BJ |
96 | if (rootdev == dumpdev) |
97 | bp->b_blkno += MINIROOTSIZE; | |
98 | #endif | |
ca1f746a | 99 | sz = howmany(bp->b_bcount, DEV_BSIZE); |
be2fd2c3 | 100 | if (bp->b_blkno + sz > nswap) { |
013037be | 101 | bp->b_flags |= B_ERROR; |
ec67a3ce | 102 | biodone(bp); |
013037be BJ |
103 | return; |
104 | } | |
d668d9ba SL |
105 | if (nswdev > 1) { |
106 | off = bp->b_blkno % dmmax; | |
107 | if (off+sz > dmmax) { | |
108 | bp->b_flags |= B_ERROR; | |
ec67a3ce | 109 | biodone(bp); |
d668d9ba SL |
110 | return; |
111 | } | |
112 | seg = bp->b_blkno / dmmax; | |
ec67a3ce | 113 | index = seg % nswdev; |
d668d9ba SL |
114 | seg /= nswdev; |
115 | bp->b_blkno = seg*dmmax + off; | |
116 | } else | |
ec67a3ce MK |
117 | index = 0; |
118 | sp = &swdevt[index]; | |
119 | #ifdef SECSIZE | |
120 | bp->b_blkno <<= sp->sw_bshift; | |
121 | bp->b_blksize = sp->sw_blksize; | |
122 | #endif SECSIZE | |
123 | bp->b_dev = sp->sw_dev; | |
124 | if (bp->b_dev == 0) | |
013037be | 125 | panic("swstrategy"); |
ec67a3ce | 126 | (*bdevsw[major(bp->b_dev)].d_strategy)(bp); |
013037be BJ |
127 | } |
128 | ||
013037be BJ |
129 | /* |
130 | * System call swapon(name) enables swapping on device name, | |
131 | * which must be in the swdevsw. Return EBUSY | |
132 | * if already swapping on this device. | |
133 | */ | |
f6c3fd73 | 134 | /* ARGSUSED */ |
3266719e | 135 | int |
f6c3fd73 KM |
136 | swapon(p, uap, retval) |
137 | struct proc *p; | |
138 | struct args { | |
2dfa06c1 | 139 | char *name; |
f6c3fd73 KM |
140 | } *uap; |
141 | int *retval; | |
142 | { | |
c4ec2128 | 143 | register struct vnode *vp; |
013037be | 144 | register struct swdevt *sp; |
f6c3fd73 KM |
145 | dev_t dev; |
146 | int error; | |
be2fd2c3 | 147 | struct nameidata nd; |
013037be | 148 | |
be2fd2c3 | 149 | if (error = suser(p->p_ucred, &p->p_acflag)) |
d9c2f47f | 150 | return (error); |
56b1696d KM |
151 | NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->name, p); |
152 | if (error = namei(&nd)) | |
d9c2f47f | 153 | return (error); |
56b1696d | 154 | vp = nd.ni_vp; |
c4ec2128 KM |
155 | if (vp->v_type != VBLK) { |
156 | vrele(vp); | |
d9c2f47f | 157 | return (ENOTBLK); |
013037be | 158 | } |
c4ec2128 | 159 | dev = (dev_t)vp->v_rdev; |
013037be | 160 | if (major(dev) >= nblkdev) { |
c4ec2128 | 161 | vrele(vp); |
d9c2f47f | 162 | return (ENXIO); |
013037be | 163 | } |
ae0ffeb1 | 164 | for (sp = &swdevt[0]; sp->sw_dev; sp++) |
013037be BJ |
165 | if (sp->sw_dev == dev) { |
166 | if (sp->sw_freed) { | |
c4ec2128 | 167 | vrele(vp); |
d9c2f47f | 168 | return (EBUSY); |
013037be | 169 | } |
ec67a3ce | 170 | u.u_error = swfree(sp - swdevt); |
d9c2f47f | 171 | return (0); |
013037be | 172 | } |
c4ec2128 | 173 | vrele(vp); |
d9c2f47f | 174 | return (EINVAL); |
013037be BJ |
175 | } |
176 | ||
ec67a3ce MK |
177 | #ifdef SECSIZE |
178 | long argdbsize; /* XXX */ | |
179 | ||
180 | #endif SECSIZE | |
013037be BJ |
181 | /* |
182 | * Swfree(index) frees the index'th portion of the swap map. | |
183 | * Each of the nswdev devices provides 1/nswdev'th of the swap | |
d668d9ba | 184 | * space, which is laid out with blocks of dmmax pages circularly |
013037be BJ |
185 | * among the devices. |
186 | */ | |
3266719e | 187 | int |
be2fd2c3 MK |
188 | swfree(p, index) |
189 | struct proc *p; | |
013037be BJ |
190 | int index; |
191 | { | |
609e7cfa | 192 | register struct swdevt *sp; |
ec67a3ce | 193 | register struct swdevt *sp; |
013037be | 194 | register swblk_t vsbase; |
39d536e6 | 195 | register long blk; |
c4ec2128 | 196 | struct vnode *vp; |
d668d9ba SL |
197 | register swblk_t dvbase; |
198 | register int nblks; | |
ec67a3ce | 199 | int error; |
609e7cfa | 200 | int error; |
013037be | 201 | |
ec67a3ce MK |
202 | sp = &swdevt[index]; |
203 | dev = sp->sw_dev; | |
204 | if (error = (*bdevsw[major(dev)].d_open)(dev, FREAD|FWRITE, S_IFBLK)) | |
205 | return (error); | |
206 | sp->sw_freed = 1; | |
207 | nblks = sp->sw_nblks; | |
d668d9ba SL |
208 | for (dvbase = 0; dvbase < nblks; dvbase += dmmax) { |
209 | blk = nblks - dvbase; | |
210 | if ((vsbase = index*dmmax + dvbase*nswdev) >= nswap) | |
211 | panic("swfree"); | |
212 | if (blk > dmmax) | |
213 | blk = dmmax; | |
013037be | 214 | if (vsbase == 0) { |
c84ff1f9 BJ |
215 | /* |
216 | * First of all chunks... initialize the swapmap | |
217 | * the second half of the hunk. | |
218 | */ | |
c4ec2128 | 219 | rminit(swapmap, (long)(blk/2), (long)(blk/2), |
a29f7995 | 220 | "swap", nswapmap); |
ec67a3ce MK |
221 | } else if (dvbase == 0) { |
222 | /* | |
223 | * Don't use the first cluster of the device | |
224 | * in case it starts with a label or boot block. | |
225 | */ | |
226 | rmfree(swapmap, blk - ctod(CLSIZE), | |
227 | vsbase + ctod(CLSIZE)); | |
609e7cfa MK |
228 | } else if (dvbase == 0) { |
229 | /* | |
230 | * Don't use the first cluster of the device | |
231 | * in case it starts with a label or boot block. | |
232 | */ | |
233 | rmfree(swapmap, blk - ctod(CLSIZE), | |
234 | vsbase + ctod(CLSIZE)); | |
013037be | 235 | } else |
c84ff1f9 | 236 | rmfree(swapmap, blk, vsbase); |
013037be | 237 | } |
ec67a3ce | 238 | return (0); |
609e7cfa | 239 | return (0); |
013037be | 240 | } |