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