hidraw: don't deallocate memory when it is in use
PATCH 1/1 hidraw: don't deallocate memory when it is in use
When a device is unplugged, wait for all processes that have opened the device to close before deallocating the device.
Signed-off-by Ratan Nalumasu <[email protected]>
--- drivers/hid/hidraw.c | 69 +++++++++++++++++++------------------------------- 1 files changed, 26 insertions(+), 43 deletions(-)
drivers/hid/hidraw.c +26 -43
@@ -42,6 +42,7 @@ static struct cdev hidraw_cdev;static struct class *hidraw_class;static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES ];static DEFINE_MUTEX (minors_lock); +static void drop_ref (struct hidraw *hid,int exists_bit);static ssize_t hidraw_read (struct file *file,char __user *buffer,size_t count,loff_t *ppos) {
@@ -113,7 +114,7 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer,__u8 *buf;int ret =0 ; -if (!hidraw_table[minor]) { +if (!hidraw_table[minor] || !hidraw_table[minor]->exist) { ret = -ENODEV ; goto out; }
@@ -261,7 +262,7 @@ static int hidraw_open(struct inode *inode, struct file *file) }mutex_lock (&minors_lock); -if (!hidraw_table[minor]) { +if (!hidraw_table[minor] || !hidraw_table[minor]->exist) { err = -ENODEV ; goto out_unlock; }
@@ -298,36 +299,12 @@ out:static int hidraw_release (struct inode * inode,struct file * file) {unsigned int minor =iminor (inode); -struct hidraw *dev;struct hidraw_list *list = file->private_data; -int ret; -int i; - -mutex_lock (&minors_lock); -if (!hidraw_table[minor]) { - ret = -ENODEV ; - goto unlock; - } +drop_ref (hidraw_table[minor],0 );list_del (&list->node); - dev = hidraw_table[minor]; -if (!--dev->open) { -if (list->hidraw->exist) { -hid_hw_power (dev->hid,PM_HINT_NORMAL ); -hid_hw_close (dev->hid); - }else { -kfree (list->hidraw); - } - } - -for (i =0 ; i <HIDRAW_BUFFER_SIZE ; ++i) -kfree (list->buffer[i].value);kfree (list); - ret =0 ; -unlock: -mutex_unlock (&minors_lock); - -return ret; +return 0 ; } static long hidraw_ioctl(struct file *file, unsigned int cmd,
@@ -529,21 +506,7 @@ EXPORT_SYMBOL_GPL(hidraw_connect);void hidraw_disconnect (struct hid_device *hid) {struct hidraw *hidraw = hid->hidraw; - -mutex_lock (&minors_lock); - hidraw->exist =0 ; - -device_destroy (hidraw_class,MKDEV (hidraw_major, hidraw->minor)); - - hidraw_table[hidraw->minor] =NULL ; - -if (hidraw->open) { -hid_hw_close (hid); -wake_up_interruptible (&hidraw->wait); - }else { -kfree (hidraw); - } -mutex_unlock (&minors_lock); +drop_ref (hidraw,1 ); }EXPORT_SYMBOL_GPL (hidraw_disconnect);
@@ -585,3 +548,23 @@ void hidraw_exit(void)unregister_chrdev_region (dev_id,HIDRAW_MAX_DEVICES ); } + +static void drop_ref (struct hidraw *hidraw,int exists_bit) +{ +mutex_lock (&minors_lock); +if (exists_bit) { +hid_hw_close (hidraw->hid); + hidraw->exist =0 ; +if (hidraw->open) +wake_up_interruptible (&hidraw->wait); + }else { + --hidraw->open; + } + +if (!hidraw->open && !hidraw->exist) { +device_destroy (hidraw_class,MKDEV (hidraw_major, hidraw->minor)); + hidraw_table[hidraw->minor] =NULL ; +kfree (hidraw); + } +mutex_unlock (&minors_lock); +}
Signature · 1 line
1.7.7.3
Jiri Kosina
AppliedQuoted 4 lines · Ratan Nalumasu
When a device is unplugged, wait for all processes that have opened the device to close before deallocating the device.
Signed-off-by Ratan Nalumasu <[email protected]>
Applied, thanks.
Signature · 2 lines
Jiri Kosina SUSE Labs