* Copyright (c) 1989 The Regents of the University of California.
* %sccs.include.redist.c%
* @(#)mfs_vnops.c 7.38 (Berkeley) %G%
#include <miscfs/specfs/specdev.h>
#include <machine/vmparam.h>
#include <ufs/mfs/mfsnode.h>
#include <ufs/mfs/mfsiom.h>
#include <ufs/mfs/mfs_extern.h>
#if !defined(hp300) && !defined(i386) && !defined(mips) && !defined(sparc) && !defined(luna68k)
static int mfsmap_want
; /* 1 => need kernel I/O resources */
struct map mfsmap
[MFS_MAPSIZE
];
struct vnodeopv_entry_desc mfs_vnodeop_entries
[] = {
{ &vop_default_desc
, vn_default_error
},
{ &vop_lookup_desc
, mfs_lookup
}, /* lookup */
{ &vop_create_desc
, mfs_create
}, /* create */
{ &vop_mknod_desc
, mfs_mknod
}, /* mknod */
{ &vop_open_desc
, mfs_open
}, /* open */
{ &vop_close_desc
, mfs_close
}, /* close */
{ &vop_access_desc
, mfs_access
}, /* access */
{ &vop_getattr_desc
, mfs_getattr
}, /* getattr */
{ &vop_setattr_desc
, mfs_setattr
}, /* setattr */
{ &vop_read_desc
, mfs_read
}, /* read */
{ &vop_write_desc
, mfs_write
}, /* write */
{ &vop_ioctl_desc
, mfs_ioctl
}, /* ioctl */
{ &vop_select_desc
, mfs_select
}, /* select */
{ &vop_mmap_desc
, mfs_mmap
}, /* mmap */
{ &vop_fsync_desc
, spec_fsync
}, /* fsync */
{ &vop_seek_desc
, mfs_seek
}, /* seek */
{ &vop_remove_desc
, mfs_remove
}, /* remove */
{ &vop_link_desc
, mfs_link
}, /* link */
{ &vop_rename_desc
, mfs_rename
}, /* rename */
{ &vop_mkdir_desc
, mfs_mkdir
}, /* mkdir */
{ &vop_rmdir_desc
, mfs_rmdir
}, /* rmdir */
{ &vop_symlink_desc
, mfs_symlink
}, /* symlink */
{ &vop_readdir_desc
, mfs_readdir
}, /* readdir */
{ &vop_readlink_desc
, mfs_readlink
}, /* readlink */
{ &vop_abortop_desc
, mfs_abortop
}, /* abortop */
{ &vop_inactive_desc
, mfs_inactive
}, /* inactive */
{ &vop_reclaim_desc
, mfs_reclaim
}, /* reclaim */
{ &vop_lock_desc
, mfs_lock
}, /* lock */
{ &vop_unlock_desc
, mfs_unlock
}, /* unlock */
{ &vop_bmap_desc
, mfs_bmap
}, /* bmap */
{ &vop_strategy_desc
, mfs_strategy
}, /* strategy */
{ &vop_print_desc
, mfs_print
}, /* print */
{ &vop_islocked_desc
, mfs_islocked
}, /* islocked */
{ &vop_advlock_desc
, mfs_advlock
}, /* advlock */
{ &vop_blkatoff_desc
, mfs_blkatoff
}, /* blkatoff */
{ &vop_valloc_desc
, mfs_valloc
}, /* valloc */
{ &vop_vfree_desc
, mfs_vfree
}, /* vfree */
{ &vop_truncate_desc
, mfs_truncate
}, /* truncate */
{ &vop_update_desc
, mfs_update
}, /* update */
{ &vop_bwrite_desc
, mfs_bwrite
}, /* bwrite */
{ (struct vnodeop_desc
*)NULL
, (int(*)())NULL
}
struct vnodeopv_desc mfs_vnodeop_opv_desc
=
{ &mfs_vnodeop_p
, mfs_vnodeop_entries
};
* Open called to allow memory filesystem to initialize and
* validate before actual IO. Record our process identifier
* so we can tell when we are doing I/O to ourself.
struct vop_open_args
/* {
if (ap
->a_vp
->v_type
!= VBLK
) {
panic("mfs_ioctl not VBLK");
struct vop_ioctl_args
/* {
* Pass I/O requests to the memory filesystem process.
struct vop_strategy_args
/* {
register struct buf
*bp
= ap
->a_bp
;
register struct mfsnode
*mfsp
;
struct proc
*p
= curproc
; /* XXX */
if (vfinddev(bp
->b_dev
, VBLK
, &vp
) || vp
->v_usecount
== 0)
panic("mfs_strategy: bad dev");
/* check for mini-root access */
if (mfsp
->mfs_pid
== 0) {
base
= mfsp
->mfs_baseoff
+ (bp
->b_blkno
<< DEV_BSHIFT
);
if (bp
->b_flags
& B_READ
)
bcopy(base
, bp
->b_un
.b_addr
, bp
->b_bcount
);
bcopy(bp
->b_un
.b_addr
, base
, bp
->b_bcount
);
} else if (mfsp
->mfs_pid
== p
->p_pid
) {
mfs_doio(bp
, mfsp
->mfs_baseoff
);
bp
->av_forw
= mfsp
->mfs_buflist
;
#if defined(vax) || defined(tahoe)
* Memory file system I/O.
* Essentially play ubasetup() and disk interrupt service routine by
* doing the copies to or from the memfs process. If doing physio
* (i.e. pagein), we must map the I/O through the kernel virtual
register struct pte
*pte
, *ppte
;
caddr_t kernaddr
, offset
;
* For phys I/O, map the b_addr into kernel virtual space using
if ((bp
->b_flags
& B_PHYS
) == 0) {
kernaddr
= bp
->b_un
.b_addr
;
if (bp
->b_flags
& (B_PAGET
| B_UAREA
| B_DIRTY
))
off
= (int)bp
->b_un
.b_addr
& PGOFSET
;
npf
= btoc(bp
->b_bcount
+ off
);
* Get some mapping page table entries
while ((reg
= rmalloc(mfsmap
, (long)npf
)) == 0) {
sleep((caddr_t
)&mfsmap_want
, PZERO
-1);
pte
= vtopte(bp
->b_proc
, btop(bp
->b_un
.b_addr
));
* Do vmaccess() but with the Mfsiomap page table.
vaddr
= &mfsiobuf
[reg
* NBPG
];
for (npf2
= npf
; npf2
; npf2
--) {
mapin(ppte
, (u_int
)vaddr
, pte
->pg_pfnum
,
if ((bp
->b_flags
& B_READ
) == 0)
offset
= base
+ (bp
->b_blkno
<< DEV_BSHIFT
);
if (bp
->b_flags
& B_READ
)
bp
->b_error
= copyin(offset
, kernaddr
, bp
->b_bcount
);
bp
->b_error
= copyout(kernaddr
, offset
, bp
->b_bcount
);
* Release pte's used by physical I/O.
if (bp
->b_flags
& B_PHYS
) {
rmfree(mfsmap
, (long)npf
, (long)++reg
);
wakeup((caddr_t
)&mfsmap_want
);
#endif /* vax || tahoe */
#if defined(hp300) || defined(i386) || defined(mips) || defined(sparc) || defined(luna68k)
* Memory file system I/O.
* Trivial on the HP since buffer has already been mapping into KVA space.
base
+= (bp
->b_blkno
<< DEV_BSHIFT
);
if (bp
->b_flags
& B_READ
)
bp
->b_error
= copyin(base
, bp
->b_un
.b_addr
, bp
->b_bcount
);
bp
->b_error
= copyout(bp
->b_un
.b_addr
, base
, bp
->b_bcount
);
* This is a noop, simply returning what one has been given.
struct vop_bmap_args
/* {
* Memory filesystem close routine
struct vop_close_args
/* {
register struct vnode
*vp
= ap
->a_vp
;
register struct mfsnode
*mfsp
= VTOMFS(vp
);
* Finish any pending I/O requests.
while (bp
= mfsp
->mfs_buflist
) {
mfsp
->mfs_buflist
= bp
->av_forw
;
mfs_doio(bp
, mfsp
->mfs_baseoff
);
* On last close of a memory filesystem
* we must invalidate any in core blocks, so that
* we can, free up its vnode.
if (error
= vinvalbuf(vp
, 1, ap
->a_cred
, ap
->a_p
))
* There should be no way to have any more uses of this
* vnode, so if we find any other uses, it is a panic.
printf("mfs_close: ref count %d > 1\n", vp
->v_usecount
);
if (vp
->v_usecount
> 1 || mfsp
->mfs_buflist
)
* Send a request to the filesystem server to exit.
mfsp
->mfs_buflist
= (struct buf
*)(-1);
* Memory filesystem inactive routine
struct vop_inactive_args
/* {
register struct mfsnode
*mfsp
= VTOMFS(ap
->a_vp
);
if (mfsp
->mfs_buflist
&& mfsp
->mfs_buflist
!= (struct buf
*)(-1))
panic("mfs_inactive: not inactive (mfs_buflist %x)",
* Reclaim a memory filesystem devvp so that it can be reused.
struct vop_reclaim_args
/* {
FREE(ap
->a_vp
->v_data
, M_MFSNODE
);
* Print out the contents of an mfsnode.
struct vop_print_args
/* {
register struct mfsnode
*mfsp
= VTOMFS(ap
->a_vp
);
printf("tag VT_MFS, pid %d, base %d, size %d\n", mfsp
->mfs_pid
,
mfsp
->mfs_baseoff
, mfsp
->mfs_size
);
* Block device bad operation
panic("mfs_badop called\n");
* Memory based filesystem initialization.
#if !defined(hp300) && !defined(i386) && !defined(mips) && !defined(sparc) && !defined(luna68k)
rminit(mfsmap
, (long)MFS_MAPREG
, (long)1, "mfs mapreg", MFS_MAPSIZE
);