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);
}