1*7435Sroot /* vm_swap.c 4.7 82/07/15 */ 21404Sbill 31404Sbill #include "../h/param.h" 41404Sbill #include "../h/systm.h" 51404Sbill #include "../h/buf.h" 61404Sbill #include "../h/conf.h" 71404Sbill #include "../h/dir.h" 81404Sbill #include "../h/user.h" 91404Sbill #include "../h/inode.h" 101404Sbill #include "../h/map.h" 111404Sbill 121404Sbill struct buf rswbuf; 131404Sbill /* 141404Sbill * Indirect driver for multi-controller paging. 151404Sbill */ 161404Sbill swstrategy(bp) 171404Sbill register struct buf *bp; 181404Sbill { 191404Sbill int sz, off, seg; 201404Sbill dev_t dev; 211404Sbill 22*7435Sroot #ifdef GENERIC 23*7435Sroot /* 24*7435Sroot * A mini-root gets copied into the front of the swap 25*7435Sroot * and we run over top of the swap area just long 26*7435Sroot * enough for us to do a mkfs and restor of the real 27*7435Sroot * root (sure beats rewriting standalone restor). 28*7435Sroot */ 29*7435Sroot #define MINIROOTSIZE 2048 30*7435Sroot if (rootdev == dumpdev) 31*7435Sroot bp->b_blkno += MINIROOTSIZE; 32*7435Sroot #endif 331404Sbill sz = (bp->b_bcount+511)/512; 341404Sbill off = bp->b_blkno % DMMAX; 351404Sbill if (bp->b_blkno+sz > nswap || off+sz > DMMAX) { 361404Sbill bp->b_flags |= B_ERROR; 371404Sbill iodone(bp); 381404Sbill return; 391404Sbill } 401404Sbill seg = bp->b_blkno / DMMAX; 411404Sbill dev = swdevt[seg % nswdev].sw_dev; 421404Sbill seg /= nswdev; 431404Sbill bp->b_blkno = seg*DMMAX + off; 441404Sbill bp->b_dev = dev; 451404Sbill if (dev == 0) 461404Sbill panic("swstrategy"); 471404Sbill (*bdevsw[major(dev)].d_strategy)(bp); 481404Sbill } 491404Sbill 501404Sbill swread(dev) 511404Sbill { 521404Sbill 531404Sbill physio(swstrategy, &rswbuf, dev, B_READ, minphys); 541404Sbill } 551404Sbill 561404Sbill swwrite(dev) 571404Sbill { 581404Sbill 591404Sbill physio(swstrategy, &rswbuf, dev, B_WRITE, minphys); 601404Sbill } 611404Sbill 621404Sbill /* 631404Sbill * System call swapon(name) enables swapping on device name, 641404Sbill * which must be in the swdevsw. Return EBUSY 651404Sbill * if already swapping on this device. 661404Sbill */ 671404Sbill vswapon() 681404Sbill { 691404Sbill register struct inode *ip; 701404Sbill dev_t dev; 711404Sbill register struct swdevt *sp; 721404Sbill 736139Ssam ip = namei(uchar, 0, 1); 741404Sbill if (ip == NULL) 751404Sbill return; 761404Sbill if ((ip->i_mode&IFMT) != IFBLK) { 771404Sbill u.u_error = ENOTBLK; 781404Sbill iput(ip); 791404Sbill return; 801404Sbill } 817278Swnj dev = (dev_t)ip->i_rdev; 821404Sbill iput(ip); 831404Sbill if (major(dev) >= nblkdev) { 841404Sbill u.u_error = ENXIO; 851404Sbill return; 861404Sbill } 871404Sbill /* 881404Sbill * Search starting at second table entry, 891404Sbill * since first (primary swap area) is freed at boot. 901404Sbill */ 911404Sbill for (sp = &swdevt[1]; sp->sw_dev; sp++) 921404Sbill if (sp->sw_dev == dev) { 931404Sbill if (sp->sw_freed) { 941404Sbill u.u_error = EBUSY; 951404Sbill return; 961404Sbill } 971404Sbill swfree(sp - swdevt); 981404Sbill return; 991404Sbill } 1001404Sbill u.u_error = ENODEV; 1011404Sbill } 1021404Sbill 1031404Sbill /* 1041404Sbill * Swfree(index) frees the index'th portion of the swap map. 1051404Sbill * Each of the nswdev devices provides 1/nswdev'th of the swap 1061404Sbill * space, which is laid out with blocks of DMMAX pages circularly 1071404Sbill * among the devices. 1081404Sbill */ 1091404Sbill swfree(index) 1101404Sbill int index; 1111404Sbill { 1121404Sbill register swblk_t vsbase; 1131404Sbill register int blk; 1141404Sbill 1151404Sbill swdevt[index].sw_freed = 1; 1161404Sbill for (vsbase = index*DMMAX; vsbase < nswap; vsbase += nswdev*DMMAX) { 1171404Sbill blk = nswap - vsbase; 1181404Sbill if (blk > DMMAX) 1191404Sbill blk = DMMAX; 1201404Sbill if (vsbase == 0) { 1211404Sbill /* 1221404Sbill * Can't free a block starting at 0 in the swapmap 1232788Swnj * but need some space for argmap so use 1/2 this 1241404Sbill * hunk which needs special treatment anyways. 1251404Sbill */ 1261404Sbill argdev = swdevt[0].sw_dev; 1272788Swnj rminit(argmap, blk/2-CLSIZE, CLSIZE, 1282788Swnj "argmap", ARGMAPSIZE); 1292788Swnj /* 1302788Swnj * First of all chunks... initialize the swapmap 1312788Swnj * the second half of the hunk. 1322788Swnj */ 1332788Swnj rminit(swapmap, blk/2, blk/2, "swap", nswapmap); 1341404Sbill } else 1352788Swnj rmfree(swapmap, blk, vsbase); 1361404Sbill } 1371404Sbill } 138