1*17879Sbloom /* vm_swap.c 6.4 85/01/29 */ 21404Sbill 317107Sbloom #include "param.h" 417107Sbloom #include "systm.h" 517107Sbloom #include "buf.h" 617107Sbloom #include "conf.h" 717107Sbloom #include "dir.h" 817107Sbloom #include "user.h" 917107Sbloom #include "inode.h" 1017107Sbloom #include "map.h" 1117107Sbloom #include "uio.h" 1217107Sbloom #include "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 */ 3111051Ssam #define MINIROOTSIZE 4096 327435Sroot if (rootdev == dumpdev) 337435Sroot bp->b_blkno += MINIROOTSIZE; 347435Sroot #endif 359010Sroot sz = howmany(bp->b_bcount, DEV_BSIZE); 3612490Ssam if (bp->b_blkno+sz > nswap) { 371404Sbill bp->b_flags |= B_ERROR; 381404Sbill iodone(bp); 391404Sbill return; 401404Sbill } 4112490Ssam if (nswdev > 1) { 4212490Ssam off = bp->b_blkno % dmmax; 4312490Ssam if (off+sz > dmmax) { 4412490Ssam bp->b_flags |= B_ERROR; 4512490Ssam iodone(bp); 4612490Ssam return; 4712490Ssam } 4812490Ssam seg = bp->b_blkno / dmmax; 4912490Ssam dev = swdevt[seg % nswdev].sw_dev; 5012490Ssam seg /= nswdev; 5112490Ssam bp->b_blkno = seg*dmmax + off; 5212490Ssam } else 5312490Ssam dev = swdevt[0].sw_dev; 541404Sbill bp->b_dev = dev; 551404Sbill if (dev == 0) 561404Sbill panic("swstrategy"); 571404Sbill (*bdevsw[major(dev)].d_strategy)(bp); 581404Sbill } 591404Sbill 607828Sroot swread(dev, uio) 617828Sroot dev_t dev; 627828Sroot struct uio *uio; 631404Sbill { 641404Sbill 658819Sroot return (physio(swstrategy, &rswbuf, dev, B_READ, minphys, uio)); 661404Sbill } 671404Sbill 687828Sroot swwrite(dev, uio) 697828Sroot dev_t dev; 707828Sroot struct uio *uio; 711404Sbill { 721404Sbill 738819Sroot return (physio(swstrategy, &rswbuf, dev, B_WRITE, minphys, uio)); 741404Sbill } 751404Sbill 761404Sbill /* 771404Sbill * System call swapon(name) enables swapping on device name, 781404Sbill * which must be in the swdevsw. Return EBUSY 791404Sbill * if already swapping on this device. 801404Sbill */ 8112359Ssam swapon() 821404Sbill { 8312359Ssam struct a { 8412359Ssam char *name; 8516695Smckusick } *uap = (struct a *)u.u_ap; 861404Sbill register struct inode *ip; 871404Sbill dev_t dev; 881404Sbill register struct swdevt *sp; 8916695Smckusick register struct nameidata *ndp = &u.u_nd; 901404Sbill 9116695Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW; 9216695Smckusick ndp->ni_segflg = UIO_USERSPACE; 9316695Smckusick ndp->ni_dirp = uap->name; 9416695Smckusick ip = namei(ndp); 951404Sbill if (ip == NULL) 961404Sbill return; 971404Sbill if ((ip->i_mode&IFMT) != IFBLK) { 981404Sbill u.u_error = ENOTBLK; 991404Sbill iput(ip); 1001404Sbill return; 1011404Sbill } 1027278Swnj dev = (dev_t)ip->i_rdev; 1031404Sbill iput(ip); 1041404Sbill if (major(dev) >= nblkdev) { 1051404Sbill u.u_error = ENXIO; 1061404Sbill return; 1071404Sbill } 108*17879Sbloom for (sp = &swdevt[0]; sp->sw_dev; sp++) 1091404Sbill if (sp->sw_dev == dev) { 1101404Sbill if (sp->sw_freed) { 1111404Sbill u.u_error = EBUSY; 1121404Sbill return; 1131404Sbill } 1141404Sbill swfree(sp - swdevt); 1151404Sbill return; 1161404Sbill } 117*17879Sbloom u.u_error = EINVAL; 1181404Sbill } 1191404Sbill 1201404Sbill /* 1211404Sbill * Swfree(index) frees the index'th portion of the swap map. 1221404Sbill * Each of the nswdev devices provides 1/nswdev'th of the swap 12312490Ssam * space, which is laid out with blocks of dmmax pages circularly 1241404Sbill * among the devices. 1251404Sbill */ 1261404Sbill swfree(index) 1271404Sbill int index; 1281404Sbill { 1291404Sbill register swblk_t vsbase; 1308772Sroot register long blk; 1318961Sroot dev_t dev; 13212490Ssam register swblk_t dvbase; 13312490Ssam register int nblks; 1341404Sbill 1358961Sroot dev = swdevt[index].sw_dev; 1368961Sroot (*bdevsw[major(dev)].d_open)(dev, FREAD|FWRITE); 1371404Sbill swdevt[index].sw_freed = 1; 13812490Ssam nblks = swdevt[index].sw_nblks; 13912490Ssam for (dvbase = 0; dvbase < nblks; dvbase += dmmax) { 14012490Ssam blk = nblks - dvbase; 14112490Ssam if ((vsbase = index*dmmax + dvbase*nswdev) >= nswap) 14212490Ssam panic("swfree"); 14312490Ssam if (blk > dmmax) 14412490Ssam blk = dmmax; 1451404Sbill if (vsbase == 0) { 1461404Sbill /* 1471404Sbill * Can't free a block starting at 0 in the swapmap 1482788Swnj * but need some space for argmap so use 1/2 this 1491404Sbill * hunk which needs special treatment anyways. 1501404Sbill */ 1511404Sbill argdev = swdevt[0].sw_dev; 1528961Sroot rminit(argmap, (long)(blk/2-ctod(CLSIZE)), 1538961Sroot (long)ctod(CLSIZE), "argmap", ARGMAPSIZE); 1542788Swnj /* 1552788Swnj * First of all chunks... initialize the swapmap 1562788Swnj * the second half of the hunk. 1572788Swnj */ 1588794Sroot rminit(swapmap, (long)blk/2, (long)blk/2, 1598794Sroot "swap", nswapmap); 1601404Sbill } else 1612788Swnj rmfree(swapmap, blk, vsbase); 1621404Sbill } 1631404Sbill } 164