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); | ||||
| /* 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; | ||||
| } | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user