a45b4e453e88ba0d1349fff3f3e0fd8cbc7184ca
* Copyright (c) 1989 The Regents of the University of California.
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* @(#)mfs_vnops.c 7.1 (Berkeley) %G%
#include "../ufs/inode.h"
#include "../ufs/mfsiom.h"
#include "../machine/vmparam.h"
#include "../machine/pte.h"
#include "../machine/mtpr.h"
int mfs_running
; /* 1 => daemon has started running */
static int mfsmap_want
; /* 1 => need kernel I/O resources */
struct map mfsmap
[MFS_MAPSIZE
];
struct vnodeops mfs_vnodeops
= {
* Open called to allow memory filesystem to initialize and
* validate before actual IO. Nothing to do here as the
* filesystem is ready to go in the process address space.
register struct vnode
*vp
;
if (vp
->v_type
!= VBLK
) {
panic("mfs_ioctl not VBLK");
mfs_ioctl(vp
, com
, data
, fflag
, cred
)
* Pass I/O requests to the memory filesystem process.
register struct inode
*ip
= VTOI(bp
->b_vp
);
mfs_doio(bp
, (caddr_t
)ip
->i_diroff
);
ip
->i_spare
[0] = (long)bp
;
wakeup((caddr_t
)bp
->b_vp
);
* 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
);
* Memory filesystem close routine
mfs_close(vp
, flag
, cred
)
register struct vnode
*vp
;
register struct inode
*ip
= VTOI(vp
);
* On last close of a memory filesystem
* we must invalidate any in core blocks, so that
* we can, free up its vnode.
* We don't want to really close the device if it is still
* in use. Since every use (buffer, inode, swap, cmap)
* holds a reference to the vnode, and because we ensure
* that there cannot be more than one vnode per device,
* we need only check that we are down to the last
* reference before closing.
printf("mfs_close: ref count %d > 1\n", vp
->v_count
);
* Send a request to the filesystem server to exit.
* Block device bad operation
printf("mfs_badop called\n");
* Block device null operation
* Memory based filesystem initialization.
rminit(mfsmap
, (long)MFS_MAPREG
, (long)1, "mfs mapreg", MFS_MAPSIZE
);