fix segfault if no kprobe defined
[lttngtop.git] / src / iostreamtop.c
CommitLineData
1fc22eb4 1/*
aa15ac1c 2 * Copyright (C) 2011-2012 Mathieu Bain <mathieu.bain@polymtl.ca>
1fc22eb4
JD
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
71bd7ce1
AM
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1fc22eb4
JD
16 */
17
b093de8a
MB
18#include <stdlib.h>
19#include <unistd.h>
20#include <sys/types.h>
21#include <sys/stat.h>
22#include <string.h>
1fc22eb4
JD
23#include <babeltrace/babeltrace.h>
24
25#include "lttngtoptypes.h"
26#include "common.h"
27#include "iostreamtop.h"
28
b093de8a
MB
29void add_file(struct processtop *proc, struct files *file, int fd)
30{
ceb3a221 31 struct files *tmp_file;
59288610 32 struct processtop *parent;
ceb3a221 33 int size;
32647247 34 int i;
ceb3a221
MB
35
36 size = proc->process_files_table->len;
59288610
MB
37 parent = proc->threadparent;
38 if (parent)
39 insert_file(parent, fd);
ceb3a221 40 if (size <= fd) {
32647247
JD
41 /* Add NULL file structures for undefined FDs */
42 for (i = size; i < fd; i++) {
43 g_ptr_array_add(proc->process_files_table, NULL);
44 }
b093de8a
MB
45 g_ptr_array_add(proc->process_files_table, file);
46 } else {
ceb3a221
MB
47 tmp_file = g_ptr_array_index(proc->process_files_table, fd);
48 if (tmp_file == NULL)
49 g_ptr_array_index(proc->process_files_table, fd) = file;
50 else {
51 if (strcmp(tmp_file->name, file->name) != 0) {
52 size = proc->process_files_table->len;
53 g_ptr_array_set_size(proc->process_files_table,
59288610 54 size+1);
ceb3a221
MB
55 g_ptr_array_index(proc->process_files_table,
56 size) = tmp_file;
57 g_ptr_array_index(proc->process_files_table,
58 fd) = file;
59 } else
60 tmp_file->flag = __NR_open;
61 }
b093de8a 62 }
59288610
MB
63 /*
64 * The file may have be created in the parent
65 */
66 if (file->flag == -1) {
67 file->fd = fd;
68 file->flag = __NR_open;
69 lttngtop.nbfiles++;
70 lttngtop.nbnewfiles++;
71 }
b093de8a
MB
72}
73
59288610
MB
74/*
75 * Edit the file
76 * Called by handled_statedump_filename
77 */
ceb3a221
MB
78void edit_file(struct processtop *proc, struct files *file, int fd)
79{
80 int size = proc->process_files_table->len;
81 struct files *tmpfile;
82
59288610
MB
83 if (fd >= size) {
84 add_file(proc, file, fd);
85 } else {
ceb3a221 86 tmpfile = g_ptr_array_index(proc->process_files_table, fd);
59288610
MB
87 if (tmpfile) {
88 tmpfile->name = strdup(file->name);
89 free(file);
90 } else
91 add_file(proc, file, fd);
ceb3a221
MB
92 }
93}
b093de8a
MB
94
95void insert_file(struct processtop *proc, int fd)
96{
97 struct files *tmp;
59288610
MB
98 struct files *tmp_parent;
99 struct processtop *parent;
b093de8a 100
59288610
MB
101 if (fd < 0)
102 return;
b093de8a
MB
103 if (fd >= proc->process_files_table->len) {
104 tmp = g_new0(struct files, 1);
105 tmp->name = "Unknown";
ceb3a221
MB
106 tmp->read = 0;
107 tmp->write = 0;
108 tmp->fd = fd;
59288610 109 tmp->flag = -1;
b093de8a
MB
110 add_file(proc, tmp, fd);
111 } else {
b093de8a
MB
112 tmp = g_ptr_array_index(proc->process_files_table, fd);
113 if (tmp == NULL) {
114 tmp = g_new0(struct files, 1);
115 tmp->name = "Unknown";
116 tmp->read = 0;
117 tmp->write = 0;
118 tmp->fd = fd;
59288610 119 tmp->flag = -1;
b093de8a 120 add_file(proc, tmp, fd);
59288610
MB
121 } else {
122 parent = proc->threadparent;
123 if (parent) {
124 tmp_parent = g_ptr_array_index(
125 parent->process_files_table, fd);
126 if (tmp_parent &&
127 (strcmp(tmp->name, tmp_parent->name)) != 0)
128 tmp->name = strdup(tmp_parent->name);
129 }
b093de8a
MB
130 }
131 }
132}
133
134void close_file(struct processtop *proc, int fd)
ceb3a221
MB
135{
136 struct files *file;
137
ceb3a221 138 file = get_file(proc, fd);
e05a35a6 139 if (file != NULL) {
ceb3a221 140 file->flag = __NR_close;
e05a35a6
JD
141 lttngtop.nbfiles--;
142 }
143 lttngtop.nbclosedfiles++;
ceb3a221
MB
144}
145
146struct files *get_file(struct processtop *proc, int fd)
b093de8a
MB
147{
148 int len;
ceb3a221 149 struct files *tmp = NULL;
b093de8a
MB
150
151 len = proc->process_files_table->len;
152
153 /*
154 * It is possible that a file was open before taking the trace
155 * and its fd could be greater than all of the others fd
156 * used by the process
157 */
ceb3a221
MB
158 if (fd < len && fd >= 0)
159 tmp = g_ptr_array_index(proc->process_files_table, fd);
b093de8a 160
b093de8a
MB
161 return tmp;
162}
163
164void show_table(GPtrArray *tab)
165{
166 int i;
167 struct files *file;
168
169 for (i = 0 ; i < tab->len; i++) {
170 file = g_ptr_array_index(tab, i);
171 if (file == NULL)
172 fprintf(stderr, "NULL, ");
173 else
174 fprintf(stderr, "%s, ", file->name);
175 }
176 fprintf(stderr, "]\n\n");
177}
1fc22eb4 178
ceb3a221
MB
179void show_history(struct file_history *history)
180{
181 struct file_history *tmp = history;
182
183 while (tmp != NULL) {
184 fprintf(stderr, "fd = %d, name = %s\n", tmp->file->fd,
185 tmp->file->name);
186 tmp = tmp->next;
187 }
188
189}
190
1fc22eb4 191int update_iostream_ret(struct lttngtop *ctx, int tid, char *comm,
d67167cd 192 unsigned long timestamp, uint64_t cpu_id, int ret)
1fc22eb4
JD
193{
194 struct processtop *tmp;
b093de8a 195 struct files *tmpfile;
1fc22eb4
JD
196 int err = 0;
197
198 tmp = get_proc(ctx, tid, comm, timestamp);
b093de8a 199
96aa77de
JD
200 if (!tmp) {
201 err = -1;
202 goto end;
203 }
b093de8a
MB
204 if (tmp->syscall_info != NULL) {
205 if (tmp->syscall_info->type == __NR_read
206 && ret > 0) {
207 tmp->totalfileread += ret;
208 tmp->fileread += ret;
209 tmpfile = get_file(tmp, tmp->syscall_info->fd);
6f29d91e
JD
210 if (tmpfile)
211 tmpfile->read += ret;
b093de8a
MB
212 } else if (tmp->syscall_info->type == __NR_write
213 && ret > 0) {
214 tmp->totalfilewrite += ret;
215 tmp->filewrite += ret;
216 tmpfile = get_file(tmp, tmp->syscall_info->fd);
6f29d91e
JD
217 if (tmpfile)
218 tmpfile->write += ret;
b093de8a
MB
219 } else if (tmp->syscall_info->type == __NR_open
220 && ret > 0) {
ceb3a221
MB
221 tmpfile = tmp->files_history->file;
222 add_file(tmp, tmpfile, ret);
223 tmpfile->fd = ret;
b093de8a 224 } else {
1fc22eb4
JD
225 err = -1;
226 }
b093de8a
MB
227 g_free(tmp->syscall_info);
228 tmp->syscall_info = NULL;
229 }
96aa77de
JD
230
231end:
1fc22eb4
JD
232 return err;
233}
234
d67167cd 235struct syscalls *create_syscall_info(unsigned int type, uint64_t cpu_id,
b093de8a
MB
236 unsigned int tid, int fd)
237{
238 struct syscalls *syscall_info;
239
240 syscall_info = g_new0(struct syscalls, 1);
241 syscall_info->type = type;
242 syscall_info->cpu_id = cpu_id;
243 syscall_info->tid = tid;
244 syscall_info->fd = fd;
245
246 return syscall_info;
247}
248
249struct file_history *create_file(struct file_history *history, char *file_name)
250{
251 struct files *new_file;
252 struct file_history *new_history;
253
254 new_file = g_new0(struct files, 1);
255 new_history = g_new0(struct file_history, 1);
256 new_file->name = strdup(file_name);
257 new_file->read = 0;
258 new_file->write = 0;
59288610 259 new_file->flag = -1;
b093de8a
MB
260 new_history->file = new_file;
261 new_history->next = history;
262
263 return new_history;
264}
265
4adc8274 266enum bt_cb_ret handle_exit_syscall(struct bt_ctf_event *call_data,
1fc22eb4
JD
267 void *private_data)
268{
2e0a1190 269 const struct bt_definition *scope;
1fc22eb4
JD
270 unsigned long timestamp;
271 char *comm;
272 uint64_t ret, tid;
d67167cd 273 uint64_t cpu_id;
1fc22eb4 274
c78f2cdc 275 timestamp = bt_ctf_get_timestamp(call_data);
1fc22eb4
JD
276 if (timestamp == -1ULL)
277 goto error;
278
1dec520a
JD
279 comm = get_context_comm(call_data);
280 tid = get_context_tid(call_data);
1fc22eb4
JD
281
282 scope = bt_ctf_get_top_level_scope(call_data,
283 BT_EVENT_FIELDS);
284 ret = bt_ctf_get_int64(bt_ctf_get_field(call_data,
285 scope, "_ret"));
286 if (bt_ctf_field_get_error()) {
287 fprintf(stderr, "Missing ret context info\n");
288 goto error;
289 }
290
d67167cd 291 cpu_id = get_cpu_id(call_data);
1fc22eb4
JD
292
293 /*
b093de8a
MB
294 * if we encounter an exit_syscall and
295 * it is not for a syscall read or write
1fc22eb4
JD
296 * we just abort the execution of this callback
297 */
298 if ((update_iostream_ret(&lttngtop, tid, comm, timestamp, cpu_id, ret)) < 0)
299 return BT_CB_ERROR_CONTINUE;
300
301 return BT_CB_OK;
302
303error:
304 return BT_CB_ERROR_STOP;
305}
306
307
4adc8274 308enum bt_cb_ret handle_sys_write(struct bt_ctf_event *call_data,
1fc22eb4
JD
309 void *private_data)
310{
2e0a1190 311 const struct bt_definition *scope;
1fc22eb4 312 struct processtop *tmp;
1fc22eb4
JD
313 unsigned long timestamp;
314 uint64_t cpu_id;
928f18a6
MB
315 int64_t tid;
316 char *procname;
b093de8a 317 int fd;
1fc22eb4 318
c78f2cdc 319 timestamp = bt_ctf_get_timestamp(call_data);
1fc22eb4
JD
320 if (timestamp == -1ULL)
321 goto error;
322
1dec520a 323 tid = get_context_tid(call_data);
d67167cd 324 cpu_id = get_cpu_id(call_data);
1fc22eb4 325
928f18a6 326 procname = get_context_comm(call_data);
59288610 327
b093de8a
MB
328 scope = bt_ctf_get_top_level_scope(call_data,
329 BT_EVENT_FIELDS);
330 fd = bt_ctf_get_uint64(bt_ctf_get_field(call_data,
331 scope, "_fd"));
332 if (bt_ctf_field_get_error()) {
333 fprintf(stderr, "Missing fd context info\n");
334 goto error;
335 }
336
928f18a6 337 tmp = get_proc(&lttngtop, tid, procname, timestamp);
96aa77de
JD
338 if (!tmp)
339 goto end;
340
b093de8a
MB
341 tmp->syscall_info = create_syscall_info(__NR_write, cpu_id, tid, fd);
342
343 insert_file(tmp, fd);
1fc22eb4 344
96aa77de 345end:
1fc22eb4
JD
346 return BT_CB_OK;
347
348error:
349 return BT_CB_ERROR_STOP;
350}
351
4adc8274 352enum bt_cb_ret handle_sys_read(struct bt_ctf_event *call_data,
1fc22eb4
JD
353 void *private_data)
354{
355 struct processtop *tmp;
2e0a1190 356 const struct bt_definition *scope;
1fc22eb4
JD
357 unsigned long timestamp;
358 uint64_t cpu_id;
928f18a6
MB
359 int64_t tid;
360 char *procname;
b093de8a 361 int fd;
1fc22eb4 362
c78f2cdc 363 timestamp = bt_ctf_get_timestamp(call_data);
1fc22eb4
JD
364 if (timestamp == -1ULL)
365 goto error;
366
1dec520a 367 tid = get_context_tid(call_data);
d67167cd 368 cpu_id = get_cpu_id(call_data);
1fc22eb4 369
928f18a6 370 procname = get_context_comm(call_data);
59288610 371
b093de8a
MB
372 scope = bt_ctf_get_top_level_scope(call_data,
373 BT_EVENT_FIELDS);
374 fd = bt_ctf_get_uint64(bt_ctf_get_field(call_data,
375 scope, "_fd"));
376 if (bt_ctf_field_get_error()) {
377 fprintf(stderr, "Missing fd context info\n");
378 goto error;
379 }
380
928f18a6 381 tmp = get_proc(&lttngtop, tid, procname, timestamp);
96aa77de
JD
382 if (!tmp)
383 goto end;
384
b093de8a
MB
385 tmp->syscall_info = create_syscall_info(__NR_read, cpu_id, tid, fd);
386
387 insert_file(tmp, fd);
388
96aa77de 389end:
b093de8a
MB
390 return BT_CB_OK;
391
392error:
393 return BT_CB_ERROR_STOP;
394}
395
396
4adc8274 397enum bt_cb_ret handle_sys_open(struct bt_ctf_event *call_data,
b093de8a
MB
398 void *private_data)
399{
400
401 struct processtop *tmp;
2e0a1190 402 const struct bt_definition *scope;
b093de8a
MB
403 unsigned long timestamp;
404 uint64_t cpu_id;
928f18a6
MB
405 int64_t tid;
406 char *procname;
b093de8a
MB
407 char *file;
408
c78f2cdc 409 timestamp = bt_ctf_get_timestamp(call_data);
b093de8a
MB
410 if (timestamp == -1ULL)
411 goto error;
412
1dec520a 413 tid = get_context_tid(call_data);
d67167cd 414 cpu_id = get_cpu_id(call_data);
b093de8a 415
928f18a6 416 procname = get_context_comm(call_data);
59288610 417
b093de8a
MB
418 scope = bt_ctf_get_top_level_scope(call_data,
419 BT_EVENT_FIELDS);
420 file = bt_ctf_get_string(bt_ctf_get_field(call_data,
421 scope, "_filename"));
422 if (bt_ctf_field_get_error()) {
ceb3a221 423 fprintf(stderr, "Missing file name context info\n");
b093de8a
MB
424 goto error;
425 }
426
928f18a6 427 tmp = get_proc(&lttngtop, tid, procname, timestamp);
96aa77de
JD
428 if (!tmp)
429 goto end;
430
b093de8a
MB
431 tmp->syscall_info = create_syscall_info(__NR_open, cpu_id, tid, -1);
432
433 tmp->files_history = create_file(tmp->files_history, file);
1fc22eb4 434
96aa77de 435end:
1fc22eb4
JD
436 return BT_CB_OK;
437
438error:
439 return BT_CB_ERROR_STOP;
440}
441
b093de8a 442
4adc8274 443enum bt_cb_ret handle_sys_close(struct bt_ctf_event *call_data,
b093de8a
MB
444 void *private_data)
445{
2e0a1190 446 const struct bt_definition *scope;
b093de8a 447 struct processtop *tmp;
928f18a6
MB
448 unsigned long timestamp;
449 int64_t tid;
450 char *procname;
b093de8a
MB
451 int fd;
452
c78f2cdc 453 timestamp = bt_ctf_get_timestamp(call_data);
b093de8a
MB
454 if (timestamp == -1ULL)
455 goto error;
456
1dec520a 457 tid = get_context_tid(call_data);
b093de8a 458
928f18a6 459 procname = get_context_comm(call_data);
59288610 460
b093de8a
MB
461 scope = bt_ctf_get_top_level_scope(call_data,
462 BT_EVENT_FIELDS);
463 fd = bt_ctf_get_uint64(bt_ctf_get_field(call_data,
464 scope, "_fd"));
465 if (bt_ctf_field_get_error()) {
466 fprintf(stderr, "Missing fd context info\n");
467 goto error;
468 }
469
928f18a6 470 tmp = get_proc(&lttngtop, tid, procname, timestamp);
96aa77de
JD
471 if (!tmp)
472 goto end;
ceb3a221 473
b093de8a
MB
474 close_file(tmp, fd);
475
96aa77de 476end:
b093de8a
MB
477 return BT_CB_OK;
478
479error:
480 return BT_CB_ERROR_STOP;
481}
59288610 482
4adc8274 483enum bt_cb_ret handle_statedump_file_descriptor(struct bt_ctf_event *call_data,
ceb3a221
MB
484 void *private_data)
485{
2e0a1190 486 const struct bt_definition *scope;
59288610 487 struct processtop *parent;
ceb3a221
MB
488 struct files *file;
489 unsigned long timestamp;
59288610
MB
490 int64_t pid;
491 char *file_name;
ceb3a221
MB
492 int fd;
493
c78f2cdc 494 timestamp = bt_ctf_get_timestamp(call_data);
ceb3a221
MB
495 if (timestamp == -1ULL)
496 goto error;
497
ceb3a221
MB
498 scope = bt_ctf_get_top_level_scope(call_data,
499 BT_EVENT_FIELDS);
59288610
MB
500 pid = bt_ctf_get_int64(bt_ctf_get_field(call_data,
501 scope, "_pid"));
ceb3a221
MB
502 if (bt_ctf_field_get_error()) {
503 fprintf(stderr, "Missing tid context info\n");
504 goto error;
505 }
506
507 scope = bt_ctf_get_top_level_scope(call_data,
508 BT_EVENT_FIELDS);
59288610 509 fd = bt_ctf_get_int64(bt_ctf_get_field(call_data,
ceb3a221
MB
510 scope, "_fd"));
511 if (bt_ctf_field_get_error()) {
512 fprintf(stderr, "Missing fd context info\n");
513 goto error;
514 }
515
516 scope = bt_ctf_get_top_level_scope(call_data,
517 BT_EVENT_FIELDS);
518 file_name = bt_ctf_get_string(bt_ctf_get_field(call_data,
519 scope, "_filename"));
520 if (bt_ctf_field_get_error()) {
521 fprintf(stderr, "Missing file name context info\n");
522 goto error;
523 }
524
59288610 525 parent = get_proc_pid(&lttngtop, pid, pid, timestamp);
96aa77de
JD
526 if (!parent)
527 goto end;
528
59288610
MB
529 parent->files_history = create_file(parent->files_history, file_name);
530 file = parent->files_history->file;
531 edit_file(parent, file, fd);
ceb3a221 532
96aa77de 533end:
ceb3a221
MB
534 return BT_CB_OK;
535
536error:
537 return BT_CB_ERROR_STOP;
538}
This page took 0.048943 seconds and 4 git commands to generate.