[FIX] race condition on probes disarming (at stop)
[kernel/swap-modules.git] / us_manager / debugfs_us_manager.c
1 #include <linux/debugfs.h>
2 #include <linux/module.h>
3
4 #include <driver/swap_debugfs.h>
5 #include <us_manager/sspt/sspt_proc.h>
6
7 #include "debugfs_us_manager.h"
8
9 #define MAX_APPS_COUNT  8   /* According to daemon defenitions */
10 #define PID_STRING      21  /* Maximum pid string = 20 (max digits count in
11                               * unsigned int on 64-bit arch) + 1 (for \n) */
12
13 /* ============================================================================
14  * =                          FOPS_TASKS                                      =
15  * ============================================================================
16  */
17
18 struct read_buf {
19         char *begin;
20         char *ptr;
21         char *end;
22 };
23
24 static void on_each_proc_callback(struct sspt_proc *proc, void *data)
25 {
26         struct read_buf *rbuf = (struct read_buf *)data;
27         char pid_str[PID_STRING];
28         int len;
29
30         sprintf(pid_str, "%d", proc->tgid);
31
32         len = strlen(pid_str);
33
34         if (rbuf->end - rbuf->ptr < len + 2)
35                 return;
36
37         if (rbuf->ptr != rbuf->begin) {
38                 *rbuf->ptr = ' ';
39                 ++rbuf->ptr;
40         }
41
42         memcpy(rbuf->ptr, pid_str, len);
43         rbuf->ptr += len;
44 }
45
46 static ssize_t read_tasks(struct file *file, char __user *user_buf,
47                           size_t count, loff_t *ppos)
48 {
49         char buf[PID_STRING * MAX_APPS_COUNT];
50         struct read_buf rbuf = {
51                 .begin = buf,
52                 .ptr = buf,
53                 .end = buf + sizeof(buf)
54         };
55
56         on_each_proc_no_lock(on_each_proc_callback, (void *)&rbuf);
57
58         if (rbuf.ptr < rbuf.end)
59                 ++rbuf.ptr;
60         *rbuf.ptr = '\n';
61
62         return simple_read_from_buffer(user_buf, count, ppos, rbuf.begin,
63                                    rbuf.ptr - rbuf.begin);
64 }
65
66 static const struct file_operations fops_tasks = {
67         .owner = THIS_MODULE,
68         .read = read_tasks
69 };
70
71 /* ============================================================================
72  * =                          INIT/EXIT                                       =
73  * ============================================================================
74  */
75
76 static struct dentry *us_manager_dir = NULL;
77
78 void exit_debugfs_us_manager(void)
79 {
80         if (us_manager_dir)
81                 debugfs_remove_recursive(us_manager_dir);
82
83         us_manager_dir = NULL;
84 }
85
86 int init_debugfs_us_manager(void)
87 {
88         struct dentry *swap_dir, *dentry;
89
90         swap_dir = get_swap_debugfs_dir();
91         if (swap_dir == NULL)
92                 return -ENOENT;
93
94         us_manager_dir = debugfs_create_dir(US_MANAGER_DFS_DIR, swap_dir);
95         if (us_manager_dir == NULL)
96                 return -ENOMEM;
97
98         dentry = debugfs_create_file(US_MANAGER_TASKS, 0600, us_manager_dir, NULL,
99                                  &fops_tasks);
100         if (dentry == NULL)
101                 goto fail;
102
103         return 0;
104
105 fail:
106         exit_debugfs_us_manager();
107         return -ENOMEM;
108 }