net/9p: Remove MAX_9P_CHAN limit
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Mon, 15 Feb 2010 17:27:01 +0000 (17:27 +0000)
committerEric Van Hensbergen <ericvh@gmail.com>
Fri, 5 Mar 2010 21:04:41 +0000 (15:04 -0600)
Use a list to track the channel instead of statically
allocated array

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
include/linux/virtio_9p.h
net/9p/trans_virtio.c

index 7a615c3..3322750 100644 (file)
@@ -5,7 +5,4 @@
 #include <linux/virtio_ids.h>
 #include <linux/virtio_config.h>
 
-/* Maximum number of virtio channels per partition (1 for now) */
-#define MAX_9P_CHAN    10
-
 #endif /* _LINUX_VIRTIO_9P_H */
index df924e5..05918d3 100644 (file)
@@ -49,8 +49,6 @@
 
 /* a single mutex to manage channel initialization and attachment */
 static DEFINE_MUTEX(virtio_9p_lock);
-/* global which tracks highest initialized channel */
-static int chan_index;
 
 /**
  * struct virtio_chan - per-instance transport information
@@ -68,8 +66,7 @@ static int chan_index;
  *
  */
 
-static struct virtio_chan {
-       bool initialized;
+struct virtio_chan {
        bool inuse;
 
        spinlock_t lock;
@@ -80,7 +77,11 @@ static struct virtio_chan {
 
        /* Scatterlist: can be too big for stack. */
        struct scatterlist sg[VIRTQUEUE_NUM];
-} channels[MAX_9P_CHAN];
+
+       struct list_head chan_list;
+};
+
+static struct list_head virtio_chan_list;
 
 /* How many bytes left in this page. */
 static unsigned int rest_of_page(void *data)
@@ -217,9 +218,7 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req)
  * p9_virtio_probe - probe for existence of 9P virtio channels
  * @vdev: virtio device to probe
  *
- * This probes for existing virtio channels.  At present only
- * a single channel is in use, so in the future more work may need
- * to be done here.
+ * This probes for existing virtio channels.
  *
  */
 
@@ -227,16 +226,10 @@ static int p9_virtio_probe(struct virtio_device *vdev)
 {
        int err;
        struct virtio_chan *chan;
-       int index;
 
-       mutex_lock(&virtio_9p_lock);
-       index = chan_index++;
-       chan = &channels[index];
-       mutex_unlock(&virtio_9p_lock);
-
-       if (chan_index > MAX_9P_CHAN) {
-               printk(KERN_ERR "9p: virtio: Maximum channels exceeded\n");
-               BUG();
+       chan = kmalloc(sizeof(struct virtio_chan), GFP_KERNEL);
+       if (!chan) {
+               printk(KERN_ERR "9p: Failed to allocate virtio 9P channel\n");
                err = -ENOMEM;
                goto fail;
        }
@@ -255,15 +248,15 @@ static int p9_virtio_probe(struct virtio_device *vdev)
        sg_init_table(chan->sg, VIRTQUEUE_NUM);
 
        chan->inuse = false;
-       chan->initialized = true;
+       mutex_lock(&virtio_9p_lock);
+       list_add_tail(&chan->chan_list, &virtio_chan_list);
+       mutex_unlock(&virtio_9p_lock);
        return 0;
 
 out_free_vq:
        vdev->config->del_vqs(vdev);
+       kfree(chan);
 fail:
-       mutex_lock(&virtio_9p_lock);
-       chan_index--;
-       mutex_unlock(&virtio_9p_lock);
        return err;
 }
 
@@ -280,35 +273,27 @@ fail:
  * We use a simple reference count mechanism to ensure that only a single
  * mount has a channel open at a time.
  *
- * Bugs: doesn't allow identification of a specific channel
- * to allocate, channels are allocated sequentially. This was
- * a pragmatic decision to get things rolling, but ideally some
- * way of identifying the channel to attach to would be nice
- * if we are going to support multiple channels.
- *
  */
 
 static int
 p9_virtio_create(struct p9_client *client, const char *devname, char *args)
 {
-       struct virtio_chan *chan = channels;
-       int index = 0;
+       struct virtio_chan *chan;
+       int found = 0;
 
        mutex_lock(&virtio_9p_lock);
-       while (index < MAX_9P_CHAN) {
-               if (chan->initialized &&
-                       !strcmp(devname, dev_name(&chan->vdev->dev))) {
+       list_for_each_entry(chan, &virtio_chan_list, chan_list) {
+               if (!strcmp(devname, dev_name(&chan->vdev->dev))) {
                        if (!chan->inuse) {
                                chan->inuse = true;
+                               found = 1;
                                break;
                        }
                }
-               index++;
-               chan = &channels[index];
        }
        mutex_unlock(&virtio_9p_lock);
 
-       if (index >= MAX_9P_CHAN) {
+       if (!found) {
                printk(KERN_ERR "9p: no channels available\n");
                return -ENODEV;
        }
@@ -331,11 +316,13 @@ static void p9_virtio_remove(struct virtio_device *vdev)
        struct virtio_chan *chan = vdev->priv;
 
        BUG_ON(chan->inuse);
+       vdev->config->del_vqs(vdev);
+
+       mutex_lock(&virtio_9p_lock);
+       list_del(&chan->chan_list);
+       mutex_unlock(&virtio_9p_lock);
+       kfree(chan);
 
-       if (chan->initialized) {
-               vdev->config->del_vqs(vdev);
-               chan->initialized = false;
-       }
 }
 
 static struct virtio_device_id id_table[] = {
@@ -366,10 +353,7 @@ static struct p9_trans_module p9_virtio_trans = {
 /* The standard init function */
 static int __init p9_virtio_init(void)
 {
-       int count;
-
-       for (count = 0; count < MAX_9P_CHAN; count++)
-               channels[count].initialized = false;
+       INIT_LIST_HEAD(&virtio_chan_list);
 
        v9fs_register_trans(&p9_virtio_trans);
        return register_virtio_driver(&p9_virtio_drv);