1*12359Ssam /* vm_swap.c 4.17 83/05/10 */ 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" 139170Ssam #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 */ 3211051Ssam #define MINIROOTSIZE 4096 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 */ 74*12359Ssam swapon() 751404Sbill { 76*12359Ssam struct a { 77*12359Ssam char *name; 78*12359Ssam }; 791404Sbill register struct inode *ip; 801404Sbill dev_t dev; 811404Sbill register struct swdevt *sp; 821404Sbill 839170Ssam ip = namei(uchar, LOOKUP, 1); 841404Sbill if (ip == NULL) 851404Sbill return; 861404Sbill if ((ip->i_mode&IFMT) != IFBLK) { 871404Sbill u.u_error = ENOTBLK; 881404Sbill iput(ip); 891404Sbill return; 901404Sbill } 917278Swnj dev = (dev_t)ip->i_rdev; 921404Sbill iput(ip); 931404Sbill if (major(dev) >= nblkdev) { 941404Sbill u.u_error = ENXIO; 951404Sbill return; 961404Sbill } 971404Sbill /* 981404Sbill * Search starting at second table entry, 991404Sbill * since first (primary swap area) is freed at boot. 1001404Sbill */ 1011404Sbill for (sp = &swdevt[1]; sp->sw_dev; sp++) 1021404Sbill if (sp->sw_dev == dev) { 1031404Sbill if (sp->sw_freed) { 1041404Sbill u.u_error = EBUSY; 1051404Sbill return; 1061404Sbill } 1071404Sbill swfree(sp - swdevt); 1081404Sbill return; 1091404Sbill } 1101404Sbill u.u_error = ENODEV; 1111404Sbill } 1121404Sbill 1131404Sbill /* 1141404Sbill * Swfree(index) frees the index'th portion of the swap map. 1151404Sbill * Each of the nswdev devices provides 1/nswdev'th of the swap 1161404Sbill * space, which is laid out with blocks of DMMAX pages circularly 1171404Sbill * among the devices. 1181404Sbill */ 1191404Sbill swfree(index) 1201404Sbill int index; 1211404Sbill { 1221404Sbill register swblk_t vsbase; 1238772Sroot register long blk; 1248961Sroot dev_t dev; 1251404Sbill 1268961Sroot dev = swdevt[index].sw_dev; 1278961Sroot (*bdevsw[major(dev)].d_open)(dev, FREAD|FWRITE); 1281404Sbill swdevt[index].sw_freed = 1; 1291404Sbill for (vsbase = index*DMMAX; vsbase < nswap; vsbase += nswdev*DMMAX) { 1301404Sbill blk = nswap - vsbase; 1311404Sbill if (blk > DMMAX) 1321404Sbill blk = DMMAX; 1331404Sbill if (vsbase == 0) { 1341404Sbill /* 1351404Sbill * Can't free a block starting at 0 in the swapmap 1362788Swnj * but need some space for argmap so use 1/2 this 1371404Sbill * hunk which needs special treatment anyways. 1381404Sbill */ 1391404Sbill argdev = swdevt[0].sw_dev; 1408961Sroot rminit(argmap, (long)(blk/2-ctod(CLSIZE)), 1418961Sroot (long)ctod(CLSIZE), "argmap", ARGMAPSIZE); 1422788Swnj /* 1432788Swnj * First of all chunks... initialize the swapmap 1442788Swnj * the second half of the hunk. 1452788Swnj */ 1468794Sroot rminit(swapmap, (long)blk/2, (long)blk/2, 1478794Sroot "swap", nswapmap); 1481404Sbill } else 1492788Swnj rmfree(swapmap, blk, vsbase); 1501404Sbill } 1511404Sbill } 152