mirror of
https://github.com/torvalds/linux.git
synced 2024-11-02 10:11:36 +00:00
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>
This commit is contained in:
parent
08add0c780
commit
554f76962d
@ -118,6 +118,7 @@ static const char *format_endpt =
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static DECLARE_WAIT_QUEUE_HEAD(deviceconndiscwq);
|
static DECLARE_WAIT_QUEUE_HEAD(deviceconndiscwq);
|
||||||
|
/* guarded by usbfs_mutex */
|
||||||
static unsigned int conndiscevcnt;
|
static unsigned int conndiscevcnt;
|
||||||
|
|
||||||
/* this struct stores the poll state for <mountpoint>/devices pollers */
|
/* 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)
|
void usbfs_conn_disc_event(void)
|
||||||
{
|
{
|
||||||
|
mutex_lock(&usbfs_mutex);
|
||||||
conndiscevcnt++;
|
conndiscevcnt++;
|
||||||
|
mutex_unlock(&usbfs_mutex);
|
||||||
wake_up(&deviceconndiscwq);
|
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,
|
static unsigned int usb_device_poll(struct file *file,
|
||||||
struct poll_table_struct *wait)
|
struct poll_table_struct *wait)
|
||||||
{
|
{
|
||||||
struct usb_device_status *st = file->private_data;
|
struct usb_device_status *st;
|
||||||
unsigned int mask = 0;
|
unsigned int mask = 0;
|
||||||
|
|
||||||
lock_kernel();
|
mutex_lock(&usbfs_mutex);
|
||||||
|
st = file->private_data;
|
||||||
if (!st) {
|
if (!st) {
|
||||||
st = kmalloc(sizeof(struct usb_device_status), GFP_KERNEL);
|
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) {
|
if (!st) {
|
||||||
unlock_kernel();
|
mutex_unlock(&usbfs_mutex);
|
||||||
return POLLIN;
|
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;
|
st->lastev = conndiscevcnt;
|
||||||
file->private_data = st;
|
file->private_data = st;
|
||||||
mask = POLLIN;
|
mask = POLLIN;
|
||||||
}
|
}
|
||||||
lost_race:
|
|
||||||
if (file->f_mode & FMODE_READ)
|
if (file->f_mode & FMODE_READ)
|
||||||
poll_wait(file, &deviceconndiscwq, wait);
|
poll_wait(file, &deviceconndiscwq, wait);
|
||||||
if (st->lastev != conndiscevcnt)
|
if (st->lastev != conndiscevcnt)
|
||||||
mask |= POLLIN;
|
mask |= POLLIN;
|
||||||
st->lastev = conndiscevcnt;
|
st->lastev = conndiscevcnt;
|
||||||
unlock_kernel();
|
mutex_unlock(&usbfs_mutex);
|
||||||
return mask;
|
return mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user