1/* 2 * The Virtio 9p transport driver 3 * 4 * This is a block based transport driver based on the lguest block driver 5 * code. 6 * 7 * Copyright (C) 2007, 2008 Eric Van Hensbergen, IBM Corporation 8 * 9 * Based on virtio console driver 10 * Copyright (C) 2006, 2007 Rusty Russell, IBM Corporation 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License version 2 14 * as published by the Free Software Foundation. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to: 23 * Free Software Foundation 24 * 51 Franklin Street, Fifth Floor 25 * Boston, MA 02111-1301 USA 26 * 27 */ 28 29#include <linux/in.h> 30#include <linux/module.h> 31#include <linux/net.h> 32#include <linux/ipv6.h> 33#include <linux/errno.h> 34#include <linux/kernel.h> 35#include <linux/un.h> 36#include <linux/uaccess.h> 37#include <linux/inet.h> 38#include <linux/idr.h> 39#include <linux/file.h> 40#include <linux/slab.h> 41#include <net/9p/9p.h> 42#include <linux/parser.h> 43#include <net/9p/client.h> 44#include <net/9p/transport.h> 45#include <linux/scatterlist.h> 46#include <linux/virtio.h> 47#include <linux/virtio_9p.h> 48 49#define VIRTQUEUE_NUM 128 50 51/* a single mutex to manage channel initialization and attachment */ 52static DEFINE_MUTEX(virtio_9p_lock); 53 54/** 55 * struct virtio_chan - per-instance transport information 56 * @initialized: whether the channel is initialized 57 * @inuse: whether the channel is in use 58 * @lock: protects multiple elements within this structure 59 * @client: client instance 60 * @vdev: virtio dev associated with this channel 61 * @vq: virtio queue associated with this channel 62 * @sg: scatter gather list which is used to pack a request (protected?) 63 * 64 * We keep all per-channel information in a structure. 65 * This structure is allocated within the devices dev->mem space. 66 * A pointer to the structure will get put in the transport private. 67 * 68 */ 69 70struct virtio_chan { 71 bool inuse; 72 73 spinlock_t lock; 74 75 struct p9_client *client; 76 struct virtio_device *vdev; 77 struct virtqueue *vq; 78 79 /* Scatterlist: can be too big for stack. */ 80 struct scatterlist sg[VIRTQUEUE_NUM]; 81 82 int tag_len; 83 /* 84 * tag name to identify a mount Non-null terminated 85 */ 86 char *tag; 87 88 struct list_head chan_list; 89}; 90 91static struct list_head virtio_chan_list; 92 93/* How many bytes left in this page. */ 94static unsigned int rest_of_page(void *data) 95{ 96 return PAGE_SIZE - ((unsigned long)data % PAGE_SIZE); 97} 98 99/** 100 * p9_virtio_close - reclaim resources of a channel 101 * @client: client instance 102 * 103 * This reclaims a channel by freeing its resources and 104 * reseting its inuse flag. 105 * 106 */ 107 108static void p9_virtio_close(struct p9_client *client) 109{ 110 struct virtio_chan *chan = client->trans; 111 112 mutex_lock(&virtio_9p_lock); 113 if (chan) 114 chan->inuse = false; 115 mutex_unlock(&virtio_9p_lock); 116} 117 118/** 119 * req_done - callback which signals activity from the server 120 * @vq: virtio queue activity was received on 121 * 122 * This notifies us that the server has triggered some activity 123 * on the virtio channel - most likely a response to request we 124 * sent. Figure out which requests now have responses and wake up 125 * those threads. 126 * 127 * Bugs: could do with some additional sanity checking, but appears to work. 128 * 129 */ 130 131static void req_done(struct virtqueue *vq) 132{ 133 struct virtio_chan *chan = vq->vdev->priv; 134 struct p9_fcall *rc; 135 unsigned int len; 136 struct p9_req_t *req; 137 138 P9_DPRINTK(P9_DEBUG_TRANS, ": request done\n"); 139 140 while ((rc = virtqueue_get_buf(chan->vq, &len)) != NULL) { 141 P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc); 142 P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag); 143 req = p9_tag_lookup(chan->client, rc->tag); 144 req->status = REQ_STATUS_RCVD; 145 p9_client_cb(chan->client, req); 146 } 147} 148 149/** 150 * pack_sg_list - pack a scatter gather list from a linear buffer 151 * @sg: scatter/gather list to pack into 152 * @start: which segment of the sg_list to start at 153 * @limit: maximum segment to pack data to 154 * @data: data to pack into scatter/gather list 155 * @count: amount of data to pack into the scatter/gather list 156 * 157 * sg_lists have multiple segments of various sizes. This will pack 158 * arbitrary data into an existing scatter gather list, segmenting the 159 * data as necessary within constraints. 160 * 161 */ 162 163static int 164pack_sg_list(struct scatterlist *sg, int start, int limit, char *data, 165 int count) 166{ 167 int s; 168 int index = start; 169 170 while (count) { 171 s = rest_of_page(data); 172 if (s > count) 173 s = count; 174 sg_set_buf(&sg[index++], data, s); 175 count -= s; 176 data += s; 177 BUG_ON(index > limit); 178 } 179 180 return index-start; 181} 182 183/* We don't currently allow canceling of virtio requests */ 184static int p9_virtio_cancel(struct p9_client *client, struct p9_req_t *req) 185{ 186 return 1; 187} 188 189/** 190 * p9_virtio_request - issue a request 191 * @client: client instance issuing the request 192 * @req: request to be issued 193 * 194 */ 195 196static int 197p9_virtio_request(struct p9_client *client, struct p9_req_t *req) 198{ 199 int in, out; 200 struct virtio_chan *chan = client->trans; 201 char *rdata = (char *)req->rc+sizeof(struct p9_fcall); 202 203 P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request\n"); 204 205 out = pack_sg_list(chan->sg, 0, VIRTQUEUE_NUM, req->tc->sdata, 206 req->tc->size); 207 in = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM-out, rdata, 208 client->msize); 209 210 req->status = REQ_STATUS_SENT; 211 212 if (virtqueue_add_buf(chan->vq, chan->sg, out, in, req->tc) < 0) { 213 P9_DPRINTK(P9_DEBUG_TRANS, 214 "9p debug: virtio rpc add_buf returned failure"); 215 return -EIO; 216 } 217 218 virtqueue_kick(chan->vq); 219 220 P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request kicked\n"); 221 return 0; 222} 223 224static ssize_t p9_mount_tag_show(struct device *dev, 225 struct device_attribute *attr, char *buf) 226{ 227 struct virtio_chan *chan; 228 struct virtio_device *vdev; 229 230 vdev = dev_to_virtio(dev); 231 chan = vdev->priv; 232 233 return snprintf(buf, chan->tag_len + 1, "%s", chan->tag); 234} 235 236static DEVICE_ATTR(mount_tag, 0444, p9_mount_tag_show, NULL); 237 238/** 239 * p9_virtio_probe - probe for existence of 9P virtio channels 240 * @vdev: virtio device to probe 241 * 242 * This probes for existing virtio channels. 243 * 244 */ 245 246static int p9_virtio_probe(struct virtio_device *vdev) 247{ 248 __u16 tag_len; 249 char *tag; 250 int err; 251 struct virtio_chan *chan; 252 253 chan = kmalloc(sizeof(struct virtio_chan), GFP_KERNEL); 254 if (!chan) { 255 printk(KERN_ERR "9p: Failed to allocate virtio 9P channel\n"); 256 err = -ENOMEM; 257 goto fail; 258 } 259 260 chan->vdev = vdev; 261 262 /* We expect one virtqueue, for requests. */ 263 chan->vq = virtio_find_single_vq(vdev, req_done, "requests"); 264 if (IS_ERR(chan->vq)) { 265 err = PTR_ERR(chan->vq); 266 goto out_free_vq; 267 } 268 chan->vq->vdev->priv = chan; 269 spin_lock_init(&chan->lock); 270 271 sg_init_table(chan->sg, VIRTQUEUE_NUM); 272 273 chan->inuse = false; 274 if (virtio_has_feature(vdev, VIRTIO_9P_MOUNT_TAG)) { 275 vdev->config->get(vdev, 276 offsetof(struct virtio_9p_config, tag_len), 277 &tag_len, sizeof(tag_len)); 278 } else { 279 err = -EINVAL; 280 goto out_free_vq; 281 } 282 tag = kmalloc(tag_len, GFP_KERNEL); 283 if (!tag) { 284 err = -ENOMEM; 285 goto out_free_vq; 286 } 287 vdev->config->get(vdev, offsetof(struct virtio_9p_config, tag), 288 tag, tag_len); 289 chan->tag = tag; 290 chan->tag_len = tag_len; 291 err = sysfs_create_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); 292 if (err) { 293 kfree(tag); 294 goto out_free_vq; 295 } 296 mutex_lock(&virtio_9p_lock); 297 list_add_tail(&chan->chan_list, &virtio_chan_list); 298 mutex_unlock(&virtio_9p_lock); 299 return 0; 300 301out_free_vq: 302 vdev->config->del_vqs(vdev); 303 kfree(chan); 304fail: 305 return err; 306} 307 308 309/** 310 * p9_virtio_create - allocate a new virtio channel 311 * @client: client instance invoking this transport 312 * @devname: string identifying the channel to connect to (unused) 313 * @args: args passed from sys_mount() for per-transport options (unused) 314 * 315 * This sets up a transport channel for 9p communication. Right now 316 * we only match the first available channel, but eventually we couldlook up 317 * alternate channels by matching devname versus a virtio_config entry. 318 * We use a simple reference count mechanism to ensure that only a single 319 * mount has a channel open at a time. 320 * 321 */ 322 323static int 324p9_virtio_create(struct p9_client *client, const char *devname, char *args) 325{ 326 struct virtio_chan *chan; 327 int ret = -ENOENT; 328 int found = 0; 329 330 mutex_lock(&virtio_9p_lock); 331 list_for_each_entry(chan, &virtio_chan_list, chan_list) { 332 if (!strncmp(devname, chan->tag, chan->tag_len) && 333 strlen(devname) == chan->tag_len) { 334 if (!chan->inuse) { 335 chan->inuse = true; 336 found = 1; 337 break; 338 } 339 ret = -EBUSY; 340 } 341 } 342 mutex_unlock(&virtio_9p_lock); 343 344 if (!found) { 345 printk(KERN_ERR "9p: no channels available\n"); 346 return ret; 347 } 348 349 client->trans = (void *)chan; 350 client->status = Connected; 351 chan->client = client; 352 353 return 0; 354} 355 356/** 357 * p9_virtio_remove - clean up resources associated with a virtio device 358 * @vdev: virtio device to remove 359 * 360 */ 361 362static void p9_virtio_remove(struct virtio_device *vdev) 363{ 364 struct virtio_chan *chan = vdev->priv; 365 366 BUG_ON(chan->inuse); 367 vdev->config->del_vqs(vdev); 368 369 mutex_lock(&virtio_9p_lock); 370 list_del(&chan->chan_list); 371 mutex_unlock(&virtio_9p_lock); 372 sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); 373 kfree(chan->tag); 374 kfree(chan); 375 376} 377 378static struct virtio_device_id id_table[] = { 379 { VIRTIO_ID_9P, VIRTIO_DEV_ANY_ID }, 380 { 0 }, 381}; 382 383static unsigned int features[] = { 384 VIRTIO_9P_MOUNT_TAG, 385}; 386 387/* The standard "struct lguest_driver": */ 388static struct virtio_driver p9_virtio_drv = { 389 .feature_table = features, 390 .feature_table_size = ARRAY_SIZE(features), 391 .driver.name = KBUILD_MODNAME, 392 .driver.owner = THIS_MODULE, 393 .id_table = id_table, 394 .probe = p9_virtio_probe, 395 .remove = p9_virtio_remove, 396}; 397 398static struct p9_trans_module p9_virtio_trans = { 399 .name = "virtio", 400 .create = p9_virtio_create, 401 .close = p9_virtio_close, 402 .request = p9_virtio_request, 403 .cancel = p9_virtio_cancel, 404 .maxsize = PAGE_SIZE*16, 405 .def = 0, 406 .owner = THIS_MODULE, 407}; 408 409/* The standard init function */ 410static int __init p9_virtio_init(void) 411{ 412 INIT_LIST_HEAD(&virtio_chan_list); 413 414 v9fs_register_trans(&p9_virtio_trans); 415 return register_virtio_driver(&p9_virtio_drv); 416} 417 418static void __exit p9_virtio_cleanup(void) 419{ 420 unregister_virtio_driver(&p9_virtio_drv); 421 v9fs_unregister_trans(&p9_virtio_trans); 422} 423 424module_init(p9_virtio_init); 425module_exit(p9_virtio_cleanup); 426 427MODULE_DEVICE_TABLE(virtio, id_table); 428MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>"); 429MODULE_DESCRIPTION("Virtio 9p Transport"); 430MODULE_LICENSE("GPL"); 431