···42424343 trans=name select an alternative transport. Valid options are4444 currently:4545- unix - specifying a named pipe mount point4646- tcp - specifying a normal TCP/IP connection4747- fd - used passed file descriptors for connection4545+ unix - specifying a named pipe mount point4646+ tcp - specifying a normal TCP/IP connection4747+ fd - used passed file descriptors for connection4848 (see rfdno and wfdno)4949+ virtio - connect to the next virtio channel available5050+ (from lguest or KVM with trans_virtio module)49515052 uname=name user name to attempt mount as on the remote server. The5153 server may override or ignore this value. Certain user
+10
include/linux/virtio_9p.h
···11+#ifndef _LINUX_VIRTIO_9P_H22+#define _LINUX_VIRTIO_9P_H33+#include <linux/virtio_config.h>44+55+/* The ID for virtio console */66+#define VIRTIO_ID_9P 977+/* Maximum number of virtio channels per partition (1 for now) */88+#define MAX_9P_CHAN 199+1010+#endif /* _LINUX_VIRTIO_9P_H */
+7
net/9p/Kconfig
···2323 file descriptors. TCP/IP is the default transport for 9p,2424 so if you are going to use 9p, you'll likely want this.25252626+config NET_9P_VIRTIO2727+ depends on NET_9P && EXPERIMENTAL && VIRTIO2828+ tristate "9P Virtio Transport (Experimental)"2929+ help3030+ This builds support for a transports between3131+ guest partitions and a host partition.3232+2633config NET_9P_DEBUG2734 bool "Debug information"2835 depends on NET_9P
···11+/*22+ * The Guest 9p transport driver33+ *44+ * This is a trivial pipe-based transport driver based on the lguest console55+ * code: we use lguest's DMA mechanism to send bytes out, and register a66+ * DMA buffer to receive bytes in. It is assumed to be present and available77+ * from the very beginning of boot.88+ *99+ * This may be have been done by just instaniating another HVC console,1010+ * but HVC's blocksize of 16 bytes is annoying and painful to performance.1111+ *1212+ * A more efficient transport could be built based on the virtio block driver1313+ * but it requires some changes in the 9p transport model (which are in1414+ * progress)1515+ *1616+ */1717+/*1818+ * Copyright (C) 2007 Eric Van Hensbergen, IBM Corporation1919+ *2020+ * Based on virtio console driver2121+ * Copyright (C) 2006, 2007 Rusty Russell, IBM Corporation2222+ *2323+ * This program is free software; you can redistribute it and/or modify2424+ * it under the terms of the GNU General Public License version 22525+ * as published by the Free Software Foundation.2626+ *2727+ * This program is distributed in the hope that it will be useful,2828+ * but WITHOUT ANY WARRANTY; without even the implied warranty of2929+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the3030+ * GNU General Public License for more details.3131+ *3232+ * You should have received a copy of the GNU General Public License3333+ * along with this program; if not, write to:3434+ * Free Software Foundation3535+ * 51 Franklin Street, Fifth Floor3636+ * Boston, MA 02111-1301 USA3737+ *3838+ */3939+4040+#include <linux/in.h>4141+#include <linux/module.h>4242+#include <linux/net.h>4343+#include <linux/ipv6.h>4444+#include <linux/errno.h>4545+#include <linux/kernel.h>4646+#include <linux/un.h>4747+#include <linux/uaccess.h>4848+#include <linux/inet.h>4949+#include <linux/idr.h>5050+#include <linux/file.h>5151+#include <net/9p/9p.h>5252+#include <linux/parser.h>5353+#include <net/9p/transport.h>5454+#include <linux/scatterlist.h>5555+#include <linux/virtio.h>5656+#include <linux/virtio_9p.h>5757+5858+/* a single mutex to manage channel initialization and attachment */5959+static DECLARE_MUTEX(virtio_9p_lock);6060+/* global which tracks highest initialized channel */6161+static int chan_index;6262+6363+/* We keep all per-channel information in a structure.6464+ * This structure is allocated within the devices dev->mem space.6565+ * A pointer to the structure will get put in the transport private.6666+ */6767+static struct virtio_chan {6868+ bool initialized; /* channel is initialized */6969+ bool inuse; /* channel is in use */7070+7171+ struct virtqueue *in_vq, *out_vq;7272+ struct virtio_device *vdev;7373+7474+ /* This is our input buffer, and how much data is left in it. */7575+ unsigned int in_len;7676+ char *in, *inbuf;7777+7878+ wait_queue_head_t wq; /* waitq for buffer */7979+} channels[MAX_9P_CHAN];8080+8181+/* How many bytes left in this page. */8282+static unsigned int rest_of_page(void *data)8383+{8484+ return PAGE_SIZE - ((unsigned long)data % PAGE_SIZE);8585+}8686+8787+static int p9_virtio_write(struct p9_trans *trans, void *buf, int count)8888+{8989+ struct virtio_chan *chan = (struct virtio_chan *) trans->priv;9090+ struct virtqueue *out_vq = chan->out_vq;9191+ struct scatterlist sg[1];9292+ unsigned int len;9393+9494+ P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio write (%d)\n", count);9595+9696+ /* keep it simple - make sure we don't overflow a page */9797+ if (rest_of_page(buf) < count)9898+ count = rest_of_page(buf);9999+100100+ sg_init_one(sg, buf, count);101101+102102+ /* add_buf wants a token to identify this buffer: we hand it any103103+ * non-NULL pointer, since there's only ever one buffer. */104104+ if (out_vq->vq_ops->add_buf(out_vq, sg, 1, 0, (void *)1) == 0) {105105+ /* Tell Host to go! */106106+ out_vq->vq_ops->kick(out_vq);107107+ /* Chill out until it's done with the buffer. */108108+ while (!out_vq->vq_ops->get_buf(out_vq, &len))109109+ cpu_relax();110110+ }111111+112112+ P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio wrote (%d)\n", count);113113+114114+ /* We're expected to return the amount of data we wrote: all of it. */115115+ return count;116116+}117117+118118+/* Create a scatter-gather list representing our input buffer and put it in the119119+ * queue. */120120+static void add_inbuf(struct virtio_chan *chan)121121+{122122+ struct scatterlist sg[1];123123+124124+ sg_init_one(sg, chan->inbuf, PAGE_SIZE);125125+126126+ /* We should always be able to add one buffer to an empty queue. */127127+ if (chan->in_vq->vq_ops->add_buf(chan->in_vq, sg, 0, 1, chan->inbuf))128128+ BUG();129129+ chan->in_vq->vq_ops->kick(chan->in_vq);130130+}131131+132132+static int p9_virtio_read(struct p9_trans *trans, void *buf, int count)133133+{134134+ struct virtio_chan *chan = (struct virtio_chan *) trans->priv;135135+ struct virtqueue *in_vq = chan->in_vq;136136+137137+ P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio read (%d)\n", count);138138+139139+ /* If we don't have an input queue yet, we can't get input. */140140+ BUG_ON(!in_vq);141141+142142+ /* No buffer? Try to get one. */143143+ if (!chan->in_len) {144144+ chan->in = in_vq->vq_ops->get_buf(in_vq, &chan->in_len);145145+ if (!chan->in)146146+ return 0;147147+ }148148+149149+ /* You want more than we have to give? Well, try wanting less! */150150+ if (chan->in_len < count)151151+ count = chan->in_len;152152+153153+ /* Copy across to their buffer and increment offset. */154154+ memcpy(buf, chan->in, count);155155+ chan->in += count;156156+ chan->in_len -= count;157157+158158+ /* Finished? Re-register buffer so Host will use it again. */159159+ if (chan->in_len == 0)160160+ add_inbuf(chan);161161+162162+ P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio finished read (%d)\n",163163+ count);164164+165165+ return count;166166+}167167+168168+/* The poll function is used by 9p transports to determine if there169169+ * is there is activity available on a particular channel. In our case170170+ * we use it to wait for a callback from the input routines.171171+ */172172+static unsigned int173173+p9_virtio_poll(struct p9_trans *trans, struct poll_table_struct *pt)174174+{175175+ struct virtio_chan *chan = (struct virtio_chan *)trans->priv;176176+ struct virtqueue *in_vq = chan->in_vq;177177+ int ret = POLLOUT; /* we can always handle more output */178178+179179+ poll_wait(NULL, &chan->wq, pt);180180+181181+ /* No buffer? Try to get one. */182182+ if (!chan->in_len)183183+ chan->in = in_vq->vq_ops->get_buf(in_vq, &chan->in_len);184184+185185+ if (chan->in_len)186186+ ret |= POLLIN;187187+188188+ return ret;189189+}190190+191191+static void p9_virtio_close(struct p9_trans *trans)192192+{193193+ struct virtio_chan *chan = trans->priv;194194+195195+ down(&virtio_9p_lock);196196+ chan->inuse = false;197197+ up(&virtio_9p_lock);198198+199199+ kfree(trans);200200+}201201+202202+static bool p9_virtio_intr(struct virtqueue *q)203203+{204204+ struct virtio_chan *chan = q->vdev->priv;205205+206206+ P9_DPRINTK(P9_DEBUG_TRANS, "9p poll_wakeup: %p\n", &chan->wq);207207+ wake_up_interruptible(&chan->wq);208208+209209+ return true;210210+}211211+212212+static int p9_virtio_probe(struct virtio_device *dev)213213+{214214+ int err;215215+ struct virtio_chan *chan;216216+ int index;217217+218218+ down(&virtio_9p_lock);219219+ index = chan_index++;220220+ chan = &channels[index];221221+ up(&virtio_9p_lock);222222+223223+ if (chan_index > MAX_9P_CHAN) {224224+ printk(KERN_ERR "9p: virtio: Maximum channels exceeded\n");225225+ BUG();226226+ }227227+228228+ chan->vdev = dev;229229+230230+ /* This is the scratch page we use to receive console input */231231+ chan->inbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);232232+ if (!chan->inbuf) {233233+ err = -ENOMEM;234234+ goto fail;235235+ }236236+237237+ /* Find the input queue. */238238+ dev->priv = chan;239239+ chan->in_vq = dev->config->find_vq(dev, p9_virtio_intr);240240+ if (IS_ERR(chan->in_vq)) {241241+ err = PTR_ERR(chan->in_vq);242242+ goto free;243243+ }244244+245245+ chan->out_vq = dev->config->find_vq(dev, NULL);246246+ if (IS_ERR(chan->out_vq)) {247247+ err = PTR_ERR(chan->out_vq);248248+ goto free_in_vq;249249+ }250250+251251+ init_waitqueue_head(&chan->wq);252252+253253+ /* Register the input buffer the first time. */254254+ add_inbuf(chan);255255+ chan->inuse = false;256256+ chan->initialized = true;257257+258258+ return 0;259259+260260+free_in_vq:261261+ dev->config->del_vq(chan->in_vq);262262+free:263263+ kfree(chan->inbuf);264264+fail:265265+ down(&virtio_9p_lock);266266+ chan_index--;267267+ up(&virtio_9p_lock);268268+ return err;269269+}270270+271271+/* This sets up a transport channel for 9p communication. Right now272272+ * we only match the first available channel, but eventually we couldlook up273273+ * alternate channels by matching devname versus a virtio_config entry.274274+ * We use a simple reference count mechanism to ensure that only a single275275+ * mount has a channel open at a time. */276276+static struct p9_trans *p9_virtio_create(const char *devname, char *args)277277+{278278+ struct p9_trans *trans;279279+ int index = 0;280280+ struct virtio_chan *chan = channels;281281+282282+ down(&virtio_9p_lock);283283+ while (index < MAX_9P_CHAN) {284284+ if (chan->initialized && !chan->inuse) {285285+ chan->inuse = true;286286+ break;287287+ } else {288288+ index++;289289+ chan = &channels[index];290290+ }291291+ }292292+ up(&virtio_9p_lock);293293+294294+ if (index >= MAX_9P_CHAN) {295295+ printk(KERN_ERR "9p: virtio: couldn't find a free channel\n");296296+ return NULL;297297+ }298298+299299+ trans = kmalloc(sizeof(struct p9_trans), GFP_KERNEL);300300+ if (!trans) {301301+ printk(KERN_ERR "9p: couldn't allocate transport\n");302302+ return ERR_PTR(-ENOMEM);303303+ }304304+305305+ trans->write = p9_virtio_write;306306+ trans->read = p9_virtio_read;307307+ trans->close = p9_virtio_close;308308+ trans->poll = p9_virtio_poll;309309+ trans->priv = chan;310310+311311+ return trans;312312+}313313+314314+#define VIRTIO_ID_9P 9315315+316316+static struct virtio_device_id id_table[] = {317317+ { VIRTIO_ID_9P, VIRTIO_DEV_ANY_ID },318318+ { 0 },319319+};320320+321321+/* The standard "struct lguest_driver": */322322+static struct virtio_driver p9_virtio_drv = {323323+ .driver.name = KBUILD_MODNAME,324324+ .driver.owner = THIS_MODULE,325325+ .id_table = id_table,326326+ .probe = p9_virtio_probe,327327+};328328+329329+static struct p9_trans_module p9_virtio_trans = {330330+ .name = "virtio",331331+ .create = p9_virtio_create,332332+ .maxsize = PAGE_SIZE,333333+ .def = 0,334334+};335335+336336+/* The standard init function */337337+static int __init p9_virtio_init(void)338338+{339339+ int count;340340+341341+ for (count = 0; count < MAX_9P_CHAN; count++)342342+ channels[count].initialized = false;343343+344344+ v9fs_register_trans(&p9_virtio_trans);345345+ return register_virtio_driver(&p9_virtio_drv);346346+}347347+348348+module_init(p9_virtio_init);349349+350350+MODULE_DEVICE_TABLE(virtio, id_table);351351+MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>");352352+MODULE_DESCRIPTION("Virtio 9p Transport");353353+MODULE_LICENSE("GPL");