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