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 */ 52 static 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 70 struct 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 91 static struct list_head virtio_chan_list; 92 93 /* How many bytes left in this page. */ 94 static 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 108 static 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 131 static 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 163 static int 164 pack_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 */ 184 static 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 196 static int 197 p9_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 224 static 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 236 static 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 246 static 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 301 out_free_vq: 302 vdev->config->del_vqs(vdev); 303 kfree(chan); 304 fail: 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 323 static int 324 p9_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 if (!chan->inuse) { 334 chan->inuse = true; 335 found = 1; 336 break; 337 } 338 ret = -EBUSY; 339 } 340 } 341 mutex_unlock(&virtio_9p_lock); 342 343 if (!found) { 344 printk(KERN_ERR "9p: no channels available\n"); 345 return ret; 346 } 347 348 client->trans = (void *)chan; 349 client->status = Connected; 350 chan->client = client; 351 352 return 0; 353 } 354 355 /** 356 * p9_virtio_remove - clean up resources associated with a virtio device 357 * @vdev: virtio device to remove 358 * 359 */ 360 361 static void p9_virtio_remove(struct virtio_device *vdev) 362 { 363 struct virtio_chan *chan = vdev->priv; 364 365 BUG_ON(chan->inuse); 366 vdev->config->del_vqs(vdev); 367 368 mutex_lock(&virtio_9p_lock); 369 list_del(&chan->chan_list); 370 mutex_unlock(&virtio_9p_lock); 371 sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); 372 kfree(chan->tag); 373 kfree(chan); 374 375 } 376 377 static struct virtio_device_id id_table[] = { 378 { VIRTIO_ID_9P, VIRTIO_DEV_ANY_ID }, 379 { 0 }, 380 }; 381 382 static unsigned int features[] = { 383 VIRTIO_9P_MOUNT_TAG, 384 }; 385 386 /* The standard "struct lguest_driver": */ 387 static struct virtio_driver p9_virtio_drv = { 388 .feature_table = features, 389 .feature_table_size = ARRAY_SIZE(features), 390 .driver.name = KBUILD_MODNAME, 391 .driver.owner = THIS_MODULE, 392 .id_table = id_table, 393 .probe = p9_virtio_probe, 394 .remove = p9_virtio_remove, 395 }; 396 397 static struct p9_trans_module p9_virtio_trans = { 398 .name = "virtio", 399 .create = p9_virtio_create, 400 .close = p9_virtio_close, 401 .request = p9_virtio_request, 402 .cancel = p9_virtio_cancel, 403 .maxsize = PAGE_SIZE*16, 404 .def = 0, 405 .owner = THIS_MODULE, 406 }; 407 408 /* The standard init function */ 409 static int __init p9_virtio_init(void) 410 { 411 INIT_LIST_HEAD(&virtio_chan_list); 412 413 v9fs_register_trans(&p9_virtio_trans); 414 return register_virtio_driver(&p9_virtio_drv); 415 } 416 417 static void __exit p9_virtio_cleanup(void) 418 { 419 unregister_virtio_driver(&p9_virtio_drv); 420 v9fs_unregister_trans(&p9_virtio_trans); 421 } 422 423 module_init(p9_virtio_init); 424 module_exit(p9_virtio_cleanup); 425 426 MODULE_DEVICE_TABLE(virtio, id_table); 427 MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>"); 428 MODULE_DESCRIPTION("Virtio 9p Transport"); 429 MODULE_LICENSE("GPL"); 430