misc: tegra-profiler: reduce size of sample
[linux-2.6.git] / drivers / misc / tegra-profiler / mmap.c
1 /*
2  * drivers/misc/tegra-profiler/mmap.c
3  *
4  * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  */
16
17 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18
19 #include <linux/mm.h>
20 #include <linux/fs.h>
21 #include <linux/slab.h>
22 #include <linux/err.h>
23 #include <linux/sched.h>
24
25 #include <linux/tegra_profiler.h>
26
27 #include "mmap.h"
28 #include "comm.h"
29 #include "hrt.h"
30
31 static void
32 put_mmap_sample(struct quadd_mmap_data *s, char *filename,
33                 size_t length, unsigned long pgoff)
34 {
35         struct quadd_record_data r;
36         struct quadd_iovec vec[2];
37         u64 pgoff_val = pgoff << PAGE_SHIFT;
38
39         r.record_type = QUADD_RECORD_TYPE_MMAP;
40
41         memcpy(&r.mmap, s, sizeof(*s));
42         r.mmap.filename_length = length;
43
44         vec[0].base = &pgoff_val;
45         vec[0].len = sizeof(pgoff_val);
46
47         vec[1].base = filename;
48         vec[1].len = length;
49
50         pr_debug("MMAP: pid: %u, file_name: '%s', addr: %#llx - %#llx, len: %llx, pgoff: %#lx\n",
51                  s->pid, filename, s->addr, s->addr + s->len, s->len, pgoff);
52
53         quadd_put_sample(&r, vec, ARRAY_SIZE(vec));
54 }
55
56 void quadd_process_mmap(struct vm_area_struct *vma, pid_t pid)
57 {
58         struct file *vm_file;
59         struct path *path;
60         char *file_name, *tmp_buf;
61         struct quadd_mmap_data sample;
62         size_t length, length_aligned;
63
64         if (!vma)
65                 return;
66
67         if (!(vma->vm_flags & VM_EXEC))
68                 return;
69
70         vm_file = vma->vm_file;
71         if (!vm_file)
72                 return;
73
74         path = &vm_file->f_path;
75
76         tmp_buf = kzalloc(PATH_MAX + sizeof(u64), GFP_KERNEL);
77         if (!tmp_buf)
78                 return;
79
80         file_name = d_path(path, tmp_buf, PATH_MAX);
81         if (IS_ERR(file_name))
82                 goto out;
83
84         if (strstr(file_name, " (deleted)"))
85                 goto out;
86
87         sample.pid = pid;
88         sample.user_mode = 1;
89
90         sample.addr = vma->vm_start;
91         sample.len = vma->vm_end - vma->vm_start;
92
93         length = strlen(file_name) + 1;
94         length_aligned = ALIGN(length, sizeof(u64));
95
96         put_mmap_sample(&sample, file_name, length_aligned, vma->vm_pgoff);
97
98 out:
99         kfree(tmp_buf);
100 }
101
102 int quadd_get_current_mmap(pid_t pid)
103 {
104         struct vm_area_struct *vma;
105         struct file *vm_file;
106         struct path *path;
107         char *file_name;
108         struct task_struct *task;
109         struct mm_struct *mm;
110         struct quadd_mmap_data sample;
111         size_t length, length_aligned;
112         char *tmp_buf;
113
114         rcu_read_lock();
115         task = pid_task(find_vpid(pid), PIDTYPE_PID);
116         rcu_read_unlock();
117         if (!task) {
118                 pr_err("Process not found: %d\n", pid);
119                 return -ESRCH;
120         }
121
122         mm = task->mm;
123         if (!mm) {
124                 pr_warn("mm is not existed for task: %d\n", pid);
125                 return 0;
126         }
127
128         pr_info("Get mapped memory objects\n");
129
130         tmp_buf = kzalloc(PATH_MAX + sizeof(u64), GFP_KERNEL);
131         if (!tmp_buf)
132                 return -ENOMEM;
133
134         for (vma = mm->mmap; vma; vma = vma->vm_next) {
135                 if (!(vma->vm_flags & VM_EXEC))
136                         continue;
137
138                 vm_file = vma->vm_file;
139                 if (!vm_file)
140                         continue;
141
142                 path = &vm_file->f_path;
143
144                 file_name = d_path(path, tmp_buf, PATH_MAX);
145                 if (IS_ERR(file_name))
146                         continue;
147
148                 if (strstr(file_name, " (deleted)"))
149                         continue;
150
151                 length = strlen(file_name) + 1;
152                 length_aligned = ALIGN(length, sizeof(u64));
153
154                 sample.pid = pid;
155                 sample.user_mode = 1;
156
157                 sample.addr = vma->vm_start;
158                 sample.len = vma->vm_end - vma->vm_start;
159
160                 put_mmap_sample(&sample, file_name, length_aligned,
161                                 vma->vm_pgoff);
162         }
163         kfree(tmp_buf);
164
165         return 0;
166 }