From 7414f0f6c7d26cc2b3d7d7aa1a0e12a97f92f211 Mon Sep 17 00:00:00 2001 From: Vasiliy Ulyanov Date: Tue, 23 Jul 2013 12:33:54 +0400 Subject: [PATCH] [FIX] module_put issue on EC_IOCTL_STOP_AND_DETACH --- driver/device_driver.c | 10 ++-------- driver/handlers_core.h | 1 + driver/storage.c | 20 +++++++++++--------- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/driver/device_driver.c b/driver/device_driver.c index 993a807..d73b58b 100644 --- a/driver/device_driver.c +++ b/driver/device_driver.c @@ -505,7 +505,6 @@ static long device_ioctl (struct file *file UNUSED, unsigned int cmd, unsigned l unsigned long dbi_flags; struct dbi_modules_handlers *local_mh; struct dbi_modules_handlers_info *local_mhi; - unsigned int local_module_refcount = 0; int j; dbi_module_callback dmc_stop; @@ -563,14 +562,9 @@ static long device_ioctl (struct file *file UNUSED, unsigned int cmd, unsigned l sad_cleanup: spin_lock_irqsave(&local_mh->lock, dbi_flags); list_for_each_entry_rcu(local_mhi, &local_mh->modules_handlers, dbi_list_head) { - local_module_refcount = module_refcount(local_mhi->dbi_module); - if (local_module_refcount == 1) { + while (local_mhi->refcount > 0) { module_put(local_mhi->dbi_module); - } - else if (local_module_refcount > 1) { - printk("local_module_refcount too much - force set refcount to zero\n"); - while (local_module_refcount--) - module_put(local_mhi->dbi_module); + local_mhi->refcount--; } } spin_unlock_irqrestore(&local_mh->lock, dbi_flags); diff --git a/driver/handlers_core.h b/driver/handlers_core.h index d708fac..fcbbf2e 100644 --- a/driver/handlers_core.h +++ b/driver/handlers_core.h @@ -38,6 +38,7 @@ struct dbi_modules_handlers_info { int dbi_module_priority_start; int dbi_module_priority_stop; void * (*get_uprobes)(void); + int refcount; }; extern int dbi_register_handlers_module(struct dbi_modules_handlers_info *dbi_mhi); diff --git a/driver/storage.c b/driver/storage.c index bde6cfa..c7d82a8 100644 --- a/driver/storage.c +++ b/driver/storage.c @@ -88,7 +88,6 @@ static void dbi_find_and_set_handler_for_probe(kernel_probe_t *p) unsigned long jp_handler_addr, rp_handler_addr; struct dbi_modules_handlers_info *local_mhi; unsigned long dbi_flags; - unsigned int local_module_refcount = 0; spin_lock_irqsave(&dbi_mh.lock, dbi_flags); list_for_each_entry_rcu(local_mhi, &dbi_mh.modules_handlers, dbi_list_head) { @@ -101,14 +100,15 @@ static void dbi_find_and_set_handler_for_probe(kernel_probe_t *p) (local_mhi->dbi_module)->name, p->addr); } else { - local_module_refcount = module_refcount(local_mhi->dbi_module); - if (local_module_refcount == 0) { - if (!try_module_get(local_mhi->dbi_module)) + if (local_mhi->refcount == 0) { + if (!try_module_get(local_mhi->dbi_module)) { printk("Error of try_module_get() for module %s\n", (local_mhi->dbi_module)->name); - else + } else { + local_mhi->refcount++; printk("Module %s in use now\n", (local_mhi->dbi_module)->name); + } } p->jprobe.entry = (kprobe_opcode_t *)jp_handler_addr; printk("Set jp_handler for %s module (address %0lX)\n", @@ -121,14 +121,15 @@ static void dbi_find_and_set_handler_for_probe(kernel_probe_t *p) (local_mhi->dbi_module)->name, p->addr); } else { - local_module_refcount = module_refcount(local_mhi->dbi_module); - if (local_module_refcount == 0) { - if (!try_module_get(local_mhi->dbi_module)) + if (local_mhi->refcount == 0) { + if (!try_module_get(local_mhi->dbi_module)) { printk("Error of try_module_get() for module %s\n", (local_mhi->dbi_module)->name); - else + } else { + local_mhi->refcount++; printk("Module %s in use now\n", (local_mhi->dbi_module)->name); + } } p->retprobe.handler = (kretprobe_handler_t)rp_handler_addr; printk("Set rp_handler for %s module (address %0lX)\n", @@ -171,6 +172,7 @@ int dbi_register_handlers_module(struct dbi_modules_handlers_info *dbi_mhi) spin_lock_irqsave(&dbi_mh.lock, dbi_flags); // local_mhi = container_of(&dbi_mhi->dbi_list_head, struct dbi_modules_handlers_info, dbi_list_head); list_add_rcu(&dbi_mhi->dbi_list_head, &dbi_mh.modules_handlers); + dbi_mhi->refcount = 0; printk("Added module %s (head is %p)\n", (dbi_mhi->dbi_module)->name, &dbi_mhi->dbi_list_head); spin_unlock_irqrestore(&dbi_mh.lock, dbi_flags); return 0; -- 2.7.4