Files
Arquivotheca.SunOS-4.1.4/sys/old/swap_vnodeops.c
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

244 lines
5.0 KiB
C

/* @(#)swap_vnodeops.c 1.1 94/10/31 */
/*
* Copyright (c) 1987 by Sun Microsystems, Inc.
*/
/*
* Vnode operations for the swap vnode.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/user.h>
#include <sys/buf.h>
#include <sys/vfs.h>
#include <sys/vnode.h>
#include <sys/proc.h>
#include <sys/file.h>
#include <sys/uio.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/mman.h>
#include <sys/bootconf.h>
#include <machine/mmu.h>
#include <machine/vm_hat.h>
#include <vm/anon.h>
#include <vm/swap.h>
#include <vm/page.h>
#include <vm/pvn.h>
#include <vm/as.h>
#include <vm/seg.h>
#include <vm/seg_map.h>
#include <vm/seg_vn.h>
int swapvpdebug = 1;
/*
* The system itself only uses swap_pageio and swap_blksize.
* Through the /dev/drum interface we can only get at swap_rdwr.
* All the others "should never be called".
*/
static int swap_rdwr();
static int swap_pageio();
static int swap_blksize();
static int swap_panic();
struct vnodeops swap_vnodeops = {
swap_panic, /* open */
swap_panic, /* close */
swap_rdwr,
swap_panic, /* ioctl */
swap_panic, /* select */
swap_panic, /* getattr */
swap_panic, /* setattr */
swap_panic, /* access */
swap_panic, /* lookup */
swap_panic, /* create */
swap_panic, /* remove */
swap_panic, /* link */
swap_panic, /* rename */
swap_panic, /* mkdir */
swap_panic, /* rmdir */
swap_panic, /* readdir */
swap_panic, /* symlink */
swap_panic, /* readlink */
swap_panic, /* fsync */
swap_panic, /* inactive */
swap_panic, /* lockctl */
swap_panic, /* fid */
swap_pageio,
swap_blksize,
swap_panic, /* map */
};
/*
* Read or write the swap vnode.
*/
/*ARGSUSED*/
static int
swap_rdwr(vp, uiop, rw, ioflag, cred)
struct vnode *vp;
struct uio *uiop;
enum uio_rw rw;
int ioflag;
struct ucred *cred;
{
register addr_t base;
register u_int off;
register int n, on;
u_int flags;
u_int asize;
int err = 0;
if (rw != UIO_READ && rw != UIO_WRITE)
panic("swap_rdwr");
if (uiop->uio_resid == 0)
return (0);
if ((uiop->uio_offset < 0 || (uiop->uio_offset + uiop->uio_resid) < 0))
return (EINVAL);
asize = anoninfo.ani_max<<PAGESHIFT;
do {
off = uiop->uio_offset & ~(MAXBSIZE - 1);
on = uiop->uio_offset & (MAXBSIZE - 1);
n = MIN(MAXBSIZE - on, uiop->uio_resid);
if (rw == UIO_READ) {
if (asize) {
int diff = asize - uiop->uio_offset;
if (diff <= 0)
return (0);
if (diff < n)
n = diff;
}
}
/*
* Check to see if we can not read in the page and just bzero
* the memory. We can do this if we are going to rewrite
* the entire mapping or if we are going to write to end
* of the device from the beginning of the mapping.
*/
if ((rw == UIO_WRITE) && (on == 0) && ((n == MAXBSIZE) ||
((off + n) == asize))) {
/*
* XXX - need to allocate private zfod pages,
* then RENAME to the destination vp.
*/
}
base = segmap_getmap(segkmap, vp, off);
err = uiomove(base + on, n, rw, uiop);
if (rw == UIO_WRITE && err == 0) {
/*
* Force write back for synchronous write cases
*/
if (ioflag & IO_SYNC)
flags = SM_SYNC;
else
flags = 0;
} else
flags = 0;
if (segmap_release(segkmap, base, flags))
err = EIO;
} while (err == 0 && uiop->uio_resid > 0 && n != 0);
return (err);
}
/*
* Read or write physical page frames given by [vp, offset].
*/
/*ARGSUSED*/
static int
swap_pageio(vp, offset, pp, len, flags)
struct vnode *vp;
register u_int offset;
struct page *pp;
u_int len;
int flags;
{
register struct swapinfo *sip = &swapinfo;
do {
if (offset < sip->si_size) {
if (offset + len > sip->si_size)
panic("swap_pageio: req crosses devs");
return (VOP_PAGEIO(sip->si_vp, offset, pp, len, flags));
}
offset -= sip->si_size;
} while (sip = sip->si_next);
panic("swap_pageio");
/*NOTREACHED*/
}
/*ARGSUSED*/
static int
swap_blksize(vp, offset, offsetp, sizep, noffsetp, nsizep)
struct vnode *vp;
register u_int offset;
register u_int *offsetp, *sizep;
u_int *noffsetp, *nsizep;
{
register struct swapinfo *sip = &swapinfo;
register u_int soff = 0;
int err;
do {
if (offset < sip->si_size) {
err = VOP_BLKSIZE(sip->si_vp, offset, offsetp, sizep,
noffsetp, nsizep);
if (err)
return (err);
/* check that request isn't past si_size */
if (offsetp) {
if (*offsetp >= sip->si_size)
*sizep = 0;
else if (*offsetp + *sizep > sip->si_size)
*sizep = sip->si_size - *offsetp;
*offsetp += soff;
}
if (noffsetp) {
if (*noffsetp >= sip->si_size)
*nsizep = 0;
else if (*noffsetp + *nsizep > sip->si_size)
*nsizep = sip->si_size - *noffsetp;
*noffsetp += soff;
}
if (swapvpdebug) {
if (offsetp)
if (offset < *offsetp || offset >= *offsetp + *sizep) {
printf("offset 0x%x *offsetp 0x%x *sizep 0x%x\n",
offset, *offsetp, *sizep);
call_debug("swap_vnodeops");
}
}
return (0);
}
offset -= sip->si_size;
soff += sip->si_size;
} while (sip = sip->si_next);
/* EOF on /dev/drum */
if (sizep)
*sizep = 0;
if (nsizep)
*nsizep = 0;
return (0);
}
static int
swap_panic()
{
panic("swap: bad vnode op");
/*NOTREACHED*/
}