1 /* 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)vm_swap.c 7.27 (Berkeley) 10/22/92 8 */ 9 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/map.h> 19 #include <sys/file.h> 20 21 #include <miscfs/specfs/specdev.h> 22 23 /* 24 * Indirect driver for multi-controller paging. 25 */ 26 27 int nswap, nswdev; 28 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 */ 36 void 37 swapinit() 38 { 39 register int i; 40 register struct buf *sp = swbuf; 41 register struct proc *p = &proc0; /* XXX */ 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"); 64 if (error = swfree(p, 0)) { 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.b_actf = sp; 73 for (i = 0; i < nswbuf - 1; i++, sp++) { 74 sp->b_actf = sp + 1; 75 sp->b_rcred = sp->b_wcred = p->p_ucred; 76 sp->b_vnbufs.qe_next = NOLIST; 77 } 78 sp->b_rcred = sp->b_wcred = p->p_ucred; 79 sp->b_vnbufs.qe_next = NOLIST; 80 sp->b_actf = NULL; 81 } 82 83 void 84 swstrategy(bp) 85 register struct buf *bp; 86 { 87 int sz, off, seg, index; 88 register struct swdevt *sp; 89 struct vnode *vp; 90 91 #ifdef GENERIC 92 /* 93 * A mini-root gets copied into the front of the swap 94 * and we run over top of the swap area just long 95 * enough for us to do a mkfs and restor of the real 96 * root (sure beats rewriting standalone restor). 97 */ 98 #define MINIROOTSIZE 4096 99 if (rootdev == dumpdev) 100 bp->b_blkno += MINIROOTSIZE; 101 #endif 102 sz = howmany(bp->b_bcount, DEV_BSIZE); 103 if (bp->b_blkno + sz > nswap) { 104 bp->b_flags |= B_ERROR; 105 biodone(bp); 106 return; 107 } 108 if (nswdev > 1) { 109 off = bp->b_blkno % dmmax; 110 if (off+sz > dmmax) { 111 bp->b_flags |= B_ERROR; 112 biodone(bp); 113 return; 114 } 115 seg = bp->b_blkno / dmmax; 116 index = seg % nswdev; 117 seg /= nswdev; 118 bp->b_blkno = seg*dmmax + off; 119 } else 120 index = 0; 121 sp = &swdevt[index]; 122 if ((bp->b_dev = sp->sw_dev) == 0) 123 panic("swstrategy"); 124 if (sp->sw_vp == NULL) { 125 bp->b_error |= B_ERROR; 126 biodone(bp); 127 return; 128 } 129 VHOLD(sp->sw_vp); 130 if ((bp->b_flags & B_READ) == 0) { 131 if (vp = bp->b_vp) { 132 vp->v_numoutput--; 133 if ((vp->v_flag & VBWAIT) && vp->v_numoutput <= 0) { 134 vp->v_flag &= ~VBWAIT; 135 wakeup((caddr_t)&vp->v_numoutput); 136 } 137 } 138 sp->sw_vp->v_numoutput++; 139 } 140 if (bp->b_vp != NULL) 141 brelvp(bp); 142 bp->b_vp = sp->sw_vp; 143 VOP_STRATEGY(bp); 144 } 145 146 /* 147 * System call swapon(name) enables swapping on device name, 148 * which must be in the swdevsw. Return EBUSY 149 * if already swapping on this device. 150 */ 151 struct swapon_args { 152 char *name; 153 }; 154 /* ARGSUSED */ 155 int 156 swapon(p, uap, retval) 157 struct proc *p; 158 struct swapon_args *uap; 159 int *retval; 160 { 161 register struct vnode *vp; 162 register struct swdevt *sp; 163 dev_t dev; 164 int error; 165 struct nameidata nd; 166 167 if (error = suser(p->p_ucred, &p->p_acflag)) 168 return (error); 169 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->name, p); 170 if (error = namei(&nd)) 171 return (error); 172 vp = nd.ni_vp; 173 if (vp->v_type != VBLK) { 174 vrele(vp); 175 return (ENOTBLK); 176 } 177 dev = (dev_t)vp->v_rdev; 178 if (major(dev) >= nblkdev) { 179 vrele(vp); 180 return (ENXIO); 181 } 182 for (sp = &swdevt[0]; sp->sw_dev; sp++) 183 if (sp->sw_dev == dev) { 184 if (sp->sw_freed) { 185 vrele(vp); 186 return (EBUSY); 187 } 188 sp->sw_vp = vp; 189 if (error = swfree(p, sp - swdevt)) { 190 vrele(vp); 191 return (error); 192 } 193 return (0); 194 } 195 vrele(vp); 196 return (EINVAL); 197 } 198 199 /* 200 * Swfree(index) frees the index'th portion of the swap map. 201 * Each of the nswdev devices provides 1/nswdev'th of the swap 202 * space, which is laid out with blocks of dmmax pages circularly 203 * among the devices. 204 */ 205 int 206 swfree(p, index) 207 struct proc *p; 208 int index; 209 { 210 register struct swdevt *sp; 211 register swblk_t vsbase; 212 register long blk; 213 struct vnode *vp; 214 register swblk_t dvbase; 215 register int nblks; 216 int error; 217 218 sp = &swdevt[index]; 219 vp = sp->sw_vp; 220 if (error = VOP_OPEN(vp, FREAD|FWRITE, p->p_ucred, p)) 221 return (error); 222 sp->sw_freed = 1; 223 nblks = sp->sw_nblks; 224 for (dvbase = 0; dvbase < nblks; dvbase += dmmax) { 225 blk = nblks - dvbase; 226 if ((vsbase = index*dmmax + dvbase*nswdev) >= nswap) 227 panic("swfree"); 228 if (blk > dmmax) 229 blk = dmmax; 230 if (vsbase == 0) { 231 /* 232 * First of all chunks... initialize the swapmap 233 * the second half of the hunk. 234 */ 235 rminit(swapmap, (long)(blk/2), (long)(blk/2), 236 "swap", nswapmap); 237 } else if (dvbase == 0) { 238 /* 239 * Don't use the first cluster of the device 240 * in case it starts with a label or boot block. 241 */ 242 rmfree(swapmap, blk - ctod(CLSIZE), 243 vsbase + ctod(CLSIZE)); 244 } else 245 rmfree(swapmap, blk, vsbase); 246 } 247 return (0); 248 } 249