1 /* vm_swap.c 6.5 85/05/22 */ 2 3 #include "param.h" 4 #include "systm.h" 5 #include "buf.h" 6 #include "conf.h" 7 #include "dir.h" 8 #include "user.h" 9 #include "inode.h" 10 #include "map.h" 11 #include "uio.h" 12 #include "file.h" 13 14 struct buf rswbuf; 15 /* 16 * Indirect driver for multi-controller paging. 17 */ 18 swstrategy(bp) 19 register struct buf *bp; 20 { 21 int sz, off, seg; 22 dev_t dev; 23 24 #ifdef GENERIC 25 /* 26 * A mini-root gets copied into the front of the swap 27 * and we run over top of the swap area just long 28 * enough for us to do a mkfs and restor of the real 29 * root (sure beats rewriting standalone restor). 30 */ 31 #define MINIROOTSIZE 4096 32 if (rootdev == dumpdev) 33 bp->b_blkno += MINIROOTSIZE; 34 #endif 35 sz = howmany(bp->b_bcount, DEV_BSIZE); 36 if (bp->b_blkno+sz > nswap) { 37 bp->b_flags |= B_ERROR; 38 iodone(bp); 39 return; 40 } 41 if (nswdev > 1) { 42 off = bp->b_blkno % dmmax; 43 if (off+sz > dmmax) { 44 bp->b_flags |= B_ERROR; 45 iodone(bp); 46 return; 47 } 48 seg = bp->b_blkno / dmmax; 49 dev = swdevt[seg % nswdev].sw_dev; 50 seg /= nswdev; 51 bp->b_blkno = seg*dmmax + off; 52 } else 53 dev = swdevt[0].sw_dev; 54 bp->b_dev = dev; 55 if (dev == 0) 56 panic("swstrategy"); 57 (*bdevsw[major(dev)].d_strategy)(bp); 58 } 59 60 swread(dev, uio) 61 dev_t dev; 62 struct uio *uio; 63 { 64 65 return (physio(swstrategy, &rswbuf, dev, B_READ, minphys, uio)); 66 } 67 68 swwrite(dev, uio) 69 dev_t dev; 70 struct uio *uio; 71 { 72 73 return (physio(swstrategy, &rswbuf, dev, B_WRITE, minphys, uio)); 74 } 75 76 /* 77 * System call swapon(name) enables swapping on device name, 78 * which must be in the swdevsw. Return EBUSY 79 * if already swapping on this device. 80 */ 81 swapon() 82 { 83 struct a { 84 char *name; 85 } *uap = (struct a *)u.u_ap; 86 register struct inode *ip; 87 dev_t dev; 88 register struct swdevt *sp; 89 register struct nameidata *ndp = &u.u_nd; 90 91 if (!suser()) 92 return; 93 ndp->ni_nameiop = LOOKUP | FOLLOW; 94 ndp->ni_segflg = UIO_USERSPACE; 95 ndp->ni_dirp = uap->name; 96 ip = namei(ndp); 97 if (ip == NULL) 98 return; 99 if ((ip->i_mode&IFMT) != IFBLK) { 100 u.u_error = ENOTBLK; 101 iput(ip); 102 return; 103 } 104 dev = (dev_t)ip->i_rdev; 105 iput(ip); 106 if (major(dev) >= nblkdev) { 107 u.u_error = ENXIO; 108 return; 109 } 110 for (sp = &swdevt[0]; sp->sw_dev; sp++) 111 if (sp->sw_dev == dev) { 112 if (sp->sw_freed) { 113 u.u_error = EBUSY; 114 return; 115 } 116 swfree(sp - swdevt); 117 return; 118 } 119 u.u_error = EINVAL; 120 } 121 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 125 * space, which is laid out with blocks of dmmax pages circularly 126 * among the devices. 127 */ 128 swfree(index) 129 int index; 130 { 131 register swblk_t vsbase; 132 register long blk; 133 dev_t dev; 134 register swblk_t dvbase; 135 register int nblks; 136 137 dev = swdevt[index].sw_dev; 138 (*bdevsw[major(dev)].d_open)(dev, FREAD|FWRITE); 139 swdevt[index].sw_freed = 1; 140 nblks = swdevt[index].sw_nblks; 141 for (dvbase = 0; dvbase < nblks; dvbase += dmmax) { 142 blk = nblks - dvbase; 143 if ((vsbase = index*dmmax + dvbase*nswdev) >= nswap) 144 panic("swfree"); 145 if (blk > dmmax) 146 blk = dmmax; 147 if (vsbase == 0) { 148 /* 149 * Can't free a block starting at 0 in the swapmap 150 * but need some space for argmap so use 1/2 this 151 * hunk which needs special treatment anyways. 152 */ 153 argdev = swdevt[0].sw_dev; 154 rminit(argmap, (long)(blk/2-ctod(CLSIZE)), 155 (long)ctod(CLSIZE), "argmap", ARGMAPSIZE); 156 /* 157 * First of all chunks... initialize the swapmap 158 * the second half of the hunk. 159 */ 160 rminit(swapmap, (long)blk/2, (long)blk/2, 161 "swap", nswapmap); 162 } else 163 rmfree(swapmap, blk, vsbase); 164 } 165 } 166