2 * Copyright (C) 2011-2012 Mathieu Bain <mathieu.bain@polymtl.ca>
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;
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.
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.
20 #include <sys/types.h>
23 #include <babeltrace/babeltrace.h>
25 #include "lttngtoptypes.h"
27 #include "iostreamtop.h"
29 void add_file(struct processtop
*proc
, struct files
*file
, int fd
)
31 struct files
*tmp_file
;
32 struct processtop
*parent
;
36 size
= proc
->process_files_table
->len
;
37 parent
= proc
->threadparent
;
39 insert_file(parent
, fd
);
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
);
45 g_ptr_array_add(proc
->process_files_table
, file
);
47 tmp_file
= g_ptr_array_index(proc
->process_files_table
, fd
);
49 g_ptr_array_index(proc
->process_files_table
, fd
) = file
;
51 if (!tmp_file
->name
||
52 strcmp(tmp_file
->name
, file
->name
) != 0) {
53 size
= proc
->process_files_table
->len
;
54 g_ptr_array_set_size(proc
->process_files_table
,
56 g_ptr_array_index(proc
->process_files_table
,
58 g_ptr_array_index(proc
->process_files_table
,
61 tmp_file
->flag
= __NR_open
;
65 * The file may have be created in the parent
67 if (file
->flag
== -1) {
69 file
->flag
= __NR_open
;
71 lttngtop
.nbnewfiles
++;
77 * Called by handled_statedump_filename
79 void edit_file(struct processtop
*proc
, struct files
*file
, int fd
)
81 int size
= proc
->process_files_table
->len
;
82 struct files
*tmpfile
;
85 add_file(proc
, file
, fd
);
87 tmpfile
= g_ptr_array_index(proc
->process_files_table
, fd
);
89 tmpfile
->name
= strdup(file
->name
);
92 add_file(proc
, file
, fd
);
96 void insert_file(struct processtop
*proc
, int fd
)
99 struct files
*tmp_parent
;
100 struct processtop
*parent
;
104 if (fd
>= proc
->process_files_table
->len
) {
105 tmp
= g_new0(struct files
, 1);
111 add_file(proc
, tmp
, fd
);
113 tmp
= g_ptr_array_index(proc
->process_files_table
, fd
);
115 tmp
= g_new0(struct files
, 1);
121 add_file(proc
, tmp
, fd
);
123 parent
= proc
->threadparent
;
125 tmp_parent
= g_ptr_array_index(
126 parent
->process_files_table
, fd
);
127 if (tmp_parent
&& tmp
->name
&& tmp_parent
->name
&&
128 (strcmp(tmp
->name
, tmp_parent
->name
)) != 0)
129 tmp
->name
= strdup(tmp_parent
->name
);
135 void close_file(struct processtop
*proc
, int fd
)
139 file
= get_file(proc
, fd
);
141 file
->flag
= __NR_close
;
148 lttngtop
.nbclosedfiles
++;
151 struct files
*get_file(struct processtop
*proc
, int fd
)
154 struct files
*tmp
= NULL
;
156 len
= proc
->process_files_table
->len
;
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
163 if (fd
< len
&& fd
>= 0)
164 tmp
= g_ptr_array_index(proc
->process_files_table
, fd
);
169 void show_table(GPtrArray
*tab
)
174 for (i
= 0 ; i
< tab
->len
; i
++) {
175 file
= g_ptr_array_index(tab
, i
);
177 fprintf(stderr
, "NULL, ");
179 fprintf(stderr
, "%s, ", file
->name
);
181 fprintf(stderr
, "]\n\n");
184 void show_history(struct file_history
*history
)
186 struct file_history
*tmp
= history
;
188 while (tmp
!= NULL
) {
189 fprintf(stderr
, "fd = %d, name = %s\n", tmp
->file
->fd
,
196 int update_iostream_ret(struct lttngtop
*ctx
, int tid
, char *comm
,
197 unsigned long timestamp
, uint64_t cpu_id
, int ret
,
200 struct processtop
*tmp
;
201 struct files
*tmpfile
;
204 tmp
= get_proc(ctx
, tid
, comm
, timestamp
, hostname
);
210 if (tmp
->syscall_info
!= NULL
) {
211 if (tmp
->syscall_info
->type
== __NR_read
213 tmp
->totalfileread
+= ret
;
214 tmp
->fileread
+= ret
;
215 tmpfile
= get_file(tmp
, tmp
->syscall_info
->fd
);
217 tmpfile
->read
+= ret
;
218 } else if (tmp
->syscall_info
->type
== __NR_write
220 tmp
->totalfilewrite
+= ret
;
221 tmp
->filewrite
+= ret
;
222 tmpfile
= get_file(tmp
, tmp
->syscall_info
->fd
);
224 tmpfile
->write
+= ret
;
225 } else if (tmp
->syscall_info
->type
== __NR_open
227 tmpfile
= tmp
->files_history
->file
;
228 add_file(tmp
, tmpfile
, ret
);
233 g_free(tmp
->syscall_info
);
234 tmp
->syscall_info
= NULL
;
241 struct syscalls
*create_syscall_info(unsigned int type
, uint64_t cpu_id
,
242 unsigned int tid
, int fd
)
244 struct syscalls
*syscall_info
;
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
;
255 struct file_history
*create_file(struct file_history
*history
, char *file_name
)
257 struct files
*new_file
;
258 struct file_history
*new_history
;
260 new_file
= g_new0(struct files
, 1);
261 new_history
= g_new0(struct file_history
, 1);
262 new_file
->name
= strdup(file_name
);
266 new_history
->file
= new_file
;
267 new_history
->next
= history
;
272 enum bt_cb_ret
handle_exit_syscall(struct bt_ctf_event
*call_data
,
275 const struct bt_definition
*scope
;
276 unsigned long timestamp
;
282 timestamp
= bt_ctf_get_timestamp(call_data
);
283 if (timestamp
== -1ULL)
286 comm
= get_context_comm(call_data
);
287 tid
= get_context_tid(call_data
);
289 scope
= bt_ctf_get_top_level_scope(call_data
,
291 ret
= bt_ctf_get_int64(bt_ctf_get_field(call_data
,
293 if (bt_ctf_field_get_error()) {
294 fprintf(stderr
, "Missing ret context info\n");
298 cpu_id
= get_cpu_id(call_data
);
299 hostname
= get_context_hostname(call_data
);
302 * if we encounter an exit_syscall and
303 * it is not for a syscall read or write
304 * we just abort the execution of this callback
306 if ((update_iostream_ret(<tngtop
, tid
, comm
, timestamp
, cpu_id
,
308 return BT_CB_ERROR_CONTINUE
;
313 return BT_CB_ERROR_STOP
;
317 enum bt_cb_ret
handle_sys_write(struct bt_ctf_event
*call_data
,
320 const struct bt_definition
*scope
;
321 struct processtop
*tmp
;
322 unsigned long timestamp
;
325 char *procname
, *hostname
;
328 timestamp
= bt_ctf_get_timestamp(call_data
);
329 if (timestamp
== -1ULL)
332 tid
= get_context_tid(call_data
);
333 cpu_id
= get_cpu_id(call_data
);
335 procname
= get_context_comm(call_data
);
336 hostname
= get_context_hostname(call_data
);
338 scope
= bt_ctf_get_top_level_scope(call_data
,
340 fd
= bt_ctf_get_uint64(bt_ctf_get_field(call_data
,
342 if (bt_ctf_field_get_error()) {
343 fprintf(stderr
, "Missing fd context info\n");
347 tmp
= get_proc(<tngtop
, tid
, procname
, timestamp
, hostname
);
351 tmp
->syscall_info
= create_syscall_info(__NR_write
, cpu_id
, tid
, fd
);
353 insert_file(tmp
, fd
);
359 return BT_CB_ERROR_STOP
;
362 enum bt_cb_ret
handle_sys_read(struct bt_ctf_event
*call_data
,
365 struct processtop
*tmp
;
366 const struct bt_definition
*scope
;
367 unsigned long timestamp
;
374 timestamp
= bt_ctf_get_timestamp(call_data
);
375 if (timestamp
== -1ULL)
378 tid
= get_context_tid(call_data
);
379 cpu_id
= get_cpu_id(call_data
);
381 procname
= get_context_comm(call_data
);
382 hostname
= get_context_hostname(call_data
);
384 scope
= bt_ctf_get_top_level_scope(call_data
,
386 fd
= bt_ctf_get_uint64(bt_ctf_get_field(call_data
,
388 if (bt_ctf_field_get_error()) {
389 fprintf(stderr
, "Missing fd context info\n");
393 tmp
= get_proc(<tngtop
, tid
, procname
, timestamp
, hostname
);
397 tmp
->syscall_info
= create_syscall_info(__NR_read
, cpu_id
, tid
, fd
);
399 insert_file(tmp
, fd
);
405 return BT_CB_ERROR_STOP
;
408 enum bt_cb_ret
handle_sys_open(struct bt_ctf_event
*call_data
,
412 struct processtop
*tmp
;
413 const struct bt_definition
*scope
;
414 unsigned long timestamp
;
417 char *procname
, *hostname
;
420 timestamp
= bt_ctf_get_timestamp(call_data
);
421 if (timestamp
== -1ULL)
424 tid
= get_context_tid(call_data
);
425 cpu_id
= get_cpu_id(call_data
);
427 procname
= get_context_comm(call_data
);
428 hostname
= get_context_hostname(call_data
);
430 scope
= bt_ctf_get_top_level_scope(call_data
,
432 file
= bt_ctf_get_string(bt_ctf_get_field(call_data
,
433 scope
, "_filename"));
434 if (bt_ctf_field_get_error()) {
435 fprintf(stderr
, "Missing file name context info\n");
439 tmp
= get_proc(<tngtop
, tid
, procname
, timestamp
, hostname
);
443 tmp
->syscall_info
= create_syscall_info(__NR_open
, cpu_id
, tid
, -1);
445 tmp
->files_history
= create_file(tmp
->files_history
, file
);
451 return BT_CB_ERROR_STOP
;
454 enum bt_cb_ret
handle_sys_socket(struct bt_ctf_event
*call_data
,
458 struct processtop
*tmp
;
459 unsigned long timestamp
;
462 char *procname
, *hostname
;
465 timestamp
= bt_ctf_get_timestamp(call_data
);
466 if (timestamp
== -1ULL)
469 tid
= get_context_tid(call_data
);
470 cpu_id
= get_cpu_id(call_data
);
472 procname
= get_context_comm(call_data
);
473 hostname
= get_context_hostname(call_data
);
475 file
= strdup("socket");
477 tmp
= get_proc(<tngtop
, tid
, procname
, timestamp
, hostname
);
481 tmp
->syscall_info
= create_syscall_info(__NR_open
, cpu_id
, tid
, -1);
483 tmp
->files_history
= create_file(tmp
->files_history
, file
);
489 return BT_CB_ERROR_STOP
;
492 enum bt_cb_ret
handle_sys_close(struct bt_ctf_event
*call_data
,
495 const struct bt_definition
*scope
;
496 struct processtop
*tmp
;
497 unsigned long timestamp
;
503 timestamp
= bt_ctf_get_timestamp(call_data
);
504 if (timestamp
== -1ULL)
507 tid
= get_context_tid(call_data
);
509 procname
= get_context_comm(call_data
);
510 hostname
= get_context_hostname(call_data
);
512 scope
= bt_ctf_get_top_level_scope(call_data
,
514 fd
= bt_ctf_get_uint64(bt_ctf_get_field(call_data
,
516 if (bt_ctf_field_get_error()) {
517 fprintf(stderr
, "Missing fd context info\n");
521 tmp
= get_proc(<tngtop
, tid
, procname
, timestamp
, hostname
);
531 return BT_CB_ERROR_STOP
;
534 enum bt_cb_ret
handle_statedump_file_descriptor(struct bt_ctf_event
*call_data
,
537 const struct bt_definition
*scope
;
538 struct processtop
*parent
;
540 unsigned long timestamp
;
542 char *file_name
, *hostname
;
545 timestamp
= bt_ctf_get_timestamp(call_data
);
546 if (timestamp
== -1ULL)
549 scope
= bt_ctf_get_top_level_scope(call_data
,
551 pid
= bt_ctf_get_int64(bt_ctf_get_field(call_data
,
553 if (bt_ctf_field_get_error()) {
554 fprintf(stderr
, "Missing tid context info\n");
558 scope
= bt_ctf_get_top_level_scope(call_data
,
560 fd
= bt_ctf_get_int64(bt_ctf_get_field(call_data
,
562 if (bt_ctf_field_get_error()) {
563 fprintf(stderr
, "Missing fd context info\n");
567 scope
= bt_ctf_get_top_level_scope(call_data
,
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");
575 hostname
= get_context_hostname(call_data
);
577 parent
= get_proc_pid(<tngtop
, pid
, pid
, timestamp
, hostname
);
581 parent
->files_history
= create_file(parent
->files_history
, file_name
);
582 file
= parent
->files_history
->file
;
583 edit_file(parent
, file
, fd
);
589 return BT_CB_ERROR_STOP
;
This page took 0.042267 seconds and 4 git commands to generate.