91f3a27bf1126f0f16c97adc667f17ec57f7f968
3 * Linux Trace Toolkit Daemon
5 * This is a simple daemon that reads a few relay+debugfs channels and save
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>
16 * This library is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU Lesser General Public
18 * License as published by the Free Software Foundation; either
19 * version 2.1 of the License, or (at your option) any later version.
21 * This library is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * Lesser General Public License for more details.
26 * You should have received a copy of the GNU Lesser General Public
27 * License along with this library; if not, write to the Free Software
28 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
43 #include <sys/types.h>
51 #include <sys/syscall.h>
53 #include <asm/ioctls.h>
55 #include <linux/version.h>
58 #include <asm/ioctl.h>
59 #include <asm/types.h>
61 /* Get the next sub buffer that can be read. */
62 #define RELAY_GET_SB _IOR(0xF5, 0x00,__u32)
63 /* Release the oldest reserved (by "get") sub buffer. */
64 #define RELAY_PUT_SB _IOW(0xF5, 0x01,__u32)
65 /* returns the number of sub buffers in the per cpu channel. */
66 #define RELAY_GET_N_SB _IOR(0xF5, 0x02,__u32)
67 /* returns the size of the current sub buffer. */
68 #define RELAY_GET_SB_SIZE _IOR(0xF5, 0x03, __u32)
69 /* returns the size of data to consume in the current sub-buffer. */
70 #define RELAY_GET_MAX_SB_SIZE _IOR(0xF5, 0x04, __u32)
73 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
74 #include <sys/inotify.h>
78 static inline int inotify_init (void)
83 static inline int inotify_add_watch (int fd
, const char *name
, __u32 mask
)
88 static inline int inotify_rm_watch (int fd
, __u32 wd
)
95 struct liblttd_thread_data
{
97 struct liblttd_instance
*instance
;
100 #define printf_verbose(fmt, args...) \
102 if (instance->verbose_mode) \
103 printf(fmt, ##args); \
107 int open_buffer_file(struct liblttd_instance
*instance
, char *filename
,
108 char *path_channel
, char *base_path_channel
)
113 if (strncmp(filename
, "flight-", sizeof("flight-")-1) != 0) {
114 if (instance
->dump_flight_only
) {
115 printf_verbose("Skipping normal channel %s\n",
120 if (instance
->dump_normal_only
) {
121 printf_verbose("Skipping flight channel %s\n",
126 printf_verbose("Opening file.\n");
128 instance
->fd_pairs
.pair
= realloc(instance
->fd_pairs
.pair
,
129 ++instance
->fd_pairs
.num_pairs
* sizeof(struct fd_pair
));
131 /* Open the channel in read mode */
132 instance
->fd_pairs
.pair
[instance
->fd_pairs
.num_pairs
-1].channel
=
133 open(path_channel
, O_RDONLY
| O_NONBLOCK
);
134 if (instance
->fd_pairs
.pair
[instance
->fd_pairs
.num_pairs
-1].channel
== -1) {
135 perror(path_channel
);
136 instance
->fd_pairs
.num_pairs
--;
137 return 0; /* continue */
140 if (instance
->callbacks
->on_open_channel
) ret
= instance
->callbacks
->on_open_channel(
141 instance
->callbacks
, &instance
->fd_pairs
.pair
[instance
->fd_pairs
.num_pairs
-1],
146 close(instance
->fd_pairs
.pair
[instance
->fd_pairs
.num_pairs
-1].channel
);
147 instance
->fd_pairs
.num_pairs
--;
155 int open_channel_trace_pairs(struct liblttd_instance
*instance
,
156 char *subchannel_name
, char *base_subchannel_name
)
158 DIR *channel_dir
= opendir(subchannel_name
);
159 struct dirent
*entry
;
160 struct stat stat_buf
;
162 char path_channel
[PATH_MAX
];
163 int path_channel_len
;
164 char *path_channel_ptr
;
165 char *base_subchannel_ptr
;
169 if (channel_dir
== NULL
) {
170 perror(subchannel_name
);
175 printf_verbose("Calling : on new channels folder\n");
176 if (instance
->callbacks
->on_new_channels_folder
) ret
= instance
->callbacks
->
177 on_new_channels_folder(instance
->callbacks
,
178 base_subchannel_name
);
184 strncpy(path_channel
, subchannel_name
, PATH_MAX
-1);
185 path_channel_len
= strlen(path_channel
);
186 path_channel
[path_channel_len
] = '/';
188 path_channel_ptr
= path_channel
+ path_channel_len
;
189 base_subchannel_ptr
= path_channel
+
190 (base_subchannel_name
- subchannel_name
);
193 instance
->inotify_watch_array
.elem
= realloc(instance
->inotify_watch_array
.elem
,
194 ++instance
->inotify_watch_array
.num
* sizeof(struct inotify_watch
));
196 printf_verbose("Adding inotify for channel %s\n", path_channel
);
197 instance
->inotify_watch_array
.elem
[instance
->inotify_watch_array
.num
-1].wd
= inotify_add_watch(instance
->inotify_fd
, path_channel
, IN_CREATE
);
198 strcpy(instance
->inotify_watch_array
.elem
[instance
->inotify_watch_array
.num
-1].path_channel
, path_channel
);
199 instance
->inotify_watch_array
.elem
[instance
->inotify_watch_array
.num
-1].base_path_channel
=
200 instance
->inotify_watch_array
.elem
[instance
->inotify_watch_array
.num
-1].path_channel
+
201 (base_subchannel_name
- subchannel_name
);
202 printf_verbose("Added inotify for channel %s, wd %u\n",
203 instance
->inotify_watch_array
.elem
[instance
->inotify_watch_array
.num
-1].path_channel
,
204 instance
->inotify_watch_array
.elem
[instance
->inotify_watch_array
.num
-1].wd
);
207 while((entry
= readdir(channel_dir
)) != NULL
) {
209 if (entry
->d_name
[0] == '.') continue;
211 strncpy(path_channel_ptr
, entry
->d_name
, PATH_MAX
- path_channel_len
);
213 ret
= stat(path_channel
, &stat_buf
);
215 perror(path_channel
);
219 printf_verbose("Channel file : %s\n", path_channel
);
221 if (S_ISDIR(stat_buf
.st_mode
)) {
223 printf_verbose("Entering channel subdirectory...\n");
224 ret
= open_channel_trace_pairs(instance
, path_channel
, base_subchannel_ptr
);
225 if (ret
< 0) continue;
226 } else if (S_ISREG(stat_buf
.st_mode
)) {
227 open_ret
= open_buffer_file(instance
, entry
->d_name
,
228 path_channel
, base_subchannel_ptr
);
235 closedir(channel_dir
);
241 int read_subbuffer(struct liblttd_instance
*instance
, struct fd_pair
*pair
)
243 unsigned int consumed_old
, len
;
248 err
= ioctl(pair
->channel
, RELAY_GET_SB
, &consumed_old
);
249 printf_verbose("cookie : %u\n", consumed_old
);
252 perror("Reserving sub buffer failed (everything is normal, it is due to concurrency)");
256 err
= ioctl(pair
->channel
, RELAY_GET_SB_SIZE
, &len
);
259 perror("Getting sub-buffer len failed.");
263 if (instance
->callbacks
->on_read_subbuffer
)
264 ret
= instance
->callbacks
->on_read_subbuffer(
265 instance
->callbacks
, pair
, len
);
269 err
= ioctl(pair
->channel
, RELAY_PUT_SB
, &consumed_old
);
272 if (errno
== EFAULT
) {
273 perror("Error in unreserving sub buffer\n");
274 } else if (errno
== EIO
) {
275 /* Should never happen with newer LTTng versions */
276 perror("Reader has been pushed by the writer, last sub-buffer corrupted.");
286 int map_channels(struct liblttd_instance
*instance
, int idx_begin
, int idx_end
)
291 if (instance
->fd_pairs
.num_pairs
<= 0) {
292 printf("No channel to read\n");
296 /* Get the subbuf sizes and number */
298 for(i
=idx_begin
;i
<idx_end
;i
++) {
299 struct fd_pair
*pair
= &instance
->fd_pairs
.pair
[i
];
301 ret
= ioctl(pair
->channel
, RELAY_GET_N_SB
, &pair
->n_sb
);
303 perror("Error in getting the number of sub-buffers");
306 ret
= ioctl(pair
->channel
, RELAY_GET_MAX_SB_SIZE
,
309 perror("Error in getting the max sub-buffer size");
312 ret
= pthread_mutex_init(&pair
->mutex
, NULL
); /* Fast mutex */
314 perror("Error in mutex init");
323 int unmap_channels(struct liblttd_instance
*instance
)
329 for(j
=0;j
<instance
->fd_pairs
.num_pairs
;j
++) {
330 struct fd_pair
*pair
= &instance
->fd_pairs
.pair
[j
];
333 err_ret
= pthread_mutex_destroy(&pair
->mutex
);
335 perror("Error in mutex destroy");
344 /* Inotify event arrived.
346 * Only support add file for now.
348 int read_inotify(struct liblttd_instance
*instance
)
350 char buf
[sizeof(struct inotify_event
) + PATH_MAX
];
351 char path_channel
[PATH_MAX
];
353 struct inotify_event
*ievent
;
360 len
= read(instance
->inotify_fd
, buf
, sizeof(struct inotify_event
) + PATH_MAX
);
364 return 0; /* another thread got the data before us */
366 printf("Error in read from inotify FD %s.\n", strerror(len
));
369 while(offset
< len
) {
370 ievent
= (struct inotify_event
*)&(buf
[offset
]);
371 for(i
=0; i
<instance
->inotify_watch_array
.num
; i
++) {
372 if (instance
->inotify_watch_array
.elem
[i
].wd
== ievent
->wd
&&
373 ievent
->mask
== IN_CREATE
) {
375 "inotify wd %u event mask : %u for %s%s\n",
376 ievent
->wd
, ievent
->mask
,
377 instance
->inotify_watch_array
.elem
[i
].path_channel
,
379 old_num
= instance
->fd_pairs
.num_pairs
;
380 strcpy(path_channel
, instance
->inotify_watch_array
.elem
[i
].path_channel
);
381 strcat(path_channel
, ievent
->name
);
382 if (ret
= open_buffer_file(instance
, ievent
->name
, path_channel
,
383 path_channel
+ (instance
->inotify_watch_array
.elem
[i
].base_path_channel
-
384 instance
->inotify_watch_array
.elem
[i
].path_channel
))) {
385 printf("Error opening buffer file\n");
388 if (ret
= map_channels(instance
, old_num
, instance
->fd_pairs
.num_pairs
)) {
389 printf("Error mapping channel\n");
395 offset
+= sizeof(*ievent
) + ievent
->len
;
405 * Read the debugfs channels and write them in the paired tracefiles.
407 * @fd_pairs : paired channels and trace files.
409 * returns 0 on success, -1 on error.
411 * Note that the high priority polled channels are consumed first. We then poll
412 * again to see if these channels are still in priority. Only when no
413 * high priority channel is left, we start reading low priority channels.
415 * Note that a channel is considered high priority when the buffer is almost
419 int read_channels(struct liblttd_instance
*instance
, unsigned long thread_num
)
421 struct pollfd
*pollfd
= NULL
;
424 int num_rdy
, num_hup
;
428 unsigned int old_num
;
436 pthread_rwlock_rdlock(&instance
->fd_pairs_lock
);
438 /* Start polling the FD. Keep one fd for inotify */
439 pollfd
= malloc((inotify_fds
+ instance
->fd_pairs
.num_pairs
) * sizeof(struct pollfd
));
442 pollfd
[0].fd
= instance
->inotify_fd
;
443 pollfd
[0].events
= POLLIN
|POLLPRI
;
446 for(i
=0;i
<instance
->fd_pairs
.num_pairs
;i
++) {
447 pollfd
[inotify_fds
+i
].fd
= instance
->fd_pairs
.pair
[i
].channel
;
448 pollfd
[inotify_fds
+i
].events
= POLLIN
|POLLPRI
;
450 num_pollfd
= inotify_fds
+ instance
->fd_pairs
.num_pairs
;
453 pthread_rwlock_unlock(&instance
->fd_pairs_lock
);
459 printf("Press a key for next poll...\n");
461 read(STDIN_FILENO
, &buf
, 1);
462 printf("Next poll (polling %d fd) :\n", num_pollfd
);
465 /* Have we received a signal ? */
466 if (instance
->quit_program
) break;
468 num_rdy
= poll(pollfd
, num_pollfd
, -1);
471 perror("Poll error");
475 printf_verbose("Data received\n");
477 switch(pollfd
[0].revents
) {
480 "Error returned in polling inotify fd %d.\n",
485 "Polling inotify fd %d tells it has hung up.\n",
490 "Polling inotify fd %d tells fd is not open.\n",
496 "Polling inotify fd %d : data ready.\n",
499 pthread_rwlock_wrlock(&instance
->fd_pairs_lock
);
500 read_inotify(instance
);
501 pthread_rwlock_unlock(&instance
->fd_pairs_lock
);
507 for(i
=inotify_fds
;i
<num_pollfd
;i
++) {
508 switch(pollfd
[i
].revents
) {
511 "Error returned in polling fd %d.\n",
517 "Polling fd %d tells it has hung up.\n",
523 "Polling fd %d tells fd is not open.\n",
528 pthread_rwlock_rdlock(&instance
->fd_pairs_lock
);
529 if (pthread_mutex_trylock(&instance
->fd_pairs
.pair
[i
-inotify_fds
].mutex
) == 0) {
531 "Urgent read on fd %d\n",
533 /* Take care of high priority channels first. */
535 /* it's ok to have an unavailable sub-buffer */
536 ret
= read_subbuffer(instance
, &instance
->fd_pairs
.pair
[i
-inotify_fds
]);
537 if (ret
== EAGAIN
) ret
= 0;
539 ret
= pthread_mutex_unlock(&instance
->fd_pairs
.pair
[i
-inotify_fds
].mutex
);
541 printf("Error in mutex unlock : %s\n", strerror(ret
));
543 pthread_rwlock_unlock(&instance
->fd_pairs_lock
);
547 /* If every buffer FD has hung up, we end the read loop here */
548 if (num_hup
== num_pollfd
- inotify_fds
) break;
551 for(i
=inotify_fds
;i
<num_pollfd
;i
++) {
552 switch(pollfd
[i
].revents
) {
554 pthread_rwlock_rdlock(&instance
->fd_pairs_lock
);
555 if (pthread_mutex_trylock(&instance
->fd_pairs
.pair
[i
-inotify_fds
].mutex
) == 0) {
556 /* Take care of low priority channels. */
558 "Normal read on fd %d\n",
560 /* it's ok to have an unavailable subbuffer */
561 ret
= read_subbuffer(instance
, &instance
->fd_pairs
.pair
[i
-inotify_fds
]);
562 if (ret
== EAGAIN
) ret
= 0;
564 ret
= pthread_mutex_unlock(&instance
->fd_pairs
.pair
[i
-inotify_fds
].mutex
);
566 printf("Error in mutex unlock : %s\n", strerror(ret
));
568 pthread_rwlock_unlock(&instance
->fd_pairs_lock
);
574 /* Update pollfd array if an entry was added to fd_pairs */
575 pthread_rwlock_rdlock(&instance
->fd_pairs_lock
);
576 if ((inotify_fds
+ instance
->fd_pairs
.num_pairs
) != num_pollfd
) {
577 pollfd
= realloc(pollfd
,
578 (inotify_fds
+ instance
->fd_pairs
.num_pairs
) * sizeof(struct pollfd
));
579 for(i
=num_pollfd
-inotify_fds
;i
<instance
->fd_pairs
.num_pairs
;i
++) {
580 pollfd
[inotify_fds
+i
].fd
= instance
->fd_pairs
.pair
[i
].channel
;
581 pollfd
[inotify_fds
+i
].events
= POLLIN
|POLLPRI
;
583 num_pollfd
= instance
->fd_pairs
.num_pairs
+ inotify_fds
;
585 pthread_rwlock_unlock(&instance
->fd_pairs_lock
);
587 /* NB: If the fd_pairs structure is updated by another thread from this
588 * point forward, the current thread will wait in the poll without
589 * monitoring the new channel. However, this thread will add the
590 * new channel on next poll (and this should not take too much time
591 * on a loaded system).
593 * This event is quite unlikely and can only occur if a CPU is
594 * hot-plugged while multple lttd threads are running.
606 void close_channel_trace_pairs(struct liblttd_instance
*instance
)
611 for(i
=0;i
<instance
->fd_pairs
.num_pairs
;i
++) {
612 ret
= close(instance
->fd_pairs
.pair
[i
].channel
);
613 if (ret
== -1) perror("Close error on channel");
614 if (instance
->callbacks
->on_close_channel
) {
615 ret
= instance
->callbacks
->on_close_channel(
616 instance
->callbacks
, &instance
->fd_pairs
.pair
[i
]);
617 if (ret
!= 0) perror("Error on close channel callback");
620 free(instance
->fd_pairs
.pair
);
621 free(instance
->inotify_watch_array
.elem
);
625 void * thread_main(void *arg
)
628 struct liblttd_thread_data
*thread_data
= (struct liblttd_thread_data
*) arg
;
630 if (thread_data
->instance
->callbacks
->on_new_thread
)
631 ret
= thread_data
->instance
->callbacks
->on_new_thread(
632 thread_data
->instance
->callbacks
, thread_data
->thread_num
);
637 ret
= read_channels(thread_data
->instance
, thread_data
->thread_num
);
639 if (thread_data
->instance
->callbacks
->on_close_thread
)
640 thread_data
->instance
->callbacks
->on_close_thread(
641 thread_data
->instance
->callbacks
, thread_data
->thread_num
);
648 int channels_init(struct liblttd_instance
*instance
)
652 instance
->inotify_fd
= inotify_init();
653 fcntl(instance
->inotify_fd
, F_SETFL
, O_NONBLOCK
);
655 if (ret
= open_channel_trace_pairs(instance
, instance
->channel_name
,
656 instance
->channel_name
+
657 strlen(instance
->channel_name
)))
659 if (instance
->fd_pairs
.num_pairs
== 0) {
660 printf("No channel available for reading, exiting\n");
665 if (ret
= map_channels(instance
, 0, instance
->fd_pairs
.num_pairs
))
670 close_channel_trace_pairs(instance
);
671 if (instance
->inotify_fd
>= 0)
672 close(instance
->inotify_fd
);
676 int delete_instance(struct liblttd_instance
*instance
)
678 pthread_rwlock_destroy(&instance
->fd_pairs_lock
);
683 int liblttd_start_instance(struct liblttd_instance
*instance
)
693 if (ret
= channels_init(instance
))
696 tids
= malloc(sizeof(pthread_t
) * instance
->num_threads
);
697 for(i
=0; i
<instance
->num_threads
; i
++) {
698 struct liblttd_thread_data
*thread_data
=
699 malloc(sizeof(struct liblttd_thread_data
));
700 thread_data
->thread_num
= i
;
701 thread_data
->instance
= instance
;
703 ret
= pthread_create(&tids
[i
], NULL
, thread_main
, thread_data
);
705 perror("Error creating thread");
710 for(i
=0; i
<instance
->num_threads
; i
++) {
711 ret
= pthread_join(tids
[i
], &tret
);
713 perror("Error joining thread");
716 if ((long)tret
!= 0) {
717 printf("Error %s occured in thread %ld\n",
718 strerror((long)tret
), i
);
723 ret
= unmap_channels(instance
);
724 close_channel_trace_pairs(instance
);
725 if (instance
->inotify_fd
>= 0)
726 close(instance
->inotify_fd
);
728 if (instance
->callbacks
->on_trace_end
)
729 instance
->callbacks
->on_trace_end(instance
);
731 delete_instance(instance
);
736 struct liblttd_instance
* liblttd_new_instance(
737 struct liblttd_callbacks
*callbacks
, char *channel_path
,
738 unsigned long n_threads
, int flight_only
, int normal_only
, int verbose
)
740 struct liblttd_instance
* instance
;
742 if (!channel_path
|| !callbacks
)
746 if (flight_only
&& normal_only
)
749 instance
= malloc(sizeof(struct liblttd_instance
));
753 instance
->callbacks
= callbacks
;
755 instance
->inotify_fd
= -1;
757 instance
->fd_pairs
.pair
= NULL
;
758 instance
->fd_pairs
.num_pairs
= 0;
760 instance
->inotify_watch_array
.elem
= NULL
;
761 instance
->inotify_watch_array
.num
= 0;
763 pthread_rwlock_init(&instance
->fd_pairs_lock
, NULL
);
765 strncpy(instance
->channel_name
, channel_path
, PATH_MAX
-1);
766 instance
->num_threads
= n_threads
;
767 instance
->dump_flight_only
= flight_only
;
768 instance
->dump_normal_only
= normal_only
;
769 instance
->verbose_mode
= verbose
;
770 instance
->quit_program
= 0;
775 int liblttd_stop_instance(struct liblttd_instance
*instance
)
777 instance
->quit_program
= 1;
This page took 0.072133 seconds and 3 git commands to generate.