9p: add remove function to trans_virtio
[linux-2.6.git] / net / 9p / trans_virtio.c
1 /*
2  * The Guest 9p transport driver
3  *
4  * This is a block based transport driver based on the lguest block driver
5  * code.
6  *
7  */
8 /*
9  *  Copyright (C) 2007 Eric Van Hensbergen, IBM Corporation
10  *
11  *  Based on virtio console driver
12  *  Copyright (C) 2006, 2007 Rusty Russell, IBM Corporation
13  *
14  *  This program is free software; you can redistribute it and/or modify
15  *  it under the terms of the GNU General Public License version 2
16  *  as published by the Free Software Foundation.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, write to:
25  *  Free Software Foundation
26  *  51 Franklin Street, Fifth Floor
27  *  Boston, MA  02111-1301  USA
28  *
29  */
30
31 #include <linux/in.h>
32 #include <linux/module.h>
33 #include <linux/net.h>
34 #include <linux/ipv6.h>
35 #include <linux/errno.h>
36 #include <linux/kernel.h>
37 #include <linux/un.h>
38 #include <linux/uaccess.h>
39 #include <linux/inet.h>
40 #include <linux/idr.h>
41 #include <linux/file.h>
42 #include <net/9p/9p.h>
43 #include <linux/parser.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 DECLARE_MUTEX(virtio_9p_lock);
53 /* global which tracks highest initialized channel */
54 static int chan_index;
55
56 #define P9_INIT_MAXTAG  16
57
58 #define REQ_STATUS_IDLE 0
59 #define REQ_STATUS_SENT 1
60 #define REQ_STATUS_RCVD 2
61 #define REQ_STATUS_FLSH 3
62
63 struct p9_req_t {
64         int status;
65         wait_queue_head_t *wq;
66 };
67
68 /* We keep all per-channel information in a structure.
69  * This structure is allocated within the devices dev->mem space.
70  * A pointer to the structure will get put in the transport private.
71  */
72 static struct virtio_chan {
73         bool initialized;               /* channel is initialized */
74         bool inuse;                     /* channel is in use */
75
76         spinlock_t lock;
77
78         struct virtio_device *vdev;
79         struct virtqueue *vq;
80
81         struct p9_idpool *tagpool;
82         struct p9_req_t *reqs;
83         int max_tag;
84
85         /* Scatterlist: can be too big for stack. */
86         struct scatterlist sg[VIRTQUEUE_NUM];
87 } channels[MAX_9P_CHAN];
88
89 /* Lookup requests by tag */
90 static struct p9_req_t *p9_lookup_tag(struct virtio_chan *c, u16 tag)
91 {
92         /* This looks up the original request by tag so we know which
93          * buffer to read the data into */
94         tag++;
95
96         while (tag >= c->max_tag) {
97                 int old_max = c->max_tag;
98                 int count;
99
100                 if (c->max_tag)
101                         c->max_tag *= 2;
102                 else
103                         c->max_tag = P9_INIT_MAXTAG;
104
105                 c->reqs = krealloc(c->reqs, sizeof(struct p9_req_t)*c->max_tag,
106                                                                 GFP_ATOMIC);
107                 if (!c->reqs) {
108                         printk(KERN_ERR "Couldn't grow tag array\n");
109                         BUG();
110                 }
111                 for (count = old_max; count < c->max_tag; count++) {
112                         c->reqs[count].status = REQ_STATUS_IDLE;
113                         c->reqs[count].wq = kmalloc(sizeof(wait_queue_t),
114                                                                 GFP_ATOMIC);
115                         if (!c->reqs[count].wq) {
116                                 printk(KERN_ERR "Couldn't grow tag array\n");
117                                 BUG();
118                         }
119                         init_waitqueue_head(c->reqs[count].wq);
120                 }
121         }
122
123         return &c->reqs[tag];
124 }
125
126
127 /* How many bytes left in this page. */
128 static unsigned int rest_of_page(void *data)
129 {
130         return PAGE_SIZE - ((unsigned long)data % PAGE_SIZE);
131 }
132
133 static int p9_virtio_write(struct p9_trans *trans, void *buf, int count)
134 {
135         /* Only use the rpc mechanism for now */
136         return count;
137 }
138
139 static int p9_virtio_read(struct p9_trans *trans, void *buf, int count)
140 {
141         /* Only use the rpc mechanism for now */
142         return 0;
143 }
144
145 /* The poll function is used by 9p transports to determine if there
146  * is there is activity available on a particular channel.  In our case
147  * we use it to wait for a callback from the input routines.
148  */
149 static unsigned int
150 p9_virtio_poll(struct p9_trans *trans, struct poll_table_struct *pt)
151 {
152         /* Only use the rpc mechanism for now */
153         return 0;
154 }
155
156 static void p9_virtio_close(struct p9_trans *trans)
157 {
158         struct virtio_chan *chan = trans->priv;
159         int count;
160         unsigned int flags;
161
162         spin_lock_irqsave(&chan->lock, flags);
163         p9_idpool_destroy(chan->tagpool);
164         for (count = 0; count < chan->max_tag; count++)
165                 kfree(chan->reqs[count].wq);
166         kfree(chan->reqs);
167         chan->max_tag = 0;
168         spin_unlock_irqrestore(&chan->lock, flags);
169
170         down(&virtio_9p_lock);
171         chan->inuse = false;
172         up(&virtio_9p_lock);
173
174         kfree(trans);
175 }
176
177 static void req_done(struct virtqueue *vq)
178 {
179         struct virtio_chan *chan = vq->vdev->priv;
180         struct p9_fcall *rc;
181         unsigned int len;
182         unsigned long flags;
183         struct p9_req_t *req;
184
185         spin_lock_irqsave(&chan->lock, flags);
186         while ((rc = chan->vq->vq_ops->get_buf(chan->vq, &len)) != NULL) {
187                 req = p9_lookup_tag(chan, rc->tag);
188                 req->status = REQ_STATUS_RCVD;
189                 wake_up(req->wq);
190         }
191         /* In case queue is stopped waiting for more buffers. */
192         spin_unlock_irqrestore(&chan->lock, flags);
193 }
194
195 static int
196 pack_sg_list(struct scatterlist *sg, int start, int limit, char *data,
197                                                                 int count)
198 {
199         int s;
200         int index = start;
201
202         while (count) {
203                 s = rest_of_page(data);
204                 if (s > count)
205                         s = count;
206                 sg_set_buf(&sg[index++], data, s);
207                 count -= s;
208                 data += s;
209                 if (index > limit)
210                         BUG();
211         }
212
213         return index-start;
214 }
215
216 static int
217 p9_virtio_rpc(struct p9_trans *t, struct p9_fcall *tc, struct p9_fcall **rc,
218                 int msize, int dotu)
219 {
220         int in, out;
221         int n, err, size;
222         struct virtio_chan *chan = t->priv;
223         char *rdata;
224         struct p9_req_t *req;
225         unsigned long flags;
226
227         if (*rc == NULL) {
228                 *rc = kmalloc(sizeof(struct p9_fcall) + msize, GFP_KERNEL);
229                 if (!*rc)
230                         return -ENOMEM;
231         }
232
233         rdata = (char *)*rc+sizeof(struct p9_fcall);
234
235         n = P9_NOTAG;
236         if (tc->id != P9_TVERSION) {
237                 n = p9_idpool_get(chan->tagpool);
238                 if (n < 0)
239                         return -ENOMEM;
240         }
241
242         spin_lock_irqsave(&chan->lock, flags);
243         req = p9_lookup_tag(chan, n);
244         spin_unlock_irqrestore(&chan->lock, flags);
245
246         p9_set_tag(tc, n);
247
248         P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio rpc tag %d\n", n);
249
250         out = pack_sg_list(chan->sg, 0, VIRTQUEUE_NUM, tc->sdata, tc->size);
251         in = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM-out, rdata, msize);
252
253         req->status = REQ_STATUS_SENT;
254
255         if (chan->vq->vq_ops->add_buf(chan->vq, chan->sg, out, in, tc)) {
256                 P9_DPRINTK(P9_DEBUG_TRANS,
257                         "9p debug: virtio rpc add_buf returned failure");
258                 return -EIO;
259         }
260
261         chan->vq->vq_ops->kick(chan->vq);
262
263         wait_event(*req->wq, req->status == REQ_STATUS_RCVD);
264
265         size = le32_to_cpu(*(__le32 *) rdata);
266
267         err = p9_deserialize_fcall(rdata, size, *rc, dotu);
268         if (err < 0) {
269                 P9_DPRINTK(P9_DEBUG_TRANS,
270                         "9p debug: virtio rpc deserialize returned %d\n", err);
271                 return err;
272         }
273
274 #ifdef CONFIG_NET_9P_DEBUG
275         if ((p9_debug_level&P9_DEBUG_FCALL) == P9_DEBUG_FCALL) {
276                 char buf[150];
277
278                 p9_printfcall(buf, sizeof(buf), *rc, dotu);
279                 printk(KERN_NOTICE ">>> %p %s\n", t, buf);
280         }
281 #endif
282
283         if (n != P9_NOTAG && p9_idpool_check(n, chan->tagpool))
284                 p9_idpool_put(n, chan->tagpool);
285
286         req->status = REQ_STATUS_IDLE;
287
288         return 0;
289 }
290
291 static int p9_virtio_probe(struct virtio_device *vdev)
292 {
293         int err;
294         struct virtio_chan *chan;
295         int index;
296
297         down(&virtio_9p_lock);
298         index = chan_index++;
299         chan = &channels[index];
300         up(&virtio_9p_lock);
301
302         if (chan_index > MAX_9P_CHAN) {
303                 printk(KERN_ERR "9p: virtio: Maximum channels exceeded\n");
304                 BUG();
305                 err = -ENOMEM;
306                 goto fail;
307         }
308
309         chan->vdev = vdev;
310
311         /* We expect one virtqueue, for requests. */
312         chan->vq = vdev->config->find_vq(vdev, 0, req_done);
313         if (IS_ERR(chan->vq)) {
314                 err = PTR_ERR(chan->vq);
315                 goto out_free_vq;
316         }
317         chan->vq->vdev->priv = chan;
318         spin_lock_init(&chan->lock);
319
320         sg_init_table(chan->sg, VIRTQUEUE_NUM);
321
322         chan->inuse = false;
323         chan->initialized = true;
324         return 0;
325
326 out_free_vq:
327         vdev->config->del_vq(chan->vq);
328 fail:
329         down(&virtio_9p_lock);
330         chan_index--;
331         up(&virtio_9p_lock);
332         return err;
333 }
334
335 /* This sets up a transport channel for 9p communication.  Right now
336  * we only match the first available channel, but eventually we couldlook up
337  * alternate channels by matching devname versus a virtio_config entry.
338  * We use a simple reference count mechanism to ensure that only a single
339  * mount has a channel open at a time. */
340 static struct p9_trans *p9_virtio_create(const char *devname, char *args)
341 {
342         struct p9_trans *trans;
343         struct virtio_chan *chan = channels;
344         int index = 0;
345
346         down(&virtio_9p_lock);
347         while (index < MAX_9P_CHAN) {
348                 if (chan->initialized && !chan->inuse) {
349                         chan->inuse = true;
350                         break;
351                 } else {
352                         index++;
353                         chan = &channels[index];
354                 }
355         }
356         up(&virtio_9p_lock);
357
358         if (index >= MAX_9P_CHAN) {
359                 printk(KERN_ERR "9p: no channels available\n");
360                 return ERR_PTR(-ENODEV);
361         }
362
363         chan->tagpool = p9_idpool_create();
364         if (IS_ERR(chan->tagpool)) {
365                 printk(KERN_ERR "9p: couldn't allocate tagpool\n");
366                 return ERR_PTR(-ENOMEM);
367         }
368         p9_idpool_get(chan->tagpool); /* reserve tag 0 */
369         chan->max_tag = 0;
370         chan->reqs = NULL;
371
372         trans = kmalloc(sizeof(struct p9_trans), GFP_KERNEL);
373         if (!trans) {
374                 printk(KERN_ERR "9p: couldn't allocate transport\n");
375                 return ERR_PTR(-ENOMEM);
376         }
377
378         trans->write = p9_virtio_write;
379         trans->read = p9_virtio_read;
380         trans->close = p9_virtio_close;
381         trans->poll = p9_virtio_poll;
382         trans->rpc = p9_virtio_rpc;
383         trans->priv = chan;
384
385         return trans;
386 }
387
388 static void p9_virtio_remove(struct virtio_device *vdev)
389 {
390         struct virtio_chan *chan = vdev->priv;
391
392         BUG_ON(chan->inuse);
393
394         if (chan->initialized) {
395                 vdev->config->del_vq(chan->vq);
396                 chan->initialized = false;
397         }
398 }
399
400 #define VIRTIO_ID_9P 9
401
402 static struct virtio_device_id id_table[] = {
403         { VIRTIO_ID_9P, VIRTIO_DEV_ANY_ID },
404         { 0 },
405 };
406
407 /* The standard "struct lguest_driver": */
408 static struct virtio_driver p9_virtio_drv = {
409         .driver.name =  KBUILD_MODNAME,
410         .driver.owner = THIS_MODULE,
411         .id_table =     id_table,
412         .probe =        p9_virtio_probe,
413         .remove =       p9_virtio_remove,
414 };
415
416 static struct p9_trans_module p9_virtio_trans = {
417         .name = "virtio",
418         .create = p9_virtio_create,
419         .maxsize = PAGE_SIZE*16,
420         .def = 0,
421 };
422
423 /* The standard init function */
424 static int __init p9_virtio_init(void)
425 {
426         int count;
427
428         for (count = 0; count < MAX_9P_CHAN; count++)
429                 channels[count].initialized = false;
430
431         v9fs_register_trans(&p9_virtio_trans);
432         return register_virtio_driver(&p9_virtio_drv);
433 }
434
435 static void __exit p9_virtio_cleanup(void)
436 {
437         unregister_virtio_driver(&p9_virtio_drv);
438 }
439
440 module_init(p9_virtio_init);
441 module_exit(p9_virtio_cleanup);
442
443 MODULE_DEVICE_TABLE(virtio, id_table);
444 MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>");
445 MODULE_DESCRIPTION("Virtio 9p Transport");
446 MODULE_LICENSE("GPL");