#include <sys/param.h>
#include <sys/systm.h>
#include <sys/namei.h>
#include <sys/proc.h>
#include <sys/kernel.h>
#include <mach/machine/vm_types.h>
#include <sys/vnode.h>
#include <sys/socket.h>
#include <sys/mount.h>
#include <sys/buf.h>
#include <sys/mbuf.h>
#include <sys/file.h>
#include <dev/disk.h>
#include <sys/ioctl.h>
#include <sys/errno.h>
#include <sys/malloc.h>
#include <dev/ldd.h>
#include <miscfs/specfs/specdev.h>
#include "volfs.h"
struct vfsops volfs_vfsops = {
volfs_mount,
volfs_start,
volfs_unmount,
volfs_root,
volfs_quotactl,
volfs_statfs,
volfs_sync,
volfs_vget,
volfs_fhtovp,
volfs_vptofh,
volfs_init,
volfs_sysctl
};
static char volfs_fs_name[MFSNAMELEN] = "volfs";
extern struct vnodeopv_desc volfs_vnodeop_opv_desc;
extern int maxvfsslots;
extern int maxvfsconf;
extern int vfs_opv_numops;
extern int kdp_flag;
void
volfs_load(int loadArgument) {
struct vfsconf *vfsconflistentry;
int entriesRemaining;
struct vfsconf *newvfsconf = NULL;
struct vfsconf *lastentry = NULL;
int j;
int (***opv_desc_vector_p)();
int (**opv_desc_vector)();
struct vnodeopv_entry_desc *opve_descp;
#pragma unused(loadArgument)
DBG_VOP(("load_volfs: Scanning vfsconf list...\n"));
vfsconflistentry = vfsconf;
for (entriesRemaining = maxvfsslots; entriesRemaining > 0; --entriesRemaining) {
if (vfsconflistentry->vfc_vfsops != NULL) {
if (strcmp(vfsconflistentry->vfc_name, volfs_fs_name) == 0) {
newvfsconf = vfsconflistentry;
break;
} else {
lastentry = vfsconflistentry;
};
} else {
newvfsconf = vfsconflistentry;
};
++vfsconflistentry;
};
if (newvfsconf) {
DBG_VOP(("load_volfs: filling in vfsconf entry at 0x%08lX; lastentry = 0x%08lX.\n", (long)newvfsconf, (long)lastentry));
newvfsconf->vfc_vfsops = &volfs_vfsops;
strncpy(&newvfsconf->vfc_name[0], "volfs", MFSNAMELEN);
newvfsconf->vfc_typenum = maxvfsconf++;
newvfsconf->vfc_refcount = 0;
newvfsconf->vfc_flags = 0;
newvfsconf->vfc_mountroot = NULL;
newvfsconf->vfc_next = NULL;
if (lastentry) {
newvfsconf->vfc_next = lastentry->vfc_next;
lastentry->vfc_next = newvfsconf;
};
opv_desc_vector_p = volfs_vnodeop_opv_desc.opv_desc_vector_p;
DBG_VOP(("load_volfs: Allocating and initializing VNode ops vector...\n"));
MALLOC(*opv_desc_vector_p, PFI *, vfs_opv_numops*sizeof(PFI), M_TEMP, M_WAITOK);
bzero (*opv_desc_vector_p, vfs_opv_numops*sizeof(PFI));
opv_desc_vector = *opv_desc_vector_p;
for (j=0; volfs_vnodeop_opv_desc.opv_desc_ops[j].opve_op; j++) {
opve_descp = &(volfs_vnodeop_opv_desc.opv_desc_ops[j]);
if (opve_descp->opve_op->vdesc_offset == 0 &&
opve_descp->opve_op->vdesc_offset != VOFFSET(vop_default)) {
DBG_VOP(("load_volfs: operation %s not listed in %s.\n",
opve_descp->opve_op->vdesc_name,
"vfs_op_descs"));
panic ("load_volfs: bad operation");
}
opv_desc_vector[opve_descp->opve_op->vdesc_offset] =
opve_descp->opve_impl;
}
opv_desc_vector_p = volfs_vnodeop_opv_desc.opv_desc_vector_p;
opv_desc_vector = *opv_desc_vector_p;
if (opv_desc_vector[VOFFSET(vop_default)]==NULL) {
panic("load_vp;fs: operation vector without default routine.");
}
for (j = 0;j<vfs_opv_numops; j++)
if (opv_desc_vector[j] == NULL)
opv_desc_vector[j] =
opv_desc_vector[VOFFSET(vop_default)];
DBG_VOP(("load_volfs: calling volfs_init()...\n"));
volfs_init(newvfsconf);
};
}
int
volfs_mount(mp, path, data, ndp, p)
register struct mount *mp;
char *path;
caddr_t data;
struct nameidata *ndp;
struct proc *p;
{
struct volfs_mntdata *priv_mnt_data;
struct vnode *root_vp;
struct volfs_vndata *priv_vn_data;
int error;
size_t size;
DBG_VOP(("volfs_mount called\n"));
MALLOC(priv_mnt_data, struct volfs_mntdata *, sizeof(struct volfs_mntdata),
M_VOLFSMNT, M_WAITOK);
DBG_VOP(("MALLOC succeeded\n"));
LIST_INIT(&priv_mnt_data->volfs_fsvnodes);
DBG_VOP(("LIST_INIT succeeded\n"));
mp->mnt_data = (void *)priv_mnt_data;
strcpy(mp->mnt_stat.f_fstypename, "volfs");
(void) copyinstr(path, mp->mnt_stat.f_mntonname, sizeof(mp->mnt_stat.f_mntonname) - 1, &size);
strcpy(mp->mnt_stat.f_mntfromname, "<volfs>");
MALLOC(priv_vn_data, struct volfs_vndata *, sizeof(struct volfs_vndata), M_VOLFSNODE, M_WAITOK);
error = getnewvnode(VT_VOLFS, mp, volfs_vnodeop_p, &root_vp);
if (error != 0)
{
FREE(priv_mnt_data, M_VOLFSMNT);
FREE(priv_vn_data, M_VOLFSNODE);
DBG_VOP(("getnewvnode failed with error code %d\n", error));
return(error);
}
root_vp->v_type = VDIR;
root_vp->v_flag |= VROOT;
lockinit(&priv_vn_data->lock, PINOD, "volfsnode", 0, 0);
priv_vn_data->vnode_type = VOLFS_ROOT;
priv_vn_data->nodeID = 0;
priv_vn_data->fs_mount = mp;
root_vp->v_data = priv_vn_data;
priv_mnt_data->volfs_rootvp = root_vp;
return (0);
}
int
volfs_start(mp, flags, p)
struct mount * mp;
int flags;
struct proc * p;
{
DBG_VOP(("volfs_start called\n"));
return (0);
}
int
volfs_root(mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
struct volfs_mntdata *priv_data;
DBG_VOP(("volfs_root called\n"));
priv_data = (struct volfs_mntdata *)mp->mnt_data;
if (priv_data->volfs_rootvp) {
vref(priv_data->volfs_rootvp);
VOP_LOCK(priv_data->volfs_rootvp, LK_EXCLUSIVE, current_proc());
*vpp = priv_data->volfs_rootvp;
} else {
panic("volfs: root vnode missing!");
};
DBG_VOP(("volfs_root returned with "));
DBG_VOP_PRINT_VNODE_INFO(*vpp);DBG_VOP(("\n"));
return(0);
}
int
volfs_quotactl(mp, cmds, uid, arg, p)
struct mount *mp;
int cmds;
uid_t uid;
caddr_t arg;
struct proc * p;
{
DBG_VOP(("volfs_quotactl called\n"));
return (0);
}
int
volfs_unmount(mp, mntflags, p)
struct mount *mp;
int mntflags;
struct proc *p;
{
struct volfs_mntdata *priv_data;
struct vnode *root_vp;
int retval;
DBG_VOP(("volfs_unmount called\n"));
priv_data = (struct volfs_mntdata *)mp->mnt_data;
root_vp = priv_data->volfs_rootvp;
retval = vflush(mp, root_vp, 0);
if (retval) goto Err_Exit;
if (root_vp) {
retval = vn_lock(root_vp, LK_EXCLUSIVE, p);
if (retval) goto Err_Exit;
if (root_vp->v_usecount > 1) {
DBG_VOP(("VOLFS ERROR: root vnode = %x, usecount = %d\n", (int)root_vp, priv_data->volfs_rootvp->v_usecount));
VOP_UNLOCK(root_vp, 0, p);
retval = EBUSY;
goto Err_Exit;
};
priv_data->volfs_rootvp = NULL;
vput(root_vp);
vgone(root_vp);
};
mp->mnt_data = NULL;
FREE(priv_data, M_VOLFSMNT);
Err_Exit:
return(retval);
}
int
volfs_statfs(mp, sbp, p)
struct mount *mp;
register struct statfs *sbp;
struct proc *p;
{
DBG_VOP(("volfs_statfs called\n"));
sbp->f_bsize = 512;
sbp->f_iosize = 512;
sbp->f_blocks = 1024; sbp->f_bfree = 0; sbp->f_bavail = 0;
sbp->f_files = 0; sbp->f_ffree = 0;
return (0);
}
int
volfs_sync(mp, waitfor, cred, p)
struct mount *mp;
int waitfor;
struct ucred *cred;
struct proc *p;
{
return 0;
}
int
volfs_vget(mp, ino, vpp)
struct mount *mp;
void *ino;
struct vnode **vpp;
{
return(0);
}
int
volfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
register struct mount *mp;
struct fid *fhp;
struct mbuf *nam;
struct vnode **vpp;
int *exflagsp;
struct ucred **credanonp;
{
DBG_VOP(("volfs_fhtovp called\n"));
return(0);
}
int
volfs_vptofh(vp, fhp)
struct vnode *vp;
struct fid *fhp;
{
DBG_VOP(("volfs_vptofh called\n"));
return(0);
}
int
volfs_init(vfsp)
struct vfsconf *vfsp;
{
DBG_VOP(("volfs_init called\n"));
return (0);
}
int
volfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
int *name;
u_int namelen;
void *oldp;
size_t *oldlenp;
void *newp;
size_t newlen;
struct proc *p;
{
DBG_VOP(("volfs_sysctl called\n"));
return (EOPNOTSUPP);
}