[FIX] module_put issue on EC_IOCTL_STOP_AND_DETACH
authorVasiliy Ulyanov <v.ulyanov@samsung.com>
Tue, 23 Jul 2013 08:33:54 +0000 (12:33 +0400)
committerVasiliy Ulyanov <v.ulyanov@samsung.com>
Tue, 23 Jul 2013 08:33:54 +0000 (12:33 +0400)
driver/device_driver.c
driver/handlers_core.h
driver/storage.c

index 993a807..d73b58b 100644 (file)
@@ -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);
index d708fac..fcbbf2e 100644 (file)
@@ -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);
index bde6cfa..c7d82a8 100644 (file)
@@ -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;