Module Name:    src
Committed By:   pooka
Date:           Sun Oct  4 16:31:08 UTC 2009

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

Log Message:
Implement RUMP_ETFS_REG.  Usable e.g. by firmload(9).
(well, it should probably be RUMP_ETFS_PATH, but simple things first)


To generate a diff of this commit:
cvs rdiff -u -r1.23 -r1.24 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.23 src/sys/rump/librump/rumpvfs/rumpfs.c:1.24
--- src/sys/rump/librump/rumpvfs/rumpfs.c:1.23	Sat Sep  5 11:02:49 2009
+++ src/sys/rump/librump/rumpvfs/rumpfs.c	Sun Oct  4 16:31:08 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: rumpfs.c,v 1.23 2009/09/05 11:02:49 pooka Exp $	*/
+/*	$NetBSD: rumpfs.c,v 1.24 2009/10/04 16:31:08 pooka Exp $	*/
 
 /*
  * Copyright (c) 2007 Antti Kantee.  All Rights Reserved.
@@ -28,21 +28,23 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rumpfs.c,v 1.23 2009/09/05 11:02:49 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rumpfs.c,v 1.24 2009/10/04 16:31:08 pooka Exp $");
 
 #include <sys/param.h>
-#include <sys/mount.h>
-#include <sys/vnode.h>
+#include <sys/atomic.h>
+#include <sys/filedesc.h>
 #include <sys/errno.h>
+#include <sys/fcntl.h>
 #include <sys/kauth.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
+#include <sys/namei.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/stat.h>
 #include <sys/syscallargs.h>
-#include <sys/atomic.h>
+#include <sys/vnode.h>
 
 #include <miscfs/fifofs/fifo.h>
 #include <miscfs/specfs/specdev.h>
@@ -61,6 +63,9 @@
 static int rump_vop_reclaim(void *);
 static int rump_vop_success(void *);
 static int rump_vop_spec(void *);
+static int rump_vop_read(void *);
+static int rump_vop_write(void *);
+static int rump_vop_open(void *);
 
 int (**fifo_vnodeop_p)(void *);
 const struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
@@ -78,6 +83,9 @@
 	{ &vop_mkdir_desc, rump_vop_mkdir },
 	{ &vop_mknod_desc, rump_vop_mknod },
 	{ &vop_access_desc, rump_vop_success },
+	{ &vop_read_desc, rump_vop_read },
+	{ &vop_write_desc, rump_vop_write },
+	{ &vop_open_desc, rump_vop_open },
 	{ &vop_putpages_desc, genfs_null_putpages },
 	{ &vop_fsync_desc, rump_vop_success },
 	{ &vop_lock_desc, genfs_lock },
@@ -114,11 +122,21 @@
 	struct vattr rn_va;
 	struct vnode *rn_vp;
 
-	/* only for VDIR */
-	LIST_HEAD(, rumpfs_dent) rn_dir;
+	union {
+		struct {
+			char *hostpath;		/* VREG */
+			int readfd;
+			int writefd;
+		} reg;
+		LIST_HEAD(, rumpfs_dent) dir;	/* VDIR */
+	} rn_u;
 };
+#define rn_hostpath	rn_u.reg.hostpath
+#define rn_readfd	rn_u.reg.readfd
+#define rn_writefd	rn_u.reg.writefd
+#define rn_dir		rn_u.dir
 
-static struct rumpfs_node *makeprivate(enum vtype, dev_t, off_t);
+static struct rumpfs_node *makeprivate(enum vtype, dev_t, off_t, const char *);
 
 /*
  * Extra Terrestrial stuff.  We map a given key (pathname) to a file on
@@ -130,6 +148,8 @@
 
 struct etfs {
 	char et_key[MAXPATHLEN];
+	size_t et_keylen;
+
 	LIST_ENTRY(etfs) et_entries;
 
 	struct rumpfs_node *et_rn;
@@ -163,12 +183,13 @@
 etfs_find(const char *key, struct rumpfs_node **rnp)
 {
 	struct etfs *et;
+	size_t keylen = strlen(key);
 	bool rv = false;
 
 	KASSERT(mutex_owned(&etfs_lock));
 
 	LIST_FOREACH(et, &etfs_list, et_entries) {
-		if (strcmp(key, et->et_key) == 0) {
+		if (keylen == et->et_keylen && strcmp(key, et->et_key) == 0) {
 			*rnp = et->et_rn;
 			rv = true;
 			break;
@@ -185,26 +206,25 @@
 	struct etfs *et;
 	struct rumpfs_node *rn_dummy;
 	uint64_t fsize;
-	dev_t rdev;
+	dev_t rdev = NODEV;
 	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;
+	if (ftype == RUMP_ETFS_BLK || ftype == RUMP_ETFS_CHR) {
+		error = rumpblk_register(hostpath, &dmin);
+		if (error != 0) {
+			return error;
+		}
+		rdev = makedev(RUMPBLK, dmin);
 	}
-	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);
+	et->et_keylen = strlen(et->et_key);
+	et->et_rn = makeprivate(ettype_to_vtype(ftype), rdev, fsize, hostpath);
 
 	mutex_enter(&etfs_lock);
 	if (etfs_find(key, &rn_dummy)) {
@@ -223,10 +243,11 @@
 rump_etfs_remove(const char *key)
 {
 	struct etfs *et;
+	size_t keylen = strlen(key);
 
 	mutex_enter(&etfs_lock);
 	LIST_FOREACH(et, &etfs_list, et_entries) {
-		if (strcmp(et->et_key, key) == 0) {
+		if (keylen == et->et_keylen && strcmp(et->et_key, key) == 0) {
 			LIST_REMOVE(et, et_entries);
 			kmem_free(et, sizeof(*et));
 			break;
@@ -248,14 +269,28 @@
 static kmutex_t reclock;
 
 static struct rumpfs_node *
-makeprivate(enum vtype vt, dev_t rdev, off_t size)
+makeprivate(enum vtype vt, dev_t rdev, off_t size, const char *hostpath)
 {
 	struct rumpfs_node *rn;
 	struct vattr *va;
 	struct timespec ts;
 
 	rn = kmem_zalloc(sizeof(*rn), KM_SLEEP);
-	LIST_INIT(&rn->rn_dir);
+
+	switch (vt) {
+	case VDIR:
+		LIST_INIT(&rn->rn_dir);
+		break;
+	case VREG:
+		rn->rn_readfd = -1;
+		rn->rn_writefd = -1;
+		rn->rn_hostpath = malloc(strlen(hostpath)+1, M_TEMP, M_WAITOK);
+		strcpy(rn->rn_hostpath, hostpath);
+		break;
+	default:
+		break;
+	}
+
 	nanotime(&ts);
 
 	va = &rn->rn_va;
@@ -300,7 +335,8 @@
 	} else {
 		vpops = rump_vnodeop_p;
 	}
-	if (vpops != rump_specop_p && va->va_type != VDIR)
+	if (vpops != rump_specop_p && va->va_type != VDIR
+	    && !(va->va_type == VREG && rn->rn_hostpath != NULL))
 		return EOPNOTSUPP;
 
 	rv = getnewvnode(VT_RUMP, &rump_mnt, vpops, &vp);
@@ -435,7 +471,7 @@
 	struct rumpfs_dent *rdent;
 	int rv = 0;
 
-	rn = makeprivate(VDIR, NODEV, DEV_BSIZE);
+	rn = makeprivate(VDIR, NODEV, DEV_BSIZE, NULL);
 	mutex_enter(&reclock);
 	rv = makevnode(rn, vpp);
 	mutex_exit(&reclock);
@@ -471,7 +507,7 @@
 	struct rumpfs_dent *rdent;
 	int rv;
 
-	rn = makeprivate(va->va_type, va->va_rdev, DEV_BSIZE);
+	rn = makeprivate(va->va_type, va->va_rdev, DEV_BSIZE, NULL);
 	mutex_enter(&reclock);
 	rv = makevnode(rn, vpp);
 	mutex_exit(&reclock);
@@ -492,6 +528,93 @@
 }
 
 static int
+rump_vop_open(void *v)
+{
+	struct vop_open_args /* {
+		struct vnode *a_vp;
+		int a_mode;
+		kauth_cred_t a_cred;
+	} */ *ap = v;
+	struct vnode *vp = ap->a_vp;
+	struct rumpfs_node *rn = vp->v_data;
+	int mode = ap->a_mode;
+	int error = EINVAL;
+
+	if (vp->v_type != VREG)
+		return 0;
+
+	if (mode & FREAD) {
+		if (rn->rn_readfd != -1)
+			return 0;
+		rn->rn_readfd = rumpuser_open(rn->rn_hostpath,
+		    O_RDONLY, &error);
+	} else if (mode & FWRITE) {
+		if (rn->rn_writefd != -1)
+			return 0;
+		rn->rn_writefd = rumpuser_open(rn->rn_hostpath,
+		    O_WRONLY, &error);
+	}
+
+	return error;
+}
+
+static int
+rump_vop_read(void *v)
+{
+	struct vop_read_args /* {
+		struct vnode *a_vp;
+		struct uio *a_uio;
+		int ioflags a_ioflag;
+		kauth_cred_t a_cred;
+	}; */ *ap = v;
+	struct vnode *vp = ap->a_vp;
+	struct rumpfs_node *rn = vp->v_data;
+	struct uio *uio = ap->a_uio;
+	uint8_t *buf;
+	size_t bufsize;
+	int error = 0;
+
+	bufsize = uio->uio_resid;
+	buf = kmem_alloc(bufsize, KM_SLEEP);
+	if (rumpuser_read(rn->rn_readfd, buf, bufsize, &error) == -1)
+		goto out;
+	error = uiomove(buf, bufsize, uio);
+
+ out:
+	kmem_free(buf, bufsize);
+	return error;
+}
+
+static int
+rump_vop_write(void *v)
+{
+	struct vop_read_args /* {
+		struct vnode *a_vp;
+		struct uio *a_uio;
+		int ioflags a_ioflag;
+		kauth_cred_t a_cred;
+	}; */ *ap = v;
+	struct vnode *vp = ap->a_vp;
+	struct rumpfs_node *rn = vp->v_data;
+	struct uio *uio = ap->a_uio;
+	uint8_t *buf;
+	size_t bufsize;
+	int error = 0;
+
+	bufsize = uio->uio_resid;
+	buf = kmem_alloc(bufsize, KM_SLEEP);
+	error = uiomove(buf, bufsize, uio);
+	if (error)
+		goto out;
+	KASSERT(uio->uio_resid == 0);
+	rumpuser_write(rn->rn_writefd, buf, bufsize, &error);
+
+ out:
+	kmem_free(buf, bufsize);
+	return error;
+}
+
+static int
 rump_vop_success(void *v)
 {
 
@@ -502,8 +625,22 @@
 rump_vop_inactive(void *v)
 {
 	struct vop_inactive_args *ap = v;
+	struct vnode *vp = ap->a_vp;
+	struct rumpfs_node *rn = vp->v_data;
+	int error;
 
-	VOP_UNLOCK(ap->a_vp, 0);
+	if (vp->v_type == VREG) {
+		if (rn->rn_readfd != -1) {
+			rumpuser_close(rn->rn_readfd, &error);
+			rn->rn_readfd = -1;
+		}
+		if (rn->rn_writefd != -1) {
+			rumpuser_close(rn->rn_writefd, &error);
+			rn->rn_writefd = -1;
+		}
+	}
+		
+	VOP_UNLOCK(vp, 0);
 	return 0;
 }
 
@@ -561,7 +698,7 @@
 	TAILQ_INIT(&rump_mnt.mnt_vnodelist);
 
 	vfs_opv_init(rump_opv_descs);
-	rn = makeprivate(VDIR, NODEV, DEV_BSIZE);
+	rn = makeprivate(VDIR, NODEV, DEV_BSIZE, NULL);
 	mutex_enter(&reclock);
 	rv = makevnode(rn, &rootvnode);
 	mutex_exit(&reclock);

Reply via email to