[FIX] Use stop_machine to disarm kretprobe_instance 58/46858/4
authorVasiliy Ulyanov <v.ulyanov@samsung.com>
Wed, 26 Aug 2015 11:32:29 +0000 (14:32 +0300)
committerDmitry Kovalenko <d.kovalenko@samsung.com>
Fri, 28 Aug 2015 06:38:06 +0000 (23:38 -0700)
Change-Id: Id1fb5f1ad1a13dc76b465bb08d42f55a4886b713
Signed-off-by: Vyacheslav Cherkashin <v.cherkashin@samsung.com>
kprobe/swap_kprobes.c
task_data/task_data.c

index 1a08278..ce18b00 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/pagemap.h>
+#include <linux/stop_machine.h>
 
 #include <ksyms/ksyms.h>
 #include <master/swap_initializer.h>
@@ -930,6 +931,33 @@ static void swap_disarm_krp(struct kretprobe *rp)
        }
 }
 
+
+struct unreg_krp_args {
+       struct kretprobe **rps;
+       size_t size;
+       int rp_disarm;
+};
+
+static int __swap_unregister_kretprobes_top(void *data)
+{
+       struct unreg_krp_args *args = data;
+       struct kretprobe **rps = args->rps;
+       size_t size = args->size;
+       int rp_disarm = args->rp_disarm;
+       unsigned long flags;
+       const size_t end = ((size_t) 0) - 1;
+
+       spin_lock_irqsave(&kretprobe_lock, flags);
+       for (--size; size != end; --size) {
+               swap_unregister_kprobe(&rps[size]->kp);
+               if (rp_disarm)
+                       swap_disarm_krp(rps[size]);
+       }
+       spin_unlock_irqrestore(&kretprobe_lock, flags);
+
+       return 0;
+}
+
 /**
  * @brief Kretprobes unregister top. Unregisters kprobes.
  *
@@ -941,16 +969,22 @@ static void swap_disarm_krp(struct kretprobe *rp)
 void swap_unregister_kretprobes_top(struct kretprobe **rps, size_t size,
                                   int rp_disarm)
 {
-       unsigned long flags;
-       const size_t end = ((size_t) 0) - 1;
-
-       spin_lock_irqsave(&kretprobe_lock, flags);
-       for (--size; size != end; --size) {
-               swap_unregister_kprobe(&rps[size]->kp);
-               if (rp_disarm)
-                       swap_disarm_krp(rps[size]);
+       struct unreg_krp_args args = {
+               .rps = rps,
+               .size = size,
+               .rp_disarm = rp_disarm,
+       };
+
+       if (rp_disarm) {
+               int ret;
+
+               ret = stop_machine(__swap_unregister_kretprobes_top,
+                                  &args, NULL);
+               if (ret)
+                       pr_err("%s failed (%d)\n", __func__, ret);
+       } else {
+               __swap_unregister_kretprobes_top(&args);
        }
-       spin_unlock_irqrestore(&kretprobe_lock, flags);
 }
 EXPORT_SYMBOL_GPL(swap_unregister_kretprobes_top);
 
index 51f1578..085e016 100644 (file)
@@ -161,7 +161,6 @@ static int __task_data_exit(void *data)
        struct task_data *td;
 
        swap_unregister_kprobe(&do_exit_probe);
-       swap_unregister_kretprobe(&copy_process_rp);
 
        do_each_thread(g, t) {
                td = __td(t);
@@ -185,14 +184,15 @@ static void task_data_stop(void)
 {
        int ret;
 
+       swap_unregister_kretprobe(&copy_process_rp);
+
        /* stop_machine: the same here */
-       ret = stop_machine(__task_data_exit, &copy_process_rp, NULL);
+       ret = stop_machine(__task_data_exit, NULL, NULL);
        if (ret) {
                printk(TD_PREFIX "task data cleanup failed: %d\n", ret);
                /* something went wrong: at least make sure we unregister
                 * all the installed probes */
                swap_unregister_kprobe(&do_exit_probe);
-               swap_unregister_kretprobe(&copy_process_rp);
        }
 }