[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] linux evtchn: Read function in evtchn driver requires locking.
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Date 1175086323 -3600 # Node ID 77b210daefee957faa220e94501ace6bf50e3b97 # Parent 7e6ef2b914aa739c51f15b0700aa54de41b4707d linux evtchn: Read function in evtchn driver requires locking. Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> --- linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c | 34 +++++++++++++++-------- 1 files changed, 23 insertions(+), 11 deletions(-) diff -r 7e6ef2b914aa -r 77b210daefee linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c --- a/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c Wed Mar 28 12:38:13 2007 +0100 +++ b/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c Wed Mar 28 13:52:03 2007 +0100 @@ -56,6 +56,7 @@ struct per_user_data { #define EVTCHN_RING_MASK(_i) ((_i)&(EVTCHN_RING_SIZE-1)) evtchn_port_t *ring; unsigned int ring_cons, ring_prod, ring_overflow; + struct mutex ring_cons_mutex; /* protect against concurrent readers */ /* Processes wait on this queue when ring is empty. */ wait_queue_head_t evtchn_wait; @@ -108,11 +109,16 @@ static ssize_t evtchn_read(struct file * count = PAGE_SIZE; for (;;) { + mutex_lock(&u->ring_cons_mutex); + + rc = -EFBIG; if (u->ring_overflow) - return -EFBIG; + goto unlock_out; if ((c = u->ring_cons) != (p = u->ring_prod)) break; + + mutex_unlock(&u->ring_cons_mutex); if (file->f_flags & O_NONBLOCK) return -EAGAIN; @@ -141,20 +147,24 @@ static ssize_t evtchn_read(struct file * bytes2 = count - bytes1; } + rc = -EFAULT; if (copy_to_user(buf, &u->ring[EVTCHN_RING_MASK(c)], bytes1) || ((bytes2 != 0) && copy_to_user(&buf[bytes1], &u->ring[0], bytes2))) - return -EFAULT; + goto unlock_out; u->ring_cons += (bytes1 + bytes2) / sizeof(evtchn_port_t); - - return bytes1 + bytes2; + rc = bytes1 + bytes2; + + unlock_out: + mutex_unlock(&u->ring_cons_mutex); + return rc; } static ssize_t evtchn_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - int rc, i; + int rc, i; evtchn_port_t *kbuf = (evtchn_port_t *)__get_free_page(GFP_KERNEL); struct per_user_data *u = file->private_data; @@ -164,18 +174,16 @@ static ssize_t evtchn_write(struct file /* Whole number of ports. */ count &= ~(sizeof(evtchn_port_t)-1); - if (count == 0) { - rc = 0; + rc = 0; + if (count == 0) goto out; - } if (count > PAGE_SIZE) count = PAGE_SIZE; - if (copy_from_user(kbuf, buf, count) != 0) { - rc = -EFAULT; + rc = -EFAULT; + if (copy_from_user(kbuf, buf, count) != 0) goto out; - } spin_lock_irq(&port_user_lock); for (i = 0; i < (count/sizeof(evtchn_port_t)); i++) @@ -321,9 +329,11 @@ static int evtchn_ioctl(struct inode *in case IOCTL_EVTCHN_RESET: { /* Initialise the ring to empty. Clear errors. */ + mutex_lock(&u->ring_cons_mutex); spin_lock_irq(&port_user_lock); u->ring_cons = u->ring_prod = u->ring_overflow = 0; spin_unlock_irq(&port_user_lock); + mutex_unlock(&u->ring_cons_mutex); rc = 0; break; } @@ -370,6 +380,8 @@ static int evtchn_open(struct inode *ino kfree(u); return -ENOMEM; } + + mutex_init(&u->ring_cons_mutex); filp->private_data = u; _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |