trans_virtio.c revision 68da9ba4eeadae86ad42e52b80822fbd56971267
1b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen/* 2fea511a644fb0fb938309c6ab286725ac31b87e2Eric Van Hensbergen * The Virtio 9p transport driver 3b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * 4e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen * This is a block based transport driver based on the lguest block driver 5e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen * code. 6b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * 7fea511a644fb0fb938309c6ab286725ac31b87e2Eric Van Hensbergen * Copyright (C) 2007, 2008 Eric Van Hensbergen, IBM Corporation 8b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * 9b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * Based on virtio console driver 10b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * Copyright (C) 2006, 2007 Rusty Russell, IBM Corporation 11b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * 12b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * This program is free software; you can redistribute it and/or modify 13b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * it under the terms of the GNU General Public License version 2 14b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * as published by the Free Software Foundation. 15b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * 16b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * This program is distributed in the hope that it will be useful, 17b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * but WITHOUT ANY WARRANTY; without even the implied warranty of 18b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * GNU General Public License for more details. 20b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * 21b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * You should have received a copy of the GNU General Public License 22b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * along with this program; if not, write to: 23b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * Free Software Foundation 24b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * 51 Franklin Street, Fifth Floor 25b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * Boston, MA 02111-1301 USA 26b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * 27b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen */ 28b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 29b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/in.h> 30b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/module.h> 31b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/net.h> 32b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/ipv6.h> 33b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/errno.h> 34b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/kernel.h> 35b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/un.h> 36b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/uaccess.h> 37b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/inet.h> 38b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/idr.h> 39b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/file.h> 405a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 41b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <net/9p/9p.h> 42b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/parser.h> 438b81ef589ad1483dd977ef47fe00d4ce4d91a0abEric Van Hensbergen#include <net/9p/client.h> 44b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <net/9p/transport.h> 45b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/scatterlist.h> 4668da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV)#include <linux/swap.h> 47b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/virtio.h> 48b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/virtio_9p.h> 494038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)#include "trans_common.h" 50b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 51e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen#define VIRTQUEUE_NUM 128 52e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen 53b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen/* a single mutex to manage channel initialization and attachment */ 54c1549497e903a1ffa1c5808337a987180e480e7aJosef 'Jeff' Sipekstatic DEFINE_MUTEX(virtio_9p_lock); 5568da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV)static DECLARE_WAIT_QUEUE_HEAD(vp_wq); 5668da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV)static atomic_t vp_pinned = ATOMIC_INIT(0); 57b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 58ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen/** 59ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * struct virtio_chan - per-instance transport information 60ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @initialized: whether the channel is initialized 61ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @inuse: whether the channel is in use 62ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @lock: protects multiple elements within this structure 630e15597ebfe00e28857185f46aba00f400480ffeAbhishek Kulkarni * @client: client instance 64ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @vdev: virtio dev associated with this channel 65ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @vq: virtio queue associated with this channel 66ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @sg: scatter gather list which is used to pack a request (protected?) 67ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * 68ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * We keep all per-channel information in a structure. 69b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * This structure is allocated within the devices dev->mem space. 70b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * A pointer to the structure will get put in the transport private. 71ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * 72b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen */ 73ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen 7437c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.Vstruct virtio_chan { 75ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen bool inuse; 76b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 77e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen spinlock_t lock; 78e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen 79fea511a644fb0fb938309c6ab286725ac31b87e2Eric Van Hensbergen struct p9_client *client; 80b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen struct virtio_device *vdev; 81e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen struct virtqueue *vq; 8252f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) int ring_bufs_avail; 8352f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) wait_queue_head_t *vc_wq; 8468da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV) /* This is global limit. Since we don't have a global structure, 8568da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV) * will be placing it in each channel. 8668da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV) */ 8768da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV) int p9_max_pages; 88e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen /* Scatterlist: can be too big for stack. */ 89e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen struct scatterlist sg[VIRTQUEUE_NUM]; 9037c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V 9197ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V int tag_len; 9297ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V /* 9397ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V * tag name to identify a mount Non-null terminated 9497ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V */ 9597ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V char *tag; 9697ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V 9737c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V struct list_head chan_list; 9837c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V}; 9937c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V 10037c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.Vstatic struct list_head virtio_chan_list; 101b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 102b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen/* How many bytes left in this page. */ 103b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergenstatic unsigned int rest_of_page(void *data) 104b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen{ 105b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen return PAGE_SIZE - ((unsigned long)data % PAGE_SIZE); 106b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen} 107b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 108ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen/** 109ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * p9_virtio_close - reclaim resources of a channel 1100e15597ebfe00e28857185f46aba00f400480ffeAbhishek Kulkarni * @client: client instance 111ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * 112ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * This reclaims a channel by freeing its resources and 113ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * reseting its inuse flag. 114ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * 115ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen */ 116ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen 1178b81ef589ad1483dd977ef47fe00d4ce4d91a0abEric Van Hensbergenstatic void p9_virtio_close(struct p9_client *client) 118e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen{ 1198b81ef589ad1483dd977ef47fe00d4ce4d91a0abEric Van Hensbergen struct virtio_chan *chan = client->trans; 120b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 121c1549497e903a1ffa1c5808337a987180e480e7aJosef 'Jeff' Sipek mutex_lock(&virtio_9p_lock); 122fb786100f7c75e154e63d0f5a2982e6d46dfb602Aneesh Kumar K.V if (chan) 123fb786100f7c75e154e63d0f5a2982e6d46dfb602Aneesh Kumar K.V chan->inuse = false; 124c1549497e903a1ffa1c5808337a987180e480e7aJosef 'Jeff' Sipek mutex_unlock(&virtio_9p_lock); 125b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen} 126b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 127ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen/** 128ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * req_done - callback which signals activity from the server 129ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @vq: virtio queue activity was received on 130ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * 131ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * This notifies us that the server has triggered some activity 132ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * on the virtio channel - most likely a response to request we 133ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * sent. Figure out which requests now have responses and wake up 134ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * those threads. 135ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * 136ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * Bugs: could do with some additional sanity checking, but appears to work. 137ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * 138ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen */ 139ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen 140e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergenstatic void req_done(struct virtqueue *vq) 141b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen{ 142e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen struct virtio_chan *chan = vq->vdev->priv; 143e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen struct p9_fcall *rc; 144e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen unsigned int len; 145e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen struct p9_req_t *req; 146419b39561e698d73a42f8010655d22e0134486daVenkateswararao Jujjuri (JV) unsigned long flags; 147e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen 14891b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen P9_DPRINTK(P9_DEBUG_TRANS, ": request done\n"); 14991b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen 150a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV) while (1) { 151419b39561e698d73a42f8010655d22e0134486daVenkateswararao Jujjuri (JV) spin_lock_irqsave(&chan->lock, flags); 152419b39561e698d73a42f8010655d22e0134486daVenkateswararao Jujjuri (JV) rc = virtqueue_get_buf(chan->vq, &len); 153419b39561e698d73a42f8010655d22e0134486daVenkateswararao Jujjuri (JV) 154a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV) if (rc == NULL) { 15552f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) spin_unlock_irqrestore(&chan->lock, flags); 156a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV) break; 157a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV) } 158a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV) 159a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV) chan->ring_bufs_avail = 1; 160a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV) spin_unlock_irqrestore(&chan->lock, flags); 161a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV) /* Wakeup if anyone waiting for VirtIO ring space. */ 162a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV) wake_up(chan->vc_wq); 163a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV) P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc); 164a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV) P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag); 165a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV) req = p9_tag_lookup(chan->client, rc->tag); 166a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV) if (req->tc->private) { 167a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV) struct trans_rpage_info *rp = req->tc->private; 16868da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV) int p = rp->rp_nr_pages; 169a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV) /*Release pages */ 170a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV) p9_release_req_pages(rp); 17168da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV) atomic_sub(p, &vp_pinned); 17268da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV) wake_up(&vp_wq); 173a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV) if (rp->rp_alloc) 174a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV) kfree(rp); 175a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV) req->tc->private = NULL; 176419b39561e698d73a42f8010655d22e0134486daVenkateswararao Jujjuri (JV) } 177a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV) req->status = REQ_STATUS_RCVD; 178a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV) p9_client_cb(chan->client, req); 179a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV) } 180e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen} 181b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 182ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen/** 183ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * pack_sg_list - pack a scatter gather list from a linear buffer 184ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @sg: scatter/gather list to pack into 185ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @start: which segment of the sg_list to start at 186ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @limit: maximum segment to pack data to 187ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @data: data to pack into scatter/gather list 188ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @count: amount of data to pack into the scatter/gather list 189ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * 190ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * sg_lists have multiple segments of various sizes. This will pack 191ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * arbitrary data into an existing scatter gather list, segmenting the 192ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * data as necessary within constraints. 193ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * 194ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen */ 195ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen 196e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergenstatic int 197e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergenpack_sg_list(struct scatterlist *sg, int start, int limit, char *data, 198e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen int count) 199e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen{ 200e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen int s; 201e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen int index = start; 202e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen 203e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen while (count) { 204e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen s = rest_of_page(data); 205e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen if (s > count) 206e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen s = count; 207e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen sg_set_buf(&sg[index++], data, s); 208e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen count -= s; 209e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen data += s; 210d6584f3a08055688b2344eb26379fb2f3147ce91Julia Lawall BUG_ON(index > limit); 211e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen } 212b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 213e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen return index-start; 214b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen} 215b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 21691b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen/* We don't currently allow canceling of virtio requests */ 21791b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergenstatic int p9_virtio_cancel(struct p9_client *client, struct p9_req_t *req) 21891b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen{ 21991b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen return 1; 22091b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen} 22191b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen 222ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen/** 2234038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) * pack_sg_list_p - Just like pack_sg_list. Instead of taking a buffer, 2244038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) * this takes a list of pages. 2254038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) * @sg: scatter/gather list to pack into 2264038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) * @start: which segment of the sg_list to start at 2274038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) * @pdata_off: Offset into the first page 2284038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) * @**pdata: a list of pages to add into sg. 2294038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) * @count: amount of data to pack into the scatter/gather list 2304038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) */ 2314038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)static int 2324038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)pack_sg_list_p(struct scatterlist *sg, int start, int limit, size_t pdata_off, 2334038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) struct page **pdata, int count) 2344038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV){ 2354038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) int s; 2364038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) int i = 0; 2374038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) int index = start; 2384038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) 2394038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) if (pdata_off) { 2404038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) s = min((int)(PAGE_SIZE - pdata_off), count); 2414038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) sg_set_page(&sg[index++], pdata[i++], s, pdata_off); 2424038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) count -= s; 2434038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) } 2444038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) 2454038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) while (count) { 2464038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) BUG_ON(index > limit); 2474038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) s = min((int)PAGE_SIZE, count); 2484038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) sg_set_page(&sg[index++], pdata[i++], s, 0); 2494038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) count -= s; 2504038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) } 2514038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) return index-start; 2524038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)} 2534038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) 2544038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)/** 25591b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen * p9_virtio_request - issue a request 2560e15597ebfe00e28857185f46aba00f400480ffeAbhishek Kulkarni * @client: client instance issuing the request 2570e15597ebfe00e28857185f46aba00f400480ffeAbhishek Kulkarni * @req: request to be issued 258ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * 259ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen */ 260ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen 261e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergenstatic int 26291b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergenp9_virtio_request(struct p9_client *client, struct p9_req_t *req) 263b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen{ 2644038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) int in, out, inp, outp; 26591b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen struct virtio_chan *chan = client->trans; 26691b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen char *rdata = (char *)req->rc+sizeof(struct p9_fcall); 267419b39561e698d73a42f8010655d22e0134486daVenkateswararao Jujjuri (JV) unsigned long flags; 2684038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) size_t pdata_off = 0; 2694038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) struct trans_rpage_info *rpinfo = NULL; 2704038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) int err, pdata_len = 0; 271b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 27291b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request\n"); 273b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 274419b39561e698d73a42f8010655d22e0134486daVenkateswararao Jujjuri (JV) req->status = REQ_STATUS_SENT; 275419b39561e698d73a42f8010655d22e0134486daVenkateswararao Jujjuri (JV) 2764038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) if (req->tc->pbuf_size && (req->tc->pubuf && P9_IS_USER_CONTEXT)) { 2774038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) int nr_pages = p9_nr_pages(req); 2784038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) int rpinfo_size = sizeof(struct trans_rpage_info) + 2794038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) sizeof(struct page *) * nr_pages; 2804038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) 28168da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV) if (atomic_read(&vp_pinned) >= chan->p9_max_pages) { 28268da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV) err = wait_event_interruptible(vp_wq, 28368da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV) atomic_read(&vp_pinned) < chan->p9_max_pages); 28468da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV) if (err == -ERESTARTSYS) 28568da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV) return err; 28668da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV) P9_DPRINTK(P9_DEBUG_TRANS, "9p: May gup pages now.\n"); 28768da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV) } 28868da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV) 2894038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) if (rpinfo_size <= (req->tc->capacity - req->tc->size)) { 2904038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) /* We can use sdata */ 2914038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) req->tc->private = req->tc->sdata + req->tc->size; 2924038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) rpinfo = (struct trans_rpage_info *)req->tc->private; 2934038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) rpinfo->rp_alloc = 0; 2944038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) } else { 2954038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) req->tc->private = kmalloc(rpinfo_size, GFP_NOFS); 2964038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) if (!req->tc->private) { 2974038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: " 2984038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) "private kmalloc returned NULL"); 2994038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) return -ENOMEM; 3004038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) } 3014038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) rpinfo = (struct trans_rpage_info *)req->tc->private; 3024038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) rpinfo->rp_alloc = 1; 3034038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) } 3044038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) 3054038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) err = p9_payload_gup(req, &pdata_off, &pdata_len, nr_pages, 3064038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) req->tc->id == P9_TREAD ? 1 : 0); 3074038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) if (err < 0) { 3084038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) if (rpinfo->rp_alloc) 3094038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) kfree(rpinfo); 3104038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) return err; 31168da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV) } else { 31268da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV) atomic_add(rpinfo->rp_nr_pages, &vp_pinned); 3134038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) } 3144038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) } 3154038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) 316316ad5501c2098cb2a2a25ed77a0421f1671411cVenkateswararao Jujjuri (JV)req_retry_pinned: 317419b39561e698d73a42f8010655d22e0134486daVenkateswararao Jujjuri (JV) spin_lock_irqsave(&chan->lock, flags); 3184038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) 3194038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) /* Handle out VirtIO ring buffers */ 32091b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen out = pack_sg_list(chan->sg, 0, VIRTQUEUE_NUM, req->tc->sdata, 3214038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) req->tc->size); 3224038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) 3234038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) if (req->tc->pbuf_size && (req->tc->id == P9_TWRITE)) { 3244038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) /* We have additional write payload buffer to take care */ 3254038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) if (req->tc->pubuf && P9_IS_USER_CONTEXT) { 3264038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) outp = pack_sg_list_p(chan->sg, out, VIRTQUEUE_NUM, 3274038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) pdata_off, rpinfo->rp_data, pdata_len); 3284038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) } else { 3294038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) char *pbuf = req->tc->pubuf ? req->tc->pubuf : 3304038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) req->tc->pkbuf; 3314038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) outp = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM, pbuf, 3324038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) req->tc->pbuf_size); 3334038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) } 3344038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) out += outp; 3354038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) } 3364038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) 3374038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) /* Handle in VirtIO ring buffers */ 3384038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) if (req->tc->pbuf_size && 3394038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) ((req->tc->id == P9_TREAD) || (req->tc->id == P9_TREADDIR))) { 3404038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) /* 3414038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) * Take care of additional Read payload. 3424038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) * 11 is the read/write header = PDU Header(7) + IO Size (4). 3434038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) * Arrange in such a way that server places header in the 3444038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) * alloced memory and payload onto the user buffer. 3454038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) */ 3464038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) inp = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM, rdata, 11); 3474038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) /* 3484038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) * Running executables in the filesystem may result in 3494038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) * a read request with kernel buffer as opposed to user buffer. 3504038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) */ 3514038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) if (req->tc->pubuf && P9_IS_USER_CONTEXT) { 3524038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) in = pack_sg_list_p(chan->sg, out+inp, VIRTQUEUE_NUM, 3534038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) pdata_off, rpinfo->rp_data, pdata_len); 3544038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) } else { 3554038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) char *pbuf = req->tc->pubuf ? req->tc->pubuf : 3564038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) req->tc->pkbuf; 3574038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) in = pack_sg_list(chan->sg, out+inp, VIRTQUEUE_NUM, 3584038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) pbuf, req->tc->pbuf_size); 3594038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) } 3604038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) in += inp; 3614038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) } else { 3624038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) in = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM, rdata, 3634038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) client->msize); 3644038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) } 365b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 366419b39561e698d73a42f8010655d22e0134486daVenkateswararao Jujjuri (JV) err = virtqueue_add_buf(chan->vq, chan->sg, out, in, req->tc); 367419b39561e698d73a42f8010655d22e0134486daVenkateswararao Jujjuri (JV) if (err < 0) { 36852f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) if (err == -ENOSPC) { 36952f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) chan->ring_bufs_avail = 0; 37052f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) spin_unlock_irqrestore(&chan->lock, flags); 37152f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) err = wait_event_interruptible(*chan->vc_wq, 37252f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) chan->ring_bufs_avail); 37352f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) if (err == -ERESTARTSYS) 37452f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) return err; 37552f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) 37652f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) P9_DPRINTK(P9_DEBUG_TRANS, "9p:Retry virtio request\n"); 377316ad5501c2098cb2a2a25ed77a0421f1671411cVenkateswararao Jujjuri (JV) goto req_retry_pinned; 37852f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) } else { 37952f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) spin_unlock_irqrestore(&chan->lock, flags); 38052f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) P9_DPRINTK(P9_DEBUG_TRANS, 38152f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) "9p debug: " 38252f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) "virtio rpc add_buf returned failure"); 3834038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) if (rpinfo && rpinfo->rp_alloc) 3844038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) kfree(rpinfo); 38552f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) return -EIO; 38652f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) } 387e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen } 388b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 389dc3f5e68f846eec38fb31d78f0b6e83633ad375eMichael S. Tsirkin virtqueue_kick(chan->vq); 390419b39561e698d73a42f8010655d22e0134486daVenkateswararao Jujjuri (JV) spin_unlock_irqrestore(&chan->lock, flags); 391b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 39291b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request kicked\n"); 393e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen return 0; 394b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen} 395b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 39686c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.Vstatic ssize_t p9_mount_tag_show(struct device *dev, 39786c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V struct device_attribute *attr, char *buf) 39886c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V{ 39986c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V struct virtio_chan *chan; 40086c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V struct virtio_device *vdev; 40186c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V 40286c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V vdev = dev_to_virtio(dev); 40386c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V chan = vdev->priv; 40486c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V 40586c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V return snprintf(buf, chan->tag_len + 1, "%s", chan->tag); 40686c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V} 40786c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V 40886c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.Vstatic DEVICE_ATTR(mount_tag, 0444, p9_mount_tag_show, NULL); 40986c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V 410ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen/** 411ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * p9_virtio_probe - probe for existence of 9P virtio channels 412ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @vdev: virtio device to probe 413ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * 41437c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V * This probes for existing virtio channels. 415ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * 416ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen */ 417ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen 418e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergenstatic int p9_virtio_probe(struct virtio_device *vdev) 419b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen{ 42097ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V __u16 tag_len; 42197ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V char *tag; 422b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen int err; 423b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen struct virtio_chan *chan; 424b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 42537c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V chan = kmalloc(sizeof(struct virtio_chan), GFP_KERNEL); 42637c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V if (!chan) { 42737c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V printk(KERN_ERR "9p: Failed to allocate virtio 9P channel\n"); 428b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen err = -ENOMEM; 429b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen goto fail; 430b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen } 431b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 432e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen chan->vdev = vdev; 433b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 434e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen /* We expect one virtqueue, for requests. */ 435d2a7ddda9ffb1c8961abff6714b0f1eb925c120fMichael S. Tsirkin chan->vq = virtio_find_single_vq(vdev, req_done, "requests"); 436e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen if (IS_ERR(chan->vq)) { 437e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen err = PTR_ERR(chan->vq); 438e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen goto out_free_vq; 439b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen } 440e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen chan->vq->vdev->priv = chan; 441e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen spin_lock_init(&chan->lock); 442b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 443e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen sg_init_table(chan->sg, VIRTQUEUE_NUM); 444b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 445b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen chan->inuse = false; 44697ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V if (virtio_has_feature(vdev, VIRTIO_9P_MOUNT_TAG)) { 44797ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V vdev->config->get(vdev, 44897ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V offsetof(struct virtio_9p_config, tag_len), 44997ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V &tag_len, sizeof(tag_len)); 45097ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V } else { 45197ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V err = -EINVAL; 45297ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V goto out_free_vq; 45397ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V } 45497ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V tag = kmalloc(tag_len, GFP_KERNEL); 45597ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V if (!tag) { 45697ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V err = -ENOMEM; 45797ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V goto out_free_vq; 45897ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V } 45997ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V vdev->config->get(vdev, offsetof(struct virtio_9p_config, tag), 46097ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V tag, tag_len); 46197ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V chan->tag = tag; 46297ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V chan->tag_len = tag_len; 46386c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V err = sysfs_create_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); 46486c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V if (err) { 46552f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) goto out_free_tag; 46686c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V } 46752f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) chan->vc_wq = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL); 46852f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) if (!chan->vc_wq) { 46952f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) err = -ENOMEM; 47052f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) goto out_free_tag; 47152f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) } 47252f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) init_waitqueue_head(chan->vc_wq); 47352f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) chan->ring_bufs_avail = 1; 47468da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV) /* Ceiling limit to avoid denial of service attacks */ 47568da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV) chan->p9_max_pages = nr_free_buffer_pages()/4; 47652f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) 47737c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V mutex_lock(&virtio_9p_lock); 47837c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V list_add_tail(&chan->chan_list, &virtio_chan_list); 47937c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V mutex_unlock(&virtio_9p_lock); 480b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen return 0; 481b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 48252f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)out_free_tag: 48352f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) kfree(tag); 484e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergenout_free_vq: 485d2a7ddda9ffb1c8961abff6714b0f1eb925c120fMichael S. Tsirkin vdev->config->del_vqs(vdev); 48637c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V kfree(chan); 487b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergenfail: 488b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen return err; 489b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen} 490b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 491ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen 492ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen/** 493ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * p9_virtio_create - allocate a new virtio channel 4948b81ef589ad1483dd977ef47fe00d4ce4d91a0abEric Van Hensbergen * @client: client instance invoking this transport 495ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @devname: string identifying the channel to connect to (unused) 496ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @args: args passed from sys_mount() for per-transport options (unused) 497ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * 498ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * This sets up a transport channel for 9p communication. Right now 499b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * we only match the first available channel, but eventually we couldlook up 500b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * alternate channels by matching devname versus a virtio_config entry. 501b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * We use a simple reference count mechanism to ensure that only a single 502ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * mount has a channel open at a time. 503ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * 504ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen */ 505ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen 5068b81ef589ad1483dd977ef47fe00d4ce4d91a0abEric Van Hensbergenstatic int 5078b81ef589ad1483dd977ef47fe00d4ce4d91a0abEric Van Hensbergenp9_virtio_create(struct p9_client *client, const char *devname, char *args) 508b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen{ 50937c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V struct virtio_chan *chan; 510c1a7c2262035e83a8f70ebe1328b3451702cf51bAneesh Kumar K.V int ret = -ENOENT; 51137c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V int found = 0; 512b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 513c1549497e903a1ffa1c5808337a987180e480e7aJosef 'Jeff' Sipek mutex_lock(&virtio_9p_lock); 51437c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V list_for_each_entry(chan, &virtio_chan_list, chan_list) { 5150b20406cda621c2495d10baab1e87127ceb43337Sven Eckelmann if (!strncmp(devname, chan->tag, chan->tag_len) && 5160b20406cda621c2495d10baab1e87127ceb43337Sven Eckelmann strlen(devname) == chan->tag_len) { 517f75580c4afb72c156746b3fc1ec977b1a85d3deeAneesh Kumar K.V if (!chan->inuse) { 518f75580c4afb72c156746b3fc1ec977b1a85d3deeAneesh Kumar K.V chan->inuse = true; 51937c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V found = 1; 520f75580c4afb72c156746b3fc1ec977b1a85d3deeAneesh Kumar K.V break; 521f75580c4afb72c156746b3fc1ec977b1a85d3deeAneesh Kumar K.V } 522c1a7c2262035e83a8f70ebe1328b3451702cf51bAneesh Kumar K.V ret = -EBUSY; 523b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen } 524b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen } 525c1549497e903a1ffa1c5808337a987180e480e7aJosef 'Jeff' Sipek mutex_unlock(&virtio_9p_lock); 526b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 52737c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V if (!found) { 528e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen printk(KERN_ERR "9p: no channels available\n"); 529c1a7c2262035e83a8f70ebe1328b3451702cf51bAneesh Kumar K.V return ret; 530e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen } 531e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen 5328b81ef589ad1483dd977ef47fe00d4ce4d91a0abEric Van Hensbergen client->trans = (void *)chan; 533562ada612058133a5483c68a73605f3c5f42fffeEric Van Hensbergen client->status = Connected; 534fea511a644fb0fb938309c6ab286725ac31b87e2Eric Van Hensbergen chan->client = client; 535b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 5368b81ef589ad1483dd977ef47fe00d4ce4d91a0abEric Van Hensbergen return 0; 537b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen} 538b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 539ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen/** 540ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * p9_virtio_remove - clean up resources associated with a virtio device 541ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @vdev: virtio device to remove 542ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * 543ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen */ 544ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen 545f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergenstatic void p9_virtio_remove(struct virtio_device *vdev) 546f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen{ 547f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen struct virtio_chan *chan = vdev->priv; 548f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen 549f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen BUG_ON(chan->inuse); 55037c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V vdev->config->del_vqs(vdev); 55137c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V 55237c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V mutex_lock(&virtio_9p_lock); 55337c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V list_del(&chan->chan_list); 55437c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V mutex_unlock(&virtio_9p_lock); 55586c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); 55697ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V kfree(chan->tag); 55752f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV) kfree(chan->vc_wq); 55837c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V kfree(chan); 559f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen 560f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen} 561f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen 562b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergenstatic struct virtio_device_id id_table[] = { 563b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen { VIRTIO_ID_9P, VIRTIO_DEV_ANY_ID }, 564b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen { 0 }, 565b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen}; 566b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 56797ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.Vstatic unsigned int features[] = { 56897ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V VIRTIO_9P_MOUNT_TAG, 56997ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V}; 57097ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V 571b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen/* The standard "struct lguest_driver": */ 572b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergenstatic struct virtio_driver p9_virtio_drv = { 57397ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V .feature_table = features, 57497ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V .feature_table_size = ARRAY_SIZE(features), 57597ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V .driver.name = KBUILD_MODNAME, 57697ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V .driver.owner = THIS_MODULE, 57797ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V .id_table = id_table, 57897ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V .probe = p9_virtio_probe, 57997ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V .remove = p9_virtio_remove, 580b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen}; 581b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 582b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergenstatic struct p9_trans_module p9_virtio_trans = { 583b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen .name = "virtio", 584b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen .create = p9_virtio_create, 5858b81ef589ad1483dd977ef47fe00d4ce4d91a0abEric Van Hensbergen .close = p9_virtio_close, 58691b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen .request = p9_virtio_request, 58791b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen .cancel = p9_virtio_cancel, 588e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen .maxsize = PAGE_SIZE*16, 5896f69c395cefb26ebba2c9bb725296a3a4a9200ecVenkateswararao Jujjuri (JV) .pref = P9_TRANS_PREF_PAYLOAD_SEP, 590b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen .def = 0, 59172029fe85d8d060b3f966f2dbc36b3c75b5a6532Tejun Heo .owner = THIS_MODULE, 592b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen}; 593b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 594b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen/* The standard init function */ 595b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergenstatic int __init p9_virtio_init(void) 596b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen{ 59737c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V INIT_LIST_HEAD(&virtio_chan_list); 598b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 599b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen v9fs_register_trans(&p9_virtio_trans); 600b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen return register_virtio_driver(&p9_virtio_drv); 601b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen} 602b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 603f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergenstatic void __exit p9_virtio_cleanup(void) 604f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen{ 605f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen unregister_virtio_driver(&p9_virtio_drv); 60672029fe85d8d060b3f966f2dbc36b3c75b5a6532Tejun Heo v9fs_unregister_trans(&p9_virtio_trans); 607f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen} 608f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen 609b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergenmodule_init(p9_virtio_init); 610f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergenmodule_exit(p9_virtio_cleanup); 611b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen 612b530cc794024be227876a089e66fb17b7b512763Eric Van HensbergenMODULE_DEVICE_TABLE(virtio, id_table); 613b530cc794024be227876a089e66fb17b7b512763Eric Van HensbergenMODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>"); 614b530cc794024be227876a089e66fb17b7b512763Eric Van HensbergenMODULE_DESCRIPTION("Virtio 9p Transport"); 615b530cc794024be227876a089e66fb17b7b512763Eric Van HensbergenMODULE_LICENSE("GPL"); 616