ia64/xen-unstable

changeset 7276:e69413dca684

Fix locking in /dev/xen/evtchn ioctl.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Sat Oct 08 10:22:01 2005 +0100 (2005-10-08)
parents 801b2bd7ef2e
children 2144de6eabcc
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	Sat Oct 08 09:54:06 2005 +0100
     1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c	Sat Oct 08 10:22:01 2005 +0100
     1.3 @@ -206,6 +206,15 @@ static ssize_t evtchn_write(struct file 
     1.4  	return rc;
     1.5  }
     1.6  
     1.7 +static void evtchn_bind_to_user(struct per_user_data *u, int port)
     1.8 +{
     1.9 +	spin_lock_irq(&port_user_lock);
    1.10 +	BUG_ON(port_user[port] != NULL);
    1.11 +	port_user[port] = u;
    1.12 +	unmask_evtchn(port);
    1.13 +	spin_unlock_irq(&port_user_lock);
    1.14 +}
    1.15 +
    1.16  static int evtchn_ioctl(struct inode *inode, struct file *file,
    1.17                          unsigned int cmd, unsigned long arg)
    1.18  {
    1.19 @@ -213,8 +222,6 @@ static int evtchn_ioctl(struct inode *in
    1.20  	struct per_user_data *u = file->private_data;
    1.21  	evtchn_op_t op = { 0 };
    1.22  
    1.23 -	spin_lock_irq(&port_user_lock);
    1.24 -    
    1.25  	switch (cmd) {
    1.26  	case IOCTL_EVTCHN_BIND_VIRQ: {
    1.27  		struct ioctl_evtchn_bind_virq bind;
    1.28 @@ -231,8 +238,7 @@ static int evtchn_ioctl(struct inode *in
    1.29  			break;
    1.30  
    1.31  		rc = op.u.bind_virq.port;
    1.32 -		port_user[rc] = u;
    1.33 -		unmask_evtchn(rc);
    1.34 +		evtchn_bind_to_user(u, rc);
    1.35  		break;
    1.36  	}
    1.37  
    1.38 @@ -251,8 +257,7 @@ static int evtchn_ioctl(struct inode *in
    1.39  			break;
    1.40  
    1.41  		rc = op.u.bind_interdomain.local_port;
    1.42 -		port_user[rc] = u;
    1.43 -		unmask_evtchn(rc);
    1.44 +		evtchn_bind_to_user(u, rc);
    1.45  		break;
    1.46  	}
    1.47  
    1.48 @@ -271,8 +276,7 @@ static int evtchn_ioctl(struct inode *in
    1.49  			break;
    1.50  
    1.51  		rc = op.u.alloc_unbound.port;
    1.52 -		port_user[rc] = u;
    1.53 -		unmask_evtchn(rc);
    1.54 +		evtchn_bind_to_user(u, rc);
    1.55  		break;
    1.56  	}
    1.57  
    1.58 @@ -283,20 +287,28 @@ static int evtchn_ioctl(struct inode *in
    1.59  		if (copy_from_user(&unbind, (void *)arg, sizeof(unbind)))
    1.60  			break;
    1.61  
    1.62 -		if (unbind.port >= NR_EVENT_CHANNELS) {
    1.63 -			rc = -EINVAL;
    1.64 -		} else if (port_user[unbind.port] != u) {
    1.65 -			rc = -ENOTCONN;
    1.66 -		} else {
    1.67 -			port_user[unbind.port] = NULL;
    1.68 -			mask_evtchn(unbind.port);
    1.69 +		rc = -EINVAL;
    1.70 +		if (unbind.port >= NR_EVENT_CHANNELS)
    1.71 +			break;
    1.72  
    1.73 -			op.cmd = EVTCHNOP_close;
    1.74 -			op.u.close.port = unbind.port;
    1.75 -			BUG_ON(HYPERVISOR_event_channel_op(&op));
    1.76 +		spin_lock_irq(&port_user_lock);
    1.77 +    
    1.78 +		rc = -ENOTCONN;
    1.79 +		if (port_user[unbind.port] != u) {
    1.80 +			spin_unlock_irq(&port_user_lock);
    1.81 +			break;
    1.82 +		}
    1.83  
    1.84 -			rc = 0;
    1.85 -		}
    1.86 +		port_user[unbind.port] = NULL;
    1.87 +		mask_evtchn(unbind.port);
    1.88 +
    1.89 +		spin_unlock_irq(&port_user_lock);
    1.90 +
    1.91 +		op.cmd = EVTCHNOP_close;
    1.92 +		op.u.close.port = unbind.port;
    1.93 +		BUG_ON(HYPERVISOR_event_channel_op(&op));
    1.94 +
    1.95 +		rc = 0;
    1.96  		break;
    1.97  	}
    1.98  
    1.99 @@ -320,7 +332,9 @@ static int evtchn_ioctl(struct inode *in
   1.100  
   1.101  	case IOCTL_EVTCHN_RESET: {
   1.102  		/* Initialise the ring to empty. Clear errors. */
   1.103 +		spin_lock_irq(&port_user_lock);
   1.104  		u->ring_cons = u->ring_prod = u->ring_overflow = 0;
   1.105 +		spin_unlock_irq(&port_user_lock);
   1.106  		rc = 0;
   1.107  		break;
   1.108  	}
   1.109 @@ -330,8 +344,6 @@ static int evtchn_ioctl(struct inode *in
   1.110  		break;
   1.111  	}
   1.112  
   1.113 -	spin_unlock_irq(&port_user_lock);   
   1.114 -
   1.115  	return rc;
   1.116  }
   1.117