* get rid of the old fakeblk registration interface. Instead,

introduce a new and improved "etfs" interface, which can be used
  to register host files accessible from rump fs namespace.  This
  new interface is not restriced to block devices, and neither does
  it require the same pathname in host namespace and rump namespace.
  Therefore, the same host file can be represented both as a char
  and block device in rump namespace.

* adjust rumpblk to make the above possible

* improve rumpfs: nodes are now created properly and not implicitly
  tied to the vnode lifecycle
This commit is contained in:
pooka 2009-08-03 14:23:30 +00:00
parent 38b252cce6
commit eddab4e9bc
5 changed files with 232 additions and 163 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: rump.h,v 1.23 2009/05/26 15:44:35 pooka Exp $ */
/* $NetBSD: rump.h,v 1.24 2009/08/03 14:23:30 pooka Exp $ */
/*
* Copyright (c) 2007 Antti Kantee. All Rights Reserved.
@ -93,9 +93,9 @@ int rump_namei(uint32_t, uint32_t, const char *,
void rump_getvninfo(struct vnode *, enum vtype *, off_t * /*XXX*/, dev_t *);
int rump_fakeblk_register(const char *);
int rump_fakeblk_find(const char *);
void rump_fakeblk_deregister(const char *);
enum rump_etfs_type { RUMP_ETFS_REG, RUMP_ETFS_BLK, RUMP_ETFS_CHR };
int rump_etfs_register(const char *, const char *, enum rump_etfs_type);
int rump_etfs_remove(const char *);
struct vfsops *rump_vfslist_iterate(struct vfsops *);
struct vfsops *rump_vfs_getopsbyname(const char *);

View File

@ -1,4 +1,4 @@
/* $NetBSD: rump_vfs.c,v 1.23 2009/06/29 07:11:06 dholland Exp $ */
/* $NetBSD: rump_vfs.c,v 1.24 2009/08/03 14:23:30 pooka Exp $ */
/*
* Copyright (c) 2008 Antti Kantee. All Rights Reserved.
@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: rump_vfs.c,v 1.23 2009/06/29 07:11:06 dholland Exp $");
__KERNEL_RCSID(0, "$NetBSD: rump_vfs.c,v 1.24 2009/08/03 14:23:30 pooka Exp $");
#include <sys/param.h>
#include <sys/buf.h>
@ -54,12 +54,6 @@ __KERNEL_RCSID(0, "$NetBSD: rump_vfs.c,v 1.23 2009/06/29 07:11:06 dholland Exp $
#include "rump_private.h"
#include "rump_vfs_private.h"
struct fakeblk {
char path[MAXPATHLEN];
LIST_ENTRY(fakeblk) entries;
};
static LIST_HEAD(, fakeblk) fakeblks = LIST_HEAD_INITIALIZER(fakeblks);
static struct cwdinfo rump_cwdi;
static void rump_rcvp_lwpset(struct vnode *, struct vnode *, struct lwp *);
@ -271,66 +265,6 @@ rump_namei(uint32_t op, uint32_t flags, const char *namep,
return rv;
}
static struct fakeblk *
_rump_fakeblk_find(const char *path)
{
char buf[MAXPATHLEN];
struct fakeblk *fblk;
int error;
if (rumpuser_realpath(path, buf, &error) == NULL)
return NULL;
LIST_FOREACH(fblk, &fakeblks, entries)
if (strcmp(fblk->path, buf) == 0)
return fblk;
return NULL;
}
int
rump_fakeblk_register(const char *path)
{
char buf[MAXPATHLEN];
struct fakeblk *fblk;
int error;
if (_rump_fakeblk_find(path))
return EEXIST;
if (rumpuser_realpath(path, buf, &error) == NULL)
return error;
fblk = kmem_alloc(sizeof(struct fakeblk), KM_NOSLEEP);
if (fblk == NULL)
return ENOMEM;
strlcpy(fblk->path, buf, MAXPATHLEN);
LIST_INSERT_HEAD(&fakeblks, fblk, entries);
return 0;
}
int
rump_fakeblk_find(const char *path)
{
return _rump_fakeblk_find(path) != NULL;
}
void
rump_fakeblk_deregister(const char *path)
{
struct fakeblk *fblk;
fblk = _rump_fakeblk_find(path);
if (fblk == NULL)
return;
LIST_REMOVE(fblk, entries);
kmem_free(fblk, sizeof(*fblk));
}
void
rump_getvninfo(struct vnode *vp, enum vtype *vtype, voff_t *vsize, dev_t *vdev)
{

View File

@ -1,4 +1,4 @@
/* $NetBSD: rump_vfs_private.h,v 1.2 2009/01/13 01:57:35 pooka Exp $ */
/* $NetBSD: rump_vfs_private.h,v 1.3 2009/08/03 14:23:30 pooka Exp $ */
/*
* Copyright (c) 2008 Antti Kantee. All Rights Reserved.
@ -28,11 +28,13 @@
#ifndef _SYS_RUMP_VFS_PRIVATE_H_
#define _SYS_RUMP_VFS_PRIVATE_H_
#include <sys/types.h>
void rump_vfs_init(void);
void rumpfs_init(void);
#define RUMPBLK 254
int rumpblk_register(const char *);
int rumpblk_register(const char *, devminor_t *);
int rumpblk_init(void);
void rump_biodone(void *, size_t, int);

View File

@ -1,4 +1,4 @@
/* $NetBSD: rumpblk.c,v 1.23 2009/04/30 17:43:07 pooka Exp $ */
/* $NetBSD: rumpblk.c,v 1.24 2009/08/03 14:23:30 pooka Exp $ */
/*
* Copyright (c) 2009 Antti Kantee. All Rights Reserved.
@ -43,7 +43,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: rumpblk.c,v 1.23 2009/04/30 17:43:07 pooka Exp $");
__KERNEL_RCSID(0, "$NetBSD: rumpblk.c,v 1.24 2009/08/03 14:23:30 pooka Exp $");
#include <sys/param.h>
#include <sys/buf.h>
@ -89,6 +89,7 @@ struct blkwin {
static struct rblkdev {
char *rblk_path;
int rblk_fd;
int rblk_refcnt;
#ifdef HAS_ODIRECT
int rblk_dfd;
#endif
@ -145,6 +146,7 @@ static const struct cdevsw rumpblk_cdevsw = {
#define BLKFAIL_MAX 10000
static int blkfail;
static unsigned randstate;
static kmutex_t rumpblk_lock;
static struct blkwin *
getwindow(struct rblkdev *rblk, off_t off, int *wsize, int *error)
@ -253,6 +255,8 @@ rumpblk_init(void)
unsigned tmp;
int error, i;
mutex_init(&rumpblk_lock, MUTEX_DEFAULT, IPL_NONE);
if (rumpuser_getenv("RUMP_BLKFAIL", buf, sizeof(buf), &error) == 0) {
blkfail = strtoul(buf, NULL, 10);
/* fail everything */
@ -321,27 +325,47 @@ rumpblk_init(void)
}
}
/* XXX: no deregister */
int
rumpblk_register(const char *path)
rumpblk_register(const char *path, devminor_t *dmin)
{
uint64_t flen;
size_t len;
int i;
int ftype, error, i;
for (i = 0; i < RUMPBLK_SIZE; i++)
if (minors[i].rblk_path && strcmp(minors[i].rblk_path, path)==0)
return i;
if (rumpuser_getfileinfo(path, &flen, &ftype, &error))
return error;
/* verify host file is of supported type */
if (!(ftype == RUMPUSER_FT_REG
|| ftype == RUMPUSER_FT_BLK
|| ftype == RUMPUSER_FT_CHR))
return EINVAL;
mutex_enter(&rumpblk_lock);
for (i = 0; i < RUMPBLK_SIZE; i++) {
if (minors[i].rblk_path&&strcmp(minors[i].rblk_path, path)==0) {
mutex_exit(&rumpblk_lock);
*dmin = i;
return 0;
}
}
for (i = 0; i < RUMPBLK_SIZE; i++)
if (minors[i].rblk_path == NULL)
break;
if (i == RUMPBLK_SIZE)
return -1;
if (i == RUMPBLK_SIZE) {
mutex_exit(&rumpblk_lock);
return EBUSY;
}
len = strlen(path);
minors[i].rblk_path = malloc(len + 1, M_TEMP, M_WAITOK);
strcpy(minors[i].rblk_path, path);
minors[i].rblk_fd = -1;
return i;
mutex_exit(&rumpblk_lock);
*dmin = i;
return 0;
}
int
@ -352,7 +376,7 @@ rumpblk_open(dev_t dev, int flag, int fmt, struct lwp *l)
int ft, dummy;
int error, fd;
KASSERT(rblk->rblk_fd == -1);
KASSERT(rblk->rblk_fd == -1); /* XXX */
fd = rumpuser_open(rblk->rblk_path, OFLAGS(flag), &error);
if (error)
return error;

View File

@ -1,4 +1,4 @@
/* $NetBSD: rumpfs.c,v 1.20 2009/07/22 21:06:56 pooka Exp $ */
/* $NetBSD: rumpfs.c,v 1.21 2009/08/03 14:23:30 pooka Exp $ */
/*
* Copyright (c) 2007 Antti Kantee. All Rights Reserved.
@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: rumpfs.c,v 1.20 2009/07/22 21:06:56 pooka Exp $");
__KERNEL_RCSID(0, "$NetBSD: rumpfs.c,v 1.21 2009/08/03 14:23:30 pooka Exp $");
#include <sys/param.h>
#include <sys/mount.h>
@ -103,10 +103,6 @@ const struct vnodeopv_desc * const rump_opv_descs[] = {
NULL
};
static struct mount rump_mnt;
static int lastino = 1;
static kmutex_t reclock;
struct rumpfs_dent {
char *rd_name;
struct rumpfs_node *rd_node;
@ -122,8 +118,137 @@ struct rumpfs_node {
LIST_HEAD(, rumpfs_dent) rn_dir;
};
static struct rumpfs_node *makeprivate(enum vtype, dev_t, off_t);
/*
* Extra Terrestrial stuff. We map a given key (pathname) to a file on
* the host FS. ET phones home only from the root node of rumpfs.
*
* When an etfs node is removed, a vnode potentially behind it is not
* immediately recycled.
*/
struct etfs {
char et_key[MAXPATHLEN];
LIST_ENTRY(etfs) et_entries;
struct rumpfs_node *et_rn;
};
static kmutex_t etfs_lock;
static LIST_HEAD(, etfs) etfs_list = LIST_HEAD_INITIALIZER(etfs_list);
static enum vtype
ettype_to_vtype(enum rump_etfs_type et)
{
enum vtype vt;
switch (et) {
case RUMP_ETFS_REG:
vt = VREG;
break;
case RUMP_ETFS_BLK:
vt = VBLK;
break;
case RUMP_ETFS_CHR:
vt = VCHR;
break;
default:
panic("invalid et type: %d", et);
}
return vt;
}
static bool
etfs_find(const char *key, struct rumpfs_node **rnp)
{
struct etfs *et;
bool rv = false;
KASSERT(mutex_owned(&etfs_lock));
LIST_FOREACH(et, &etfs_list, et_entries) {
if (strcmp(key, et->et_key) == 0) {
*rnp = et->et_rn;
rv = true;
break;
}
}
return rv;
}
int
rump_etfs_register(const char *key, const char *hostpath,
enum rump_etfs_type ftype)
{
struct etfs *et;
struct rumpfs_node *rn_dummy;
uint64_t fsize;
dev_t rdev;
devminor_t dmin;
int hft, error;
/* not supported for now, need r/w VOPs ... */
if (ftype == RUMP_ETFS_REG)
return EOPNOTSUPP;
if (rumpuser_getfileinfo(hostpath, &fsize, &hft, &error))
return error;
error = rumpblk_register(hostpath, &dmin);
if (error != 0) {
return error;
}
rdev = makedev(RUMPBLK, dmin);
et = kmem_alloc(sizeof(*et), KM_SLEEP);
strcpy(et->et_key, key);
et->et_rn = makeprivate(ettype_to_vtype(ftype), rdev, fsize);
mutex_enter(&etfs_lock);
if (etfs_find(key, &rn_dummy)) {
mutex_exit(&etfs_lock);
kmem_free(et, sizeof(*et));
/* XXX: rumpblk_deregister(hostpath); */
return EEXIST;
}
LIST_INSERT_HEAD(&etfs_list, et, et_entries);
mutex_exit(&etfs_lock);
return 0;
}
int
rump_etfs_remove(const char *key)
{
struct etfs *et;
mutex_enter(&etfs_lock);
LIST_FOREACH(et, &etfs_list, et_entries) {
if (strcmp(et->et_key, key) == 0) {
LIST_REMOVE(et, et_entries);
kmem_free(et, sizeof(*et));
break;
}
}
mutex_exit(&etfs_lock);
if (!et)
return ENOENT;
return 0;
}
/*
* rumpfs
*/
static struct mount rump_mnt;
static int lastino = 1;
static kmutex_t reclock;
static struct rumpfs_node *
makeprivate(enum vtype vt, dev_t rdev, voff_t size)
makeprivate(enum vtype vt, dev_t rdev, off_t size)
{
struct rumpfs_node *rn;
struct vattr *va;
@ -161,46 +286,37 @@ makeprivate(enum vtype vt, dev_t rdev, voff_t size)
}
static int
rump_makevnode(const char *path, voff_t size, enum vtype vt, dev_t rdev,
struct vnode **vpp, bool regrumpblk)
makevnode(struct rumpfs_node *rn, struct vnode **vpp)
{
struct vnode *vp;
struct rumpfs_node *rn;
int (**vpops)(void *);
struct vattr *va = &rn->rn_va;
int rv;
if (vt == VREG || vt == VCHR || vt == VBLK) {
vt = VBLK;
KASSERT(mutex_owned(&reclock));
if (va->va_type == VCHR || va->va_type == VBLK) {
vpops = rump_specop_p;
} else {
vpops = rump_vnodeop_p;
}
if (vt != VBLK && vt != VDIR)
panic("rump_makevnode: only VBLK/VDIR vnodes supported");
if (vpops != rump_specop_p && va->va_type != VDIR)
return EOPNOTSUPP;
rv = getnewvnode(VT_RUMP, &rump_mnt, vpops, &vp);
if (rv)
return rv;
vp->v_size = vp->v_writesize = size;
vp->v_type = vt;
vp->v_size = vp->v_writesize = va->va_size;
vp->v_type = va->va_type;
if (vp->v_type == VBLK) {
if (regrumpblk) {
rv = rumpblk_register(path);
if (rv == -1)
panic("rump_makevnode: lazy bum");
rdev = makedev(RUMPBLK, rv);
spec_node_init(vp, rdev);
} else {
spec_node_init(vp, rdev);
}
if (vpops == rump_specop_p) {
spec_node_init(vp, va->va_rdev);
}
rn = makeprivate(vp->v_type, rdev, size);
rn->rn_vp = vp;
vp->v_data = rn;
vn_lock(vp, LK_RETRY | LK_EXCLUSIVE);
rn->rn_vp = vp;
*vpp = vp;
return 0;
@ -210,6 +326,8 @@ rump_makevnode(const char *path, voff_t size, enum vtype vt, dev_t rdev,
* Simple lookup for faking lookup of device entry for rump file systems
* and for locating/creating directories. Yes, this will panic if you
* call it with the wrong arguments.
*
* uhm, this is twisted. C F C C, hope of C C F C looming
*/
static int
rump_vop_lookup(void *v)
@ -223,11 +341,9 @@ rump_vop_lookup(void *v)
struct vnode *dvp = ap->a_dvp;
struct vnode **vpp = ap->a_vpp;
struct vnode *vp;
struct rumpfs_node *rn = dvp->v_data;
struct rumpfs_dent *rd;
uint64_t fsize;
enum vtype vt;
int rv, error, ft;
struct rumpfs_node *rnd = dvp->v_data, *rn;
struct rumpfs_dent *rd = NULL;
int rv;
/* we handle only some "non-special" cases */
if (!(((cnp->cn_flags & ISLASTCN) == 0)
@ -240,44 +356,23 @@ rump_vop_lookup(void *v)
/* check if we are returning a faked block device */
if (dvp == rootvnode && cnp->cn_nameiop == LOOKUP) {
if (rump_fakeblk_find(cnp->cn_pnbuf)) {
rv = rumpuser_getfileinfo(cnp->cn_pnbuf, &fsize,
&ft, &error);
if (rv)
return rv;
switch (ft) {
case RUMPUSER_FT_DIR:
vt = VDIR;
break;
case RUMPUSER_FT_REG:
vt = VREG;
break;
case RUMPUSER_FT_BLK:
vt = VBLK;
break;
case RUMPUSER_FT_CHR:
vt = VCHR;
break;
default:
vt = VBAD;
break;
}
error = rump_makevnode(cnp->cn_pnbuf, fsize, vt, -1,
vpp, true);
if (error)
return error;
mutex_enter(&etfs_lock);
if (etfs_find(cnp->cn_pnbuf, &rn)) {
mutex_exit(&etfs_lock);
cnp->cn_consume = strlen(cnp->cn_nameptr
+ cnp->cn_namelen);
cnp->cn_flags &= ~REQUIREDIR;
return 0;
goto getvnode;
}
mutex_exit(&etfs_lock);
}
LIST_FOREACH(rd, &rn->rn_dir, rd_entries) {
if (strncmp(rd->rd_name, cnp->cn_nameptr,
cnp->cn_namelen) == 0)
break;
if (!rd) {
LIST_FOREACH(rd, &rnd->rn_dir, rd_entries) {
if (strncmp(rd->rd_name, cnp->cn_nameptr,
cnp->cn_namelen) == 0)
break;
}
}
if (!rd && ((cnp->cn_flags & ISLASTCN) == 0||cnp->cn_nameiop != CREATE))
@ -287,19 +382,22 @@ rump_vop_lookup(void *v)
cnp->cn_flags |= SAVENAME;
return EJUSTRETURN;
}
KASSERT(rd);
rn = rd->rd_node;
rd = NULL;
retry:
getvnode:
KASSERT(rn);
mutex_enter(&reclock);
if ((vp = rd->rd_node->rn_vp)) {
if ((vp = rn->rn_vp)) {
mutex_enter(&vp->v_interlock);
mutex_exit(&reclock);
if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK))
goto retry;
goto getvnode;
*vpp = vp;
} else {
rv = rump_makevnode(cnp->cn_nameptr, DEV_BSIZE, VDIR, -1,
vpp, false);
rv = makevnode(rn, vpp);
rn->rn_vp = *vpp;
mutex_exit(&reclock);
if (rv)
return rv;
}
@ -333,12 +431,15 @@ rump_vop_mkdir(void *v)
struct vnode *dvp = ap->a_dvp;
struct vnode **vpp = ap->a_vpp;
struct componentname *cnp = ap->a_cnp;
struct rumpfs_node *rnd = dvp->v_data;
struct rumpfs_node *rnd = dvp->v_data, *rn;
struct rumpfs_dent *rdent;
int rv = 0;
if ((rv = rump_makevnode(cnp->cn_nameptr, DEV_BSIZE, VDIR, -1,
vpp, false)) != 0)
rn = makeprivate(VDIR, NODEV, DEV_BSIZE);
mutex_enter(&reclock);
rv = makevnode(rn, vpp);
mutex_exit(&reclock);
if (rv)
goto out;
rdent = kmem_alloc(sizeof(*rdent), KM_SLEEP);
@ -366,12 +467,15 @@ rump_vop_mknod(void *v)
struct vnode **vpp = ap->a_vpp;
struct componentname *cnp = ap->a_cnp;
struct vattr *va = ap->a_vap;
struct rumpfs_node *rnd = dvp->v_data;
struct rumpfs_node *rnd = dvp->v_data, *rn;
struct rumpfs_dent *rdent;
int rv;
if ((rv = rump_makevnode(cnp->cn_nameptr, DEV_BSIZE, va->va_type,
va->va_rdev, vpp, false)) != 0)
rn = makeprivate(va->va_type, va->va_rdev, DEV_BSIZE);
mutex_enter(&reclock);
rv = makevnode(rn, vpp);
mutex_exit(&reclock);
if (rv)
goto out;
rdent = kmem_alloc(sizeof(*rdent), KM_SLEEP);
@ -442,9 +546,11 @@ rump_vop_spec(void *v)
void
rumpfs_init(void)
{
struct rumpfs_node *rn;
int rv;
mutex_init(&reclock, MUTEX_DEFAULT, IPL_NONE);
mutex_init(&etfs_lock, MUTEX_DEFAULT, IPL_NONE);
/* XXX: init properly instead of this crap */
rump_mnt.mnt_refcnt = 1;
@ -453,7 +559,10 @@ rumpfs_init(void)
TAILQ_INIT(&rump_mnt.mnt_vnodelist);
vfs_opv_init(rump_opv_descs);
rv = rump_makevnode("/", 0, VDIR, -1, &rootvnode, false);
rn = makeprivate(VDIR, NODEV, DEV_BSIZE);
mutex_enter(&reclock);
rv = makevnode(rn, &rootvnode);
mutex_exit(&reclock);
if (rv)
panic("could not create root vnode: %d", rv);
rootvnode->v_vflag |= VV_ROOT;