1*8961Sroot /* vm_swap.c 4.13 82/10/31 */ 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" 117828Sroot #include "../h/uio.h" 121404Sbill 131404Sbill struct buf rswbuf; 141404Sbill /* 151404Sbill * Indirect driver for multi-controller paging. 161404Sbill */ 171404Sbill swstrategy(bp) 181404Sbill register struct buf *bp; 191404Sbill { 201404Sbill int sz, off, seg; 211404Sbill dev_t dev; 221404Sbill 237435Sroot #ifdef GENERIC 247435Sroot /* 257435Sroot * A mini-root gets copied into the front of the swap 267435Sroot * and we run over top of the swap area just long 277435Sroot * enough for us to do a mkfs and restor of the real 287435Sroot * root (sure beats rewriting standalone restor). 297435Sroot */ 307435Sroot #define MINIROOTSIZE 2048 317435Sroot if (rootdev == dumpdev) 327435Sroot bp->b_blkno += MINIROOTSIZE; 337435Sroot #endif 34*8961Sroot sz = howmany(bp->b_bocunt, DEV_BSIZE); 351404Sbill off = bp->b_blkno % DMMAX; 361404Sbill if (bp->b_blkno+sz > nswap || off+sz > DMMAX) { 371404Sbill bp->b_flags |= B_ERROR; 381404Sbill iodone(bp); 391404Sbill return; 401404Sbill } 411404Sbill seg = bp->b_blkno / DMMAX; 421404Sbill dev = swdevt[seg % nswdev].sw_dev; 431404Sbill seg /= nswdev; 441404Sbill bp->b_blkno = seg*DMMAX + off; 451404Sbill bp->b_dev = dev; 461404Sbill if (dev == 0) 471404Sbill panic("swstrategy"); 481404Sbill (*bdevsw[major(dev)].d_strategy)(bp); 491404Sbill } 501404Sbill 517828Sroot swread(dev, uio) 527828Sroot dev_t dev; 537828Sroot struct uio *uio; 541404Sbill { 551404Sbill 568819Sroot return (physio(swstrategy, &rswbuf, dev, B_READ, minphys, uio)); 571404Sbill } 581404Sbill 597828Sroot swwrite(dev, uio) 607828Sroot dev_t dev; 617828Sroot struct uio *uio; 621404Sbill { 631404Sbill 648819Sroot return (physio(swstrategy, &rswbuf, dev, B_WRITE, minphys, uio)); 651404Sbill } 661404Sbill 671404Sbill /* 681404Sbill * System call swapon(name) enables swapping on device name, 691404Sbill * which must be in the swdevsw. Return EBUSY 701404Sbill * if already swapping on this device. 711404Sbill */ 728110Sroot oswapon() 731404Sbill { 741404Sbill register struct inode *ip; 751404Sbill dev_t dev; 761404Sbill register struct swdevt *sp; 771404Sbill 786139Ssam ip = namei(uchar, 0, 1); 791404Sbill if (ip == NULL) 801404Sbill return; 811404Sbill if ((ip->i_mode&IFMT) != IFBLK) { 821404Sbill u.u_error = ENOTBLK; 831404Sbill iput(ip); 841404Sbill return; 851404Sbill } 867278Swnj dev = (dev_t)ip->i_rdev; 871404Sbill iput(ip); 881404Sbill if (major(dev) >= nblkdev) { 891404Sbill u.u_error = ENXIO; 901404Sbill return; 911404Sbill } 921404Sbill /* 931404Sbill * Search starting at second table entry, 941404Sbill * since first (primary swap area) is freed at boot. 951404Sbill */ 961404Sbill for (sp = &swdevt[1]; sp->sw_dev; sp++) 971404Sbill if (sp->sw_dev == dev) { 981404Sbill if (sp->sw_freed) { 991404Sbill u.u_error = EBUSY; 1001404Sbill return; 1011404Sbill } 1021404Sbill swfree(sp - swdevt); 1031404Sbill return; 1041404Sbill } 1051404Sbill u.u_error = ENODEV; 1061404Sbill } 1071404Sbill 1081404Sbill /* 1091404Sbill * Swfree(index) frees the index'th portion of the swap map. 1101404Sbill * Each of the nswdev devices provides 1/nswdev'th of the swap 1111404Sbill * space, which is laid out with blocks of DMMAX pages circularly 1121404Sbill * among the devices. 1131404Sbill */ 1141404Sbill swfree(index) 1151404Sbill int index; 1161404Sbill { 1171404Sbill register swblk_t vsbase; 1188772Sroot register long blk; 119*8961Sroot dev_t dev; 1201404Sbill 121*8961Sroot dev = swdevt[index].sw_dev; 122*8961Sroot (*bdevsw[major(dev)].d_open)(dev, FREAD|FWRITE); 1231404Sbill swdevt[index].sw_freed = 1; 1241404Sbill for (vsbase = index*DMMAX; vsbase < nswap; vsbase += nswdev*DMMAX) { 1251404Sbill blk = nswap - vsbase; 1261404Sbill if (blk > DMMAX) 1271404Sbill blk = DMMAX; 1281404Sbill if (vsbase == 0) { 1291404Sbill /* 1301404Sbill * Can't free a block starting at 0 in the swapmap 1312788Swnj * but need some space for argmap so use 1/2 this 1321404Sbill * hunk which needs special treatment anyways. 1331404Sbill */ 1341404Sbill argdev = swdevt[0].sw_dev; 135*8961Sroot rminit(argmap, (long)(blk/2-ctod(CLSIZE)), 136*8961Sroot (long)ctod(CLSIZE), "argmap", ARGMAPSIZE); 1372788Swnj /* 1382788Swnj * First of all chunks... initialize the swapmap 1392788Swnj * the second half of the hunk. 1402788Swnj */ 1418794Sroot rminit(swapmap, (long)blk/2, (long)blk/2, 1428794Sroot "swap", nswapmap); 1431404Sbill } else 1442788Swnj rmfree(swapmap, blk, vsbase); 1451404Sbill } 1461404Sbill } 147