Filter based on procname
[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 {
38be0c3f
JD
51 if (!tmp_file->name ||
52 strcmp(tmp_file->name, file->name) != 0) {
ceb3a221
MB
53 size = proc->process_files_table->len;
54 g_ptr_array_set_size(proc->process_files_table,
59288610 55 size+1);
ceb3a221
MB
56 g_ptr_array_index(proc->process_files_table,
57 size) = tmp_file;
58 g_ptr_array_index(proc->process_files_table,
59 fd) = file;
60 } else
61 tmp_file->flag = __NR_open;
62 }
b093de8a 63 }
59288610
MB
64 /*
65 * The file may have be created in the parent
66 */
67 if (file->flag == -1) {
68 file->fd = fd;
69 file->flag = __NR_open;
70 lttngtop.nbfiles++;
71 lttngtop.nbnewfiles++;
72 }
b093de8a
MB
73}
74
59288610
MB
75/*
76 * Edit the file
77 * Called by handled_statedump_filename
78 */
ceb3a221
MB
79void edit_file(struct processtop *proc, struct files *file, int fd)
80{
81 int size = proc->process_files_table->len;
82 struct files *tmpfile;
83
59288610
MB
84 if (fd >= size) {
85 add_file(proc, file, fd);
86 } else {
ceb3a221 87 tmpfile = g_ptr_array_index(proc->process_files_table, fd);
59288610
MB
88 if (tmpfile) {
89 tmpfile->name = strdup(file->name);
90 free(file);
91 } else
92 add_file(proc, file, fd);
ceb3a221
MB
93 }
94}
b093de8a
MB
95
96void insert_file(struct processtop *proc, int fd)
97{
98 struct files *tmp;
59288610
MB
99 struct files *tmp_parent;
100 struct processtop *parent;
b093de8a 101
59288610
MB
102 if (fd < 0)
103 return;
b093de8a
MB
104 if (fd >= proc->process_files_table->len) {
105 tmp = g_new0(struct files, 1);
106 tmp->name = "Unknown";
ceb3a221
MB
107 tmp->read = 0;
108 tmp->write = 0;
109 tmp->fd = fd;
59288610 110 tmp->flag = -1;
b093de8a
MB
111 add_file(proc, tmp, fd);
112 } else {
b093de8a
MB
113 tmp = g_ptr_array_index(proc->process_files_table, fd);
114 if (tmp == NULL) {
115 tmp = g_new0(struct files, 1);
116 tmp->name = "Unknown";
117 tmp->read = 0;
118 tmp->write = 0;
119 tmp->fd = fd;
59288610 120 tmp->flag = -1;
b093de8a 121 add_file(proc, tmp, fd);
59288610
MB
122 } else {
123 parent = proc->threadparent;
124 if (parent) {
125 tmp_parent = g_ptr_array_index(
126 parent->process_files_table, fd);
127 if (tmp_parent &&
128 (strcmp(tmp->name, tmp_parent->name)) != 0)
129 tmp->name = strdup(tmp_parent->name);
130 }
b093de8a
MB
131 }
132 }
133}
134
135void close_file(struct processtop *proc, int fd)
ceb3a221
MB
136{
137 struct files *file;
138
ceb3a221 139 file = get_file(proc, fd);
e05a35a6 140 if (file != NULL) {
ceb3a221 141 file->flag = __NR_close;
e05a35a6 142 lttngtop.nbfiles--;
38be0c3f
JD
143 if (file->name) {
144 free(file->name);
145 file->name = NULL;
146 }
e05a35a6
JD
147 }
148 lttngtop.nbclosedfiles++;
ceb3a221
MB
149}
150
151struct files *get_file(struct processtop *proc, int fd)
b093de8a
MB
152{
153 int len;
ceb3a221 154 struct files *tmp = NULL;
b093de8a
MB
155
156 len = proc->process_files_table->len;
157
158 /*
159 * It is possible that a file was open before taking the trace
160 * and its fd could be greater than all of the others fd
161 * used by the process
162 */
ceb3a221
MB
163 if (fd < len && fd >= 0)
164 tmp = g_ptr_array_index(proc->process_files_table, fd);
b093de8a 165
b093de8a
MB
166 return tmp;
167}
168
169void show_table(GPtrArray *tab)
170{
171 int i;
172 struct files *file;
173
174 for (i = 0 ; i < tab->len; i++) {
175 file = g_ptr_array_index(tab, i);
176 if (file == NULL)
177 fprintf(stderr, "NULL, ");
178 else
179 fprintf(stderr, "%s, ", file->name);
180 }
181 fprintf(stderr, "]\n\n");
182}
1fc22eb4 183
ceb3a221
MB
184void show_history(struct file_history *history)
185{
186 struct file_history *tmp = history;
187
188 while (tmp != NULL) {
189 fprintf(stderr, "fd = %d, name = %s\n", tmp->file->fd,
190 tmp->file->name);
191 tmp = tmp->next;
192 }
193
194}
195
1fc22eb4 196int update_iostream_ret(struct lttngtop *ctx, int tid, char *comm,
906c08f6
JD
197 unsigned long timestamp, uint64_t cpu_id, int ret,
198 char *hostname)
1fc22eb4
JD
199{
200 struct processtop *tmp;
b093de8a 201 struct files *tmpfile;
1fc22eb4
JD
202 int err = 0;
203
906c08f6 204 tmp = get_proc(ctx, tid, comm, timestamp, hostname);
b093de8a 205
96aa77de
JD
206 if (!tmp) {
207 err = -1;
208 goto end;
209 }
b093de8a
MB
210 if (tmp->syscall_info != NULL) {
211 if (tmp->syscall_info->type == __NR_read
212 && ret > 0) {
213 tmp->totalfileread += ret;
214 tmp->fileread += ret;
215 tmpfile = get_file(tmp, tmp->syscall_info->fd);
6f29d91e
JD
216 if (tmpfile)
217 tmpfile->read += ret;
b093de8a
MB
218 } else if (tmp->syscall_info->type == __NR_write
219 && ret > 0) {
220 tmp->totalfilewrite += ret;
221 tmp->filewrite += ret;
222 tmpfile = get_file(tmp, tmp->syscall_info->fd);
6f29d91e
JD
223 if (tmpfile)
224 tmpfile->write += ret;
b093de8a
MB
225 } else if (tmp->syscall_info->type == __NR_open
226 && ret > 0) {
ceb3a221
MB
227 tmpfile = tmp->files_history->file;
228 add_file(tmp, tmpfile, ret);
229 tmpfile->fd = ret;
b093de8a 230 } else {
1fc22eb4
JD
231 err = -1;
232 }
b093de8a
MB
233 g_free(tmp->syscall_info);
234 tmp->syscall_info = NULL;
235 }
96aa77de
JD
236
237end:
1fc22eb4
JD
238 return err;
239}
240
d67167cd 241struct syscalls *create_syscall_info(unsigned int type, uint64_t cpu_id,
b093de8a
MB
242 unsigned int tid, int fd)
243{
244 struct syscalls *syscall_info;
245
246 syscall_info = g_new0(struct syscalls, 1);
247 syscall_info->type = type;
248 syscall_info->cpu_id = cpu_id;
249 syscall_info->tid = tid;
250 syscall_info->fd = fd;
251
252 return syscall_info;
253}
254
255struct file_history *create_file(struct file_history *history, char *file_name)
256{
257 struct files *new_file;
258 struct file_history *new_history;
259
260 new_file = g_new0(struct files, 1);
261 new_history = g_new0(struct file_history, 1);
262 new_file->name = strdup(file_name);
263 new_file->read = 0;
264 new_file->write = 0;
59288610 265 new_file->flag = -1;
b093de8a
MB
266 new_history->file = new_file;
267 new_history->next = history;
268
269 return new_history;
270}
271
4adc8274 272enum bt_cb_ret handle_exit_syscall(struct bt_ctf_event *call_data,
1fc22eb4
JD
273 void *private_data)
274{
2e0a1190 275 const struct bt_definition *scope;
1fc22eb4
JD
276 unsigned long timestamp;
277 char *comm;
278 uint64_t ret, tid;
d67167cd 279 uint64_t cpu_id;
906c08f6 280 char *hostname;
1fc22eb4 281
c78f2cdc 282 timestamp = bt_ctf_get_timestamp(call_data);
1fc22eb4
JD
283 if (timestamp == -1ULL)
284 goto error;
285
1dec520a
JD
286 comm = get_context_comm(call_data);
287 tid = get_context_tid(call_data);
1fc22eb4
JD
288
289 scope = bt_ctf_get_top_level_scope(call_data,
290 BT_EVENT_FIELDS);
291 ret = bt_ctf_get_int64(bt_ctf_get_field(call_data,
292 scope, "_ret"));
293 if (bt_ctf_field_get_error()) {
294 fprintf(stderr, "Missing ret context info\n");
295 goto error;
296 }
297
d67167cd 298 cpu_id = get_cpu_id(call_data);
906c08f6 299 hostname = get_context_hostname(call_data);
1fc22eb4
JD
300
301 /*
b093de8a
MB
302 * if we encounter an exit_syscall and
303 * it is not for a syscall read or write
1fc22eb4
JD
304 * we just abort the execution of this callback
305 */
906c08f6
JD
306 if ((update_iostream_ret(&lttngtop, tid, comm, timestamp, cpu_id,
307 ret, hostname)) < 0)
1fc22eb4
JD
308 return BT_CB_ERROR_CONTINUE;
309
310 return BT_CB_OK;
311
312error:
313 return BT_CB_ERROR_STOP;
314}
315
316
4adc8274 317enum bt_cb_ret handle_sys_write(struct bt_ctf_event *call_data,
1fc22eb4
JD
318 void *private_data)
319{
2e0a1190 320 const struct bt_definition *scope;
1fc22eb4 321 struct processtop *tmp;
1fc22eb4
JD
322 unsigned long timestamp;
323 uint64_t cpu_id;
928f18a6 324 int64_t tid;
906c08f6 325 char *procname, *hostname;
b093de8a 326 int fd;
1fc22eb4 327
c78f2cdc 328 timestamp = bt_ctf_get_timestamp(call_data);
1fc22eb4
JD
329 if (timestamp == -1ULL)
330 goto error;
331
1dec520a 332 tid = get_context_tid(call_data);
d67167cd 333 cpu_id = get_cpu_id(call_data);
1fc22eb4 334
928f18a6 335 procname = get_context_comm(call_data);
906c08f6 336 hostname = get_context_hostname(call_data);
59288610 337
b093de8a
MB
338 scope = bt_ctf_get_top_level_scope(call_data,
339 BT_EVENT_FIELDS);
340 fd = bt_ctf_get_uint64(bt_ctf_get_field(call_data,
341 scope, "_fd"));
342 if (bt_ctf_field_get_error()) {
343 fprintf(stderr, "Missing fd context info\n");
344 goto error;
345 }
346
906c08f6 347 tmp = get_proc(&lttngtop, tid, procname, timestamp, hostname);
96aa77de
JD
348 if (!tmp)
349 goto end;
350
b093de8a
MB
351 tmp->syscall_info = create_syscall_info(__NR_write, cpu_id, tid, fd);
352
353 insert_file(tmp, fd);
1fc22eb4 354
96aa77de 355end:
1fc22eb4
JD
356 return BT_CB_OK;
357
358error:
359 return BT_CB_ERROR_STOP;
360}
361
4adc8274 362enum bt_cb_ret handle_sys_read(struct bt_ctf_event *call_data,
1fc22eb4
JD
363 void *private_data)
364{
365 struct processtop *tmp;
2e0a1190 366 const struct bt_definition *scope;
1fc22eb4
JD
367 unsigned long timestamp;
368 uint64_t cpu_id;
928f18a6
MB
369 int64_t tid;
370 char *procname;
b093de8a 371 int fd;
906c08f6 372 char *hostname;
1fc22eb4 373
c78f2cdc 374 timestamp = bt_ctf_get_timestamp(call_data);
1fc22eb4
JD
375 if (timestamp == -1ULL)
376 goto error;
377
1dec520a 378 tid = get_context_tid(call_data);
d67167cd 379 cpu_id = get_cpu_id(call_data);
1fc22eb4 380
928f18a6 381 procname = get_context_comm(call_data);
906c08f6 382 hostname = get_context_hostname(call_data);
59288610 383
b093de8a
MB
384 scope = bt_ctf_get_top_level_scope(call_data,
385 BT_EVENT_FIELDS);
386 fd = bt_ctf_get_uint64(bt_ctf_get_field(call_data,
387 scope, "_fd"));
388 if (bt_ctf_field_get_error()) {
389 fprintf(stderr, "Missing fd context info\n");
390 goto error;
391 }
392
906c08f6 393 tmp = get_proc(&lttngtop, tid, procname, timestamp, hostname);
96aa77de
JD
394 if (!tmp)
395 goto end;
396
b093de8a
MB
397 tmp->syscall_info = create_syscall_info(__NR_read, cpu_id, tid, fd);
398
399 insert_file(tmp, fd);
400
96aa77de 401end:
b093de8a
MB
402 return BT_CB_OK;
403
404error:
405 return BT_CB_ERROR_STOP;
406}
407
4adc8274 408enum bt_cb_ret handle_sys_open(struct bt_ctf_event *call_data,
b093de8a
MB
409 void *private_data)
410{
411
412 struct processtop *tmp;
2e0a1190 413 const struct bt_definition *scope;
b093de8a
MB
414 unsigned long timestamp;
415 uint64_t cpu_id;
928f18a6 416 int64_t tid;
906c08f6 417 char *procname, *hostname;
b093de8a
MB
418 char *file;
419
c78f2cdc 420 timestamp = bt_ctf_get_timestamp(call_data);
b093de8a
MB
421 if (timestamp == -1ULL)
422 goto error;
423
1dec520a 424 tid = get_context_tid(call_data);
d67167cd 425 cpu_id = get_cpu_id(call_data);
b093de8a 426
928f18a6 427 procname = get_context_comm(call_data);
906c08f6 428 hostname = get_context_hostname(call_data);
59288610 429
b093de8a
MB
430 scope = bt_ctf_get_top_level_scope(call_data,
431 BT_EVENT_FIELDS);
432 file = bt_ctf_get_string(bt_ctf_get_field(call_data,
433 scope, "_filename"));
434 if (bt_ctf_field_get_error()) {
ceb3a221 435 fprintf(stderr, "Missing file name context info\n");
b093de8a
MB
436 goto error;
437 }
438
906c08f6 439 tmp = get_proc(&lttngtop, tid, procname, timestamp, hostname);
96aa77de
JD
440 if (!tmp)
441 goto end;
442
b093de8a
MB
443 tmp->syscall_info = create_syscall_info(__NR_open, cpu_id, tid, -1);
444
445 tmp->files_history = create_file(tmp->files_history, file);
1fc22eb4 446
96aa77de 447end:
1fc22eb4
JD
448 return BT_CB_OK;
449
450error:
451 return BT_CB_ERROR_STOP;
452}
453
9f2856ad
JD
454enum bt_cb_ret handle_sys_socket(struct bt_ctf_event *call_data,
455 void *private_data)
456{
457
458 struct processtop *tmp;
459 unsigned long timestamp;
460 uint64_t cpu_id;
461 int64_t tid;
462 char *procname, *hostname;
463 char *file;
464
465 timestamp = bt_ctf_get_timestamp(call_data);
466 if (timestamp == -1ULL)
467 goto error;
468
469 tid = get_context_tid(call_data);
470 cpu_id = get_cpu_id(call_data);
471
472 procname = get_context_comm(call_data);
473 hostname = get_context_hostname(call_data);
474
475 file = strdup("socket");
476
477 tmp = get_proc(&lttngtop, tid, procname, timestamp, hostname);
478 if (!tmp)
479 goto end;
480
481 tmp->syscall_info = create_syscall_info(__NR_open, cpu_id, tid, -1);
482
483 tmp->files_history = create_file(tmp->files_history, file);
484
485end:
486 return BT_CB_OK;
487
488error:
489 return BT_CB_ERROR_STOP;
490}
b093de8a 491
4adc8274 492enum bt_cb_ret handle_sys_close(struct bt_ctf_event *call_data,
b093de8a
MB
493 void *private_data)
494{
2e0a1190 495 const struct bt_definition *scope;
b093de8a 496 struct processtop *tmp;
928f18a6
MB
497 unsigned long timestamp;
498 int64_t tid;
499 char *procname;
b093de8a 500 int fd;
906c08f6 501 char *hostname;
b093de8a 502
c78f2cdc 503 timestamp = bt_ctf_get_timestamp(call_data);
b093de8a
MB
504 if (timestamp == -1ULL)
505 goto error;
506
1dec520a 507 tid = get_context_tid(call_data);
b093de8a 508
928f18a6 509 procname = get_context_comm(call_data);
906c08f6 510 hostname = get_context_hostname(call_data);
59288610 511
b093de8a
MB
512 scope = bt_ctf_get_top_level_scope(call_data,
513 BT_EVENT_FIELDS);
514 fd = bt_ctf_get_uint64(bt_ctf_get_field(call_data,
515 scope, "_fd"));
516 if (bt_ctf_field_get_error()) {
517 fprintf(stderr, "Missing fd context info\n");
518 goto error;
519 }
520
906c08f6 521 tmp = get_proc(&lttngtop, tid, procname, timestamp, hostname);
96aa77de
JD
522 if (!tmp)
523 goto end;
ceb3a221 524
b093de8a
MB
525 close_file(tmp, fd);
526
96aa77de 527end:
b093de8a
MB
528 return BT_CB_OK;
529
530error:
531 return BT_CB_ERROR_STOP;
532}
59288610 533
4adc8274 534enum bt_cb_ret handle_statedump_file_descriptor(struct bt_ctf_event *call_data,
ceb3a221
MB
535 void *private_data)
536{
2e0a1190 537 const struct bt_definition *scope;
59288610 538 struct processtop *parent;
ceb3a221
MB
539 struct files *file;
540 unsigned long timestamp;
59288610 541 int64_t pid;
906c08f6 542 char *file_name, *hostname;
ceb3a221
MB
543 int fd;
544
c78f2cdc 545 timestamp = bt_ctf_get_timestamp(call_data);
ceb3a221
MB
546 if (timestamp == -1ULL)
547 goto error;
548
ceb3a221
MB
549 scope = bt_ctf_get_top_level_scope(call_data,
550 BT_EVENT_FIELDS);
59288610
MB
551 pid = bt_ctf_get_int64(bt_ctf_get_field(call_data,
552 scope, "_pid"));
ceb3a221
MB
553 if (bt_ctf_field_get_error()) {
554 fprintf(stderr, "Missing tid context info\n");
555 goto error;
556 }
557
558 scope = bt_ctf_get_top_level_scope(call_data,
559 BT_EVENT_FIELDS);
59288610 560 fd = bt_ctf_get_int64(bt_ctf_get_field(call_data,
ceb3a221
MB
561 scope, "_fd"));
562 if (bt_ctf_field_get_error()) {
563 fprintf(stderr, "Missing fd context info\n");
564 goto error;
565 }
566
567 scope = bt_ctf_get_top_level_scope(call_data,
568 BT_EVENT_FIELDS);
569 file_name = bt_ctf_get_string(bt_ctf_get_field(call_data,
570 scope, "_filename"));
571 if (bt_ctf_field_get_error()) {
572 fprintf(stderr, "Missing file name context info\n");
573 goto error;
574 }
906c08f6 575 hostname = get_context_hostname(call_data);
ceb3a221 576
906c08f6 577 parent = get_proc_pid(&lttngtop, pid, pid, timestamp, hostname);
96aa77de
JD
578 if (!parent)
579 goto end;
580
59288610
MB
581 parent->files_history = create_file(parent->files_history, file_name);
582 file = parent->files_history->file;
583 edit_file(parent, file, fd);
ceb3a221 584
96aa77de 585end:
ceb3a221
MB
586 return BT_CB_OK;
587
588error:
589 return BT_CB_ERROR_STOP;
590}
This page took 0.052945 seconds and 4 git commands to generate.