All of lore.kernel.org
 help / color / mirror / Atom feed
From: ericvh@gmail.com
To: lguest@ozlabds.org, v9fs-developer@lists.sourceforge.net,
	linux-kernel@vger.kernel.org
Cc: Eric Van Hensbergen <ericvh@gmail.com>
Subject: [PATCH] lguest: add 9p socket gateway to launcher
Date: Fri, 19 Oct 2007 09:21:19 -0500	[thread overview]
Message-ID: <11928036793399-git-send-email-ericvh@gmail.com> (raw)

From: Eric Van Hensbergen <ericvh@gmail.com>

This adds code to setup a gateway between virtio and a 9p server on the other
side of a TCP/IP socket.  I looked into trying to come up with more of a
"plug-in" model for such lguest launcher extensions, but wasn't happy with
any of the alternatives I had initially come up with.

Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
---
 Documentation/lguest/lguest.c |  127 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 127 insertions(+), 0 deletions(-)

diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c
index ea88188..eb3707f 100644
--- a/Documentation/lguest/lguest.c
+++ b/Documentation/lguest/lguest.c
@@ -51,6 +51,7 @@ typedef uint8_t u8;
 #include "linux/virtio_net.h"
 #include "linux/virtio_blk.h"
 #include "linux/virtio_console.h"
+#include "linux/virtio_9p.h"
 #include "linux/virtio_ring.h"
 #include "asm/e820.h"
 /*:*/
@@ -1466,6 +1467,127 @@ static void setup_block_file(const char *filename)
 }
 /* That's the end of device setup. */
 
+/* 9p transport code.
+ * This code implements the host side of the 9p transport.  Right now
+ * this is heavily based on the console code and just proxies data to
+ * a socket connected to an external server.
+ */
+/* This is the routine proxies 9p channel input */
+static bool handle_9p_input(int fd, struct device *dev)
+{
+	int len;
+	unsigned int head, in_num, out_num;
+	struct iovec iov[dev->vq->vring.num];
+
+	/* First we get the console buffer from the Guest. */
+	head = get_vq_desc(dev->vq, iov, &out_num, &in_num);
+
+	/* If they're not ready for input, stop listening to this file
+	 * descriptor.  We'll start again once they add an input buffer. */
+	if (head == dev->vq->vring.num)
+		return false;
+
+	if (out_num)
+		errx(1, "Output buffers in console in queue?");
+
+	/* This is why we convert to iovecs: the readv() call uses them, and so
+	 * it reads straight into the Guest's buffer. */
+	len = readv(dev->fd, iov, in_num);
+	if (len == 0)
+		err(1, "9p: zero length read!");
+
+	if (len < 0) /* Something has gone horribly wrong */
+		errx(1, "9p: input readv returned %d", len);
+
+	/* Now, if we didn't read anything, return failure */
+	if (!len)
+		return false;
+
+	/* Tell the Guest about the new input. */
+	add_used_and_trigger(fd, dev->vq, head, len);
+
+	/* Everything went OK! */
+	return true;
+}
+
+/*  Proxy output to socket - similar to console, without the hardcoded fd */
+static void handle_9p_output(int fd, struct virtqueue *vq)
+{
+	unsigned int head, out, in;
+	int len;
+	struct iovec iov[vq->vring.num];
+
+	/* Keep getting output buffers from the Guest until we run out. */
+	while ((head = get_vq_desc(vq, iov, &out, &in)) != vq->vring.num) {
+		if (in)
+			errx(1, "Input buffers in output queue?");
+		len = writev(vq->dev->fd, iov, out); /* FIXME: ??? */
+		add_used_and_trigger(fd, vq, head, len);
+	}
+}
+
+/* Connect to 9p server (based on spfsclient by Lucho Ionkov) */
+/* We can't use gethostbyname because it makes us link a shared library */
+static int connect_9p(const char *arg)
+{
+	int fd, port;
+	char *addr, *p, *s;
+	struct sockaddr_in saddr;
+	u32 ipaddr;
+
+	if (!arg)
+		err(1, "9p: problem with args");
+
+	addr = strdup(arg);
+	ipaddr = str2ip(addr);
+
+	port = 567;
+	p = strrchr(addr, ':');
+	if (p) {
+		*p = '\0';
+		p++;
+		port = strtol(p, &s, 10);
+		if (*s != '\0')
+			err(1, "9p: invalid port format");
+	}
+
+	fd = socket(PF_INET, SOCK_STREAM, 0);
+	if (fd < 0)
+		err(1, "9p: problem allocating socket");
+
+
+	saddr.sin_family = AF_INET;
+	saddr.sin_port = htons(port);
+	saddr.sin_addr.s_addr = htonl(ipaddr);
+
+	if (connect(fd, (struct sockaddr *) &saddr, sizeof(saddr)) < 0)
+		err(1, "9p: problem connecting to server");
+
+	free(addr);
+
+	return fd;
+}
+
+/* This sets up the 9p transport */
+static void setup_9p(const char *addr)
+{
+	struct device *dev;
+	int fd = connect_9p(addr);
+
+	/* We allocate a page to store or channel info and
+	   give a unique offset for our dma key */
+	dev = new_device("9p", VIRTIO_ID_9P,
+			 fd, handle_9p_input);
+
+	/* For the moment we use two virtqueues, although we should be able
+	 * to get by with one */
+	add_virtqueue(dev, VIRTQUEUE_NUM, enable_fd);
+	add_virtqueue(dev, VIRTQUEUE_NUM, handle_9p_output);
+
+	verbose("device %u: 9p transport\n", devices.device_num++);
+}
+/* End 9p Additions */
+
 /*L:220 Finally we reach the core of the Launcher, which runs the Guest, serves
  * its input and output, and finally, lays it to rest. */
 static void __attribute__((noreturn)) run_guest(int lguest_fd)
@@ -1512,6 +1634,7 @@ static struct option opts[] = {
 	{ "tunnet", 1, NULL, 't' },
 	{ "block", 1, NULL, 'b' },
 	{ "initrd", 1, NULL, 'i' },
+	{ "9p", 1, NULL, '9'},
 	{ NULL },
 };
 static void usage(void)
@@ -1519,6 +1642,7 @@ static void usage(void)
 	errx(1, "Usage: lguest [--verbose] "
 	     "[--tunnet=(<ipaddr>|bridge:<bridgename>)\n"
 	     "|--block=<filename>|--initrd=<filename>]...\n"
+	     "[--9p=(<ipaddr>:<port>)] "
 	     "<mem-in-mb> vmlinux [args...]");
 }
 
@@ -1581,6 +1705,9 @@ int main(int argc, char *argv[])
 		case 'i':
 			initrd_name = optarg;
 			break;
+		case '9':
+			setup_9p(optarg);
+			break;
 		default:
 			warnx("Unknown argument %s", argv[optind]);
 			usage();
-- 
1.5.0.2.gfbe3d-dirty


                 reply	other threads:[~2007-10-19 14:28 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=11928036793399-git-send-email-ericvh@gmail.com \
    --to=ericvh@gmail.com \
    --cc=lguest@ozlabds.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=v9fs-developer@lists.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.