debuggers.hg
changeset 14657:77b210daefee
linux evtchn: Read function in evtchn driver requires locking.
Signed-off-by: Keir Fraser <keir@xensource.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
author | kfraser@localhost.localdomain |
---|---|
date | Wed Mar 28 13:52:03 2007 +0100 (2007-03-28) |
parents | 7e6ef2b914aa |
children | 72a5f76ac8dd |
files | linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c |
line diff
1.1 --- a/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c Wed Mar 28 12:38:13 2007 +0100 1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c Wed Mar 28 13:52:03 2007 +0100 1.3 @@ -56,6 +56,7 @@ struct per_user_data { 1.4 #define EVTCHN_RING_MASK(_i) ((_i)&(EVTCHN_RING_SIZE-1)) 1.5 evtchn_port_t *ring; 1.6 unsigned int ring_cons, ring_prod, ring_overflow; 1.7 + struct mutex ring_cons_mutex; /* protect against concurrent readers */ 1.8 1.9 /* Processes wait on this queue when ring is empty. */ 1.10 wait_queue_head_t evtchn_wait; 1.11 @@ -108,12 +109,17 @@ static ssize_t evtchn_read(struct file * 1.12 count = PAGE_SIZE; 1.13 1.14 for (;;) { 1.15 + mutex_lock(&u->ring_cons_mutex); 1.16 + 1.17 + rc = -EFBIG; 1.18 if (u->ring_overflow) 1.19 - return -EFBIG; 1.20 + goto unlock_out; 1.21 1.22 if ((c = u->ring_cons) != (p = u->ring_prod)) 1.23 break; 1.24 1.25 + mutex_unlock(&u->ring_cons_mutex); 1.26 + 1.27 if (file->f_flags & O_NONBLOCK) 1.28 return -EAGAIN; 1.29 1.30 @@ -141,20 +147,24 @@ static ssize_t evtchn_read(struct file * 1.31 bytes2 = count - bytes1; 1.32 } 1.33 1.34 + rc = -EFAULT; 1.35 if (copy_to_user(buf, &u->ring[EVTCHN_RING_MASK(c)], bytes1) || 1.36 ((bytes2 != 0) && 1.37 copy_to_user(&buf[bytes1], &u->ring[0], bytes2))) 1.38 - return -EFAULT; 1.39 + goto unlock_out; 1.40 1.41 u->ring_cons += (bytes1 + bytes2) / sizeof(evtchn_port_t); 1.42 + rc = bytes1 + bytes2; 1.43 1.44 - return bytes1 + bytes2; 1.45 + unlock_out: 1.46 + mutex_unlock(&u->ring_cons_mutex); 1.47 + return rc; 1.48 } 1.49 1.50 static ssize_t evtchn_write(struct file *file, const char __user *buf, 1.51 size_t count, loff_t *ppos) 1.52 { 1.53 - int rc, i; 1.54 + int rc, i; 1.55 evtchn_port_t *kbuf = (evtchn_port_t *)__get_free_page(GFP_KERNEL); 1.56 struct per_user_data *u = file->private_data; 1.57 1.58 @@ -164,18 +174,16 @@ static ssize_t evtchn_write(struct file 1.59 /* Whole number of ports. */ 1.60 count &= ~(sizeof(evtchn_port_t)-1); 1.61 1.62 - if (count == 0) { 1.63 - rc = 0; 1.64 + rc = 0; 1.65 + if (count == 0) 1.66 goto out; 1.67 - } 1.68 1.69 if (count > PAGE_SIZE) 1.70 count = PAGE_SIZE; 1.71 1.72 - if (copy_from_user(kbuf, buf, count) != 0) { 1.73 - rc = -EFAULT; 1.74 + rc = -EFAULT; 1.75 + if (copy_from_user(kbuf, buf, count) != 0) 1.76 goto out; 1.77 - } 1.78 1.79 spin_lock_irq(&port_user_lock); 1.80 for (i = 0; i < (count/sizeof(evtchn_port_t)); i++) 1.81 @@ -321,9 +329,11 @@ static int evtchn_ioctl(struct inode *in 1.82 1.83 case IOCTL_EVTCHN_RESET: { 1.84 /* Initialise the ring to empty. Clear errors. */ 1.85 + mutex_lock(&u->ring_cons_mutex); 1.86 spin_lock_irq(&port_user_lock); 1.87 u->ring_cons = u->ring_prod = u->ring_overflow = 0; 1.88 spin_unlock_irq(&port_user_lock); 1.89 + mutex_unlock(&u->ring_cons_mutex); 1.90 rc = 0; 1.91 break; 1.92 } 1.93 @@ -371,6 +381,8 @@ static int evtchn_open(struct inode *ino 1.94 return -ENOMEM; 1.95 } 1.96 1.97 + mutex_init(&u->ring_cons_mutex); 1.98 + 1.99 filp->private_data = u; 1.100 1.101 return 0;