Module Name:    src
Committed By:   pooka
Date:           Wed Apr 29 16:05:41 UTC 2009

Modified Files:
        src/sys/rump/librump/rumpvfs: rumpfs.c

Log Message:
Add enough support to be able to create directories and perform
lookups through them.  This has two implications:

1) mountpoints can be created directly onto the rump rootfs.
   this is benefitial in test programs where we want the same
   program to be easily switched between testing against rump and
   testing against the host kernel.
2) fakeblk must be used (it used to work implicitly) to register
   block devices that should be used from the host fs namespace.


To generate a diff of this commit:
cvs rdiff -u -r1.13 -r1.14 src/sys/rump/librump/rumpvfs/rumpfs.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/rump/librump/rumpvfs/rumpfs.c
diff -u src/sys/rump/librump/rumpvfs/rumpfs.c:1.13 src/sys/rump/librump/rumpvfs/rumpfs.c:1.14
--- src/sys/rump/librump/rumpvfs/rumpfs.c:1.13	Sat Apr 18 15:41:36 2009
+++ src/sys/rump/librump/rumpvfs/rumpfs.c	Wed Apr 29 16:05:41 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: rumpfs.c,v 1.13 2009/04/18 15:41:36 pooka Exp $	*/
+/*	$NetBSD: rumpfs.c,v 1.14 2009/04/29 16:05:41 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.13 2009/04/18 15:41:36 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rumpfs.c,v 1.14 2009/04/29 16:05:41 pooka Exp $");
 
 #include <sys/param.h>
 #include <sys/mount.h>
@@ -55,6 +55,8 @@
 
 static int rump_vop_lookup(void *);
 static int rump_vop_getattr(void *);
+static int rump_vop_mkdir(void *);
+static int rump_vop_inactive(void *);
 static int rump_vop_reclaim(void *);
 static int rump_vop_success(void *);
 
@@ -79,10 +81,12 @@
 	{ &vop_default_desc, vn_default_error },
 	{ &vop_lookup_desc, rump_vop_lookup },
 	{ &vop_getattr_desc, rump_vop_getattr },
+	{ &vop_mkdir_desc, rump_vop_mkdir },
 	{ &vop_putpages_desc, genfs_null_putpages },
 	{ &vop_fsync_desc, rump_vop_success },
 	{ &vop_lock_desc, genfs_lock },
 	{ &vop_unlock_desc, genfs_unlock },
+	{ &vop_inactive_desc, rump_vop_inactive },
 	{ &vop_reclaim_desc, rump_vop_reclaim },
 	{ NULL, NULL }
 };
@@ -95,19 +99,41 @@
 
 static struct mount rump_mnt;
 static int lastino = 1;
+static kmutex_t reclock;
 
-static struct vattr *
-makevattr(enum vtype vt)
+struct rumpfs_dent {
+	char *rd_name;
+	struct rumpfs_node *rd_node;
+
+	LIST_ENTRY(rumpfs_dent) rd_entries;
+};
+
+struct rumpfs_node {
+	struct vattr rn_va;
+	struct vnode *rn_vp;
+
+	/* only for VDIR */
+	LIST_HEAD(, rumpfs_dent) rn_dir;
+};
+
+static struct rumpfs_node *
+makeprivate(enum vtype vt)
 {
+	struct rumpfs_node *rn;
 	struct vattr *va;
 	struct timespec ts;
 
+	rn = kmem_alloc(sizeof(*va), KM_SLEEP);
+	LIST_INIT(&rn->rn_dir);
 	nanotime(&ts);
 
-	va = kmem_alloc(sizeof(*va), KM_SLEEP);
+	va = &rn->rn_va;
 	va->va_type = vt;
 	va->va_mode = 0755;
-	va->va_nlink = 2;
+	if (vt == VDIR)
+		va->va_nlink = 2;
+	else
+		va->va_nlink = 1;
 	va->va_uid = 0;
 	va->va_gid = 0;
 	va->va_fsid = 
@@ -125,13 +151,14 @@
 	va->va_filerev = 0;
 	va->va_vaflags = 0;
 
-	return va;
+	return rn;
 }
 
 static int
 rump_makevnode(const char *path, size_t size, enum vtype vt, struct vnode **vpp)
 {
 	struct vnode *vp;
+	struct rumpfs_node *rn;
 	int (**vpops)(void *);
 	int rv;
 
@@ -157,15 +184,22 @@
 			panic("rump_makevnode: lazy bum");
 		spec_node_init(vp, makedev(RUMPBLK, rv));
 	}
-	if (vt != VBLK)
-		vp->v_data = makevattr(vp->v_type);
+	if (vt != VBLK) {
+		rn = makeprivate(vp->v_type);
+		rn->rn_vp = vp;
+		vp->v_data = rn;
+	}
+
+	vn_lock(vp, LK_RETRY | LK_EXCLUSIVE);
 	*vpp = vp;
 
 	return 0;
 }
 
 /*
- * Simple lookup for faking lookup of device entry for rump file systems 
+ * 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.
  */
 static int
 rump_vop_lookup(void *v)
@@ -176,44 +210,85 @@
 		struct componentname *a_cnp;
 	}; */ *ap = v;
 	struct componentname *cnp = ap->a_cnp;
+	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;
 
 	/* we handle only some "non-special" cases */
-	KASSERT(cnp->cn_nameiop == LOOKUP);
-	KASSERT(cnp->cn_flags & FOLLOW);
+	KASSERT(((cnp->cn_flags & ISLASTCN) == 0)
+	    || (cnp->cn_nameiop == LOOKUP || cnp->cn_nameiop == CREATE));
 	KASSERT((cnp->cn_flags & ISDOTDOT) == 0);
 	KASSERT(cnp->cn_namelen != 0 && cnp->cn_pnbuf[0] != '.');
 
-	rv = rumpuser_getfileinfo(cnp->cn_pnbuf, &fsize, &ft, &error);
-	if (rv)
-		return error;
-	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;
+	/* 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, vpp);
+			if (error)
+				return error;
+			cnp->cn_consume = strlen(cnp->cn_nameptr
+			    + cnp->cn_namelen);
+			cnp->cn_flags &= ~REQUIREDIR;
+
+			return 0;
+		}
+	}
+
+	LIST_FOREACH(rd, &rn->rn_dir, rd_entries) {
+		if (strncmp(rd->rd_name, cnp->cn_nameptr,
+		    cnp->cn_namelen) == 0)
+			break;
 	}
 
-	error = rump_makevnode(cnp->cn_pnbuf, fsize, vt, ap->a_vpp);
-	if (error)
-		return error;
-
-	vn_lock(*ap->a_vpp, LK_RETRY | LK_EXCLUSIVE);
-	cnp->cn_consume = strlen(cnp->cn_nameptr + cnp->cn_namelen);
-	cnp->cn_flags &= ~REQUIREDIR;
+	if (!rd && ((cnp->cn_flags & ISLASTCN) == 0||cnp->cn_nameiop != CREATE))
+		return ENOENT;
+
+	if (!rd && (cnp->cn_flags & ISLASTCN) && cnp->cn_nameiop == CREATE) {
+		cnp->cn_flags |= SAVENAME;
+		return EJUSTRETURN;
+	}
+	KASSERT(rd);
+	KASSERT(rd->rd_node->rn_va.va_type == VDIR);
+
+ retry:
+	mutex_enter(&reclock);
+	if ((vp = rd->rd_node->rn_vp)) {
+		mutex_enter(&vp->v_interlock);
+		mutex_exit(&reclock);
+		if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK))
+			goto retry;
+		*vpp = vp;
+	} else {
+		rv = rump_makevnode(cnp->cn_nameptr, DEV_BSIZE, VDIR, vpp);
+		if (rv)
+			return rv;
+	}
 
 	return 0;
 }
@@ -226,12 +301,44 @@
 		struct vattr *a_vap;
 		kauth_cred_t a_cred;
 	} */ *ap = v;
+	struct rumpfs_node *rn = ap->a_vp->v_data;
 
-	memcpy(ap->a_vap, ap->a_vp->v_data, sizeof(struct vattr));
+	memcpy(ap->a_vap, &rn->rn_va, sizeof(struct vattr));
 	return 0;
 }
 
 static int
+rump_vop_mkdir(void *v)
+{
+	struct vop_mkdir_args /* {
+		struct vnode *a_dvp;
+		struct vnode **a_vpp;
+		struct componentname *a_cnp;
+		struct vattr *a_vap;
+	}; */ *ap = 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_dent *rdent;
+	int rv = 0;
+
+	if ((rv = rump_makevnode(cnp->cn_nameptr, DEV_BSIZE, VDIR, vpp)) != 0)
+		goto out;
+
+	rdent = kmem_alloc(sizeof(*rdent), KM_SLEEP);
+	rdent->rd_name = kmem_alloc(cnp->cn_namelen+1, KM_SLEEP);
+	rdent->rd_node = (*vpp)->v_data;
+	strlcpy(rdent->rd_name, cnp->cn_nameptr, cnp->cn_namelen+1);
+
+	LIST_INSERT_HEAD(&rnd->rn_dir, rdent, rd_entries);
+
+ out:
+	vput(dvp);
+	return rv;
+}
+
+static int
 rump_vop_success(void *v)
 {
 
@@ -239,14 +346,26 @@
 }
 
 static int
+rump_vop_inactive(void *v)
+{
+	struct vop_inactive_args *ap = v;
+
+	VOP_UNLOCK(ap->a_vp, 0);
+	return 0;
+}
+
+static int
 rump_vop_reclaim(void *v)
 {
 	struct vop_reclaim_args /* {
 		struct vnode *a_vp;
 	} */ *ap = v;
 	struct vnode *vp = ap->a_vp;
+	struct rumpfs_node *rn = vp->v_data;
 
-	kmem_free(vp->v_data, sizeof(struct vattr));
+	mutex_enter(&reclock);
+	rn->rn_vp = NULL;
+	mutex_exit(&reclock);
 	vp->v_data = NULL;
 
 	return 0;
@@ -257,6 +376,8 @@
 {
 	int rv;
 
+	mutex_init(&reclock, MUTEX_DEFAULT, IPL_NONE);
+
 	/* XXX: init properly instead of this crap */
 	rump_mnt.mnt_refcnt = 1;
 	rw_init(&rump_mnt.mnt_unmounting);
@@ -267,4 +388,5 @@
 	if (rv)
 		panic("could not create root vnode: %d", rv);
 	rootvnode->v_vflag |= VV_ROOT;
+	VOP_UNLOCK(rootvnode, 0);
 }

Reply via email to