goto out;
}
- __task_data_cbs_stop_h = us_manager_reg_cb(STOP_CB, task_data_stop);
+ __task_data_cbs_stop_h = us_manager_reg_cb(STOP_CB_TD, task_data_stop);
if (__task_data_cbs_stop_h < 0) {
ret = __task_data_cbs_stop_h;
enum callback_t {
START_CB = 0,
- STOP_CB
+ STOP_CB,
+ STOP_CB_TD
};
/* Gets callback type (on start or on stop) and function pointer.
{
struct task_struct *task = proc->task;
-
- task_lock(task);
- BUG_ON(task->mm == NULL);
sspt_proc_uninstall(proc, task, US_UNREGS_PROBE);
- task_unlock(task);
-
sspt_proc_cleanup(proc);
}
/* TODO: to be implemented */
}
-static void on_each_uninstall_proc(struct sspt_proc *proc, void *data)
-{
- uninstall_proc(proc);
-}
-
/**
* @brief Uninstall probes from all processes
*
*/
void uninstall_all(void)
{
+ struct list_head *proc_list = sspt_proc_list();
+
sspt_proc_write_lock();
- on_each_proc_no_lock(on_each_uninstall_proc, NULL);
+ while (!list_empty(proc_list)) {
+ struct sspt_proc *proc;
+ proc = list_first_entry(proc_list, struct sspt_proc, list);
+
+ list_del(&proc->list);
+
+ sspt_proc_write_unlock();
+ uninstall_proc(proc);
+ sspt_proc_write_lock();
+ }
sspt_proc_write_unlock();
}
+static void __do_get_proc(struct sspt_proc *proc, void *data)
+{
+ get_task_struct(proc->task);
+ proc->__task = proc->task;
+ proc->__mm = get_task_mm(proc->task);
+}
+
+static void __do_put_proc(struct sspt_proc *proc, void *data)
+{
+ if (proc->__mm) {
+ mmput(proc->__mm);
+ proc->__mm = NULL;
+ }
+
+ if (proc->__task) {
+ put_task_struct(proc->__task);
+ proc->__task = NULL;
+ }
+}
+
+void get_all_procs(void)
+{
+ sspt_proc_read_lock();
+ on_each_proc_no_lock(__do_get_proc, NULL);
+ sspt_proc_read_unlock();
+}
+
+void put_all_procs(void)
+{
+ sspt_proc_read_lock();
+ on_each_proc_no_lock(__do_put_proc, NULL);
+ sspt_proc_read_unlock();
+}
+
/**
* @brief For debug
*
void install_all(void);
void uninstall_all(void);
+void get_all_procs(void);
+void put_all_procs(void);
+
int check_task_on_filters(struct task_struct *task);
void call_page_fault(struct task_struct *task, unsigned long page_addr);
void call_mm_release(struct task_struct *task);
static DEFINE_RWLOCK(sspt_proc_rwlock);
+struct list_head *sspt_proc_list()
+{
+ return &proc_probes_list;
+}
+
/**
* @brief Global read lock for sspt_proc
*
void sspt_proc_put(struct sspt_proc *proc)
{
- if (atomic_dec_and_test(&proc->usage))
+ if (atomic_dec_and_test(&proc->usage)) {
+ if (proc->__mm) {
+ mmput(proc->__mm);
+ proc->__mm = NULL;
+ }
+ if (proc->__task) {
+ put_task_struct(proc->__task);
+ proc->__task = NULL;
+ }
kfree(proc);
+ }
}
/**
struct list_head list; /**< For global process list */
pid_t tgid; /**< Thread group ID */
struct task_struct *task; /**< Ptr to the task */
+ struct mm_struct *__mm;
+ struct task_struct *__task;
unsigned long r_state_addr; /**< address of r_state */
struct slot_manager *sm; /**< Ptr to the manager slot */
struct list_head file_list; /**< For sspt_file */
void (*priv_destroy)(struct sspt_proc *, void *);
};
+
+struct list_head *sspt_proc_list(void);
+
struct sspt_proc *sspt_proc_create(struct task_struct *task);
void sspt_proc_cleanup(struct sspt_proc *proc);
struct sspt_proc *sspt_proc_get(struct sspt_proc *proc);
#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/stop_machine.h>
#include "pf/pf_group.h"
#include "sspt/sspt_proc.h"
#include "probes/probe_info_new.h"
static enum status_type status = ST_OFF;
-static void do_usm_stop(void)
+static int __do_usm_stop(void *data)
{
- exec_cbs(STOP_CB);
+ get_all_procs();
+
+ return 0;
+}
+
+static int do_usm_stop(void)
+{
+ int ret;
+ exec_cbs(STOP_CB);
unregister_helper_top();
+
+ ret = stop_machine(__do_usm_stop, NULL, NULL);
+ if (ret)
+ printk("do_usm_stop failed: %d\n", ret);
+
uninstall_all();
unregister_helper_bottom();
sspt_proc_free_all();
+ exec_cbs(STOP_CB_TD);
+
+ return ret;
}
static int do_usm_start(void)