diff options
author | Oliver Neukum <oliver@neukum.org> | 2010-01-13 15:30:47 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-03-02 14:54:22 -0800 |
commit | 554f76962d3a6eb5110415f1591aca83f96a84ae (patch) | |
tree | 8b0408fafca6558b626be65eed95a52587f32b1b | |
parent | 08add0c780b9f5c35de49d83abb7a4e14a9cd457 (diff) |
USB: Remove BKL from poll()
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>
-rw-r--r-- | drivers/usb/core/devices.c | 28 |
1 files changed, 9 insertions, 19 deletions
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index 355dffcc23b..175529fd02f 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -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; } |