ia64/xen-unstable

changeset 14620:f9d23364567a

[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@xensource.com>
author Christian Limpach <Christian.Limpach@xensource.com>
date Wed Mar 28 11:01:58 2007 +0100 (2007-03-28)
parents 4c5ea17290fe
children 7e6ef2b914aa
files linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c
line diff
     1.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c	Wed Mar 28 10:41:53 2007 +0100
     1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c	Wed Mar 28 11:01:58 2007 +0100
     1.3 @@ -58,6 +58,13 @@ struct xenbus_dev_transaction {
     1.4  	struct xenbus_transaction handle;
     1.5  };
     1.6  
     1.7 +struct read_buffer {
     1.8 +	struct list_head list;
     1.9 +	unsigned int cons;
    1.10 +	unsigned int len;
    1.11 +	char msg[];
    1.12 +};
    1.13 +
    1.14  struct xenbus_dev_data {
    1.15  	/* In-progress transaction. */
    1.16  	struct list_head transactions;
    1.17 @@ -73,9 +80,7 @@ struct xenbus_dev_data {
    1.18  	} u;
    1.19  
    1.20  	/* Response queue. */
    1.21 -#define MASK_READ_IDX(idx) ((idx)&(PAGE_SIZE-1))
    1.22 -	char read_buffer[PAGE_SIZE];
    1.23 -	unsigned int read_cons, read_prod;
    1.24 +	struct list_head read_buffers;
    1.25  	wait_queue_head_t read_waitq;
    1.26  
    1.27  	struct mutex reply_mutex;
    1.28 @@ -88,18 +93,34 @@ static ssize_t xenbus_dev_read(struct fi
    1.29  			       size_t len, loff_t *ppos)
    1.30  {
    1.31  	struct xenbus_dev_data *u = filp->private_data;
    1.32 -	int i;
    1.33 +	struct read_buffer *rb;
    1.34 +	int i, ret;
    1.35  
    1.36 -	if (wait_event_interruptible(u->read_waitq,
    1.37 -				     u->read_prod != u->read_cons))
    1.38 -		return -EINTR;
    1.39 +	mutex_lock(&u->reply_mutex);
    1.40 +	while (list_empty(&u->read_buffers)) {
    1.41 +		mutex_unlock(&u->reply_mutex);
    1.42 +		ret = wait_event_interruptible(u->read_waitq,
    1.43 +					       !list_empty(&u->read_buffers));
    1.44 +		if (ret)
    1.45 +			return ret;
    1.46 +		mutex_lock(&u->reply_mutex);
    1.47 +	}
    1.48  
    1.49 -	for (i = 0; i < len; i++) {
    1.50 -		if (u->read_cons == u->read_prod)
    1.51 -			break;
    1.52 -		put_user(u->read_buffer[MASK_READ_IDX(u->read_cons)], ubuf+i);
    1.53 -		u->read_cons++;
    1.54 +	rb = list_entry(u->read_buffers.next, struct read_buffer, list);
    1.55 +	for (i = 0; i < len;) {
    1.56 +		put_user(rb->msg[rb->cons], ubuf + i);
    1.57 +		i++;
    1.58 +		rb->cons++;
    1.59 +		if (rb->cons == rb->len) {
    1.60 +			list_del(&rb->list);
    1.61 +			kfree(rb);
    1.62 +			if (list_empty(&u->read_buffers))
    1.63 +				break;
    1.64 +			rb = list_entry(u->read_buffers.next,
    1.65 +					struct read_buffer, list);
    1.66 +		}
    1.67  	}
    1.68 +	mutex_unlock(&u->reply_mutex);
    1.69  
    1.70  	return i;
    1.71  }
    1.72 @@ -107,16 +128,20 @@ static ssize_t xenbus_dev_read(struct fi
    1.73  static void queue_reply(struct xenbus_dev_data *u,
    1.74  			char *data, unsigned int len)
    1.75  {
    1.76 -	int i;
    1.77 +	struct read_buffer *rb;
    1.78  
    1.79 -	mutex_lock(&u->reply_mutex);
    1.80 +	if (len == 0)
    1.81 +		return;
    1.82  
    1.83 -	for (i = 0; i < len; i++, u->read_prod++)
    1.84 -		u->read_buffer[MASK_READ_IDX(u->read_prod)] = data[i];
    1.85 +	rb = kmalloc(sizeof(*rb) + len, GFP_KERNEL);
    1.86 +	BUG_ON(rb == NULL);
    1.87  
    1.88 -	BUG_ON((u->read_prod - u->read_cons) > sizeof(u->read_buffer));
    1.89 +	rb->cons = 0;
    1.90 +	rb->len = len;
    1.91  
    1.92 -	mutex_unlock(&u->reply_mutex);
    1.93 +	memcpy(rb->msg, data, len);
    1.94 +
    1.95 +	list_add_tail(&rb->list, &u->read_buffers);
    1.96  
    1.97  	wake_up(&u->read_waitq);
    1.98  }
    1.99 @@ -155,10 +180,12 @@ static void watch_fired(struct xenbus_wa
   1.100  
   1.101  	hdr.type = XS_WATCH_EVENT;
   1.102  	hdr.len = body_len;
   1.103 -	
   1.104 +
   1.105 +	mutex_lock(&adap->dev_data->reply_mutex);
   1.106  	queue_reply(adap->dev_data, (char *)&hdr, sizeof(hdr));
   1.107  	queue_reply(adap->dev_data, (char *)path, path_len);
   1.108  	queue_reply(adap->dev_data, (char *)token, tok_len);
   1.109 +	mutex_unlock(&adap->dev_data->reply_mutex);
   1.110  }
   1.111  
   1.112  static LIST_HEAD(watch_list);
   1.113 @@ -230,8 +257,10 @@ static ssize_t xenbus_dev_write(struct f
   1.114  			list_del(&trans->list);
   1.115  			kfree(trans);
   1.116  		}
   1.117 +		mutex_lock(&u->reply_mutex);
   1.118  		queue_reply(u, (char *)&u->u.msg, sizeof(u->u.msg));
   1.119  		queue_reply(u, (char *)reply, u->u.msg.len);
   1.120 +		mutex_unlock(&u->reply_mutex);
   1.121  		kfree(reply);
   1.122  		break;
   1.123  
   1.124 @@ -282,8 +311,10 @@ static ssize_t xenbus_dev_write(struct f
   1.125  
   1.126  		hdr.type = msg_type;
   1.127  		hdr.len = strlen(XS_RESP) + 1;
   1.128 +		mutex_lock(&u->reply_mutex);
   1.129  		queue_reply(u, (char *)&hdr, sizeof(hdr));
   1.130  		queue_reply(u, (char *)XS_RESP, hdr.len);
   1.131 +		mutex_unlock(&u->reply_mutex);
   1.132  		break;
   1.133  	}
   1.134  
   1.135 @@ -312,6 +343,7 @@ static int xenbus_dev_open(struct inode 
   1.136  
   1.137  	INIT_LIST_HEAD(&u->transactions);
   1.138  	INIT_LIST_HEAD(&u->watches);
   1.139 +	INIT_LIST_HEAD(&u->read_buffers);
   1.140  	init_waitqueue_head(&u->read_waitq);
   1.141  
   1.142  	mutex_init(&u->reply_mutex);
   1.143 @@ -349,7 +381,7 @@ static unsigned int xenbus_dev_poll(stru
   1.144  	struct xenbus_dev_data *u = file->private_data;
   1.145  
   1.146  	poll_wait(file, &u->read_waitq, wait);
   1.147 -	if (u->read_cons != u->read_prod)
   1.148 +	if (!list_empty(&u->read_buffers))
   1.149  		return POLLIN | POLLRDNORM;
   1.150  	return 0;
   1.151  }