6. Appendix A - Implementation Details
/*
* This structure defines the control data for the memory
* based file system.
*/
struct mfsnode {
structvnode *mfs-vnode;/* vnode associated with this mfsnode */
caddr-tmfs-baseoff;/* base of file system in memory */
longmfs-size;/* size of memory file system */
pid-tmfs-pid;/* supporting process pid */
structbuf *mfs-buflist;/* list of I/O requests */
};
/*
* Convert between mfsnode pointers and vnode pointers
*/
VTOMFS#defineVTOMFS(vp)((struct mfsnode *)(vp)->v-data)
MFSTOV#defineMFSTOV(mfsp)((mfsp)->mfs-vnode)
#defineMFS-EXIT(struct buf *)-1
/*
* Arguments to mount MFS
*/
struct mfs-args {
char*name;/* name to export for statfs */
caddr-tbase;/* base address of file system in memory */
u-longsize;/* size of file system */
};
/*
* Mount an MFS filesystem.
*/
mfs_mountmfs-mount(mp, path, data)
struct mount *mp;
char *path;
caddr-t data;
{
struct vnode *devvp;
struct mfsnode *mfsp;
struct buf *bp;
struct mfs-args args;
/*
* Create a block device to represent the disk.
*/
devvp = getnewvnode(VT-MFS, VBLK, &mfs-vnodeops);
mfsp = VTOMFS(devvp);
/*
* Save base address of the filesystem from the supporting process.
*/
copyin(data, &args, (sizeof mfs-args));
mfsp->mfs-baseoff = args.base;
mfsp->mfs-size = args.size;
/*
* Record the process identifier of the supporting process.
*/
mfsp->mfs-pid = u.u-procp->p-pid;
/*
* Mount the filesystem.
*/
mfsp->mfs-buflist = NULL;
mountfs(devvp, mp);
/*
* Loop processing I/O requests.
*/
while (mfsp->mfs-buflist != MFS-EXIT) {
while (mfsp->mfs-buflist != NULL) {
bp = mfsp->mfs-buflist;
mfsp->mfs-buflist = bp->av-forw;
offset = mfsp->mfs-baseoff + (bp->b-blkno * DEV-BSIZE);
if (bp->b-flags & B-READ)
copyin(offset, bp->b-un.b-addr, bp->b-bcount);
else /* write-request */
copyout(bp->b-un.b-addr, offset, bp->b-bcount);
biodone(bp);
}
sleep((caddr-t)devvp, PWAIT);
}
}
/*
* If the MFS process requests the I/O then we must do it directly.
* Otherwise put the request on the list and request the MFS process
* to be run.
*/
mfs_strategymfs-strategy(bp)
struct buf *bp;
{
struct vnode *devvp;
struct mfsnode *mfsp;
off-t offset;
devvp = bp->b-vp;
mfsp = VTOMFS(devvp);
if (mfsp->mfs-pid == u.u-procp->p-pid) {
offset = mfsp->mfs-baseoff + (bp->b-blkno * DEV-BSIZE);
if (bp->b-flags & B-READ)
copyin(offset, bp->b-un.b-addr, bp->b-bcount);
else /* write-request */
copyout(bp->b-un.b-addr, offset, bp->b-bcount);
biodone(bp);
} else {
bp->av-forw = mfsp->mfs-buflist;
mfsp->mfs-buflist = bp;
wakeup((caddr-t)bp->b-vp);
}
}
/*
* The close routine is called by unmount after the filesystem
* has been successfully unmounted.
*/
mfs_closemfs-close(devvp)
struct vnode *devvp;
{
struct mfsnode *mfsp = VTOMFS(vp);
struct buf *bp;
/*
* Finish any pending I/O requests.
*/
while (bp = mfsp->mfs-buflist) {
mfsp->mfs-buflist = bp->av-forw;
mfs-doio(bp, mfsp->mfs-baseoff);
wakeup((caddr-t)bp);
}
/*
* Send a request to the filesystem server to exit.
*/
mfsp->mfs-buflist = MFS-EXIT;
wakeup((caddr-t)vp);
}