[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


 


Rackspace

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