1*9010Sroot /* vm_swap.c 4.14 82/11/02 */ 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" 12*9010Sroot #include "../h/file.h" 131404Sbill 141404Sbill struct buf rswbuf; 151404Sbill /* 161404Sbill * Indirect driver for multi-controller paging. 171404Sbill */ 181404Sbill swstrategy(bp) 191404Sbill register struct buf *bp; 201404Sbill { 211404Sbill int sz, off, seg; 221404Sbill dev_t dev; 231404Sbill 247435Sroot #ifdef GENERIC 257435Sroot /* 267435Sroot * A mini-root gets copied into the front of the swap 277435Sroot * and we run over top of the swap area just long 287435Sroot * enough for us to do a mkfs and restor of the real 297435Sroot * root (sure beats rewriting standalone restor). 307435Sroot */ 317435Sroot #define MINIROOTSIZE 2048 327435Sroot if (rootdev == dumpdev) 337435Sroot bp->b_blkno += MINIROOTSIZE; 347435Sroot #endif 35*9010Sroot sz = howmany(bp->b_bcount, DEV_BSIZE); 361404Sbill off = bp->b_blkno % DMMAX; 371404Sbill if (bp->b_blkno+sz > nswap || off+sz > DMMAX) { 381404Sbill bp->b_flags |= B_ERROR; 391404Sbill iodone(bp); 401404Sbill return; 411404Sbill } 421404Sbill seg = bp->b_blkno / DMMAX; 431404Sbill dev = swdevt[seg % nswdev].sw_dev; 441404Sbill seg /= nswdev; 451404Sbill bp->b_blkno = seg*DMMAX + off; 461404Sbill bp->b_dev = dev; 471404Sbill if (dev == 0) 481404Sbill panic("swstrategy"); 491404Sbill (*bdevsw[major(dev)].d_strategy)(bp); 501404Sbill } 511404Sbill 527828Sroot swread(dev, uio) 537828Sroot dev_t dev; 547828Sroot struct uio *uio; 551404Sbill { 561404Sbill 578819Sroot return (physio(swstrategy, &rswbuf, dev, B_READ, minphys, uio)); 581404Sbill } 591404Sbill 607828Sroot swwrite(dev, uio) 617828Sroot dev_t dev; 627828Sroot struct uio *uio; 631404Sbill { 641404Sbill 658819Sroot return (physio(swstrategy, &rswbuf, dev, B_WRITE, minphys, uio)); 661404Sbill } 671404Sbill 681404Sbill /* 691404Sbill * System call swapon(name) enables swapping on device name, 701404Sbill * which must be in the swdevsw. Return EBUSY 711404Sbill * if already swapping on this device. 721404Sbill */ 738110Sroot oswapon() 741404Sbill { 751404Sbill register struct inode *ip; 761404Sbill dev_t dev; 771404Sbill register struct swdevt *sp; 781404Sbill 796139Ssam ip = namei(uchar, 0, 1); 801404Sbill if (ip == NULL) 811404Sbill return; 821404Sbill if ((ip->i_mode&IFMT) != IFBLK) { 831404Sbill u.u_error = ENOTBLK; 841404Sbill iput(ip); 851404Sbill return; 861404Sbill } 877278Swnj dev = (dev_t)ip->i_rdev; 881404Sbill iput(ip); 891404Sbill if (major(dev) >= nblkdev) { 901404Sbill u.u_error = ENXIO; 911404Sbill return; 921404Sbill } 931404Sbill /* 941404Sbill * Search starting at second table entry, 951404Sbill * since first (primary swap area) is freed at boot. 961404Sbill */ 971404Sbill for (sp = &swdevt[1]; sp->sw_dev; sp++) 981404Sbill if (sp->sw_dev == dev) { 991404Sbill if (sp->sw_freed) { 1001404Sbill u.u_error = EBUSY; 1011404Sbill return; 1021404Sbill } 1031404Sbill swfree(sp - swdevt); 1041404Sbill return; 1051404Sbill } 1061404Sbill u.u_error = ENODEV; 1071404Sbill } 1081404Sbill 1091404Sbill /* 1101404Sbill * Swfree(index) frees the index'th portion of the swap map. 1111404Sbill * Each of the nswdev devices provides 1/nswdev'th of the swap 1121404Sbill * space, which is laid out with blocks of DMMAX pages circularly 1131404Sbill * among the devices. 1141404Sbill */ 1151404Sbill swfree(index) 1161404Sbill int index; 1171404Sbill { 1181404Sbill register swblk_t vsbase; 1198772Sroot register long blk; 1208961Sroot dev_t dev; 1211404Sbill 1228961Sroot dev = swdevt[index].sw_dev; 1238961Sroot (*bdevsw[major(dev)].d_open)(dev, FREAD|FWRITE); 1241404Sbill swdevt[index].sw_freed = 1; 1251404Sbill for (vsbase = index*DMMAX; vsbase < nswap; vsbase += nswdev*DMMAX) { 1261404Sbill blk = nswap - vsbase; 1271404Sbill if (blk > DMMAX) 1281404Sbill blk = DMMAX; 1291404Sbill if (vsbase == 0) { 1301404Sbill /* 1311404Sbill * Can't free a block starting at 0 in the swapmap 1322788Swnj * but need some space for argmap so use 1/2 this 1331404Sbill * hunk which needs special treatment anyways. 1341404Sbill */ 1351404Sbill argdev = swdevt[0].sw_dev; 1368961Sroot rminit(argmap, (long)(blk/2-ctod(CLSIZE)), 1378961Sroot (long)ctod(CLSIZE), "argmap", ARGMAPSIZE); 1382788Swnj /* 1392788Swnj * First of all chunks... initialize the swapmap 1402788Swnj * the second half of the hunk. 1412788Swnj */ 1428794Sroot rminit(swapmap, (long)blk/2, (long)blk/2, 1438794Sroot "swap", nswapmap); 1441404Sbill } else 1452788Swnj rmfree(swapmap, blk, vsbase); 1461404Sbill } 1471404Sbill } 148