Re: usblp: add dynamic URBs, fix races

Oliver Neukum <[email protected]>
Newsgroups gmane.linux.usb.devel
Organization Novell
Message-ID <[email protected]>
> +	if (urb->status < 0)
> +		usblp->rstatus = urb->status;
> +	else
> +		usblp->rstatus = urb->actual_length;
>  	usblp->rcomplete = 1;
> -unplug:
> -	wake_up_interruptible(&usblp->wait);
> +	wake_up(&usblp->rwait);

Why no longer _interruptible ?

> +	spin_lock(&usblp->lock);
> +	if (urb->status < 0)
> +		usblp->wstatus = urb->status;
> +	else
> +		usblp->wstatus = urb->actual_length;

This raises the question why an error would mean that no payload
has been transfered.

> +	/* XXX Use usb_setup_bulk_urb when available. Talk to Marcel. */
> +	kfree(urb->transfer_buffer);
> +	urb->transfer_buffer = NULL;	/* Not refcounted, so to be safe... */
> +	usb_free_urb(urb);

If you want to be safe, do it without a race.
  
>  static void usblp_unlink_urbs(struct usblp *usblp)
>  {
> -	usb_kill_urb(usblp->writeurb);
> -	if (usblp->bidir)
> -		usb_kill_urb(usblp->readurb);
> +	usb_kill_anchored_urbs(&usblp->urbs);
>  }

What good does encapsulation here?
>  
>  static int usblp_release(struct inode *inode, struct file *file)
> @@ -455,10 +475,18 @@ static int usblp_release(struct inode *i
>  /* No kernel lock - fine */
>  static unsigned int usblp_poll(struct file *file, struct poll_table_struct *wait)
>  {
> +	int ret;
> +	unsigned long flags;

We are called with interrupts on.

> +
>  	struct usblp *usblp = file->private_data;
> -	poll_wait(file, &usblp->wait, wait);
> - 	return ((!usblp->bidir || !usblp->rcomplete) ? 0 : POLLIN  | POLLRDNORM)
> +	/* Should we check file->f_mode & FMODE_WRITE before poll_wait()? */
> +	poll_wait(file, &usblp->rwait, wait);
> +	poll_wait(file, &usblp->wwait, wait);
> +	spin_lock_irqsave(&usblp->lock, flags);
> +	ret = ((!usblp->bidir || !usblp->rcomplete) ? 0 : POLLIN  | POLLRDNORM)
>   			       | (!usblp->wcomplete ? 0 : POLLOUT | POLLWRNORM);
> +	spin_unlock_irqrestore(&usblp->lock, flags);
> +	return ret;
>  }

Shouldn't disconnect cause an error to be reported?

> @@ -656,168 +685,303 @@ done:
>  static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
>  {
>  	struct usblp *usblp = file->private_data;
> -	int timeout, intr, rv, err = 0, transfer_length = 0;
> -	size_t writecount = 0;
> +	char *writebuf;
> +	struct urb *writeurb;
> +	int rv;
> +	int transfer_length;
> +	ssize_t writecount = 0;
> +
> +	if (mutex_lock_interruptible(&usblp->wmut)) {
> +		rv = -EINTR;

Why not -ERESTARTSYS ?

> +static int usblp_rtest(struct usblp *usblp, int nonblock)
> +{
> +	unsigned long flags;

We know interrupts are enabled.

Otherwise it looks very good. Thanks for taking up this old code.

	Regards
		Oliver

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.