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>
25 #include <babeltrace/babeltrace.h>
28 #include "lttngtoptypes.h"
30 #include "iostreamtop.h"
32 void add_file(Quark proc_quark
, Quark file
, int fd
,
33 unsigned long timestamp
)
39 std::string old_filename
;
43 if (state_system
->attributeExists(proc_quark
, "threadparent")) {
44 parent
= state_system
->getQuark(proc_quark
, "threadparent");
45 insert_file(parent
, fd
, timestamp
);
48 path
= path_name_from_fd(fd
);
49 if (state_system
->attributeExists(proc_quark
, path
+ "/file")) {
50 file_pointer
= state_system
->getQuark(proc_quark
, path
);
51 get_current_attribute_value_quark(&file_pointer
, "file",
53 get_current_attribute_value_string(&old_file
, "name",
55 get_current_attribute_value_string(&file
, "name", filename
);
56 if (old_filename
!= filename
) {
57 /* Different file with same fd, we overwrite the
59 modify_attribute(timestamp
, &file_pointer
, "file",
62 modify_attribute(timestamp
, &old_file
, "flag",
66 file_pointer
= state_system
->getQuark(proc_quark
, path
);
67 modify_attribute(timestamp
, &file_pointer
, "file", file
);
70 /* To easily retrieve file pointer from files_history */
71 modify_attribute(timestamp
, &file
, "fd", fd
);
73 /* The file may have been created in the parent */
74 get_current_attribute_value_int(&file
, "flag", flag
);
76 modify_attribute(timestamp
, &file
, "fd", fd
);
77 modify_attribute(timestamp
, &file
, "flag", __NR_open
);
78 increment_attribute(timestamp
, NULL
, "nbfiles");
79 increment_attribute(timestamp
, NULL
, "nbnewfiles");
85 * Called by handled_statedump_filename
87 void edit_file(unsigned long timestamp
, Quark proc
, Quark file
, int fd
)
91 path
= path_name_from_fd(fd
);
92 if (!state_system
->attributeExists(proc
, path
)) {
93 add_file(proc
, file
, fd
, timestamp
);
97 Quark
create_file(Quark proc
, std::string file_name
, unsigned long timestamp
)
102 std::string current_path
;
104 std::stringstream ss
;
106 if (!get_current_attribute_value_quark(&proc
, "files_history/current",
108 /* First file for process */
109 file_history
= state_system
->getQuark(
110 proc
, "files_history/file_0");
113 current_path
= state_system
->getFullAttributeName(file_history
);
114 index
= atoi(current_path
.substr(current_path
.find_last_of('_')
116 ss
<< "files_history/file_" << index
+ 1;
117 current_path
= ss
.str();
118 file_history
= state_system
->getQuark(
122 has_old
= get_current_attribute_value_quark(
123 &proc
,"files_history/current", old_newest
);
124 modify_attribute(timestamp
, &proc
, "files_history/current",
126 modify_attribute(timestamp
, &file_history
, "file/name", file_name
);
127 modify_attribute(timestamp
, &file_history
, "file/read", 0);
128 modify_attribute(timestamp
, &file_history
, "file/write", 0);
129 modify_attribute(timestamp
, &file_history
, "file/flag", -1);
130 modify_attribute(timestamp
, &file_history
, "file/fd", -1);
131 modify_attribute(timestamp
, &file_history
, "file/birth", timestamp
);
133 modify_attribute(timestamp
, &file_history
, "next", old_newest
);
135 nullify_attribute(timestamp
, &file_history
, "next");
137 return state_system
->getQuark(file_history
, "file");
140 void insert_file(Quark proc
, int fd
, unsigned long timestamp
)
145 bool parent_has_file
;
151 if (get_file(proc
, fd
, file
)) {
152 if (state_system
->attributeExists(proc
, "threadparent")) {
153 parent
= state_system
->getQuark(proc
, "threadparent");
154 parent_has_file
= get_file(parent
, fd
,
156 if (parent_has_file
) {
157 get_current_attribute_value_string(&parent_file
,
160 modify_attribute(timestamp
, &file
, "name",
165 file
= create_file(proc
, "Unknown", timestamp
);
166 add_file(proc
, file
, fd
, timestamp
);
170 void close_file(unsigned long timestamp
, Quark proc
, int fd
)
175 file_found
= get_current_attribute_value_quark(&proc
,
176 path_name_from_fd(fd
),
179 modify_attribute(timestamp
, &file
, "flag", __NR_close
);
180 decrement_attribute(timestamp
, NULL
, "nbfiles");
182 increment_attribute(timestamp
, NULL
, "nbdeadfiles");
185 bool get_file(Quark proc_quark
, int fd
, Quark
&file_quark
)
187 std::string path
= path_name_from_fd(fd
);
189 if (state_system
->attributeExists(proc_quark
, path
)) {
190 file_pointer
= state_system
->getQuark(proc_quark
, path
);
191 return get_current_attribute_value_quark(&file_pointer
, "file",
198 void show_history(Quark proc
)
204 if (get_current_attribute_value_quark(&proc
, "files_history", file
)) {
208 get_current_attribute_value_int(&file
, "file/fd", fd
);
209 get_current_attribute_value_string(
210 &file
, "file/name", name
);
211 fprintf(stderr
, "fd = %d, name = %s\n", fd
,
213 } while (get_current_attribute_value_quark(
214 &file
, "next", file
));
219 int update_iostream_ret(int tid
, char *comm
, unsigned long timestamp
,
220 uint64_t cpu_id
, int ret
)
223 Quark syscall_info_quark
;
225 Quark file_history_quark
;
231 proc_quark
= get_proc(tid
, comm
, timestamp
);
233 if (state_system
->attributeExists(proc_quark
, "syscall_info")) {
234 syscall_info_quark
= state_system
->getQuark(proc_quark
,
236 get_current_attribute_value_int(&syscall_info_quark
, "type",
238 if (syscall_type
== __NR_read
&& ret
> 0) {
239 increase_attribute(timestamp
, &proc_quark
,
240 "totalfileread", ret
);
241 increase_attribute(timestamp
, &proc_quark
,
243 get_current_attribute_value_int(&syscall_info_quark
,
245 file_found
= get_file(proc_quark
, fd
,
248 increase_attribute(timestamp
, &file_quark
,
250 } else if (syscall_type
== __NR_write
&& ret
> 0) {
252 increase_attribute(timestamp
, &proc_quark
,
253 "totalfilewrite", ret
);
254 increase_attribute(timestamp
, &proc_quark
,
256 get_current_attribute_value_int(&syscall_info_quark
,
258 file_found
= get_file(proc_quark
, fd
,
261 increase_attribute(timestamp
, &file_quark
,
263 } else if (syscall_type
== __NR_open
&& ret
> 0) {
264 file_history_quark
= state_system
->getQuark(proc_quark
,
266 file_quark
= state_system
->getQuark(file_history_quark
,
268 add_file(proc_quark
, file_quark
, ret
,
270 modify_attribute(timestamp
, &file_quark
, "fd", fd
);
278 void update_syscall_info(unsigned long timestamp
, int type
, int cpu_id
,
283 get_current_attribute_value_int(&proc
, "tid", tid
);
284 modify_attribute(timestamp
, &proc
, "syscall_info/type", type
);
285 modify_attribute(timestamp
, &proc
, "syscall_info/cpu_id", cpu_id
);
286 modify_attribute(timestamp
, &proc
, "syscall_info/tid", tid
);
287 modify_attribute(timestamp
, &proc
, "syscall_info/fd", fd
);
290 enum bt_cb_ret
handle_exit_syscall(struct bt_ctf_event
*call_data
,
293 const struct definition
*scope
;
294 unsigned long timestamp
;
299 timestamp
= bt_ctf_get_timestamp(call_data
);
300 if (timestamp
== -1ULL)
303 comm
= get_context_comm(call_data
);
304 tid
= get_context_tid(call_data
);
306 scope
= bt_ctf_get_top_level_scope(call_data
,
308 ret
= bt_ctf_get_int64(bt_ctf_get_field(call_data
,
310 if (bt_ctf_field_get_error()) {
311 fprintf(stderr
, "Missing ret context info\n");
315 cpu_id
= get_cpu_id(call_data
);
318 * if we encounter an exit_syscall and
319 * it is not for a syscall read or write
320 * we just abort the execution of this callback
322 if (update_iostream_ret(
323 tid
, comm
, timestamp
, cpu_id
, ret
) < 0)
324 return BT_CB_ERROR_CONTINUE
;
329 return BT_CB_ERROR_STOP
;
332 enum bt_cb_ret
handle_sys_write(struct bt_ctf_event
*call_data
,
335 const struct definition
*scope
;
337 unsigned long timestamp
;
343 timestamp
= bt_ctf_get_timestamp(call_data
);
344 if (timestamp
== -1ULL)
347 tid
= get_context_tid(call_data
);
348 cpu_id
= get_cpu_id(call_data
);
350 procname
= get_context_comm(call_data
);
352 scope
= bt_ctf_get_top_level_scope(call_data
,
354 fd
= bt_ctf_get_uint64(bt_ctf_get_field(call_data
,
356 if (bt_ctf_field_get_error()) {
357 fprintf(stderr
, "Missing fd context info\n");
361 proc
= get_proc(tid
, procname
, timestamp
);
362 update_syscall_info(timestamp
, __NR_write
, cpu_id
, proc
, fd
);
364 insert_file(proc
, fd
, timestamp
);
369 return BT_CB_ERROR_STOP
;
372 enum bt_cb_ret
handle_sys_read(struct bt_ctf_event
*call_data
,
375 const struct definition
*scope
;
377 unsigned long timestamp
;
383 timestamp
= bt_ctf_get_timestamp(call_data
);
384 if (timestamp
== -1ULL)
387 tid
= get_context_tid(call_data
);
388 cpu_id
= get_cpu_id(call_data
);
390 procname
= get_context_comm(call_data
);
392 scope
= bt_ctf_get_top_level_scope(call_data
,
394 fd
= bt_ctf_get_uint64(bt_ctf_get_field(call_data
,
396 if (bt_ctf_field_get_error()) {
397 fprintf(stderr
, "Missing fd context info\n");
401 proc
= get_proc(tid
, procname
, timestamp
);
402 update_syscall_info(timestamp
, __NR_read
, cpu_id
, proc
, fd
);
404 insert_file(proc
, fd
, timestamp
);
409 return BT_CB_ERROR_STOP
;
412 enum bt_cb_ret
handle_sys_open(struct bt_ctf_event
*call_data
,
416 const struct definition
*scope
;
417 unsigned long timestamp
;
423 timestamp
= bt_ctf_get_timestamp(call_data
);
424 if (timestamp
== -1ULL)
427 tid
= get_context_tid(call_data
);
428 cpu_id
= get_cpu_id(call_data
);
430 procname
= get_context_comm(call_data
);
432 scope
= bt_ctf_get_top_level_scope(call_data
,
434 file
= bt_ctf_get_string(bt_ctf_get_field(call_data
,
435 scope
, "_filename"));
436 if (bt_ctf_field_get_error()) {
437 fprintf(stderr
, "Missing file name context info\n");
441 proc
= get_proc(tid
, procname
, timestamp
);
442 update_syscall_info(timestamp
, __NR_open
, cpu_id
, proc
, -1);
444 create_file(proc
, file
, timestamp
);
449 return BT_CB_ERROR_STOP
;
452 enum bt_cb_ret
handle_sys_close(struct bt_ctf_event
*call_data
,
455 const struct definition
*scope
;
457 unsigned long timestamp
;
462 timestamp
= bt_ctf_get_timestamp(call_data
);
463 if (timestamp
== -1ULL)
466 tid
= get_context_tid(call_data
);
468 procname
= get_context_comm(call_data
);
470 scope
= bt_ctf_get_top_level_scope(call_data
,
472 fd
= bt_ctf_get_uint64(bt_ctf_get_field(call_data
,
474 if (bt_ctf_field_get_error()) {
475 fprintf(stderr
, "Missing fd context info\n");
479 proc
= get_proc(tid
, procname
, timestamp
);
481 close_file(timestamp
, proc
, fd
);
486 return BT_CB_ERROR_STOP
;
489 enum bt_cb_ret
handle_statedump_file_descriptor(
490 struct bt_ctf_event
*call_data
, void *private_data
)
492 const struct definition
*scope
;
495 unsigned long timestamp
;
500 timestamp
= bt_ctf_get_timestamp(call_data
);
501 if (timestamp
== -1ULL)
504 scope
= bt_ctf_get_top_level_scope(call_data
,
506 pid
= bt_ctf_get_int64(bt_ctf_get_field(call_data
,
508 if (bt_ctf_field_get_error()) {
509 fprintf(stderr
, "Missing tid context info\n");
513 scope
= bt_ctf_get_top_level_scope(call_data
,
515 fd
= bt_ctf_get_int64(bt_ctf_get_field(call_data
,
517 if (bt_ctf_field_get_error()) {
518 fprintf(stderr
, "Missing fd context info\n");
522 scope
= bt_ctf_get_top_level_scope(call_data
,
524 file_name
= bt_ctf_get_string(bt_ctf_get_field(call_data
,
525 scope
, "_filename"));
526 if (bt_ctf_field_get_error()) {
527 fprintf(stderr
, "Missing file name context info\n");
531 parent
= get_proc_pid(pid
, pid
, timestamp
);
532 create_file(parent
, file_name
, timestamp
);
533 file
= state_system
->getQuark(parent
, "files_history/current/file");
534 edit_file(timestamp
, parent
, file
, fd
);
539 return BT_CB_ERROR_STOP
;
This page took 0.041644 seconds and 4 git commands to generate.