Skip to content

Commit

Permalink
USB: Remove BKL from poll()
Browse files Browse the repository at this point in the history
Replace BKL with usbfs_mutex to protect a global counter
and a per file data structure

Signed-off-by: Oliver Neukum <oliver@neukum.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Oliver Neukum authored and Greg Kroah-Hartman committed Mar 2, 2010
1 parent 08add0c commit 554f769
Showing 1 changed file with 9 additions and 19 deletions.
28 changes: 9 additions & 19 deletions drivers/usb/core/devices.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ static const char *format_endpt =
*/

static DECLARE_WAIT_QUEUE_HEAD(deviceconndiscwq);
/* guarded by usbfs_mutex */
static unsigned int conndiscevcnt;

/* this struct stores the poll state for <mountpoint>/devices pollers */
Expand Down Expand Up @@ -156,7 +157,9 @@ static const struct class_info clas_info[] =

void usbfs_conn_disc_event(void)
{
mutex_lock(&usbfs_mutex);
conndiscevcnt++;
mutex_unlock(&usbfs_mutex);
wake_up(&deviceconndiscwq);
}

Expand Down Expand Up @@ -629,42 +632,29 @@ static ssize_t usb_device_read(struct file *file, char __user *buf,
static unsigned int usb_device_poll(struct file *file,
struct poll_table_struct *wait)
{
struct usb_device_status *st = file->private_data;
struct usb_device_status *st;
unsigned int mask = 0;

lock_kernel();
mutex_lock(&usbfs_mutex);
st = file->private_data;
if (!st) {
st = kmalloc(sizeof(struct usb_device_status), GFP_KERNEL);

/* we may have dropped BKL -
* need to check for having lost the race */
if (file->private_data) {
kfree(st);
st = file->private_data;
goto lost_race;
}
/* we haven't lost - check for allocation failure now */
if (!st) {
unlock_kernel();
mutex_unlock(&usbfs_mutex);
return POLLIN;
}

/*
* need to prevent the module from being unloaded, since
* proc_unregister does not call the release method and
* we would have a memory leak
*/
st->lastev = conndiscevcnt;
file->private_data = st;
mask = POLLIN;
}
lost_race:

if (file->f_mode & FMODE_READ)
poll_wait(file, &deviceconndiscwq, wait);
if (st->lastev != conndiscevcnt)
mask |= POLLIN;
st->lastev = conndiscevcnt;
unlock_kernel();
mutex_unlock(&usbfs_mutex);
return mask;
}

Expand Down

0 comments on commit 554f769

Please sign in to comment.