1 /* vm_swap.c 4.5 82/03/12 */ 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 12 struct buf rswbuf; 13 /* 14 * Indirect driver for multi-controller paging. 15 */ 16 swstrategy(bp) 17 register struct buf *bp; 18 { 19 int sz, off, seg; 20 dev_t dev; 21 22 sz = (bp->b_bcount+511)/512; 23 off = bp->b_blkno % DMMAX; 24 if (bp->b_blkno+sz > nswap || off+sz > DMMAX) { 25 bp->b_flags |= B_ERROR; 26 iodone(bp); 27 return; 28 } 29 seg = bp->b_blkno / DMMAX; 30 dev = swdevt[seg % nswdev].sw_dev; 31 seg /= nswdev; 32 bp->b_blkno = seg*DMMAX + off; 33 bp->b_dev = dev; 34 if (dev == 0) 35 panic("swstrategy"); 36 (*bdevsw[major(dev)].d_strategy)(bp); 37 } 38 39 swread(dev) 40 { 41 42 physio(swstrategy, &rswbuf, dev, B_READ, minphys); 43 } 44 45 swwrite(dev) 46 { 47 48 physio(swstrategy, &rswbuf, dev, B_WRITE, minphys); 49 } 50 51 /* 52 * System call swapon(name) enables swapping on device name, 53 * which must be in the swdevsw. Return EBUSY 54 * if already swapping on this device. 55 */ 56 vswapon() 57 { 58 register struct inode *ip; 59 dev_t dev; 60 register struct swdevt *sp; 61 62 ip = namei(uchar, 0, 1); 63 if (ip == NULL) 64 return; 65 if ((ip->i_mode&IFMT) != IFBLK) { 66 u.u_error = ENOTBLK; 67 iput(ip); 68 return; 69 } 70 dev = (dev_t)ip->i_un.i_rdev; 71 iput(ip); 72 if (major(dev) >= nblkdev) { 73 u.u_error = ENXIO; 74 return; 75 } 76 /* 77 * Search starting at second table entry, 78 * since first (primary swap area) is freed at boot. 79 */ 80 for (sp = &swdevt[1]; sp->sw_dev; sp++) 81 if (sp->sw_dev == dev) { 82 if (sp->sw_freed) { 83 u.u_error = EBUSY; 84 return; 85 } 86 swfree(sp - swdevt); 87 return; 88 } 89 u.u_error = ENODEV; 90 } 91 92 /* 93 * Swfree(index) frees the index'th portion of the swap map. 94 * Each of the nswdev devices provides 1/nswdev'th of the swap 95 * space, which is laid out with blocks of DMMAX pages circularly 96 * among the devices. 97 */ 98 swfree(index) 99 int index; 100 { 101 register swblk_t vsbase; 102 register int blk; 103 104 swdevt[index].sw_freed = 1; 105 for (vsbase = index*DMMAX; vsbase < nswap; vsbase += nswdev*DMMAX) { 106 blk = nswap - vsbase; 107 if (blk > DMMAX) 108 blk = DMMAX; 109 if (vsbase == 0) { 110 /* 111 * Can't free a block starting at 0 in the swapmap 112 * but need some space for argmap so use 1/2 this 113 * hunk which needs special treatment anyways. 114 */ 115 argdev = swdevt[0].sw_dev; 116 rminit(argmap, blk/2-CLSIZE, CLSIZE, 117 "argmap", ARGMAPSIZE); 118 /* 119 * First of all chunks... initialize the swapmap 120 * the second half of the hunk. 121 */ 122 rminit(swapmap, blk/2, blk/2, "swap", nswapmap); 123 } else 124 rmfree(swapmap, blk, vsbase); 125 } 126 } 127