Implement UST stop command
[lttng-tools.git] / lttng-sessiond / ust-app.c
... / ...
CommitLineData
1/*
2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; only version 2
7 * of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19#define _GNU_SOURCE
20#include <errno.h>
21#include <pthread.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <sys/stat.h>
26#include <sys/types.h>
27#include <unistd.h>
28
29#include <lttngerr.h>
30#include <lttng-share.h>
31
32#include "hashtable.h"
33#include "ust-app.h"
34#include "ust-consumer.h"
35#include "ust-ctl.h"
36
37/*
38 * Delete ust app event safely. RCU read lock must be held before calling
39 * this function.
40 */
41static void delete_ust_app_event(int sock, struct ust_app_event *ua_event)
42{
43 /* TODO : remove context */
44 //struct ust_app_ctx *ltctx;
45 //cds_lfht_for_each_entry(lte->ctx, &iter, ltctx, node) {
46 // delete_ust_app_ctx(sock, ltctx);
47 //}
48
49 ustctl_release_object(sock, ua_event->obj);
50 free(ua_event);
51}
52
53/*
54 * Delete ust app stream safely. RCU read lock must be held before calling
55 * this function.
56 */
57static void delete_ust_app_stream(int sock, struct ltt_ust_stream *stream)
58{
59 //TODO
60 //stream is used for passing to consumer.
61 //send_channel_streams is responsible for freeing the streams.
62 //note that this will not play well with flight recorder mode:
63 //we might need a criterion to discard the streams.
64}
65
66/*
67 * Delete ust app channel safely. RCU read lock must be held before calling
68 * this function.
69 */
70static void delete_ust_app_channel(int sock, struct ust_app_channel *ua_chan)
71{
72 int ret;
73 struct cds_lfht_iter iter;
74 struct ust_app_event *ua_event;
75 struct ltt_ust_stream *stream, *stmp;
76
77 cds_list_for_each_entry_safe(stream, stmp, &ua_chan->streams.head, list) {
78 delete_ust_app_stream(sock, stream);
79 }
80
81 /* TODO : remove channel context */
82 //cds_lfht_for_each_entry(ltc->ctx, &iter, ltctx, node) {
83 // hashtable_del(ltc->ctx, &iter);
84 // delete_ust_app_ctx(sock, ltctx);
85 //}
86 //ret = hashtable_destroy(ltc->ctx);
87
88 cds_lfht_for_each_entry(ua_chan->events, &iter, ua_event, node) {
89 hashtable_del(ua_chan->events, &iter);
90 delete_ust_app_event(sock, ua_event);
91 }
92
93 ret = hashtable_destroy(ua_chan->events);
94 if (ret < 0) {
95 ERR("UST app destroy session hashtable failed");
96 goto error;
97 }
98
99error:
100 return;
101}
102
103/*
104 * Delete ust app session safely. RCU read lock must be held before calling
105 * this function.
106 */
107static void delete_ust_app_session(int sock,
108 struct ust_app_session *ua_sess)
109{
110 int ret;
111 struct cds_lfht_iter iter;
112 struct ust_app_channel *ua_chan;
113
114 if (ua_sess->metadata) {
115 /*
116 * We do NOT release the stream object and metadata object since they
117 * are release when fds are sent to the consumer.
118 */
119 }
120
121 cds_lfht_for_each_entry(ua_sess->channels, &iter, ua_chan, node) {
122 hashtable_del(ua_sess->channels, &iter);
123 delete_ust_app_channel(sock, ua_chan);
124 }
125
126 ret = hashtable_destroy(ua_sess->channels);
127 if (ret < 0) {
128 ERR("UST app destroy session hashtable failed");
129 goto error;
130 }
131
132error:
133 return;
134}
135
136/*
137 * Delete a traceable application structure from the global list. Never call
138 * this function outside of a call_rcu call.
139 */
140static void delete_ust_app(struct ust_app *app)
141{
142 int ret;
143 struct cds_lfht_node *node;
144 struct cds_lfht_iter iter;
145 struct ust_app_session *ua_sess;
146 int sock;
147
148 rcu_read_lock();
149
150 /* Remove from key hash table */
151 node = hashtable_lookup(ust_app_sock_key_map,
152 (void *) ((unsigned long) app->key.sock), sizeof(void *), &iter);
153 if (node == NULL) {
154 /* Not suppose to happen */
155 ERR("UST app key %d not found in key hash table", app->key.sock);
156 goto end;
157 }
158
159 ret = hashtable_del(ust_app_sock_key_map, &iter);
160 if (ret) {
161 ERR("UST app unable to delete app sock %d from key hash table",
162 app->key.sock);
163 } else {
164 DBG2("UST app pair sock %d key %d deleted",
165 app->key.sock, app->key.pid);
166 }
167
168 /* Socket is already closed at this point */
169
170 /* Delete ust app sessions info */
171 sock = app->key.sock;
172 app->key.sock = -1;
173
174 cds_lfht_for_each_entry(app->sessions, &iter, ua_sess, node) {
175 hashtable_del(app->sessions, &iter);
176 delete_ust_app_session(app->key.sock, ua_sess);
177 }
178
179 ret = hashtable_destroy(app->sessions);
180 if (ret < 0) {
181 ERR("UST app destroy session hashtable failed");
182 goto end;
183 }
184
185 /*
186 * Wait until we have removed the key from the sock hash table
187 * before closing this socket, otherwise an application could
188 * re-use the socket ID and race with the teardown, using the
189 * same hash table entry.
190 */
191 close(sock);
192
193 DBG2("UST app pid %d deleted", app->key.pid);
194 free(app);
195end:
196 rcu_read_unlock();
197}
198
199/*
200 * URCU intermediate call to delete an UST app.
201 */
202static void delete_ust_app_rcu(struct rcu_head *head)
203{
204 struct cds_lfht_node *node =
205 caa_container_of(head, struct cds_lfht_node, head);
206 struct ust_app *app =
207 caa_container_of(node, struct ust_app, node);
208
209 delete_ust_app(app);
210}
211
212/*
213 * Find an ust_app using the sock and return it. RCU read side lock must be
214 * held before calling this helper function.
215 */
216static struct ust_app *find_app_by_sock(int sock)
217{
218 struct cds_lfht_node *node;
219 struct ust_app_key *key;
220 struct cds_lfht_iter iter;
221
222 node = hashtable_lookup(ust_app_sock_key_map,
223 (void *)((unsigned long) sock), sizeof(void *), &iter);
224 if (node == NULL) {
225 DBG2("UST app find by sock %d key not found", sock);
226 goto error;
227 }
228
229 key = caa_container_of(node, struct ust_app_key, node);
230
231 node = hashtable_lookup(ust_app_ht,
232 (void *)((unsigned long) key->pid), sizeof(void *), &iter);
233 if (node == NULL) {
234 DBG2("UST app find by sock %d not found", sock);
235 goto error;
236 }
237 return caa_container_of(node, struct ust_app, node);
238
239error:
240 return NULL;
241}
242
243/*
244 * Open metadata onto the UST tracer for a UST session.
245 */
246static int open_ust_metadata(struct ust_app *app,
247 struct ust_app_session *ua_sess)
248{
249 int ret;
250 struct lttng_ust_channel_attr uattr;
251
252 uattr.overwrite = ua_sess->metadata->attr.overwrite;
253 uattr.subbuf_size = ua_sess->metadata->attr.subbuf_size;
254 uattr.num_subbuf = ua_sess->metadata->attr.num_subbuf;
255 uattr.switch_timer_interval =
256 ua_sess->metadata->attr.switch_timer_interval;
257 uattr.read_timer_interval =
258 ua_sess->metadata->attr.read_timer_interval;
259 uattr.output = ua_sess->metadata->attr.output;
260
261 /* UST tracer metadata creation */
262 ret = ustctl_open_metadata(app->key.sock, ua_sess->handle, &uattr,
263 &ua_sess->metadata->obj);
264 if (ret < 0) {
265 ERR("UST app open metadata failed for app pid:%d",
266 app->key.pid);
267 goto error;
268 }
269
270error:
271 return ret;
272}
273
274/*
275 * Create stream onto the UST tracer for a UST session.
276 */
277static int create_ust_stream(struct ust_app *app,
278 struct ust_app_session *ua_sess)
279{
280 int ret;
281
282 ret = ustctl_create_stream(app->key.sock, ua_sess->metadata->obj,
283 &ua_sess->metadata->stream_obj);
284 if (ret < 0) {
285 ERR("UST create metadata stream failed");
286 goto error;
287 }
288
289error:
290 return ret;
291}
292
293/*
294 * Create the specified channel onto the UST tracer for a UST session.
295 */
296static int create_ust_channel(struct ust_app *app,
297 struct ust_app_session *ua_sess, struct ust_app_channel *ua_chan)
298{
299 int ret;
300
301 /* TODO: remove cast and use lttng-ust-abi.h */
302 ret = ustctl_create_channel(app->key.sock, ua_sess->handle,
303 (struct lttng_ust_channel_attr *)&ua_chan->attr, &ua_chan->obj);
304 if (ret < 0) {
305 DBG("Error creating channel %s for app (pid: %d, sock: %d) "
306 "and session handle %d with ret %d",
307 ua_chan->name, app->key.pid, app->key.sock,
308 ua_sess->handle, ret);
309 goto error;
310 }
311
312 ua_chan->handle = ua_chan->obj->handle;
313 ua_chan->attr.shm_fd = ua_chan->obj->shm_fd;
314 ua_chan->attr.wait_fd = ua_chan->obj->wait_fd;
315 ua_chan->attr.memory_map_size = ua_chan->obj->memory_map_size;
316
317 DBG2("UST app channel %s created successfully for pid:%d and sock:%d",
318 ua_chan->name, app->key.pid, app->key.sock);
319
320error:
321 return ret;
322}
323
324/*
325 * Create the specified event onto the UST tracer for a UST session.
326 */
327static int create_ust_event(struct ust_app *app,
328 struct ust_app_session *ua_sess, struct ust_app_channel *ua_chan,
329 struct ust_app_event *ua_event)
330{
331 int ret = 0;
332
333 /* Create UST event on tracer */
334 ret = ustctl_create_event(app->key.sock, &ua_event->attr, ua_chan->obj,
335 &ua_event->obj);
336 if (ret < 0) {
337 ERR("Error ustctl create event %s for app pid: %d with ret %d",
338 ua_event->attr.name, app->key.pid, ret);
339 goto error;
340 }
341
342 ua_event->handle = ua_event->obj->handle;
343 ua_event->enabled = 1;
344
345 DBG2("UST app event %s created successfully for pid:%d",
346 ua_event->attr.name, app->key.pid);
347
348error:
349 return ret;
350}
351
352/*
353 * Alloc new UST app session.
354 */
355static struct ust_app_session *alloc_ust_app_session(void)
356{
357 struct ust_app_session *ua_sess;
358
359 /* Init most of the default value by allocating and zeroing */
360 ua_sess = zmalloc(sizeof(struct ust_app_session));
361 if (ua_sess == NULL) {
362 PERROR("malloc");
363 goto error;
364 }
365
366 ua_sess->handle = -1;
367 ua_sess->channels = hashtable_new_str(0);
368
369 return ua_sess;
370
371error:
372 return NULL;
373}
374
375/*
376 * Alloc new UST app channel.
377 */
378static struct ust_app_channel *alloc_ust_app_channel(char *name,
379 struct lttng_ust_channel *attr)
380{
381 struct ust_app_channel *ua_chan;
382
383 /* Init most of the default value by allocating and zeroing */
384 ua_chan = zmalloc(sizeof(struct ust_app_channel));
385 if (ua_chan == NULL) {
386 PERROR("malloc");
387 goto error;
388 }
389
390 /* Setup channel name */
391 strncpy(ua_chan->name, name, sizeof(ua_chan->name));
392 ua_chan->name[sizeof(ua_chan->name) - 1] = '\0';
393
394 ua_chan->handle = -1;
395 ua_chan->ctx = hashtable_new(0);
396 ua_chan->events = hashtable_new_str(0);
397 hashtable_node_init(&ua_chan->node, (void *) ua_chan->name,
398 strlen(ua_chan->name));
399
400 CDS_INIT_LIST_HEAD(&ua_chan->streams.head);
401
402 /* Copy attributes */
403 if (attr) {
404 memcpy(&ua_chan->attr, attr, sizeof(ua_chan->attr));
405 }
406
407 DBG3("UST app channel %s allocated", ua_chan->name);
408
409 return ua_chan;
410
411error:
412 return NULL;
413}
414
415/*
416 * Alloc new UST app event.
417 */
418static struct ust_app_event *alloc_ust_app_event(char *name,
419 struct lttng_ust_event *attr)
420{
421 struct ust_app_event *ua_event;
422
423 /* Init most of the default value by allocating and zeroing */
424 ua_event = zmalloc(sizeof(struct ust_app_event));
425 if (ua_event == NULL) {
426 PERROR("malloc");
427 goto error;
428 }
429
430 strncpy(ua_event->name, name, sizeof(ua_event->name));
431 ua_event->name[sizeof(ua_event->name) - 1] = '\0';
432 ua_event->ctx = hashtable_new(0);
433 hashtable_node_init(&ua_event->node, (void *) ua_event->name,
434 strlen(ua_event->name));
435
436 /* Copy attributes */
437 if (attr) {
438 memcpy(&ua_event->attr, attr, sizeof(ua_event->attr));
439 }
440
441 DBG3("UST app event %s allocated", ua_event->name);
442
443 return ua_event;
444
445error:
446 return NULL;
447}
448
449/*
450 * Copy data between an UST app event and a LTT event.
451 */
452static void shadow_copy_event(struct ust_app_event *ua_event,
453 struct ltt_ust_event *uevent)
454{
455 strncpy(ua_event->name, uevent->attr.name, sizeof(ua_event->name));
456 ua_event->name[sizeof(ua_event->name) - 1] = '\0';
457
458 /* Copy event attributes */
459 memcpy(&ua_event->attr, &uevent->attr, sizeof(ua_event->attr));
460
461 /* TODO: support copy context */
462}
463
464/*
465 * Copy data between an UST app channel and a LTT channel.
466 */
467static void shadow_copy_channel(struct ust_app_channel *ua_chan,
468 struct ltt_ust_channel *uchan)
469{
470 struct cds_lfht_iter iter;
471 struct cds_lfht_node *ua_event_node;
472 struct ltt_ust_event *uevent;
473 struct ust_app_event *ua_event;
474
475 DBG2("Shadow copy of UST app channel %s", ua_chan->name);
476
477 strncpy(ua_chan->name, uchan->name, sizeof(ua_chan->name));
478 ua_chan->name[sizeof(ua_chan->name) - 1] = '\0';
479 /* Copy event attributes */
480 memcpy(&ua_chan->attr, &uchan->attr, sizeof(ua_chan->attr));
481
482 /* TODO: support copy context */
483
484 /* Copy all events from ltt ust channel to ust app channel */
485 cds_lfht_for_each_entry(uchan->events, &iter, uevent, node) {
486 struct cds_lfht_iter uiter;
487
488 ua_event_node = hashtable_lookup(ua_chan->events,
489 (void *) uevent->attr.name, strlen(uevent->attr.name),
490 &uiter);
491 if (ua_event_node == NULL) {
492 DBG2("UST event %s not found on shadow copy channel",
493 uevent->attr.name);
494 ua_event = alloc_ust_app_event(uevent->attr.name, &uevent->attr);
495 if (ua_event == NULL) {
496 continue;
497 }
498 shadow_copy_event(ua_event, uevent);
499 hashtable_add_unique(ua_chan->events, &ua_event->node);
500 }
501 }
502
503 DBG3("Shadow copy channel done");
504}
505
506/*
507 * Copy data between a UST app session and a regular LTT session.
508 */
509static void shadow_copy_session(struct ust_app_session *ua_sess,
510 struct ltt_ust_session *usess,
511 struct ust_app *app)
512{
513 struct cds_lfht_node *ua_chan_node;
514 struct cds_lfht_iter iter;
515 struct ltt_ust_channel *uchan;
516 struct ust_app_channel *ua_chan;
517 time_t rawtime;
518 struct tm *timeinfo;
519 char datetime[16];
520 int ret;
521
522 /* Get date and time for unique app path */
523 time(&rawtime);
524 timeinfo = localtime(&rawtime);
525 strftime(datetime, sizeof(datetime), "%Y%m%d-%H%M%S", timeinfo);
526
527 DBG2("Shadow copy of session handle %d", ua_sess->handle);
528
529 ua_sess->uid = usess->uid;
530
531 ret = snprintf(ua_sess->path, PATH_MAX,
532 "%s/%s-%d-%s",
533 usess->pathname, app->name, app->key.pid,
534 datetime);
535 if (ret < 0) {
536 PERROR("asprintf UST shadow copy session");
537 /* TODO: We cannot return an error from here.. */
538 assert(0);
539 }
540
541 /* TODO: support all UST domain */
542
543 /* Iterate over all channels in global domain. */
544 cds_lfht_for_each_entry(usess->domain_global.channels, &iter,
545 uchan, node) {
546 struct cds_lfht_iter uiter;
547
548 ua_chan_node = hashtable_lookup(ua_sess->channels,
549 (void *)uchan->name, strlen(uchan->name),
550 &uiter);
551 if (ua_chan_node != NULL) {
552 continue;
553 }
554
555 DBG2("Channel %s not found on shadow session copy, creating it",
556 uchan->name);
557 ua_chan = alloc_ust_app_channel(uchan->name, &uchan->attr);
558 if (ua_chan == NULL) {
559 /* malloc failed... continuing */
560 continue;
561 }
562
563 shadow_copy_channel(ua_chan, uchan);
564 hashtable_add_unique(ua_sess->channels, &ua_chan->node);
565 }
566}
567
568/*
569 * Return ust app session from the app session hashtable using the UST session
570 * uid.
571 */
572static struct ust_app_session *lookup_session_by_app(
573 struct ltt_ust_session *usess, struct ust_app *app)
574{
575 struct cds_lfht_iter iter;
576 struct cds_lfht_node *node;
577
578 /* Get right UST app session from app */
579 node = hashtable_lookup(app->sessions,
580 (void *) ((unsigned long) usess->uid), sizeof(void *), &iter);
581 if (node == NULL) {
582 goto error;
583 }
584
585 return caa_container_of(node, struct ust_app_session, node);
586
587error:
588 return NULL;
589}
590
591/*
592 * Create a UST session onto the tracer of app and add it the session
593 * hashtable.
594 *
595 * Return ust app session or NULL on error.
596 */
597static struct ust_app_session *create_ust_app_session(
598 struct ltt_ust_session *usess, struct ust_app *app)
599{
600 int ret;
601 struct ust_app_session *ua_sess;
602
603 ua_sess = lookup_session_by_app(usess, app);
604 if (ua_sess == NULL) {
605 DBG2("UST app pid: %d session uid %d not found, creating it",
606 app->key.pid, usess->uid);
607 ua_sess = alloc_ust_app_session();
608 if (ua_sess == NULL) {
609 /* Only malloc can failed so something is really wrong */
610 goto error;
611 }
612 shadow_copy_session(ua_sess, usess, app);
613 }
614
615 if (ua_sess->handle == -1) {
616 ret = ustctl_create_session(app->key.sock);
617 if (ret < 0) {
618 ERR("Error creating session for app pid %d, sock %d",
619 app->key.pid, app->key.sock);
620 /* TODO: free() ua_sess */
621 goto error;
622 }
623
624 DBG2("UST app ustctl create session handle %d", ret);
625 ua_sess->handle = ret;
626
627 /* Add ust app session to app's HT */
628 hashtable_node_init(&ua_sess->node,
629 (void *)((unsigned long) ua_sess->uid), sizeof(void *));
630 hashtable_add_unique(app->sessions, &ua_sess->node);
631
632 DBG2("UST app session created successfully with handle %d", ret);
633 }
634
635 return ua_sess;
636
637error:
638 return NULL;
639}
640
641/*
642 * Create UST app channel and create it on the tracer.
643 */
644static struct ust_app_channel *create_ust_app_channel(
645 struct ust_app_session *ua_sess, struct ltt_ust_channel *uchan,
646 struct ust_app *app)
647{
648 int ret = 0;
649 struct cds_lfht_iter iter;
650 struct cds_lfht_node *ua_chan_node;
651 struct ust_app_channel *ua_chan;
652
653 /* Lookup channel in the ust app session */
654 ua_chan_node = hashtable_lookup(ua_sess->channels,
655 (void *)uchan->name, strlen(uchan->name), &iter);
656 if (ua_chan_node == NULL) {
657 DBG2("Unable to find channel %s in ust session uid %u",
658 uchan->name, ua_sess->uid);
659 ua_chan = alloc_ust_app_channel(uchan->name, &uchan->attr);
660 if (ua_chan == NULL) {
661 goto error;
662 }
663 shadow_copy_channel(ua_chan, uchan);
664
665 hashtable_add_unique(ua_sess->channels, &ua_chan->node);
666 } else {
667 ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node);
668 }
669
670 ret = create_ust_channel(app, ua_sess, ua_chan);
671 if (ret < 0) {
672 goto error;
673 }
674
675 return ua_chan;
676
677error:
678 return NULL;
679}
680
681/*
682 * Create UST app event and create it on the tracer side.
683 */
684static struct ust_app_event *create_ust_app_event(
685 struct ust_app_session *ua_sess, struct ust_app_channel *ua_chan,
686 struct ltt_ust_event *uevent, struct ust_app *app)
687{
688 int ret;
689 struct cds_lfht_iter iter;
690 struct cds_lfht_node *ua_event_node;
691 struct ust_app_event *ua_event;
692
693 /* Get event node */
694 ua_event_node = hashtable_lookup(ua_chan->events,
695 (void *)uevent->attr.name, strlen(uevent->attr.name), &iter);
696 if (ua_event_node == NULL) {
697 DBG2("UST app event %s not found, creating it", uevent->attr.name);
698 /* Does not exist so create one */
699 ua_event = alloc_ust_app_event(uevent->attr.name, &uevent->attr);
700 if (ua_event == NULL) {
701 /* Only malloc can failed so something is really wrong */
702 goto error;
703 }
704 shadow_copy_event(ua_event, uevent);
705
706 hashtable_add_unique(ua_chan->events, &ua_event->node);
707 } else {
708 ua_event = caa_container_of(ua_event_node, struct ust_app_event, node);
709 }
710
711 ret = create_ust_event(app, ua_sess, ua_chan, ua_event);
712 if (ret < 0) {
713 goto error;
714 }
715
716 return ua_event;
717
718error:
719 return NULL;
720}
721
722/*
723 * Create UST metadata and open it on the tracer side.
724 */
725static int create_ust_app_metadata(struct ust_app_session *ua_sess,
726 char *pathname, struct ust_app *app)
727{
728 int ret = 0;
729
730 if (ua_sess->metadata == NULL) {
731 /* Allocate UST metadata */
732 ua_sess->metadata = trace_ust_create_metadata(pathname);
733 if (ua_sess->metadata == NULL) {
734 ERR("UST app session %d creating metadata failed",
735 ua_sess->handle);
736 goto error;
737 }
738
739 ret = open_ust_metadata(app, ua_sess);
740 if (ret < 0) {
741 goto error;
742 }
743
744 DBG2("UST metadata opened for app pid %d", app->key.pid);
745 }
746
747 /* Open UST metadata stream */
748 if (ua_sess->metadata->stream_obj == NULL) {
749 ret = create_ust_stream(app, ua_sess);
750 if (ret < 0) {
751 goto error;
752 }
753
754 ret = mkdir(ua_sess->path, S_IRWXU | S_IRWXG);
755 if (ret < 0) {
756 PERROR("mkdir UST metadata");
757 goto error;
758 }
759
760 ret = snprintf(ua_sess->metadata->pathname, PATH_MAX,
761 "%s/metadata", ua_sess->path);
762 if (ret < 0) {
763 PERROR("asprintf UST create stream");
764 goto error;
765 }
766
767 DBG2("UST metadata stream object created for app pid %d",
768 app->key.pid);
769 } else {
770 ERR("Attempting to create stream without metadata opened");
771 goto error;
772 }
773
774 return 0;
775
776error:
777 return -1;
778}
779
780/*
781 * Return pointer to traceable apps list.
782 */
783struct cds_lfht *ust_app_get_ht(void)
784{
785 return ust_app_ht;
786}
787
788/*
789 * Return ust app pointer or NULL if not found.
790 */
791struct ust_app *ust_app_find_by_pid(pid_t pid)
792{
793 struct cds_lfht_node *node;
794 struct cds_lfht_iter iter;
795
796 rcu_read_lock();
797 node = hashtable_lookup(ust_app_ht,
798 (void *)((unsigned long) pid), sizeof(void *), &iter);
799 if (node == NULL) {
800 DBG2("UST app no found with pid %d", pid);
801 goto error;
802 }
803 rcu_read_unlock();
804
805 DBG2("Found UST app by pid %d", pid);
806
807 return caa_container_of(node, struct ust_app, node);
808
809error:
810 rcu_read_unlock();
811 return NULL;
812}
813
814/*
815 * Using pid and uid (of the app), allocate a new ust_app struct and
816 * add it to the global traceable app list.
817 *
818 * On success, return 0, else return malloc ENOMEM.
819 */
820int ust_app_register(struct ust_register_msg *msg, int sock)
821{
822 struct ust_app *lta;
823
824 lta = zmalloc(sizeof(struct ust_app));
825 if (lta == NULL) {
826 PERROR("malloc");
827 return -ENOMEM;
828 }
829
830 lta->ppid = msg->ppid;
831 lta->uid = msg->uid;
832 lta->gid = msg->gid;
833 lta->v_major = msg->major;
834 lta->v_minor = msg->minor;
835 strncpy(lta->name, msg->name, sizeof(lta->name));
836 lta->name[16] = '\0';
837 lta->sessions = hashtable_new(0);
838
839 /* Set key map */
840 lta->key.pid = msg->pid;
841 hashtable_node_init(&lta->node, (void *)((unsigned long)lta->key.pid),
842 sizeof(void *));
843 lta->key.sock = sock;
844 hashtable_node_init(&lta->key.node, (void *)((unsigned long)lta->key.sock),
845 sizeof(void *));
846
847 rcu_read_lock();
848 hashtable_add_unique(ust_app_sock_key_map, &lta->key.node);
849 hashtable_add_unique(ust_app_ht, &lta->node);
850 rcu_read_unlock();
851
852 DBG("App registered with pid:%d ppid:%d uid:%d gid:%d sock:%d name:%s"
853 " (version %d.%d)", lta->key.pid, lta->ppid, lta->uid, lta->gid,
854 lta->key.sock, lta->name, lta->v_major, lta->v_minor);
855
856 return 0;
857}
858
859/*
860 * Unregister app by removing it from the global traceable app list and freeing
861 * the data struct.
862 *
863 * The socket is already closed at this point so no close to sock.
864 */
865void ust_app_unregister(int sock)
866{
867 struct ust_app *lta;
868 struct cds_lfht_node *node;
869 struct cds_lfht_iter iter;
870
871 rcu_read_lock();
872 lta = find_app_by_sock(sock);
873 if (lta == NULL) {
874 ERR("Unregister app sock %d not found!", sock);
875 goto error;
876 }
877
878 DBG("PID %d unregistering with sock %d", lta->key.pid, sock);
879
880 /* Get the node reference for a call_rcu */
881 node = hashtable_lookup(ust_app_ht,
882 (void *)((unsigned long) lta->key.pid), sizeof(void *), &iter);
883 if (node == NULL) {
884 ERR("Unable to find app sock %d by pid %d", sock, lta->key.pid);
885 goto error;
886 }
887
888 hashtable_del(ust_app_ht, &iter);
889 call_rcu(&node->head, delete_ust_app_rcu);
890error:
891 rcu_read_unlock();
892 return;
893}
894
895/*
896 * Return traceable_app_count
897 */
898unsigned long ust_app_list_count(void)
899{
900 unsigned long count;
901
902 rcu_read_lock();
903 count = hashtable_get_count(ust_app_ht);
904 rcu_read_unlock();
905
906 return count;
907}
908
909/*
910 * Fill events array with all events name of all registered apps.
911 */
912int ust_app_list_events(struct lttng_event **events)
913{
914 int ret, handle;
915 size_t nbmem, count = 0;
916 struct cds_lfht_iter iter;
917 struct ust_app *app;
918 struct lttng_event *tmp;
919
920 nbmem = UST_APP_EVENT_LIST_SIZE;
921 tmp = zmalloc(nbmem * sizeof(struct lttng_event));
922 if (tmp == NULL) {
923 PERROR("zmalloc ust app events");
924 ret = -ENOMEM;
925 goto error;
926 }
927
928 rcu_read_lock();
929
930 cds_lfht_for_each_entry(ust_app_ht, &iter, app, node) {
931 handle = ustctl_tracepoint_list(app->key.sock);
932 if (handle < 0) {
933 ERR("UST app list events getting handle failed for app pid %d",
934 app->key.pid);
935 continue;
936 }
937
938 while ((ret = ustctl_tracepoint_list_get(app->key.sock, handle,
939 tmp[count].name)) != -ENOENT) {
940 if (count > nbmem) {
941 DBG2("Reallocating event list from %zu to %zu bytes", nbmem,
942 nbmem + UST_APP_EVENT_LIST_SIZE);
943 nbmem += UST_APP_EVENT_LIST_SIZE;
944 tmp = realloc(tmp, nbmem);
945 if (tmp == NULL) {
946 PERROR("realloc ust app events");
947 ret = -ENOMEM;
948 goto rcu_error;
949 }
950 }
951
952 tmp[count].type = LTTNG_UST_TRACEPOINT;
953 tmp[count].pid = app->key.pid;
954 tmp[count].enabled = -1;
955 count++;
956 }
957 }
958
959 ret = count;
960 *events = tmp;
961
962 DBG2("UST app list events done (%zu events)", count);
963
964rcu_error:
965 rcu_read_unlock();
966error:
967 return ret;
968}
969
970/*
971 * Free and clean all traceable apps of the global list.
972 */
973void ust_app_clean_list(void)
974{
975 int ret;
976 struct cds_lfht_node *node;
977 struct cds_lfht_iter iter;
978 struct ust_app *app;
979
980 DBG2("UST app cleaning registered apps hash table");
981
982 rcu_read_lock();
983
984 cds_lfht_for_each(ust_app_ht, &iter, node) {
985 app = caa_container_of(node, struct ust_app, node);
986
987 ret = hashtable_del(ust_app_ht, &iter);
988 if (!ret) {
989 call_rcu(&node->head, delete_ust_app_rcu);
990 }
991 }
992
993 hashtable_destroy(ust_app_ht);
994 hashtable_destroy(ust_app_sock_key_map);
995
996 rcu_read_unlock();
997}
998
999/*
1000 * Init UST app hash table.
1001 */
1002void ust_app_ht_alloc(void)
1003{
1004 ust_app_ht = hashtable_new(0);
1005 ust_app_sock_key_map = hashtable_new(0);
1006}
1007
1008/*
1009 * For a specific UST session, create the channel for all registered apps.
1010 */
1011int ust_app_create_channel_all(struct ltt_ust_session *usess,
1012 struct ltt_ust_channel *uchan)
1013{
1014 int ret = 0;
1015 struct cds_lfht_iter iter;
1016 struct ust_app *app;
1017 struct ust_app_session *ua_sess;
1018 struct ust_app_channel *ua_chan;
1019
1020 if (usess == NULL || uchan == NULL) {
1021 ERR("Adding UST global channel to NULL values");
1022 ret = -1;
1023 goto error;
1024 }
1025
1026 DBG2("UST app adding channel %s to global domain for session uid %d",
1027 uchan->name, usess->uid);
1028
1029 rcu_read_lock();
1030
1031 /* For every registered applications */
1032 cds_lfht_for_each_entry(ust_app_ht, &iter, app, node) {
1033 /* Create session on the tracer side and add it to app session HT */
1034 ua_sess = create_ust_app_session(usess, app);
1035 if (ua_sess == NULL) {
1036 continue;
1037 }
1038
1039 /* Create channel onto application */
1040 ua_chan = create_ust_app_channel(ua_sess, uchan, app);
1041 if (ua_chan == NULL) {
1042 continue;
1043 }
1044 }
1045
1046 rcu_read_unlock();
1047
1048error:
1049 return ret;
1050}
1051
1052/*
1053 * For a specific UST session and UST channel, create the event for all
1054 * registered apps.
1055 */
1056int ust_app_create_event_all(struct ltt_ust_session *usess,
1057 struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent)
1058{
1059 int ret = 0;
1060 struct cds_lfht_iter iter;
1061 struct cds_lfht_node *ua_chan_node;
1062 struct ust_app *app;
1063 struct ust_app_session *ua_sess;
1064 struct ust_app_channel *ua_chan;
1065 struct ust_app_event *ua_event;
1066
1067 DBG("UST app creating event %s for all apps for session uid %d",
1068 uevent->attr.name, usess->uid);
1069
1070 rcu_read_lock();
1071
1072 /* For all registered applications */
1073 cds_lfht_for_each_entry(ust_app_ht, &iter, app, node) {
1074 struct cds_lfht_iter uiter;
1075
1076 /* Create session on the tracer side and add it to app session HT */
1077 ua_sess = create_ust_app_session(usess, app);
1078 if (ua_sess == NULL) {
1079 continue;
1080 }
1081
1082 /* Lookup channel in the ust app session */
1083 ua_chan_node = hashtable_lookup(ua_sess->channels,
1084 (void *)uchan->name, strlen(uchan->name),
1085 &uiter);
1086 if (ua_chan_node == NULL) {
1087 ERR("Channel %s not found in session uid %d. Skipping",
1088 uchan->name, usess->uid);
1089 continue;
1090 }
1091 ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node);
1092
1093 ua_event = create_ust_app_event(ua_sess, ua_chan, uevent, app);
1094 if (ua_event == NULL) {
1095 continue;
1096 }
1097 }
1098
1099 rcu_read_unlock();
1100
1101 return ret;
1102}
1103
1104/*
1105 * Start tracing for a specific UST session and app.
1106 */
1107int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *app)
1108{
1109 int ret = 0;
1110 struct cds_lfht_iter iter;
1111 struct ust_app_session *ua_sess;
1112 struct ust_app_channel *ua_chan;
1113 struct ltt_ust_stream *ustream;
1114
1115 DBG("Starting tracing for ust app pid %d", app->key.pid);
1116
1117 rcu_read_lock();
1118
1119 ua_sess = lookup_session_by_app(usess, app);
1120 if (ua_sess == NULL) {
1121 /* Only malloc can failed so something is really wrong */
1122 goto error_rcu_unlock;
1123 }
1124
1125 /* upon restart, we skip the setup, already done */
1126 if (ua_sess->started)
1127 goto skip_setup;
1128
1129 ret = create_ust_app_metadata(ua_sess, usess->pathname, app);
1130 if (ret < 0) {
1131 goto error_rcu_unlock;
1132 }
1133
1134 /* For each channel */
1135 cds_lfht_for_each_entry(ua_sess->channels, &iter, ua_chan, node) {
1136 /* Create all streams */
1137 while (1) {
1138 /* Create UST stream */
1139 ustream = zmalloc(sizeof(*ustream));
1140 if (ustream == NULL) {
1141 PERROR("zmalloc ust stream");
1142 goto error_rcu_unlock;
1143 }
1144
1145 ret = ustctl_create_stream(app->key.sock, ua_chan->obj,
1146 &ustream->obj);
1147 if (ret < 0) {
1148 /* Got all streams */
1149 break;
1150 }
1151 ustream->handle = ustream->obj->handle;
1152
1153 /* Order is important */
1154 cds_list_add_tail(&ustream->list, &ua_chan->streams.head);
1155 ret = snprintf(ustream->pathname, PATH_MAX, "%s/%s_%u",
1156 ua_sess->path, ua_chan->name,
1157 ua_chan->streams.count++);
1158 if (ret < 0) {
1159 PERROR("asprintf UST create stream");
1160 continue;
1161 }
1162 DBG2("UST stream %d ready at %s", ua_chan->streams.count,
1163 ustream->pathname);
1164 }
1165 }
1166
1167 /* Setup UST consumer socket and send fds to it */
1168 ret = ust_consumer_send_session(ust_consumer_fd, ua_sess);
1169 if (ret < 0) {
1170 goto error_rcu_unlock;
1171 }
1172 ua_sess->started = 1;
1173
1174skip_setup:
1175 /* This start the UST tracing */
1176 ret = ustctl_start_session(app->key.sock, ua_sess->handle);
1177 if (ret < 0) {
1178 ERR("Error starting tracing for app pid: %d", app->key.pid);
1179 goto error_rcu_unlock;
1180 }
1181
1182 rcu_read_unlock();
1183
1184 /* Quiescent wait after starting trace */
1185 ustctl_wait_quiescent(app->key.sock);
1186
1187 return 0;
1188
1189error_rcu_unlock:
1190 rcu_read_unlock();
1191 return -1;
1192}
1193
1194/*
1195 * Stop tracing for a specific UST session and app.
1196 */
1197int ust_app_stop_trace(struct ltt_ust_session *usess, struct ust_app *app)
1198{
1199 int ret = 0;
1200 struct ust_app_session *ua_sess;
1201
1202 DBG("Stopping tracing for ust app pid %d", app->key.pid);
1203
1204 rcu_read_lock();
1205
1206 ua_sess = lookup_session_by_app(usess, app);
1207 if (ua_sess == NULL) {
1208 /* Only malloc can failed so something is really wrong */
1209 goto error_rcu_unlock;
1210 }
1211
1212#if 0 /* only useful when periodical flush will be supported */
1213 /* need to keep a handle on shm in session for this. */
1214 /* Flush all buffers before stopping */
1215 ret = ustctl_flush_buffer(usess->sock, usess->metadata->obj);
1216 if (ret < 0) {
1217 ERR("UST metadata flush failed");
1218 }
1219
1220 cds_list_for_each_entry(ustchan, &usess->channels.head, list) {
1221 ret = ustctl_flush_buffer(usess->sock, ustchan->obj);
1222 if (ret < 0) {
1223 ERR("UST flush buffer error");
1224 }
1225 }
1226#endif
1227
1228 /* This inhibits UST tracing */
1229 ret = ustctl_stop_session(app->key.sock, ua_sess->handle);
1230 if (ret < 0) {
1231 ERR("Error stopping tracing for app pid: %d", app->key.pid);
1232 goto error_rcu_unlock;
1233 }
1234
1235 rcu_read_unlock();
1236
1237 /* Quiescent wait after stopping trace */
1238 ustctl_wait_quiescent(app->key.sock);
1239
1240 return 0;
1241
1242error_rcu_unlock:
1243 rcu_read_unlock();
1244 return -1;
1245}
1246
1247/*
1248 * Start tracing for the UST session.
1249 */
1250int ust_app_start_trace_all(struct ltt_ust_session *usess)
1251{
1252 int ret = 0;
1253 struct cds_lfht_iter iter;
1254 struct ust_app *app;
1255
1256 DBG("Starting all UST traces");
1257
1258 rcu_read_lock();
1259
1260 cds_lfht_for_each_entry(ust_app_ht, &iter, app, node) {
1261 ret = ust_app_start_trace(usess, app);
1262 if (ret < 0) {
1263 /* Continue to next apps even on error */
1264 continue;
1265 }
1266 }
1267
1268 rcu_read_unlock();
1269
1270 return 0;
1271}
1272
1273/*
1274 * Start tracing for the UST session.
1275 */
1276int ust_app_stop_trace_all(struct ltt_ust_session *usess)
1277{
1278 int ret = 0;
1279 struct cds_lfht_iter iter;
1280 struct ust_app *app;
1281
1282 DBG("Stopping all UST traces");
1283
1284 rcu_read_lock();
1285
1286 cds_lfht_for_each_entry(ust_app_ht, &iter, app, node) {
1287 ret = ust_app_stop_trace(usess, app);
1288 if (ret < 0) {
1289 /* Continue to next apps even on error */
1290 continue;
1291 }
1292 }
1293
1294 rcu_read_unlock();
1295
1296 return 0;
1297}
1298
1299/*
1300 * Add channels/events from UST global domain to registered apps at sock.
1301 */
1302void ust_app_global_update(struct ltt_ust_session *usess, int sock)
1303{
1304 int ret = 0;
1305 struct cds_lfht_iter iter;
1306 struct ust_app *app;
1307 struct ust_app_session *ua_sess;
1308 struct ust_app_channel *ua_chan;
1309 struct ust_app_event *ua_event;
1310
1311 if (usess == NULL) {
1312 ERR("No UST session on global update. Returning");
1313 goto error;
1314 }
1315
1316 DBG2("UST app global update for app sock %d for session uid %d", sock,
1317 usess->uid);
1318
1319 rcu_read_lock();
1320
1321 app = find_app_by_sock(sock);
1322 if (app == NULL) {
1323 ERR("Failed to update app sock %d", sock);
1324 goto error;
1325 }
1326
1327 ua_sess = create_ust_app_session(usess, app);
1328 if (ua_sess == NULL) {
1329 goto error;
1330 }
1331
1332 /*
1333 * We can iterate safely here over all UST app session sicne the create ust
1334 * app session above made a shadow copy of the UST global domain from the
1335 * ltt ust session.
1336 */
1337 cds_lfht_for_each_entry(ua_sess->channels, &iter, ua_chan, node) {
1338 ret = create_ust_channel(app, ua_sess, ua_chan);
1339 if (ret < 0) {
1340 /* FIXME: Should we quit here or continue... */
1341 continue;
1342 }
1343
1344 /* For each events */
1345 cds_lfht_for_each_entry(ua_chan->events, &iter, ua_event, node) {
1346 ret = create_ust_event(app, ua_sess, ua_chan, ua_event);
1347 if (ret < 0) {
1348 /* FIXME: Should we quit here or continue... */
1349 continue;
1350 }
1351 }
1352 }
1353
1354 if (usess->start_trace) {
1355 ret = ust_app_start_trace(usess, app);
1356 if (ret < 0) {
1357 goto error;
1358 }
1359
1360 DBG2("UST trace started for app pid %d", app->key.pid);
1361 }
1362
1363error:
1364 rcu_read_unlock();
1365 return;
1366}
This page took 0.02711 seconds and 4 git commands to generate.