NetBSD-5.0.2/sys/rump/librump/rumpkern/vfs.c

Compare this file to the similar file:
Show the results in this format:

/*	$NetBSD: vfs.c,v 1.39 2008/07/29 13:17:47 pooka Exp $	*/

/*
 * Copyright (c) 2007 Antti Kantee.  All Rights Reserved.
 *
 * Development of this software was supported by Google Summer of Code.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <sys/param.h>
#include <sys/mount.h>
#include <sys/vnode.h>
#include <sys/errno.h>
#include <sys/kauth.h>
#include <sys/lock.h>
#include <sys/lockf.h>
#include <sys/stat.h>
#include <sys/namei.h>
#include <sys/queue.h>
#include <sys/filedesc.h>
#include <sys/syscallargs.h>

#include <miscfs/fifofs/fifo.h>
#include <miscfs/specfs/specdev.h>
#include <miscfs/syncfs/syncfs.h>
#include <miscfs/genfs/genfs.h>

#include <rump/rumpuser.h>

#include "rump_private.h"

static int rump_vop_lookup(void *);

int (**dead_vnodeop_p)(void *);
const struct vnodeopv_entry_desc dead_vnodeop_entries[] = {
	{ &vop_default_desc, vn_default_error },
	{ NULL, NULL }
};
const struct vnodeopv_desc dead_vnodeop_opv_desc =
	{ &dead_vnodeop_p, dead_vnodeop_entries };

int (**sync_vnodeop_p)(void *);
const struct vnodeopv_entry_desc sync_vnodeop_entries[] = {
	{ &vop_default_desc, vn_default_error },
	{ NULL, NULL }
};
const struct vnodeopv_desc sync_vnodeop_opv_desc =
	{ &sync_vnodeop_p, sync_vnodeop_entries };

int (**fifo_vnodeop_p)(void *);
const struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
	{ &vop_default_desc, vn_default_error },
	{ NULL, NULL }
};
const struct vnodeopv_desc fifo_vnodeop_opv_desc =
	{ &fifo_vnodeop_p, fifo_vnodeop_entries };

int (**rump_vnodeop_p)(void *);
const struct vnodeopv_entry_desc rump_vnodeop_entries[] = {
	{ &vop_default_desc, vn_default_error },
	{ &vop_lookup_desc, rump_vop_lookup },
	{ &vop_lock_desc, genfs_lock },
	{ &vop_unlock_desc, genfs_unlock },
	{ NULL, NULL }
};
const struct vnodeopv_desc rump_vnodeop_opv_desc =
	{ &rump_vnodeop_p, rump_vnodeop_entries };
const struct vnodeopv_desc * const rump_opv_descs[] = {
	&rump_vnodeop_opv_desc,
	NULL
};

vnode_t *specfs_hash[SPECHSZ];
int (*mountroot)(void);

int
vfs_stdextattrctl(struct mount *mp, int cmt, struct vnode *vp,
	int attrnamespace, const char *attrname)
{

	if (vp != NULL)
		VOP_UNLOCK(vp, 0);
	return EOPNOTSUPP;
}

int
vfs_allocate_syncvnode(struct mount *mp)
{

	panic("%s: unimplemented", __func__);
}

void
vfs_deallocate_syncvnode(struct mount *mp)
{

	panic("%s: unimplemented", __func__);
}

struct mount mnt_dummy;

static struct vnode *
rump_makevnode(const char *path, size_t size, enum vtype vt, dev_t rdev)
{
	struct vnode *vp;
	struct rump_specpriv *sp;

	vp = kmem_alloc(sizeof(struct vnode), KM_SLEEP);
	vp->v_size = vp->v_writesize = size;
	vp->v_type = vt;
	if (vp->v_type != VBLK)
		if (rump_fakeblk_find(path))
			vp->v_type = VBLK;

	if (vp->v_type != VBLK && vp->v_type != VDIR)
		panic("rump_makevnode: only VBLK/VDIR vnodes supported");

	if (vp->v_type == VBLK) {
		spec_node_init(vp, rdev);
		sp = kmem_alloc(sizeof(struct rump_specpriv), KM_SLEEP);
		strcpy(sp->rsp_path, path);
		vp->v_data = sp;
		vp->v_op = spec_vnodeop_p;
	} else {
		vp->v_op = rump_vnodeop_p;
	}
	vp->v_mount = &mnt_dummy;
	vp->v_vnlock = &vp->v_lock;
	vp->v_usecount = 1;
	mutex_init(&vp->v_interlock, MUTEX_DEFAULT, IPL_NONE);
	memset(&vp->v_lock, 0, sizeof(vp->v_lock));
	rw_init(&vp->v_lock.vl_lock);
	cv_init(&vp->v_cv, "vnode");

	return vp;
}

/* from libpuffs, but let's decouple this from that */
static enum vtype
mode2vt(mode_t mode)
{

	switch (mode & S_IFMT) {
	case S_IFIFO:
		return VFIFO;
	case S_IFCHR:
		return VCHR;
	case S_IFDIR:
		return VDIR;
	case S_IFBLK:
		return VBLK;
	case S_IFREG:
		return VREG;
	case S_IFLNK:
		return VLNK;
	case S_IFSOCK:
		return VSOCK;
	default:
		return VBAD; /* XXX: not really true, but ... */
	}
}

/*
 * Simple lookup for faking lookup of device entry for rump file systems 
 */
static int
rump_vop_lookup(void *v)
{
	struct vop_lookup_args /* {
		struct vnode *a_dvp;
		struct vnode **a_vpp;
		struct componentname *a_cnp;
	}; */ *ap = v;
	struct componentname *cnp = ap->a_cnp;
	struct stat sb_node;
	int rv, error;

	/* we handle only some "non-special" cases */
	KASSERT(cnp->cn_nameiop == LOOKUP);
	KASSERT((cnp->cn_flags & ISDOTDOT) == 0);
	KASSERT(cnp->cn_namelen != 0 && cnp->cn_pnbuf[0] != '.');

	if (cnp->cn_flags & FOLLOW)
		rv = rumpuser_stat(cnp->cn_pnbuf, &sb_node, &error);
	else
		rv = rumpuser_lstat(cnp->cn_pnbuf, &sb_node, &error);
	if (rv)
		return error;

	*ap->a_vpp = rump_makevnode(cnp->cn_pnbuf, sb_node.st_size,
	    mode2vt(sb_node.st_mode), sb_node.st_rdev);
	vn_lock(*ap->a_vpp, LK_RETRY | LK_EXCLUSIVE);
	cnp->cn_consume = strlen(cnp->cn_nameptr + cnp->cn_namelen);
	cnp->cn_flags &= ~REQUIREDIR;

	return 0;
}

int
lf_advlock(struct vop_advlock_args *ap, struct lockf **head, off_t size)
{

	panic("%s: unimplemented", __func__);
}

void
fifo_printinfo(struct vnode *vp)
{

	return;
}

void
rumpvfs_init()
{

	vfs_opv_init(rump_opv_descs);
	rootvnode = rump_makevnode("/", 0, VDIR, -1);
}

void
rump_rcvp_set(struct vnode *rvp, struct vnode *cvp)
{
	struct lwp *l = curlwp;
	struct cwdinfo *cwdi = l->l_proc->p_cwdi;

	KASSERT(cvp);

	rw_enter(&cwdi->cwdi_lock, RW_WRITER);
	if (cwdi->cwdi_rdir)
		vrele(cwdi->cwdi_rdir);
	if (rvp)
		vref(rvp);
	cwdi->cwdi_rdir = rvp;

	vrele(cwdi->cwdi_cdir);
	vref(cvp);
	cwdi->cwdi_cdir = cvp;
	rw_exit(&cwdi->cwdi_lock);
}

struct vnode *
rump_cdir_get()
{
	struct vnode *vp;
	struct cwdinfo *cwdi = curlwp->l_proc->p_cwdi;

	rw_enter(&cwdi->cwdi_lock, RW_READER);
	vp = cwdi->cwdi_cdir;
	rw_exit(&cwdi->cwdi_lock);
	vref(vp);

	return vp;
}