ia64/xen-unstable

changeset 14622:77b210daefee

linux evtchn: Read function in evtchn driver requires locking.
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;