Home | History | Annotate | Line # | Download | only in rumpvfs
rumpfs.c revision 1.9
      1  1.9   pooka /*	$NetBSD: rumpfs.c,v 1.9 2009/03/19 09:14:37 pooka Exp $	*/
      2  1.1   pooka 
      3  1.1   pooka /*
      4  1.1   pooka  * Copyright (c) 2007 Antti Kantee.  All Rights Reserved.
      5  1.1   pooka  *
      6  1.1   pooka  * Development of this software was supported by Google Summer of Code.
      7  1.1   pooka  *
      8  1.1   pooka  * Redistribution and use in source and binary forms, with or without
      9  1.1   pooka  * modification, are permitted provided that the following conditions
     10  1.1   pooka  * are met:
     11  1.1   pooka  * 1. Redistributions of source code must retain the above copyright
     12  1.1   pooka  *    notice, this list of conditions and the following disclaimer.
     13  1.1   pooka  * 2. Redistributions in binary form must reproduce the above copyright
     14  1.1   pooka  *    notice, this list of conditions and the following disclaimer in the
     15  1.1   pooka  *    documentation and/or other materials provided with the distribution.
     16  1.1   pooka  *
     17  1.1   pooka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
     18  1.1   pooka  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     19  1.1   pooka  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     20  1.1   pooka  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     21  1.1   pooka  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22  1.1   pooka  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     23  1.1   pooka  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     24  1.1   pooka  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     25  1.1   pooka  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     26  1.1   pooka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     27  1.1   pooka  * SUCH DAMAGE.
     28  1.1   pooka  */
     29  1.1   pooka 
     30  1.3   pooka #include <sys/cdefs.h>
     31  1.9   pooka __KERNEL_RCSID(0, "$NetBSD: rumpfs.c,v 1.9 2009/03/19 09:14:37 pooka Exp $");
     32  1.3   pooka 
     33  1.1   pooka #include <sys/param.h>
     34  1.1   pooka #include <sys/mount.h>
     35  1.1   pooka #include <sys/vnode.h>
     36  1.1   pooka #include <sys/errno.h>
     37  1.1   pooka #include <sys/kauth.h>
     38  1.1   pooka #include <sys/lock.h>
     39  1.1   pooka #include <sys/lockf.h>
     40  1.1   pooka #include <sys/stat.h>
     41  1.1   pooka #include <sys/namei.h>
     42  1.1   pooka #include <sys/queue.h>
     43  1.1   pooka #include <sys/filedesc.h>
     44  1.1   pooka #include <sys/syscallargs.h>
     45  1.1   pooka 
     46  1.1   pooka #include <miscfs/fifofs/fifo.h>
     47  1.1   pooka #include <miscfs/specfs/specdev.h>
     48  1.1   pooka #include <miscfs/genfs/genfs.h>
     49  1.1   pooka 
     50  1.1   pooka #include <rump/rumpuser.h>
     51  1.1   pooka 
     52  1.1   pooka #include "rump_private.h"
     53  1.1   pooka #include "rump_vfs_private.h"
     54  1.1   pooka 
     55  1.1   pooka static int rump_vop_lookup(void *);
     56  1.9   pooka static int rump_vop_getattr(void *);
     57  1.9   pooka static int rump_vop_success(void *);
     58  1.1   pooka 
     59  1.1   pooka int (**dead_vnodeop_p)(void *);
     60  1.1   pooka const struct vnodeopv_entry_desc dead_vnodeop_entries[] = {
     61  1.1   pooka 	{ &vop_default_desc, vn_default_error },
     62  1.1   pooka 	{ NULL, NULL }
     63  1.1   pooka };
     64  1.1   pooka const struct vnodeopv_desc dead_vnodeop_opv_desc =
     65  1.1   pooka 	{ &dead_vnodeop_p, dead_vnodeop_entries };
     66  1.1   pooka 
     67  1.1   pooka int (**fifo_vnodeop_p)(void *);
     68  1.1   pooka const struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
     69  1.1   pooka 	{ &vop_default_desc, vn_default_error },
     70  1.1   pooka 	{ NULL, NULL }
     71  1.1   pooka };
     72  1.1   pooka const struct vnodeopv_desc fifo_vnodeop_opv_desc =
     73  1.1   pooka 	{ &fifo_vnodeop_p, fifo_vnodeop_entries };
     74  1.1   pooka 
     75  1.1   pooka int (**rump_vnodeop_p)(void *);
     76  1.1   pooka const struct vnodeopv_entry_desc rump_vnodeop_entries[] = {
     77  1.1   pooka 	{ &vop_default_desc, vn_default_error },
     78  1.1   pooka 	{ &vop_lookup_desc, rump_vop_lookup },
     79  1.9   pooka 	{ &vop_getattr_desc, rump_vop_getattr },
     80  1.9   pooka 	{ &vop_putpages_desc, rump_vop_success },
     81  1.9   pooka 	{ &vop_fsync_desc, rump_vop_success },
     82  1.1   pooka 	{ &vop_lock_desc, genfs_lock },
     83  1.1   pooka 	{ &vop_unlock_desc, genfs_unlock },
     84  1.1   pooka 	{ NULL, NULL }
     85  1.1   pooka };
     86  1.1   pooka const struct vnodeopv_desc rump_vnodeop_opv_desc =
     87  1.1   pooka 	{ &rump_vnodeop_p, rump_vnodeop_entries };
     88  1.1   pooka const struct vnodeopv_desc * const rump_opv_descs[] = {
     89  1.1   pooka 	&rump_vnodeop_opv_desc,
     90  1.1   pooka 	NULL
     91  1.1   pooka };
     92  1.1   pooka 
     93  1.9   pooka static struct mount rump_mnt;
     94  1.9   pooka static int lastino = 1;
     95  1.9   pooka 
     96  1.9   pooka static struct vattr *
     97  1.9   pooka makevattr(enum vtype vt)
     98  1.9   pooka {
     99  1.9   pooka 	struct vattr *va;
    100  1.9   pooka 	struct timespec ts;
    101  1.9   pooka 
    102  1.9   pooka 	nanotime(&ts);
    103  1.9   pooka 
    104  1.9   pooka 	va = kmem_alloc(sizeof(*va), KM_SLEEP);
    105  1.9   pooka 	va->va_type = vt;
    106  1.9   pooka 	va->va_mode = 0755;
    107  1.9   pooka 	va->va_nlink = 2;
    108  1.9   pooka 	va->va_uid = 0;
    109  1.9   pooka 	va->va_gid = 0;
    110  1.9   pooka 	va->va_fsid =
    111  1.9   pooka 	va->va_fileid = atomic_inc_uint_nv(&lastino);
    112  1.9   pooka 	va->va_size = 512;
    113  1.9   pooka 	va->va_blocksize = 512;
    114  1.9   pooka 	va->va_atime = ts;
    115  1.9   pooka 	va->va_mtime = ts;
    116  1.9   pooka 	va->va_ctime = ts;
    117  1.9   pooka 	va->va_birthtime = ts;
    118  1.9   pooka 	va->va_gen = 0;
    119  1.9   pooka 	va->va_flags = 0;
    120  1.9   pooka 	va->va_rdev = -1;
    121  1.9   pooka 	va->va_bytes = 512;
    122  1.9   pooka 	va->va_filerev = 0;
    123  1.9   pooka 	va->va_vaflags = 0;
    124  1.9   pooka 
    125  1.9   pooka 	return va;
    126  1.9   pooka }
    127  1.1   pooka 
    128  1.6   pooka static int
    129  1.6   pooka rump_makevnode(const char *path, size_t size, enum vtype vt, struct vnode **vpp)
    130  1.1   pooka {
    131  1.1   pooka 	struct vnode *vp;
    132  1.6   pooka 	int rv;
    133  1.1   pooka 
    134  1.1   pooka 	vp = kmem_alloc(sizeof(struct vnode), KM_SLEEP);
    135  1.1   pooka 	vp->v_size = vp->v_writesize = size;
    136  1.1   pooka 	vp->v_type = vt;
    137  1.9   pooka 	if (vp->v_type == VREG)
    138  1.9   pooka 		vp->v_type = VBLK;
    139  1.1   pooka 
    140  1.1   pooka 	if (vp->v_type != VBLK && vp->v_type != VDIR)
    141  1.1   pooka 		panic("rump_makevnode: only VBLK/VDIR vnodes supported");
    142  1.1   pooka 
    143  1.1   pooka 	if (vp->v_type == VBLK) {
    144  1.6   pooka 		rv = rumpblk_register(path);
    145  1.6   pooka 		if (rv == -1) {
    146  1.6   pooka 			rv = EINVAL;
    147  1.6   pooka 			goto bad;
    148  1.6   pooka 		}
    149  1.6   pooka 		spec_node_init(vp, makedev(RUMPBLK, rv));
    150  1.1   pooka 		vp->v_op = spec_vnodeop_p;
    151  1.1   pooka 	} else {
    152  1.1   pooka 		vp->v_op = rump_vnodeop_p;
    153  1.1   pooka 	}
    154  1.9   pooka 	vp->v_tag = VT_RUMP;
    155  1.9   pooka 	vp->v_mount = &rump_mnt;
    156  1.1   pooka 	vp->v_vnlock = &vp->v_lock;
    157  1.1   pooka 	vp->v_usecount = 1;
    158  1.9   pooka 	vp->v_data = makevattr(vp->v_type);
    159  1.1   pooka 	mutex_init(&vp->v_interlock, MUTEX_DEFAULT, IPL_NONE);
    160  1.1   pooka 	memset(&vp->v_lock, 0, sizeof(vp->v_lock));
    161  1.1   pooka 	rw_init(&vp->v_lock.vl_lock);
    162  1.1   pooka 	cv_init(&vp->v_cv, "vnode");
    163  1.6   pooka 	*vpp = vp;
    164  1.6   pooka 
    165  1.6   pooka 	return 0;
    166  1.1   pooka 
    167  1.6   pooka  bad:
    168  1.6   pooka 	kmem_free(vp, sizeof(*vp));
    169  1.6   pooka 	return rv;
    170  1.1   pooka }
    171  1.1   pooka 
    172  1.1   pooka /*
    173  1.1   pooka  * Simple lookup for faking lookup of device entry for rump file systems
    174  1.1   pooka  */
    175  1.1   pooka static int
    176  1.1   pooka rump_vop_lookup(void *v)
    177  1.1   pooka {
    178  1.1   pooka 	struct vop_lookup_args /* {
    179  1.1   pooka 		struct vnode *a_dvp;
    180  1.1   pooka 		struct vnode **a_vpp;
    181  1.1   pooka 		struct componentname *a_cnp;
    182  1.1   pooka 	}; */ *ap = v;
    183  1.1   pooka 	struct componentname *cnp = ap->a_cnp;
    184  1.7   pooka 	uint64_t fsize;
    185  1.7   pooka 	enum vtype vt;
    186  1.7   pooka 	int rv, error, ft;
    187  1.1   pooka 
    188  1.1   pooka 	/* we handle only some "non-special" cases */
    189  1.1   pooka 	KASSERT(cnp->cn_nameiop == LOOKUP);
    190  1.7   pooka 	KASSERT(cnp->cn_flags & FOLLOW);
    191  1.1   pooka 	KASSERT((cnp->cn_flags & ISDOTDOT) == 0);
    192  1.1   pooka 	KASSERT(cnp->cn_namelen != 0 && cnp->cn_pnbuf[0] != '.');
    193  1.1   pooka 
    194  1.7   pooka 	rv = rumpuser_getfileinfo(cnp->cn_pnbuf, &fsize, &ft, &error);
    195  1.1   pooka 	if (rv)
    196  1.1   pooka 		return error;
    197  1.7   pooka 	switch (ft) {
    198  1.7   pooka 	case RUMPUSER_FT_DIR:
    199  1.7   pooka 		vt = VDIR;
    200  1.7   pooka 		break;
    201  1.7   pooka 	case RUMPUSER_FT_REG:
    202  1.7   pooka 		vt = VREG;
    203  1.7   pooka 		break;
    204  1.7   pooka 	case RUMPUSER_FT_BLK:
    205  1.7   pooka 		vt = VBLK;
    206  1.7   pooka 		break;
    207  1.7   pooka 	default:
    208  1.7   pooka 		vt = VBAD;
    209  1.7   pooka 		break;
    210  1.7   pooka 	}
    211  1.1   pooka 
    212  1.7   pooka 	error = rump_makevnode(cnp->cn_pnbuf, fsize, vt, ap->a_vpp);
    213  1.6   pooka 	if (error)
    214  1.6   pooka 		return error;
    215  1.6   pooka 
    216  1.1   pooka 	vn_lock(*ap->a_vpp, LK_RETRY | LK_EXCLUSIVE);
    217  1.1   pooka 	cnp->cn_consume = strlen(cnp->cn_nameptr + cnp->cn_namelen);
    218  1.1   pooka 	cnp->cn_flags &= ~REQUIREDIR;
    219  1.1   pooka 
    220  1.1   pooka 	return 0;
    221  1.1   pooka }
    222  1.1   pooka 
    223  1.9   pooka static int
    224  1.9   pooka rump_vop_getattr(void *v)
    225  1.9   pooka {
    226  1.9   pooka 	struct vop_getattr_args /* {
    227  1.9   pooka 		struct vnode *a_vp;
    228  1.9   pooka 		struct vattr *a_vap;
    229  1.9   pooka 		kauth_cred_t a_cred;
    230  1.9   pooka 	} */ *ap = v;
    231  1.9   pooka 
    232  1.9   pooka 	memcpy(ap->a_vap, ap->a_vp->v_data, sizeof(struct vattr));
    233  1.9   pooka 	return 0;
    234  1.9   pooka }
    235  1.9   pooka 
    236  1.9   pooka static int
    237  1.9   pooka rump_vop_success(void *v)
    238  1.9   pooka {
    239  1.9   pooka 
    240  1.9   pooka 	return 0;
    241  1.9   pooka }
    242  1.9   pooka 
    243  1.1   pooka void
    244  1.8  cegger rumpfs_init(void)
    245  1.1   pooka {
    246  1.6   pooka 	int rv;
    247  1.1   pooka 
    248  1.1   pooka 	vfs_opv_init(rump_opv_descs);
    249  1.6   pooka 	rv = rump_makevnode("/", 0, VDIR, &rootvnode);
    250  1.6   pooka 	if (rv)
    251  1.6   pooka 		panic("could not create root vnode: %d", rv);
    252  1.2   pooka 	rootvnode->v_vflag |= VV_ROOT;
    253  1.1   pooka }
    254