3 * Linux Trace Toolkit utility library
5 * This is a simple daemon implementation that reads a few relay+debugfs
6 * channels and save them in a trace.
8 * CPU hot-plugging is supported using inotify.
11 * Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
13 * Michael Sills-Lavoie <michael.sills-lavoie@polymtl.ca>
14 * Oumarou Dicko <oumarou.dicko@polymtl.ca>
33 #include "liblttdutils.h"
35 struct liblttdutils_channel_data
{
39 struct liblttdutils_data
{
40 char path_trace
[PATH_MAX
];
47 static __thread
int thread_pipe
[2];
49 #define printf_verbose(fmt, args...) \
51 if (callbacks_data->verbose_mode) \
52 printf(fmt, ##args); \
55 int liblttdutils_local_on_open_channel(struct liblttd_callbacks
*data
, struct fd_pair
*pair
, char *relative_channel_path
)
60 struct liblttdutils_channel_data
*channel_data
;
62 pair
->user_data
= malloc(sizeof(struct liblttdutils_channel_data
));
63 channel_data
= pair
->user_data
;
65 struct liblttdutils_data
* callbacks_data
= data
->user_data
;
67 strncpy(callbacks_data
->end_path_trace
, relative_channel_path
, PATH_MAX
- callbacks_data
->path_trace_len
);
68 printf_verbose("Creating trace file %s\n", callbacks_data
->path_trace
);
70 ret
= stat(callbacks_data
->path_trace
, &stat_buf
);
72 if(callbacks_data
->append_mode
) {
73 printf_verbose("Appending to file %s as requested\n",
74 callbacks_data
->path_trace
);
76 channel_data
->trace
= open(callbacks_data
->path_trace
, O_WRONLY
, S_IRWXU
|S_IRWXG
|S_IRWXO
);
77 if(channel_data
->trace
== -1) {
78 perror(callbacks_data
->path_trace
);
82 ret
= lseek(channel_data
->trace
, 0, SEEK_END
);
84 perror(callbacks_data
->path_trace
);
86 close(channel_data
->trace
);
90 printf("File %s exists, cannot open. Try append mode.\n", callbacks_data
->path_trace
);
97 open(callbacks_data
->path_trace
, O_WRONLY
|O_CREAT
|O_EXCL
, S_IRWXU
|S_IRWXG
|S_IRWXO
);
98 if(channel_data
->trace
== -1) {
99 perror(callbacks_data
->path_trace
);
111 int liblttdutils_local_on_close_channel(struct liblttd_callbacks
*data
, struct fd_pair
*pair
)
114 ret
= close(((struct liblttdutils_channel_data
*)(pair
->user_data
))->trace
);
115 free(pair
->user_data
);
119 int liblttdutils_local_on_new_channels_folder(struct liblttd_callbacks
*data
, char *relative_folder_path
)
123 struct liblttdutils_data
* callbacks_data
= data
->user_data
;
125 strncpy(callbacks_data
->end_path_trace
, relative_folder_path
, PATH_MAX
- callbacks_data
->path_trace_len
);
126 printf_verbose("Creating trace subdirectory %s\n", callbacks_data
->path_trace
);
128 ret
= mkdir(callbacks_data
->path_trace
, S_IRWXU
|S_IRWXG
|S_IRWXO
);
130 if(errno
!= EEXIST
) {
131 perror(callbacks_data
->path_trace
);
141 int liblttdutils_local_on_read_subbuffer(struct liblttd_callbacks
*data
, struct fd_pair
*pair
, unsigned int len
)
146 struct liblttdutils_data
* callbacks_data
= data
->user_data
;
149 printf_verbose("splice chan to pipe offset %lu\n",
150 (unsigned long)offset
);
151 ret
= splice(pair
->channel
, &offset
, thread_pipe
[1], NULL
,
152 len
, SPLICE_F_MOVE
| SPLICE_F_MORE
);
153 printf_verbose("splice chan to pipe ret %ld\n", ret
);
155 perror("Error in relay splice");
158 ret
= splice(thread_pipe
[0], NULL
,
159 ((struct liblttdutils_channel_data
*)(pair
->user_data
))->trace
,
160 NULL
, ret
, SPLICE_F_MOVE
| SPLICE_F_MORE
);
161 printf_verbose("splice pipe to file %ld\n", ret
);
163 perror("Error in file splice");
173 int liblttdutils_local_on_new_thread(struct liblttd_callbacks
*data
, unsigned long thread_num
)
176 ret
= pipe(thread_pipe
);
178 perror("Error creating pipe");
184 int liblttdutils_local_on_close_thread(struct liblttd_callbacks
*data
, unsigned long thread_num
)
186 close(thread_pipe
[0]); /* close read end */
187 close(thread_pipe
[1]); /* close write end */
191 int liblttdutils_local_on_trace_end(struct liblttd_instance
*instance
)
193 struct liblttd_callbacks
*callbacks
= instance
->callbacks
;
194 struct liblttdutils_data
*data
= callbacks
->user_data
;
200 struct liblttd_callbacks
* liblttdutils_local_new_callbacks(char* trace_name
,
201 int append_mode
, int verbose_mode
)
203 struct liblttdutils_data
*data
;
204 struct liblttd_callbacks
*callbacks
;
206 if(!trace_name
) return NULL
;
208 data
= malloc(sizeof(struct liblttdutils_data
));
210 strncpy(data
->path_trace
, trace_name
, PATH_MAX
-1);
211 data
->path_trace_len
= strlen(data
->path_trace
);
212 data
->end_path_trace
= data
->path_trace
+ data
->path_trace_len
;
213 data
->append_mode
= append_mode
;
214 data
->verbose_mode
= verbose_mode
;
216 callbacks
= malloc(sizeof(struct liblttd_callbacks
));
218 callbacks
->on_open_channel
= liblttdutils_local_on_open_channel
;
219 callbacks
->on_close_channel
= liblttdutils_local_on_close_channel
;
220 callbacks
->on_new_channels_folder
= liblttdutils_local_on_new_channels_folder
;
221 callbacks
->on_read_subbuffer
= liblttdutils_local_on_read_subbuffer
;
222 callbacks
->on_trace_end
= liblttdutils_local_on_trace_end
;
223 callbacks
->on_new_thread
= liblttdutils_local_on_new_thread
;
224 callbacks
->on_close_thread
= liblttdutils_local_on_close_thread
;
225 callbacks
->user_data
= data
;