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