aboutsummaryrefslogtreecommitdiffstats
path: root/net/9p
diff options
context:
space:
mode:
Diffstat (limited to 'net/9p')
-rw-r--r--net/9p/trans_virtio.c70
1 files changed, 27 insertions, 43 deletions
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
index df924e5657d3..05918d3cb40d 100644
--- a/net/9p/trans_virtio.c
+++ b/net/9p/trans_virtio.c
@@ -49,8 +49,6 @@
49 49
50/* a single mutex to manage channel initialization and attachment */ 50/* a single mutex to manage channel initialization and attachment */
51static DEFINE_MUTEX(virtio_9p_lock); 51static DEFINE_MUTEX(virtio_9p_lock);
52/* global which tracks highest initialized channel */
53static int chan_index;
54 52
55/** 53/**
56 * struct virtio_chan - per-instance transport information 54 * struct virtio_chan - per-instance transport information
@@ -68,8 +66,7 @@ static int chan_index;
68 * 66 *
69 */ 67 */
70 68
71static struct virtio_chan { 69struct virtio_chan {
72 bool initialized;
73 bool inuse; 70 bool inuse;
74 71
75 spinlock_t lock; 72 spinlock_t lock;
@@ -80,7 +77,11 @@ static struct virtio_chan {
80 77
81 /* Scatterlist: can be too big for stack. */ 78 /* Scatterlist: can be too big for stack. */
82 struct scatterlist sg[VIRTQUEUE_NUM]; 79 struct scatterlist sg[VIRTQUEUE_NUM];
83} channels[MAX_9P_CHAN]; 80
81 struct list_head chan_list;
82};
83
84static struct list_head virtio_chan_list;
84 85
85/* How many bytes left in this page. */ 86/* How many bytes left in this page. */
86static unsigned int rest_of_page(void *data) 87static unsigned int rest_of_page(void *data)
@@ -217,9 +218,7 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req)
217 * p9_virtio_probe - probe for existence of 9P virtio channels 218 * p9_virtio_probe - probe for existence of 9P virtio channels
218 * @vdev: virtio device to probe 219 * @vdev: virtio device to probe
219 * 220 *
220 * This probes for existing virtio channels. At present only 221 * This probes for existing virtio channels.
221 * a single channel is in use, so in the future more work may need
222 * to be done here.
223 * 222 *
224 */ 223 */
225 224
@@ -227,16 +226,10 @@ static int p9_virtio_probe(struct virtio_device *vdev)
227{ 226{
228 int err; 227 int err;
229 struct virtio_chan *chan; 228 struct virtio_chan *chan;
230 int index;
231 229
232 mutex_lock(&virtio_9p_lock); 230 chan = kmalloc(sizeof(struct virtio_chan), GFP_KERNEL);
233 index = chan_index++; 231 if (!chan) {
234 chan = &channels[index]; 232 printk(KERN_ERR "9p: Failed to allocate virtio 9P channel\n");
235 mutex_unlock(&virtio_9p_lock);
236
237 if (chan_index > MAX_9P_CHAN) {
238 printk(KERN_ERR "9p: virtio: Maximum channels exceeded\n");
239 BUG();
240 err = -ENOMEM; 233 err = -ENOMEM;
241 goto fail; 234 goto fail;
242 } 235 }
@@ -255,15 +248,15 @@ static int p9_virtio_probe(struct virtio_device *vdev)
255 sg_init_table(chan->sg, VIRTQUEUE_NUM); 248 sg_init_table(chan->sg, VIRTQUEUE_NUM);
256 249
257 chan->inuse = false; 250 chan->inuse = false;
258 chan->initialized = true; 251 mutex_lock(&virtio_9p_lock);
252 list_add_tail(&chan->chan_list, &virtio_chan_list);
253 mutex_unlock(&virtio_9p_lock);
259 return 0; 254 return 0;
260 255
261out_free_vq: 256out_free_vq:
262 vdev->config->del_vqs(vdev); 257 vdev->config->del_vqs(vdev);
258 kfree(chan);
263fail: 259fail:
264 mutex_lock(&virtio_9p_lock);
265 chan_index--;
266 mutex_unlock(&virtio_9p_lock);
267 return err; 260 return err;
268} 261}
269 262
@@ -280,35 +273,27 @@ fail:
280 * We use a simple reference count mechanism to ensure that only a single 273 * We use a simple reference count mechanism to ensure that only a single
281 * mount has a channel open at a time. 274 * mount has a channel open at a time.
282 * 275 *
283 * Bugs: doesn't allow identification of a specific channel
284 * to allocate, channels are allocated sequentially. This was
285 * a pragmatic decision to get things rolling, but ideally some
286 * way of identifying the channel to attach to would be nice
287 * if we are going to support multiple channels.
288 *
289 */ 276 */
290 277
291static int 278static int
292p9_virtio_create(struct p9_client *client, const char *devname, char *args) 279p9_virtio_create(struct p9_client *client, const char *devname, char *args)
293{ 280{
294 struct virtio_chan *chan = channels; 281 struct virtio_chan *chan;
295 int index = 0; 282 int found = 0;
296 283
297 mutex_lock(&virtio_9p_lock); 284 mutex_lock(&virtio_9p_lock);
298 while (index < MAX_9P_CHAN) { 285 list_for_each_entry(chan, &virtio_chan_list, chan_list) {
299 if (chan->initialized && 286 if (!strcmp(devname, dev_name(&chan->vdev->dev))) {
300 !strcmp(devname, dev_name(&chan->vdev->dev))) {
301 if (!chan->inuse) { 287 if (!chan->inuse) {
302 chan->inuse = true; 288 chan->inuse = true;
289 found = 1;
303 break; 290 break;
304 } 291 }
305 } 292 }
306 index++;
307 chan = &channels[index];
308 } 293 }
309 mutex_unlock(&virtio_9p_lock); 294 mutex_unlock(&virtio_9p_lock);
310 295
311 if (index >= MAX_9P_CHAN) { 296 if (!found) {
312 printk(KERN_ERR "9p: no channels available\n"); 297 printk(KERN_ERR "9p: no channels available\n");
313 return -ENODEV; 298 return -ENODEV;
314 } 299 }
@@ -331,11 +316,13 @@ static void p9_virtio_remove(struct virtio_device *vdev)
331 struct virtio_chan *chan = vdev->priv; 316 struct virtio_chan *chan = vdev->priv;
332 317
333 BUG_ON(chan->inuse); 318 BUG_ON(chan->inuse);
319 vdev->config->del_vqs(vdev);
320
321 mutex_lock(&virtio_9p_lock);
322 list_del(&chan->chan_list);
323 mutex_unlock(&virtio_9p_lock);
324 kfree(chan);
334 325
335 if (chan->initialized) {
336 vdev->config->del_vqs(vdev);
337 chan->initialized = false;
338 }
339} 326}
340 327
341static struct virtio_device_id id_table[] = { 328static struct virtio_device_id id_table[] = {
@@ -366,10 +353,7 @@ static struct p9_trans_module p9_virtio_trans = {
366/* The standard init function */ 353/* The standard init function */
367static int __init p9_virtio_init(void) 354static int __init p9_virtio_init(void)
368{ 355{
369 int count; 356 INIT_LIST_HEAD(&virtio_chan_list);
370
371 for (count = 0; count < MAX_9P_CHAN; count++)
372 channels[count].initialized = false;
373 357
374 v9fs_register_trans(&p9_virtio_trans); 358 v9fs_register_trans(&p9_virtio_trans);
375 return register_virtio_driver(&p9_virtio_drv); 359 return register_virtio_driver(&p9_virtio_drv);