xref: /openbmc/linux/net/9p/trans_virtio.c (revision df2634f43f5106947f3735a0b61a6527a4b278cd)
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 	int ring_bufs_avail;
79 	wait_queue_head_t *vc_wq;
80 
81 	/* Scatterlist: can be too big for stack. */
82 	struct scatterlist sg[VIRTQUEUE_NUM];
83 
84 	int tag_len;
85 	/*
86 	 * tag name to identify a mount Non-null terminated
87 	 */
88 	char *tag;
89 
90 	struct list_head chan_list;
91 };
92 
93 static struct list_head virtio_chan_list;
94 
95 /* How many bytes left in this page. */
96 static unsigned int rest_of_page(void *data)
97 {
98 	return PAGE_SIZE - ((unsigned long)data % PAGE_SIZE);
99 }
100 
101 /**
102  * p9_virtio_close - reclaim resources of a channel
103  * @client: client instance
104  *
105  * This reclaims a channel by freeing its resources and
106  * reseting its inuse flag.
107  *
108  */
109 
110 static void p9_virtio_close(struct p9_client *client)
111 {
112 	struct virtio_chan *chan = client->trans;
113 
114 	mutex_lock(&virtio_9p_lock);
115 	if (chan)
116 		chan->inuse = false;
117 	mutex_unlock(&virtio_9p_lock);
118 }
119 
120 /**
121  * req_done - callback which signals activity from the server
122  * @vq: virtio queue activity was received on
123  *
124  * This notifies us that the server has triggered some activity
125  * on the virtio channel - most likely a response to request we
126  * sent.  Figure out which requests now have responses and wake up
127  * those threads.
128  *
129  * Bugs: could do with some additional sanity checking, but appears to work.
130  *
131  */
132 
133 static void req_done(struct virtqueue *vq)
134 {
135 	struct virtio_chan *chan = vq->vdev->priv;
136 	struct p9_fcall *rc;
137 	unsigned int len;
138 	struct p9_req_t *req;
139 	unsigned long flags;
140 
141 	P9_DPRINTK(P9_DEBUG_TRANS, ": request done\n");
142 
143 	do {
144 		spin_lock_irqsave(&chan->lock, flags);
145 		rc = virtqueue_get_buf(chan->vq, &len);
146 
147 		if (rc != NULL) {
148 			if (!chan->ring_bufs_avail) {
149 				chan->ring_bufs_avail = 1;
150 				wake_up(chan->vc_wq);
151 			}
152 			spin_unlock_irqrestore(&chan->lock, flags);
153 			P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc);
154 			P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n",
155 					rc->tag);
156 			req = p9_tag_lookup(chan->client, rc->tag);
157 			req->status = REQ_STATUS_RCVD;
158 			p9_client_cb(chan->client, req);
159 		} else {
160 			spin_unlock_irqrestore(&chan->lock, flags);
161 		}
162 	} while (rc != NULL);
163 }
164 
165 /**
166  * pack_sg_list - pack a scatter gather list from a linear buffer
167  * @sg: scatter/gather list to pack into
168  * @start: which segment of the sg_list to start at
169  * @limit: maximum segment to pack data to
170  * @data: data to pack into scatter/gather list
171  * @count: amount of data to pack into the scatter/gather list
172  *
173  * sg_lists have multiple segments of various sizes.  This will pack
174  * arbitrary data into an existing scatter gather list, segmenting the
175  * data as necessary within constraints.
176  *
177  */
178 
179 static int
180 pack_sg_list(struct scatterlist *sg, int start, int limit, char *data,
181 								int count)
182 {
183 	int s;
184 	int index = start;
185 
186 	while (count) {
187 		s = rest_of_page(data);
188 		if (s > count)
189 			s = count;
190 		sg_set_buf(&sg[index++], data, s);
191 		count -= s;
192 		data += s;
193 		BUG_ON(index > limit);
194 	}
195 
196 	return index-start;
197 }
198 
199 /* We don't currently allow canceling of virtio requests */
200 static int p9_virtio_cancel(struct p9_client *client, struct p9_req_t *req)
201 {
202 	return 1;
203 }
204 
205 /**
206  * p9_virtio_request - issue a request
207  * @client: client instance issuing the request
208  * @req: request to be issued
209  *
210  */
211 
212 static int
213 p9_virtio_request(struct p9_client *client, struct p9_req_t *req)
214 {
215 	int in, out;
216 	struct virtio_chan *chan = client->trans;
217 	char *rdata = (char *)req->rc+sizeof(struct p9_fcall);
218 	unsigned long flags;
219 	int err;
220 
221 	P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request\n");
222 
223 req_retry:
224 	req->status = REQ_STATUS_SENT;
225 
226 	spin_lock_irqsave(&chan->lock, flags);
227 	out = pack_sg_list(chan->sg, 0, VIRTQUEUE_NUM, req->tc->sdata,
228 								req->tc->size);
229 	in = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM-out, rdata,
230 								client->msize);
231 
232 	err = virtqueue_add_buf(chan->vq, chan->sg, out, in, req->tc);
233 	if (err < 0) {
234 		if (err == -ENOSPC) {
235 			chan->ring_bufs_avail = 0;
236 			spin_unlock_irqrestore(&chan->lock, flags);
237 			err = wait_event_interruptible(*chan->vc_wq,
238 							chan->ring_bufs_avail);
239 			if (err  == -ERESTARTSYS)
240 				return err;
241 
242 			P9_DPRINTK(P9_DEBUG_TRANS, "9p:Retry virtio request\n");
243 			goto req_retry;
244 		} else {
245 			spin_unlock_irqrestore(&chan->lock, flags);
246 			P9_DPRINTK(P9_DEBUG_TRANS,
247 					"9p debug: "
248 					"virtio rpc add_buf returned failure");
249 			return -EIO;
250 		}
251 	}
252 
253 	virtqueue_kick(chan->vq);
254 	spin_unlock_irqrestore(&chan->lock, flags);
255 
256 	P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request kicked\n");
257 	return 0;
258 }
259 
260 static ssize_t p9_mount_tag_show(struct device *dev,
261 				struct device_attribute *attr, char *buf)
262 {
263 	struct virtio_chan *chan;
264 	struct virtio_device *vdev;
265 
266 	vdev = dev_to_virtio(dev);
267 	chan = vdev->priv;
268 
269 	return snprintf(buf, chan->tag_len + 1, "%s", chan->tag);
270 }
271 
272 static DEVICE_ATTR(mount_tag, 0444, p9_mount_tag_show, NULL);
273 
274 /**
275  * p9_virtio_probe - probe for existence of 9P virtio channels
276  * @vdev: virtio device to probe
277  *
278  * This probes for existing virtio channels.
279  *
280  */
281 
282 static int p9_virtio_probe(struct virtio_device *vdev)
283 {
284 	__u16 tag_len;
285 	char *tag;
286 	int err;
287 	struct virtio_chan *chan;
288 
289 	chan = kmalloc(sizeof(struct virtio_chan), GFP_KERNEL);
290 	if (!chan) {
291 		printk(KERN_ERR "9p: Failed to allocate virtio 9P channel\n");
292 		err = -ENOMEM;
293 		goto fail;
294 	}
295 
296 	chan->vdev = vdev;
297 
298 	/* We expect one virtqueue, for requests. */
299 	chan->vq = virtio_find_single_vq(vdev, req_done, "requests");
300 	if (IS_ERR(chan->vq)) {
301 		err = PTR_ERR(chan->vq);
302 		goto out_free_vq;
303 	}
304 	chan->vq->vdev->priv = chan;
305 	spin_lock_init(&chan->lock);
306 
307 	sg_init_table(chan->sg, VIRTQUEUE_NUM);
308 
309 	chan->inuse = false;
310 	if (virtio_has_feature(vdev, VIRTIO_9P_MOUNT_TAG)) {
311 		vdev->config->get(vdev,
312 				offsetof(struct virtio_9p_config, tag_len),
313 				&tag_len, sizeof(tag_len));
314 	} else {
315 		err = -EINVAL;
316 		goto out_free_vq;
317 	}
318 	tag = kmalloc(tag_len, GFP_KERNEL);
319 	if (!tag) {
320 		err = -ENOMEM;
321 		goto out_free_vq;
322 	}
323 	vdev->config->get(vdev, offsetof(struct virtio_9p_config, tag),
324 			tag, tag_len);
325 	chan->tag = tag;
326 	chan->tag_len = tag_len;
327 	err = sysfs_create_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr);
328 	if (err) {
329 		goto out_free_tag;
330 	}
331 	chan->vc_wq = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL);
332 	if (!chan->vc_wq) {
333 		err = -ENOMEM;
334 		goto out_free_tag;
335 	}
336 	init_waitqueue_head(chan->vc_wq);
337 	chan->ring_bufs_avail = 1;
338 
339 	mutex_lock(&virtio_9p_lock);
340 	list_add_tail(&chan->chan_list, &virtio_chan_list);
341 	mutex_unlock(&virtio_9p_lock);
342 	return 0;
343 
344 out_free_tag:
345 	kfree(tag);
346 out_free_vq:
347 	vdev->config->del_vqs(vdev);
348 	kfree(chan);
349 fail:
350 	return err;
351 }
352 
353 
354 /**
355  * p9_virtio_create - allocate a new virtio channel
356  * @client: client instance invoking this transport
357  * @devname: string identifying the channel to connect to (unused)
358  * @args: args passed from sys_mount() for per-transport options (unused)
359  *
360  * This sets up a transport channel for 9p communication.  Right now
361  * we only match the first available channel, but eventually we couldlook up
362  * alternate channels by matching devname versus a virtio_config entry.
363  * We use a simple reference count mechanism to ensure that only a single
364  * mount has a channel open at a time.
365  *
366  */
367 
368 static int
369 p9_virtio_create(struct p9_client *client, const char *devname, char *args)
370 {
371 	struct virtio_chan *chan;
372 	int ret = -ENOENT;
373 	int found = 0;
374 
375 	mutex_lock(&virtio_9p_lock);
376 	list_for_each_entry(chan, &virtio_chan_list, chan_list) {
377 		if (!strncmp(devname, chan->tag, chan->tag_len) &&
378 		    strlen(devname) == chan->tag_len) {
379 			if (!chan->inuse) {
380 				chan->inuse = true;
381 				found = 1;
382 				break;
383 			}
384 			ret = -EBUSY;
385 		}
386 	}
387 	mutex_unlock(&virtio_9p_lock);
388 
389 	if (!found) {
390 		printk(KERN_ERR "9p: no channels available\n");
391 		return ret;
392 	}
393 
394 	client->trans = (void *)chan;
395 	client->status = Connected;
396 	chan->client = client;
397 
398 	return 0;
399 }
400 
401 /**
402  * p9_virtio_remove - clean up resources associated with a virtio device
403  * @vdev: virtio device to remove
404  *
405  */
406 
407 static void p9_virtio_remove(struct virtio_device *vdev)
408 {
409 	struct virtio_chan *chan = vdev->priv;
410 
411 	BUG_ON(chan->inuse);
412 	vdev->config->del_vqs(vdev);
413 
414 	mutex_lock(&virtio_9p_lock);
415 	list_del(&chan->chan_list);
416 	mutex_unlock(&virtio_9p_lock);
417 	sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr);
418 	kfree(chan->tag);
419 	kfree(chan->vc_wq);
420 	kfree(chan);
421 
422 }
423 
424 static struct virtio_device_id id_table[] = {
425 	{ VIRTIO_ID_9P, VIRTIO_DEV_ANY_ID },
426 	{ 0 },
427 };
428 
429 static unsigned int features[] = {
430 	VIRTIO_9P_MOUNT_TAG,
431 };
432 
433 /* The standard "struct lguest_driver": */
434 static struct virtio_driver p9_virtio_drv = {
435 	.feature_table  = features,
436 	.feature_table_size = ARRAY_SIZE(features),
437 	.driver.name    = KBUILD_MODNAME,
438 	.driver.owner	= THIS_MODULE,
439 	.id_table	= id_table,
440 	.probe		= p9_virtio_probe,
441 	.remove		= p9_virtio_remove,
442 };
443 
444 static struct p9_trans_module p9_virtio_trans = {
445 	.name = "virtio",
446 	.create = p9_virtio_create,
447 	.close = p9_virtio_close,
448 	.request = p9_virtio_request,
449 	.cancel = p9_virtio_cancel,
450 	.maxsize = PAGE_SIZE*16,
451 	.def = 0,
452 	.owner = THIS_MODULE,
453 };
454 
455 /* The standard init function */
456 static int __init p9_virtio_init(void)
457 {
458 	INIT_LIST_HEAD(&virtio_chan_list);
459 
460 	v9fs_register_trans(&p9_virtio_trans);
461 	return register_virtio_driver(&p9_virtio_drv);
462 }
463 
464 static void __exit p9_virtio_cleanup(void)
465 {
466 	unregister_virtio_driver(&p9_virtio_drv);
467 	v9fs_unregister_trans(&p9_virtio_trans);
468 }
469 
470 module_init(p9_virtio_init);
471 module_exit(p9_virtio_cleanup);
472 
473 MODULE_DEVICE_TABLE(virtio, id_table);
474 MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>");
475 MODULE_DESCRIPTION("Virtio 9p Transport");
476 MODULE_LICENSE("GPL");
477