[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [linux] Fix xenbus device to allow replies larger than 4096 bytes.



# HG changeset patch
# User Christian Limpach <Christian.Limpach@xxxxxxxxxxxxx>
# Date 1175076118 -3600
# Node ID f9d23364567aef2430c47ac6e451c6b7ed0bf959
# Parent  4c5ea17290fe4157d657d46d220f47a1a9ed8256
[linux] Fix xenbus device to allow replies larger than 4096 bytes.
Also fix reply_queue mutex across fragmented replies and for concurrent
readers.

Signed-off-by: Christian Limpach <Christian.Limpach@xxxxxxxxxxxxx>
---
 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c |   86 +++++++++++++------
 1 files changed, 59 insertions(+), 27 deletions(-)

diff -r 4c5ea17290fe -r f9d23364567a 
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c      Wed Mar 28 
10:41:53 2007 +0100
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c      Wed Mar 28 
11:01:58 2007 +0100
@@ -58,6 +58,13 @@ struct xenbus_dev_transaction {
        struct xenbus_transaction handle;
 };
 
+struct read_buffer {
+       struct list_head list;
+       unsigned int cons;
+       unsigned int len;
+       char msg[];
+};
+
 struct xenbus_dev_data {
        /* In-progress transaction. */
        struct list_head transactions;
@@ -73,9 +80,7 @@ struct xenbus_dev_data {
        } u;
 
        /* Response queue. */
-#define MASK_READ_IDX(idx) ((idx)&(PAGE_SIZE-1))
-       char read_buffer[PAGE_SIZE];
-       unsigned int read_cons, read_prod;
+       struct list_head read_buffers;
        wait_queue_head_t read_waitq;
 
        struct mutex reply_mutex;
@@ -88,18 +93,34 @@ static ssize_t xenbus_dev_read(struct fi
                               size_t len, loff_t *ppos)
 {
        struct xenbus_dev_data *u = filp->private_data;
-       int i;
-
-       if (wait_event_interruptible(u->read_waitq,
-                                    u->read_prod != u->read_cons))
-               return -EINTR;
-
-       for (i = 0; i < len; i++) {
-               if (u->read_cons == u->read_prod)
-                       break;
-               put_user(u->read_buffer[MASK_READ_IDX(u->read_cons)], ubuf+i);
-               u->read_cons++;
-       }
+       struct read_buffer *rb;
+       int i, ret;
+
+       mutex_lock(&u->reply_mutex);
+       while (list_empty(&u->read_buffers)) {
+               mutex_unlock(&u->reply_mutex);
+               ret = wait_event_interruptible(u->read_waitq,
+                                              !list_empty(&u->read_buffers));
+               if (ret)
+                       return ret;
+               mutex_lock(&u->reply_mutex);
+       }
+
+       rb = list_entry(u->read_buffers.next, struct read_buffer, list);
+       for (i = 0; i < len;) {
+               put_user(rb->msg[rb->cons], ubuf + i);
+               i++;
+               rb->cons++;
+               if (rb->cons == rb->len) {
+                       list_del(&rb->list);
+                       kfree(rb);
+                       if (list_empty(&u->read_buffers))
+                               break;
+                       rb = list_entry(u->read_buffers.next,
+                                       struct read_buffer, list);
+               }
+       }
+       mutex_unlock(&u->reply_mutex);
 
        return i;
 }
@@ -107,16 +128,20 @@ static void queue_reply(struct xenbus_de
 static void queue_reply(struct xenbus_dev_data *u,
                        char *data, unsigned int len)
 {
-       int i;
-
-       mutex_lock(&u->reply_mutex);
-
-       for (i = 0; i < len; i++, u->read_prod++)
-               u->read_buffer[MASK_READ_IDX(u->read_prod)] = data[i];
-
-       BUG_ON((u->read_prod - u->read_cons) > sizeof(u->read_buffer));
-
-       mutex_unlock(&u->reply_mutex);
+       struct read_buffer *rb;
+
+       if (len == 0)
+               return;
+
+       rb = kmalloc(sizeof(*rb) + len, GFP_KERNEL);
+       BUG_ON(rb == NULL);
+
+       rb->cons = 0;
+       rb->len = len;
+
+       memcpy(rb->msg, data, len);
+
+       list_add_tail(&rb->list, &u->read_buffers);
 
        wake_up(&u->read_waitq);
 }
@@ -155,10 +180,12 @@ static void watch_fired(struct xenbus_wa
 
        hdr.type = XS_WATCH_EVENT;
        hdr.len = body_len;
-       
+
+       mutex_lock(&adap->dev_data->reply_mutex);
        queue_reply(adap->dev_data, (char *)&hdr, sizeof(hdr));
        queue_reply(adap->dev_data, (char *)path, path_len);
        queue_reply(adap->dev_data, (char *)token, tok_len);
+       mutex_unlock(&adap->dev_data->reply_mutex);
 }
 
 static LIST_HEAD(watch_list);
@@ -230,8 +257,10 @@ static ssize_t xenbus_dev_write(struct f
                        list_del(&trans->list);
                        kfree(trans);
                }
+               mutex_lock(&u->reply_mutex);
                queue_reply(u, (char *)&u->u.msg, sizeof(u->u.msg));
                queue_reply(u, (char *)reply, u->u.msg.len);
+               mutex_unlock(&u->reply_mutex);
                kfree(reply);
                break;
 
@@ -282,8 +311,10 @@ static ssize_t xenbus_dev_write(struct f
 
                hdr.type = msg_type;
                hdr.len = strlen(XS_RESP) + 1;
+               mutex_lock(&u->reply_mutex);
                queue_reply(u, (char *)&hdr, sizeof(hdr));
                queue_reply(u, (char *)XS_RESP, hdr.len);
+               mutex_unlock(&u->reply_mutex);
                break;
        }
 
@@ -312,6 +343,7 @@ static int xenbus_dev_open(struct inode 
 
        INIT_LIST_HEAD(&u->transactions);
        INIT_LIST_HEAD(&u->watches);
+       INIT_LIST_HEAD(&u->read_buffers);
        init_waitqueue_head(&u->read_waitq);
 
        mutex_init(&u->reply_mutex);
@@ -349,7 +381,7 @@ static unsigned int xenbus_dev_poll(stru
        struct xenbus_dev_data *u = file->private_data;
 
        poll_wait(file, &u->read_waitq, wait);
-       if (u->read_cons != u->read_prod)
+       if (!list_empty(&u->read_buffers))
                return POLLIN | POLLRDNORM;
        return 0;
 }

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.