1 /* vm_swap.c 6.2 84/07/08 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/buf.h" 6 #include "../h/conf.h" 7 #include "../h/dir.h" 8 #include "../h/user.h" 9 #include "../h/inode.h" 10 #include "../h/map.h" 11 #include "../h/uio.h" 12 #include "../h/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 /* 109 * Search starting at second table entry, 110 * since first (primary swap area) is freed at boot. 111 */ 112 for (sp = &swdevt[1]; sp->sw_dev; sp++) 113 if (sp->sw_dev == dev) { 114 if (sp->sw_freed) { 115 u.u_error = EBUSY; 116 return; 117 } 118 swfree(sp - swdevt); 119 return; 120 } 121 u.u_error = ENODEV; 122 } 123 124 /* 125 * Swfree(index) frees the index'th portion of the swap map. 126 * Each of the nswdev devices provides 1/nswdev'th of the swap 127 * space, which is laid out with blocks of dmmax pages circularly 128 * among the devices. 129 */ 130 swfree(index) 131 int index; 132 { 133 register swblk_t vsbase; 134 register long blk; 135 dev_t dev; 136 register swblk_t dvbase; 137 register int nblks; 138 139 dev = swdevt[index].sw_dev; 140 (*bdevsw[major(dev)].d_open)(dev, FREAD|FWRITE); 141 swdevt[index].sw_freed = 1; 142 nblks = swdevt[index].sw_nblks; 143 for (dvbase = 0; dvbase < nblks; dvbase += dmmax) { 144 blk = nblks - dvbase; 145 if ((vsbase = index*dmmax + dvbase*nswdev) >= nswap) 146 panic("swfree"); 147 if (blk > dmmax) 148 blk = dmmax; 149 if (vsbase == 0) { 150 /* 151 * Can't free a block starting at 0 in the swapmap 152 * but need some space for argmap so use 1/2 this 153 * hunk which needs special treatment anyways. 154 */ 155 argdev = swdevt[0].sw_dev; 156 rminit(argmap, (long)(blk/2-ctod(CLSIZE)), 157 (long)ctod(CLSIZE), "argmap", ARGMAPSIZE); 158 /* 159 * First of all chunks... initialize the swapmap 160 * the second half of the hunk. 161 */ 162 rminit(swapmap, (long)blk/2, (long)blk/2, 163 "swap", nswapmap); 164 } else 165 rmfree(swapmap, blk, vsbase); 166 } 167 } 168