1 /* vm_swap.c 6.4 85/01/29 */ 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 ndp->ni_nameiop = LOOKUP | FOLLOW; 92 ndp->ni_segflg = UIO_USERSPACE; 93 ndp->ni_dirp = uap->name; 94 ip = namei(ndp); 95 if (ip == NULL) 96 return; 97 if ((ip->i_mode&IFMT) != IFBLK) { 98 u.u_error = ENOTBLK; 99 iput(ip); 100 return; 101 } 102 dev = (dev_t)ip->i_rdev; 103 iput(ip); 104 if (major(dev) >= nblkdev) { 105 u.u_error = ENXIO; 106 return; 107 } 108 for (sp = &swdevt[0]; sp->sw_dev; sp++) 109 if (sp->sw_dev == dev) { 110 if (sp->sw_freed) { 111 u.u_error = EBUSY; 112 return; 113 } 114 swfree(sp - swdevt); 115 return; 116 } 117 u.u_error = EINVAL; 118 } 119 120 /* 121 * Swfree(index) frees the index'th portion of the swap map. 122 * Each of the nswdev devices provides 1/nswdev'th of the swap 123 * space, which is laid out with blocks of dmmax pages circularly 124 * among the devices. 125 */ 126 swfree(index) 127 int index; 128 { 129 register swblk_t vsbase; 130 register long blk; 131 dev_t dev; 132 register swblk_t dvbase; 133 register int nblks; 134 135 dev = swdevt[index].sw_dev; 136 (*bdevsw[major(dev)].d_open)(dev, FREAD|FWRITE); 137 swdevt[index].sw_freed = 1; 138 nblks = swdevt[index].sw_nblks; 139 for (dvbase = 0; dvbase < nblks; dvbase += dmmax) { 140 blk = nblks - dvbase; 141 if ((vsbase = index*dmmax + dvbase*nswdev) >= nswap) 142 panic("swfree"); 143 if (blk > dmmax) 144 blk = dmmax; 145 if (vsbase == 0) { 146 /* 147 * Can't free a block starting at 0 in the swapmap 148 * but need some space for argmap so use 1/2 this 149 * hunk which needs special treatment anyways. 150 */ 151 argdev = swdevt[0].sw_dev; 152 rminit(argmap, (long)(blk/2-ctod(CLSIZE)), 153 (long)ctod(CLSIZE), "argmap", ARGMAPSIZE); 154 /* 155 * First of all chunks... initialize the swapmap 156 * the second half of the hunk. 157 */ 158 rminit(swapmap, (long)blk/2, (long)blk/2, 159 "swap", nswapmap); 160 } else 161 rmfree(swapmap, blk, vsbase); 162 } 163 } 164