Commit | Line | Data |
---|---|---|
da7c5cc6 | 1 | /* |
0880b18e | 2 | * Copyright (c) 1982, 1986 Regents of the University of California. |
da7c5cc6 KM |
3 | * All rights reserved. The Berkeley software License Agreement |
4 | * specifies the terms and conditions for redistribution. | |
5 | * | |
849cbd39 | 6 | * @(#)vm_swap.c 7.4 (Berkeley) %G% |
da7c5cc6 | 7 | */ |
013037be | 8 | |
94368568 JB |
9 | #include "param.h" |
10 | #include "systm.h" | |
11 | #include "buf.h" | |
12 | #include "conf.h" | |
13 | #include "dir.h" | |
14 | #include "user.h" | |
15 | #include "inode.h" | |
16 | #include "map.h" | |
17 | #include "uio.h" | |
18 | #include "file.h" | |
ec67a3ce | 19 | #include "stat.h" |
609e7cfa | 20 | #include "stat.h" |
013037be | 21 | |
013037be BJ |
22 | /* |
23 | * Indirect driver for multi-controller paging. | |
24 | */ | |
25 | swstrategy(bp) | |
26 | register struct buf *bp; | |
27 | { | |
ec67a3ce MK |
28 | int sz, off, seg, index; |
29 | register struct swdevt *sp; | |
013037be | 30 | |
b9ee5d20 BJ |
31 | #ifdef GENERIC |
32 | /* | |
33 | * A mini-root gets copied into the front of the swap | |
34 | * and we run over top of the swap area just long | |
35 | * enough for us to do a mkfs and restor of the real | |
36 | * root (sure beats rewriting standalone restor). | |
37 | */ | |
8c5046eb | 38 | #define MINIROOTSIZE 4096 |
b9ee5d20 BJ |
39 | if (rootdev == dumpdev) |
40 | bp->b_blkno += MINIROOTSIZE; | |
41 | #endif | |
ca1f746a | 42 | sz = howmany(bp->b_bcount, DEV_BSIZE); |
d668d9ba | 43 | if (bp->b_blkno+sz > nswap) { |
013037be | 44 | bp->b_flags |= B_ERROR; |
ec67a3ce | 45 | biodone(bp); |
013037be BJ |
46 | return; |
47 | } | |
d668d9ba SL |
48 | if (nswdev > 1) { |
49 | off = bp->b_blkno % dmmax; | |
50 | if (off+sz > dmmax) { | |
51 | bp->b_flags |= B_ERROR; | |
ec67a3ce | 52 | biodone(bp); |
d668d9ba SL |
53 | return; |
54 | } | |
55 | seg = bp->b_blkno / dmmax; | |
ec67a3ce | 56 | index = seg % nswdev; |
d668d9ba SL |
57 | seg /= nswdev; |
58 | bp->b_blkno = seg*dmmax + off; | |
59 | } else | |
ec67a3ce MK |
60 | index = 0; |
61 | sp = &swdevt[index]; | |
62 | #ifdef SECSIZE | |
63 | bp->b_blkno <<= sp->sw_bshift; | |
64 | bp->b_blksize = sp->sw_blksize; | |
65 | #endif SECSIZE | |
66 | bp->b_dev = sp->sw_dev; | |
67 | if (bp->b_dev == 0) | |
013037be | 68 | panic("swstrategy"); |
ec67a3ce | 69 | (*bdevsw[major(bp->b_dev)].d_strategy)(bp); |
013037be BJ |
70 | } |
71 | ||
013037be BJ |
72 | /* |
73 | * System call swapon(name) enables swapping on device name, | |
74 | * which must be in the swdevsw. Return EBUSY | |
75 | * if already swapping on this device. | |
76 | */ | |
2dfa06c1 | 77 | swapon() |
013037be | 78 | { |
2dfa06c1 SL |
79 | struct a { |
80 | char *name; | |
715baff1 | 81 | } *uap = (struct a *)u.u_ap; |
013037be BJ |
82 | register struct inode *ip; |
83 | dev_t dev; | |
84 | register struct swdevt *sp; | |
715baff1 | 85 | register struct nameidata *ndp = &u.u_nd; |
013037be | 86 | |
849cbd39 | 87 | if (u.u_error = suser(u.u_cred, &u.u_acflag)) |
dca9bb95 | 88 | return; |
715baff1 KM |
89 | ndp->ni_nameiop = LOOKUP | FOLLOW; |
90 | ndp->ni_segflg = UIO_USERSPACE; | |
91 | ndp->ni_dirp = uap->name; | |
92 | ip = namei(ndp); | |
013037be BJ |
93 | if (ip == NULL) |
94 | return; | |
95 | if ((ip->i_mode&IFMT) != IFBLK) { | |
96 | u.u_error = ENOTBLK; | |
97 | iput(ip); | |
98 | return; | |
99 | } | |
76e9203a | 100 | dev = (dev_t)ip->i_rdev; |
013037be BJ |
101 | iput(ip); |
102 | if (major(dev) >= nblkdev) { | |
103 | u.u_error = ENXIO; | |
104 | return; | |
105 | } | |
ae0ffeb1 | 106 | for (sp = &swdevt[0]; sp->sw_dev; sp++) |
013037be BJ |
107 | if (sp->sw_dev == dev) { |
108 | if (sp->sw_freed) { | |
109 | u.u_error = EBUSY; | |
110 | return; | |
111 | } | |
ec67a3ce | 112 | u.u_error = swfree(sp - swdevt); |
013037be BJ |
113 | return; |
114 | } | |
ae0ffeb1 | 115 | u.u_error = EINVAL; |
013037be BJ |
116 | } |
117 | ||
ec67a3ce MK |
118 | #ifdef SECSIZE |
119 | long argdbsize; /* XXX */ | |
120 | ||
121 | #endif SECSIZE | |
013037be BJ |
122 | /* |
123 | * Swfree(index) frees the index'th portion of the swap map. | |
124 | * Each of the nswdev devices provides 1/nswdev'th of the swap | |
d668d9ba | 125 | * space, which is laid out with blocks of dmmax pages circularly |
013037be BJ |
126 | * among the devices. |
127 | */ | |
128 | swfree(index) | |
129 | int index; | |
130 | { | |
609e7cfa | 131 | register struct swdevt *sp; |
ec67a3ce | 132 | register struct swdevt *sp; |
013037be | 133 | register swblk_t vsbase; |
39d536e6 | 134 | register long blk; |
e438ed8e | 135 | dev_t dev; |
d668d9ba SL |
136 | register swblk_t dvbase; |
137 | register int nblks; | |
ec67a3ce | 138 | int error; |
609e7cfa | 139 | int error; |
013037be | 140 | |
ec67a3ce MK |
141 | sp = &swdevt[index]; |
142 | dev = sp->sw_dev; | |
143 | if (error = (*bdevsw[major(dev)].d_open)(dev, FREAD|FWRITE, S_IFBLK)) | |
144 | return (error); | |
145 | sp->sw_freed = 1; | |
146 | nblks = sp->sw_nblks; | |
d668d9ba SL |
147 | for (dvbase = 0; dvbase < nblks; dvbase += dmmax) { |
148 | blk = nblks - dvbase; | |
149 | if ((vsbase = index*dmmax + dvbase*nswdev) >= nswap) | |
150 | panic("swfree"); | |
151 | if (blk > dmmax) | |
152 | blk = dmmax; | |
013037be BJ |
153 | if (vsbase == 0) { |
154 | /* | |
155 | * Can't free a block starting at 0 in the swapmap | |
c84ff1f9 | 156 | * but need some space for argmap so use 1/2 this |
013037be BJ |
157 | * hunk which needs special treatment anyways. |
158 | */ | |
ec67a3ce MK |
159 | argdev = sp->sw_dev; |
160 | #ifdef SECSIZE | |
161 | argdbsize = sp->sw_blksize; | |
162 | rminit(argmap, | |
163 | ((blk / 2) * DEV_BSIZE - CLBYTES) / argdbsize, | |
164 | CLBYTES / argdbsize, "argmap", ARGMAPSIZE); | |
165 | #else SECSIZE | |
e438ed8e BJ |
166 | rminit(argmap, (long)(blk/2-ctod(CLSIZE)), |
167 | (long)ctod(CLSIZE), "argmap", ARGMAPSIZE); | |
ec67a3ce | 168 | #endif SECSIZE |
c84ff1f9 BJ |
169 | /* |
170 | * First of all chunks... initialize the swapmap | |
171 | * the second half of the hunk. | |
172 | */ | |
a29f7995 BJ |
173 | rminit(swapmap, (long)blk/2, (long)blk/2, |
174 | "swap", nswapmap); | |
ec67a3ce MK |
175 | } else if (dvbase == 0) { |
176 | /* | |
177 | * Don't use the first cluster of the device | |
178 | * in case it starts with a label or boot block. | |
179 | */ | |
180 | rmfree(swapmap, blk - ctod(CLSIZE), | |
181 | vsbase + ctod(CLSIZE)); | |
609e7cfa MK |
182 | } else if (dvbase == 0) { |
183 | /* | |
184 | * Don't use the first cluster of the device | |
185 | * in case it starts with a label or boot block. | |
186 | */ | |
187 | rmfree(swapmap, blk - ctod(CLSIZE), | |
188 | vsbase + ctod(CLSIZE)); | |
013037be | 189 | } else |
c84ff1f9 | 190 | rmfree(swapmap, blk, vsbase); |
013037be | 191 | } |
ec67a3ce | 192 | return (0); |
609e7cfa | 193 | return (0); |
013037be | 194 | } |