Files
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

174 lines
3.7 KiB
C

/* @(#)vm_sw.c 1.1 94/10/31 SMI; from UCB 4.18 83/05/18 */
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
#include <sys/conf.h>
#include <sys/user.h>
#include <sys/vnode.h>
#include <sys/map.h>
#include <sys/uio.h>
#include <sys/file.h>
#include <sys/pathname.h>
#include <sys/bootconf.h>
struct buf rswbuf;
/*
* Indirect driver for multi-controller paging.
*/
swstrategy(bp)
register struct buf *bp;
{
int sz, off, seg;
struct vnode *vp;
#ifdef GENERIC
/*
* A mini-root gets copied into the front of the swap
* and we run over top of the swap area just long
* enough for us to do a mkfs and restor of the real
* root (sure beats rewriting standalone restor).
*
* Why stop there? Setup is now going to run window
* system or curses programs from the mini-root.
*/
#define MINIROOTSIZE 9216 /* 4.5 Meg */
if (rootvp == swaptab[0].bo_vp)
bp->b_blkno += MINIROOTSIZE;
#endif
sz = howmany(bp->b_bcount, DEV_BSIZE);
if (bp->b_blkno+sz > nswap) {
bp->b_flags |= B_ERROR;
iodone(bp);
return;
}
if (nswdev > 1) {
off = bp->b_blkno % dmmax;
if (off+sz > dmmax) {
bp->b_flags |= B_ERROR;
iodone(bp);
return;
}
seg = bp->b_blkno / dmmax;
vp = swaptab[seg % nswdev].bo_vp;
seg /= nswdev;
bp->b_blkno = seg*dmmax + off;
} else {
vp = swaptab[0].bo_vp;
}
bp->b_dev = vp->v_rdev;
bsetvp(bp, vp);
VOP_STRATEGY(bp);
}
swread(dev, uio)
dev_t dev;
struct uio *uio;
{
return (physio(swstrategy, &rswbuf, dev, B_READ, minphys, uio));
}
swwrite(dev, uio)
dev_t dev;
struct uio *uio;
{
return (physio(swstrategy, &rswbuf, dev, B_WRITE, minphys, uio));
}
/*
* System call swapon(name) enables swapping on a file name,
* which must be in the swdevsw. Return EBUSY
* if already swapping on this file.
*/
swapon()
{
register struct a {
char *name;
} *uap;
register struct bootobj *sp;
struct pathname pn;
if (!suser())
return;
uap = (struct a *)u.u_ap;
pn_alloc(&pn);
if (u.u_error = pn_get(uap->name, UIO_USERSPACE, &pn)) {
return;
}
/*
* Search starting at second table entry,
* since first (primary swap area) is freed at boot.
*/
u.u_error = ENODEV;
for (sp = &swaptab[1]; sp < &swaptab[Nswaptab]; sp++) {
if ((sp->bo_flags & BO_VALID) == 0) {
continue;
}
if (strcmp(pn.pn_path, sp->bo_name) == 0) {
if (sp->bo_flags & BO_BUSY) {
u.u_error = EBUSY;
break;
}
swfree(sp - swaptab);
u.u_error = 0;
break;
}
}
pn_free(&pn);
return;
}
/*
* Swfree(index) frees the index'th portion of the swap map.
* Each of the nswdev devices provides 1/nswdev'th of the swap
* space, which is laid out with blocks of dmmax pages circularly
* among the devices.
*/
swfree(index)
int index;
{
register swblk_t vsbase;
register long blk;
struct vnode *vp;
register swblk_t dvbase;
register int nblks;
vp = swaptab[index].bo_vp;
if (vp == NULL) {
panic("swfree: null bo_vp");
}
VOP_OPEN(&vp, FREAD|FWRITE, u.u_cred);
swaptab[index].bo_flags |= BO_BUSY;
nblks = swaptab[index].bo_size;
for (dvbase = 0; dvbase < nblks; dvbase += dmmax) {
blk = nblks - dvbase;
if ((vsbase = index*dmmax + dvbase*nswdev) >= nswap)
panic("swfree");
if (blk > dmmax)
blk = dmmax;
if (vsbase == 0) {
/*
* Can't free a block starting at 0 in the swapmap
* but need some space for argmap so use 1/2 this
* hunk which needs special treatment anyways.
*/
if (argvp) {
VN_RELE(argvp);
}
argvp = swaptab[0].bo_vp;
VN_HOLD(argvp);
rminit(argmap, (long)(blk/2-ctod(CLSIZE)),
(long)ctod(CLSIZE), "argmap", ARGMAPSIZE);
/*
* First of all chunks... initialize the swapmap
* the second half of the hunk.
*/
rminit(swapmap, (long)(blk/2), (long)(blk/2),
"swap", nswapmap);
} else
rmfree(swapmap, blk, vsbase);
}
}