1*2788Swnj /* vm_swap.c 4.3 02/28/81 */ 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" 111404Sbill 121404Sbill struct buf rswbuf; 131404Sbill /* 141404Sbill * Indirect driver for multi-controller paging. 151404Sbill */ 161404Sbill swstrategy(bp) 171404Sbill register struct buf *bp; 181404Sbill { 191404Sbill int sz, off, seg; 201404Sbill dev_t dev; 211404Sbill 221404Sbill sz = (bp->b_bcount+511)/512; 231404Sbill off = bp->b_blkno % DMMAX; 241404Sbill if (bp->b_blkno+sz > nswap || off+sz > DMMAX) { 251404Sbill bp->b_flags |= B_ERROR; 261404Sbill iodone(bp); 271404Sbill return; 281404Sbill } 291404Sbill seg = bp->b_blkno / DMMAX; 301404Sbill dev = swdevt[seg % nswdev].sw_dev; 311404Sbill seg /= nswdev; 321404Sbill bp->b_blkno = seg*DMMAX + off; 331404Sbill bp->b_dev = dev; 341404Sbill if (dev == 0) 351404Sbill panic("swstrategy"); 361404Sbill (*bdevsw[major(dev)].d_strategy)(bp); 371404Sbill } 381404Sbill 391404Sbill swread(dev) 401404Sbill { 411404Sbill 421404Sbill physio(swstrategy, &rswbuf, dev, B_READ, minphys); 431404Sbill } 441404Sbill 451404Sbill swwrite(dev) 461404Sbill { 471404Sbill 481404Sbill physio(swstrategy, &rswbuf, dev, B_WRITE, minphys); 491404Sbill } 501404Sbill 511404Sbill /* 521404Sbill * System call swapon(name) enables swapping on device name, 531404Sbill * which must be in the swdevsw. Return EBUSY 541404Sbill * if already swapping on this device. 551404Sbill */ 561404Sbill vswapon() 571404Sbill { 581404Sbill register struct inode *ip; 591404Sbill dev_t dev; 601404Sbill register struct swdevt *sp; 611404Sbill 621404Sbill ip = namei(uchar, 0); 631404Sbill if (ip == NULL) 641404Sbill return; 651404Sbill if ((ip->i_mode&IFMT) != IFBLK) { 661404Sbill u.u_error = ENOTBLK; 671404Sbill iput(ip); 681404Sbill return; 691404Sbill } 701404Sbill dev = (dev_t)ip->i_un.i_rdev; 711404Sbill iput(ip); 721404Sbill if (major(dev) >= nblkdev) { 731404Sbill u.u_error = ENXIO; 741404Sbill return; 751404Sbill } 761404Sbill /* 771404Sbill * Search starting at second table entry, 781404Sbill * since first (primary swap area) is freed at boot. 791404Sbill */ 801404Sbill for (sp = &swdevt[1]; sp->sw_dev; sp++) 811404Sbill if (sp->sw_dev == dev) { 821404Sbill if (sp->sw_freed) { 831404Sbill u.u_error = EBUSY; 841404Sbill return; 851404Sbill } 861404Sbill swfree(sp - swdevt); 871404Sbill return; 881404Sbill } 891404Sbill u.u_error = ENODEV; 901404Sbill } 911404Sbill 921404Sbill /* 931404Sbill * Swfree(index) frees the index'th portion of the swap map. 941404Sbill * Each of the nswdev devices provides 1/nswdev'th of the swap 951404Sbill * space, which is laid out with blocks of DMMAX pages circularly 961404Sbill * among the devices. 971404Sbill */ 981404Sbill swfree(index) 991404Sbill int index; 1001404Sbill { 1011404Sbill register swblk_t vsbase; 1021404Sbill register int blk; 1031404Sbill 1041404Sbill swdevt[index].sw_freed = 1; 1051404Sbill for (vsbase = index*DMMAX; vsbase < nswap; vsbase += nswdev*DMMAX) { 1061404Sbill blk = nswap - vsbase; 1071404Sbill if (blk > DMMAX) 1081404Sbill blk = DMMAX; 1091404Sbill if (vsbase == 0) { 1101404Sbill /* 1111404Sbill * Can't free a block starting at 0 in the swapmap 112*2788Swnj * but need some space for argmap so use 1/2 this 1131404Sbill * hunk which needs special treatment anyways. 1141404Sbill */ 1151404Sbill argdev = swdevt[0].sw_dev; 116*2788Swnj rminit(argmap, blk/2-CLSIZE, CLSIZE, 117*2788Swnj "argmap", ARGMAPSIZE); 118*2788Swnj /* 119*2788Swnj * First of all chunks... initialize the swapmap 120*2788Swnj * the second half of the hunk. 121*2788Swnj */ 122*2788Swnj rminit(swapmap, blk/2, blk/2, "swap", nswapmap); 1231404Sbill } else 124*2788Swnj rmfree(swapmap, blk, vsbase); 1251404Sbill } 1261404Sbill } 127