USB: Remove BKL from poll()
authorOliver Neukum <oliver@neukum.org>
Wed, 13 Jan 2010 14:30:47 +0000 (15:30 +0100)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 2 Mar 2010 22:54:22 +0000 (14:54 -0800)
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>
drivers/usb/core/devices.c

index 355dffc..175529f 100644 (file)
@@ -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 */
@@ -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);
 }
 
@@ -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;
 }