Cleanup ust-app.c and make it more modular
[lttng-tools.git] / lttng-sessiond / ust-app.c
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 "../hashtable/hash.h"
35 #include "ust-ctl.h"
36 #include "ust-consumer.h"
37
38 /*
39 * Delete a traceable application structure from the global list.
40 */
41 static void delete_ust_app(struct ust_app *lta)
42 {
43 int ret;
44 struct cds_lfht_node *node;
45 struct cds_lfht_iter iter;
46
47 rcu_read_lock();
48
49 /* TODO: clean session hashtable */
50 free(lta->sessions);
51 close(lta->key.sock);
52
53 /* Remove from apps hash table */
54 node = hashtable_lookup(ust_app_ht,
55 (void *) ((unsigned long) lta->key.pid), sizeof(void *), &iter);
56 if (node == NULL) {
57 ERR("UST app pid %d not found in hash table", lta->key.pid);
58 } else {
59 ret = hashtable_del(ust_app_ht, &iter);
60 if (ret) {
61 ERR("UST app unable to delete app %d from hash table",
62 lta->key.pid);
63 } else {
64 DBG2("UST app pid %d deleted", lta->key.pid);
65 }
66 }
67
68 /* Remove from key hash table */
69 node = hashtable_lookup(ust_app_sock_key_map,
70 (void *) ((unsigned long) lta->key.sock), sizeof(void *), &iter);
71 if (node == NULL) {
72 ERR("UST app key %d not found in key hash table", lta->key.sock);
73 } else {
74 ret = hashtable_del(ust_app_sock_key_map, &iter);
75 if (ret) {
76 ERR("UST app unable to delete app sock %d from key hash table",
77 lta->key.sock);
78 } else {
79 DBG2("UST app pair sock %d key %d deleted",
80 lta->key.sock, lta->key.pid);
81 }
82 }
83
84 free(lta);
85
86 rcu_read_unlock();
87 }
88
89 /*
90 * URCU intermediate call to delete an UST app.
91 */
92 static void delete_ust_app_rcu(struct rcu_head *head)
93 {
94 struct cds_lfht_node *node =
95 caa_container_of(head, struct cds_lfht_node, head);
96 struct ust_app *app =
97 caa_container_of(node, struct ust_app, node);
98
99 delete_ust_app(app);
100 }
101
102 /*
103 * Find an ust_app using the sock and return it. RCU read side lock must be
104 * held before calling this helper function.
105 */
106 static struct ust_app *find_app_by_sock(int sock)
107 {
108 struct cds_lfht_node *node;
109 struct ust_app_key *key;
110 struct cds_lfht_iter iter;
111
112 node = hashtable_lookup(ust_app_sock_key_map,
113 (void *)((unsigned long) sock), sizeof(void *), &iter);
114 if (node == NULL) {
115 DBG2("UST app find by sock %d key not found", sock);
116 rcu_read_unlock();
117 goto error;
118 }
119
120 key = caa_container_of(node, struct ust_app_key, node);
121
122 node = hashtable_lookup(ust_app_ht,
123 (void *)((unsigned long) key->pid), sizeof(void *), &iter);
124 if (node == NULL) {
125 DBG2("UST app find by sock %d not found", sock);
126 rcu_read_unlock();
127 goto error;
128 }
129
130 return caa_container_of(node, struct ust_app, node);
131
132 error:
133 return NULL;
134 }
135
136 /*
137 * Return pointer to traceable apps list.
138 */
139 struct cds_lfht *ust_app_get_ht(void)
140 {
141 return ust_app_ht;
142 }
143
144 /*
145 * Return ust app pointer or NULL if not found.
146 */
147 struct ust_app *ust_app_find_by_pid(pid_t pid)
148 {
149 struct cds_lfht_node *node;
150 struct cds_lfht_iter iter;
151
152 rcu_read_lock();
153 node = hashtable_lookup(ust_app_ht,
154 (void *)((unsigned long) pid), sizeof(void *), &iter);
155 if (node == NULL) {
156 rcu_read_unlock();
157 DBG2("UST app no found with pid %d", pid);
158 goto error;
159 }
160 rcu_read_unlock();
161
162 DBG2("Found UST app by pid %d", pid);
163
164 return caa_container_of(node, struct ust_app, node);
165
166 error:
167 return NULL;
168 }
169
170 /*
171 * Using pid and uid (of the app), allocate a new ust_app struct and
172 * add it to the global traceable app list.
173 *
174 * On success, return 0, else return malloc ENOMEM.
175 */
176 int ust_app_register(struct ust_register_msg *msg, int sock)
177 {
178 struct ust_app *lta;
179
180 lta = malloc(sizeof(struct ust_app));
181 if (lta == NULL) {
182 PERROR("malloc");
183 return -ENOMEM;
184 }
185
186 lta->uid = msg->uid;
187 lta->gid = msg->gid;
188 lta->key.pid = msg->pid;
189 lta->ppid = msg->ppid;
190 lta->v_major = msg->major;
191 lta->v_minor = msg->minor;
192 lta->key.sock = sock;
193 strncpy(lta->name, msg->name, sizeof(lta->name));
194 lta->name[16] = '\0';
195 hashtable_node_init(&lta->node, (void *)((unsigned long)lta->key.pid),
196 sizeof(void *));
197
198 /* Session hashtable */
199 lta->sessions = hashtable_new(0);
200
201 /* Set sock key map */
202 hashtable_node_init(&lta->key.node, (void *)((unsigned long)lta->key.sock),
203 sizeof(void *));
204
205 rcu_read_lock();
206 hashtable_add_unique(ust_app_ht, &lta->node);
207 hashtable_add_unique(ust_app_sock_key_map, &lta->key.node);
208 rcu_read_unlock();
209
210 DBG("App registered with pid:%d ppid:%d uid:%d gid:%d sock:%d name:%s"
211 " (version %d.%d)", lta->key.pid, lta->ppid, lta->uid, lta->gid,
212 lta->key.sock, lta->name, lta->v_major, lta->v_minor);
213
214 return 0;
215 }
216
217 /*
218 * Unregister app by removing it from the global traceable app list and freeing
219 * the data struct.
220 *
221 * The socket is already closed at this point so no close to sock.
222 */
223 void ust_app_unregister(int sock)
224 {
225 struct ust_app *lta;
226 struct cds_lfht_node *node;
227 struct cds_lfht_iter iter;
228
229 rcu_read_lock();
230 lta = find_app_by_sock(sock);
231 if (lta == NULL) {
232 ERR("Unregister app sock %d not found!", sock);
233 goto error;
234 }
235
236 DBG("PID %d unregistering with sock %d", lta->key.pid, sock);
237
238 /* Get the node reference for a call_rcu */
239 node = hashtable_lookup(ust_app_ht,
240 (void *)((unsigned long) lta->key.pid), sizeof(void *), &iter);
241 if (node == NULL) {
242 ERR("Unable to find app sock %d by pid %d", sock, lta->key.pid);
243 goto error;
244 }
245
246 call_rcu(&node->head, delete_ust_app_rcu);
247
248 error:
249 rcu_read_unlock();
250 return;
251 }
252
253 /*
254 * Return traceable_app_count
255 */
256 unsigned long ust_app_list_count(void)
257 {
258 unsigned long count;
259
260 rcu_read_lock();
261 count = hashtable_get_count(ust_app_ht);
262 rcu_read_unlock();
263
264 return count;
265 }
266
267 /*
268 * Free and clean all traceable apps of the global list.
269 */
270 void ust_app_clean_list(void)
271 {
272 int ret;
273 struct cds_lfht_node *node;
274 struct cds_lfht_iter iter;
275
276 DBG2("UST app clean hash table");
277
278 rcu_read_lock();
279
280 hashtable_get_first(ust_app_ht, &iter);
281 while ((node = hashtable_iter_get_node(&iter)) != NULL) {
282 ret = hashtable_del(ust_app_ht, &iter);
283 if (!ret) {
284 call_rcu(&node->head, delete_ust_app_rcu);
285 }
286 hashtable_get_next(ust_app_ht, &iter);
287 }
288
289 rcu_read_unlock();
290 }
291
292 /*
293 * Init UST app hash table.
294 */
295 void ust_app_ht_alloc(void)
296 {
297 ust_app_ht = hashtable_new(0);
298 ust_app_sock_key_map = hashtable_new(0);
299 }
300
301 /*
302 * Alloc new UST app session.
303 */
304 static struct ust_app_session *alloc_ust_app_session(void)
305 {
306 struct ust_app_session *ua_sess;
307
308 /* Init most of the default value by allocating and zeroing */
309 ua_sess = zmalloc(sizeof(struct ust_app_session));
310 if (ua_sess == NULL) {
311 PERROR("malloc");
312 goto error;
313 }
314
315 ua_sess->handle = -1;
316 ua_sess->channels = hashtable_new_str(0);
317
318 return ua_sess;
319
320 error:
321 return NULL;
322 }
323
324 /*
325 * Alloc new UST app channel.
326 */
327 static struct ust_app_channel *alloc_ust_app_channel(char *name)
328 {
329 struct ust_app_channel *ua_chan;
330
331 /* Init most of the default value by allocating and zeroing */
332 ua_chan = zmalloc(sizeof(struct ust_app_channel));
333 if (ua_chan == NULL) {
334 PERROR("malloc");
335 goto error;
336 }
337
338 strncpy(ua_chan->name, name, sizeof(ua_chan->name));
339 ua_chan->name[sizeof(ua_chan->name) - 1] = '\0';
340 ua_chan->handle = -1;
341 ua_chan->ctx = hashtable_new(0);
342 CDS_INIT_LIST_HEAD(&ua_chan->streams.head);
343 ua_chan->events = hashtable_new_str(0);
344 hashtable_node_init(&ua_chan->node, (void *) ua_chan->name,
345 strlen(ua_chan->name));
346
347 DBG3("UST app channel %s allocated", ua_chan->name);
348
349 return ua_chan;
350
351 error:
352 return NULL;
353 }
354
355 /*
356 * Alloc new UST app event.
357 */
358 static struct ust_app_event *alloc_ust_app_event(char *name)
359 {
360 struct ust_app_event *ua_event;
361
362 /* Init most of the default value by allocating and zeroing */
363 ua_event = zmalloc(sizeof(struct ust_app_event));
364 if (ua_event == NULL) {
365 PERROR("malloc");
366 goto error;
367 }
368
369 strncpy(ua_event->name, name, sizeof(ua_event->name));
370 ua_event->name[sizeof(ua_event->name) - 1] = '\0';
371 ua_event->ctx = hashtable_new(0);
372 hashtable_node_init(&ua_event->node, (void *) ua_event->name,
373 strlen(ua_event->name));
374
375 DBG3("UST app event %s allocated", ua_event->name);
376
377 return ua_event;
378
379 error:
380 return NULL;
381 }
382
383 static void shadow_copy_event(struct ust_app_event *ua_event,
384 struct ltt_ust_event *uevent)
385 {
386 strncpy(ua_event->name, uevent->attr.name, sizeof(ua_event->name));
387 ua_event->name[sizeof(ua_event->name) - 1] = '\0';
388
389 /* TODO: support copy context */
390 }
391
392 static void shadow_copy_channel(struct ust_app_channel *ua_chan,
393 struct ltt_ust_channel *uchan)
394 {
395 struct cds_lfht_iter iter;
396 struct cds_lfht_node *node, *ua_event_node;
397 struct ltt_ust_event *uevent;
398 struct ust_app_event *ua_event;
399
400 DBG2("Shadow copy of UST app channel %s", ua_chan->name);
401
402 strncpy(ua_chan->name, uchan->name, sizeof(ua_chan->name));
403 ua_chan->name[sizeof(ua_chan->name) - 1] = '\0';
404
405 /* TODO: support copy context */
406
407 /* Copy all events from ltt ust channel to ust app channel */
408 hashtable_get_first(uchan->events, &iter);
409 while ((node = hashtable_iter_get_node(&iter)) != NULL) {
410 uevent = caa_container_of(node, struct ltt_ust_event, node);
411
412 ua_event_node = hashtable_lookup(ua_chan->events,
413 (void *) uevent->attr.name, strlen(uevent->attr.name), &iter);
414 if (ua_event_node == NULL) {
415 DBG2("UST event %s not found on shadow copy channel",
416 uevent->attr.name);
417 ua_event = alloc_ust_app_event(uevent->attr.name);
418 if (ua_event == NULL) {
419 goto next;
420 }
421 shadow_copy_event(ua_event, uevent);
422 hashtable_add_unique(ua_chan->events, &ua_event->node);
423 }
424
425 next:
426 /* Get next UST events */
427 hashtable_get_next(uchan->events, &iter);
428 }
429
430 DBG3("Shadow copy channel done");
431 }
432
433 static void shadow_copy_session(struct ust_app_session *ua_sess,
434 struct ltt_ust_session *usess)
435 {
436 struct cds_lfht_node *node, *ua_chan_node;
437 struct cds_lfht_iter iter;
438 struct ltt_ust_channel *uchan;
439 struct ust_app_channel *ua_chan;
440
441 DBG2("Shadow copy of session handle %d", ua_sess->handle);
442
443 ua_sess->uid = usess->uid;
444
445 /* TODO: support all UST domain */
446
447 /* Iterate over all channels in global domain. */
448 hashtable_get_first(usess->domain_global.channels, &iter);
449 while ((node = hashtable_iter_get_node(&iter)) != NULL) {
450 uchan = caa_container_of(node, struct ltt_ust_channel, node);
451
452 ua_chan_node = hashtable_lookup(ua_sess->channels,
453 (void *)uchan->name, strlen(uchan->name), &iter);
454 if (ua_chan_node == NULL) {
455 DBG2("Channel %s not found on shadow session copy, creating it",
456 uchan->name);
457 ua_chan = alloc_ust_app_channel(uchan->name);
458 if (ua_chan == NULL) {
459 /* malloc failed... continuing */
460 goto next;
461 }
462
463 shadow_copy_channel(ua_chan, uchan);
464 hashtable_add_unique(ua_sess->channels, &ua_chan->node);
465 }
466
467 next:
468 /* Next item in hash table */
469 hashtable_get_next(usess->domain_global.channels, &iter);
470 }
471 }
472
473 /*
474 * Return ust app session from the app session hashtable using the UST session
475 * uid.
476 */
477 static struct ust_app_session *lookup_session_by_app(
478 struct ltt_ust_session *usess, struct ust_app *app)
479 {
480 struct cds_lfht_iter iter;
481 struct cds_lfht_node *node;
482
483 /* Get right UST app session from app */
484 node = hashtable_lookup(app->sessions,
485 (void *) ((unsigned long) usess->uid), sizeof(void *), &iter);
486 if (node == NULL) {
487 goto error;
488 }
489
490 return caa_container_of(node, struct ust_app_session, node);
491
492 error:
493 return NULL;
494 }
495
496 /*
497 * Create a UST session onto the tracer of app and add it the session
498 * hashtable.
499 *
500 * Return ust app session or NULL on error.
501 */
502 static struct ust_app_session *create_ust_app_session(
503 struct ltt_ust_session *usess, struct ust_app *app)
504 {
505 int ret;
506 struct ust_app_session *ua_sess;
507
508 ua_sess = lookup_session_by_app(usess, app);
509 if (ua_sess == NULL) {
510 DBG2("UST app pid: %d session uid %d not found, creating it",
511 app->key.pid, usess->uid);
512 ua_sess = alloc_ust_app_session();
513 if (ua_sess == NULL) {
514 /* Only malloc can failed so something is really wrong */
515 goto error;
516 }
517 shadow_copy_session(ua_sess, usess);
518 }
519
520 if (ua_sess->handle == -1) {
521 ret = ustctl_create_session(app->key.sock);
522 if (ret < 0) {
523 ERR("Error creating session for app pid %d, sock %d",
524 app->key.pid, app->key.sock);
525 /* TODO: free() ua_sess */
526 goto error;
527 }
528
529 DBG2("UST app ustctl create session handle %d", ret);
530 ua_sess->handle = ret;
531
532 /* Add ust app session to app's HT */
533 hashtable_node_init(&ua_sess->node,
534 (void *)((unsigned long) ua_sess->uid), sizeof(void *));
535 hashtable_add_unique(app->sessions, &ua_sess->node);
536
537 DBG2("UST app session created successfully with handle %d", ret);
538 }
539
540 return ua_sess;
541
542 error:
543 return NULL;
544 }
545
546 static struct ust_app_channel *create_ust_app_channel(
547 struct ust_app_session *ua_sess, struct ltt_ust_channel *uchan,
548 struct ust_app *app)
549 {
550 int ret = 0;
551 struct cds_lfht_iter iter;
552 struct cds_lfht_node *ua_chan_node;
553 struct ust_app_channel *ua_chan;
554
555 /* Lookup channel in the ust app session */
556 ua_chan_node = hashtable_lookup(ua_sess->channels,
557 (void *)uchan->name, strlen(uchan->name), &iter);
558 if (ua_chan_node == NULL) {
559 DBG2("Unable to find channel %s in ust session uid %u",
560 uchan->name, ua_sess->uid);
561 ua_chan = alloc_ust_app_channel(uchan->name);
562 if (ua_chan == NULL) {
563 goto error;
564 }
565 shadow_copy_channel(ua_chan, uchan);
566 hashtable_add_unique(ua_sess->channels, &ua_chan->node);
567 } else {
568 ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node);
569 }
570
571 /* TODO: remove cast and use lttng-ust-abi.h */
572 ret = ustctl_create_channel(app->key.sock, ua_sess->handle,
573 (struct lttng_ust_channel_attr *)&uchan->attr, &ua_chan->obj);
574 if (ret < 0) {
575 DBG("Error creating channel %s for app (pid: %d, sock: %d) "
576 "and session handle %d with ret %d",
577 ua_chan->name, app->key.pid, app->key.sock,
578 ua_sess->handle, ret);
579 goto error;
580 }
581
582 ua_chan->handle = ua_chan->obj->handle;
583 ua_chan->attr.shm_fd = ua_chan->obj->shm_fd;
584 ua_chan->attr.wait_fd = ua_chan->obj->wait_fd;
585 ua_chan->attr.memory_map_size = ua_chan->obj->memory_map_size;
586
587 DBG2("Channel %s UST create successfully for pid:%d and sock:%d",
588 ua_chan->name, app->key.pid, app->key.sock);
589
590 return ua_chan;
591
592 error:
593 return NULL;
594 }
595
596 static struct ust_app_event *create_ust_app_event(
597 struct ust_app_session *ua_sess, struct ust_app_channel *ua_chan,
598 struct ltt_ust_event *uevent, struct ust_app *app)
599 {
600 int ret;
601 struct cds_lfht_iter iter;
602 struct cds_lfht_node *ua_event_node;
603 struct ust_app_event *ua_event;
604
605 /* Get event node */
606 ua_event_node = hashtable_lookup(ua_chan->events,
607 (void *)uevent->attr.name, strlen(uevent->attr.name), &iter);
608 if (ua_event_node == NULL) {
609 DBG2("UST app event %s not found, creating it", uevent->attr.name);
610 /* Does not exist so create one */
611 ua_event = alloc_ust_app_event(uevent->attr.name);
612 if (ua_event == NULL) {
613 /* Only malloc can failed so something is really wrong */
614 goto error;
615 }
616 shadow_copy_event(ua_event, uevent);
617
618 hashtable_add_unique(ua_chan->events, &ua_event->node);
619 } else {
620 ua_event = caa_container_of(ua_event_node, struct ust_app_event, node);
621 }
622
623 /* Create UST event on tracer */
624 ret = ustctl_create_event(app->key.sock, &uevent->attr, ua_chan->obj,
625 &ua_event->obj);
626 if (ret < 0) {
627 ERR("Error ustctl create event %s for app pid: %d with ret %d",
628 uevent->attr.name, app->key.pid, ret);
629 /* TODO: free() ua_event */
630 goto error;
631 }
632 ua_event->handle = ua_event->obj->handle;
633 ua_event->enabled = 1;
634
635
636 DBG2("Event %s UST create successfully for pid:%d", uevent->attr.name,
637 app->key.pid);
638
639 return ua_event;
640
641 error:
642 return NULL;
643 }
644
645 static int create_ust_app_metadata(struct ust_app_session *ua_sess,
646 char *pathname, struct ust_app *app)
647 {
648 int ret = 0;
649 struct lttng_ust_channel_attr uattr;
650
651 if (ua_sess->metadata == NULL) {
652 /* Allocate UST metadata */
653 ua_sess->metadata = trace_ust_create_metadata(pathname);
654 if (ua_sess->metadata == NULL) {
655 ERR("UST app session %d creating metadata failed",
656 ua_sess->handle);
657 goto error;
658 }
659
660 uattr.overwrite = ua_sess->metadata->attr.overwrite;
661 uattr.subbuf_size = ua_sess->metadata->attr.subbuf_size;
662 uattr.num_subbuf = ua_sess->metadata->attr.num_subbuf;
663 uattr.switch_timer_interval =
664 ua_sess->metadata->attr.switch_timer_interval;
665 uattr.read_timer_interval =
666 ua_sess->metadata->attr.read_timer_interval;
667 uattr.output = ua_sess->metadata->attr.output;
668
669 /* UST tracer metadata creation */
670 ret = ustctl_open_metadata(app->key.sock, ua_sess->handle, &uattr,
671 &ua_sess->metadata->obj);
672 if (ret < 0) {
673 ERR("UST app open metadata failed for app pid:%d",
674 app->key.pid);
675 goto error;
676 }
677
678 DBG2("UST metadata opened for app pid %d", app->key.pid);
679 }
680
681 /* Open UST metadata stream */
682 if (ua_sess->metadata->stream_obj == NULL) {
683 ret = ustctl_create_stream(app->key.sock, ua_sess->metadata->obj,
684 &ua_sess->metadata->stream_obj);
685 if (ret < 0) {
686 ERR("UST create metadata stream failed");
687 goto error;
688 }
689
690 ret = snprintf(ua_sess->metadata->pathname, PATH_MAX, "%s/%s-%d",
691 pathname, app->name, app->key.pid);
692 if (ret < 0) {
693 PERROR("asprintf UST create stream");
694 goto error;
695 }
696
697 ret = mkdir(ua_sess->metadata->pathname, S_IRWXU | S_IRWXG);
698 if (ret < 0) {
699 PERROR("mkdir UST metadata");
700 goto error;
701 }
702
703 ret = snprintf(ua_sess->metadata->pathname, PATH_MAX, "%s/%s-%d/metadata",
704 pathname, app->name, app->key.pid);
705 if (ret < 0) {
706 PERROR("asprintf UST create stream");
707 goto error;
708 }
709
710 DBG2("UST metadata stream object created for app pid %d",
711 app->key.pid);
712 }
713
714 return 0;
715
716 error:
717 return -1;
718 }
719
720 /*
721 * Add channel to all ust app session.
722 */
723 int ust_app_add_channel_all(struct ltt_ust_session *usess,
724 struct ltt_ust_channel *uchan)
725 {
726 int ret = 0;
727 struct cds_lfht_iter iter;
728 struct cds_lfht_node *node;
729 struct ust_app *app;
730 struct ust_app_session *ua_sess;
731 struct ust_app_channel *ua_chan;
732
733 if (usess == NULL || uchan == NULL) {
734 ERR("Adding UST global channel to NULL values");
735 ret = -1;
736 goto error;
737 }
738
739 DBG2("UST app adding channel %s to global domain for session uid %d",
740 uchan->name, usess->uid);
741
742 rcu_read_lock();
743
744 /* For every UST applications registered */
745 hashtable_get_first(ust_app_ht, &iter);
746 while ((node = hashtable_iter_get_node(&iter)) != NULL) {
747 app = caa_container_of(node, struct ust_app, node);
748
749 /* Create session on the tracer side and add it to app session HT */
750 ua_sess = create_ust_app_session(usess, app);
751 if (ret < 0) {
752 goto next;
753 }
754
755 /* Create channel onto application */
756 ua_chan = create_ust_app_channel(ua_sess, uchan, app);
757 if (ua_chan == NULL) {
758 goto next;
759 }
760
761 next:
762 /* Next applications */
763 hashtable_get_next(ust_app_ht, &iter);
764 }
765 rcu_read_unlock();
766
767 error:
768 return ret;
769 }
770
771 int ust_app_add_event_all(struct ltt_ust_session *usess,
772 struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent)
773 {
774 int ret = 0;
775 struct cds_lfht_iter iter;
776 struct cds_lfht_node *node, *ua_chan_node;
777 struct ust_app *app;
778 struct ust_app_session *ua_sess;
779 struct ust_app_channel *ua_chan;
780 struct ust_app_event *ua_event;
781
782 DBG2("UST app adding event %s to global domain for session uid %d",
783 uevent->attr.name, usess->uid);
784
785 rcu_read_lock();
786
787 /* For all registered applications */
788 hashtable_get_first(ust_app_ht, &iter);
789 while ((node = hashtable_iter_get_node(&iter)) != NULL) {
790 app = caa_container_of(node, struct ust_app, node);
791
792 /* Create session on the tracer side and add it to app session HT */
793 ua_sess = create_ust_app_session(usess, app);
794 if (ret < 0) {
795 goto next;
796 }
797
798 /* Lookup channel in the ust app session */
799 ua_chan_node = hashtable_lookup(ua_sess->channels,
800 (void *)uchan->name, strlen(uchan->name), &iter);
801 if (ua_chan_node == NULL) {
802 ERR("Channel %s not found in session uid %d. Skipping",
803 uchan->name, usess->uid);
804 goto next;
805 }
806 ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node);
807
808 ua_event = create_ust_app_event(ua_sess, ua_chan, uevent, app);
809 if (ua_event == NULL) {
810 goto next;
811 }
812
813 next:
814 /* Next applications */
815 hashtable_get_next(ust_app_ht, &iter);
816 }
817 rcu_read_unlock();
818
819 return ret;
820 }
821
822 int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *app)
823 {
824 int ret = 0;
825 struct cds_lfht_iter iter;
826 struct cds_lfht_node *node;
827 struct ust_app_session *ua_sess;
828 struct ust_app_channel *ua_chan;
829
830 DBG("Starting tracing for ust app pid %d", app->key.pid);
831
832 ua_sess = lookup_session_by_app(usess, app);
833 if (ua_sess == NULL) {
834 /* Only malloc can failed so something is really wrong */
835 goto error;
836 }
837
838 ret = create_ust_app_metadata(ua_sess, usess->pathname, app);
839 if (ret < 0) {
840 goto error;
841 }
842
843 /* For each channel */
844 hashtable_get_first(ua_sess->channels, &iter);
845 while ((node = hashtable_iter_get_node(&iter)) != NULL) {
846 ua_chan = caa_container_of(node, struct ust_app_channel, node);
847
848 /* Create all streams */
849 while (1) {
850 struct ltt_ust_stream *ustream;
851
852 ustream = zmalloc(sizeof(*ustream));
853 if (ustream == NULL) {
854 PERROR("zmalloc ust stream");
855 continue;
856 }
857
858 ret = ustctl_create_stream(app->key.sock, ua_chan->obj,
859 &ustream->obj);
860 if (ret < 0) {
861 /* Got all streams */
862 break;
863 }
864 ustream->handle = ustream->obj->handle;
865
866 /* Order is important */
867 cds_list_add_tail(&ustream->list, &ua_chan->streams.head);
868 ret = snprintf(ustream->pathname, PATH_MAX, "%s/%s-%d/%s_%u",
869 usess->pathname, app->name, app->key.pid,
870 ua_chan->name, ua_chan->streams.count++);
871 if (ret < 0) {
872 PERROR("asprintf UST create stream");
873 continue;
874 }
875 DBG2("UST stream %d ready at %s", ua_chan->streams.count,
876 ustream->pathname);
877 }
878
879 /* Next applications */
880 hashtable_get_next(ua_sess->channels, &iter);
881 }
882
883 /* Setup UST consumer socket and send fds to it */
884 ret = ust_consumer_send_session(usess->consumer_fd, ua_sess);
885 if (ret < 0) {
886 goto error;
887 }
888
889 /* This start the UST tracing */
890 ret = ustctl_start_session(app->key.sock, ua_sess->handle);
891 if (ret < 0) {
892 ERR("Error starting tracing for app pid: %d", app->key.pid);
893 goto error;
894 }
895
896 /* Quiescent wait after starting trace */
897 ustctl_wait_quiescent(app->key.sock);
898
899 return 0;
900
901 error:
902 return -1;
903 }
904
905 int ust_app_start_trace_all(struct ltt_ust_session *usess)
906 {
907 int ret = 0;
908 struct cds_lfht_iter iter;
909 struct cds_lfht_node *node;
910 struct ust_app *app;
911
912 DBG("Starting all UST traces");
913
914 rcu_read_lock();
915 hashtable_get_first(ust_app_ht, &iter);
916 while ((node = hashtable_iter_get_node(&iter)) != NULL) {
917 app = caa_container_of(node, struct ust_app, node);
918
919 ret = ust_app_start_trace(usess, app);
920 if (ret < 0) {
921 goto next;
922 }
923
924 next:
925 /* Next applications */
926 hashtable_get_next(ust_app_ht, &iter);
927 }
928 rcu_read_unlock();
929
930 return 0;
931 }
932
933 void ust_app_global_update(struct ltt_ust_session *usess, int sock)
934 {
935 int ret = 0;
936 struct cds_lfht_iter iter;
937 struct cds_lfht_node *node;
938 struct ust_app *app;
939 struct ust_app_session *ua_sess;
940 struct ust_app_channel *ua_chan;
941 struct ust_app_event *ua_event;
942 struct ltt_ust_channel *uchan;
943 struct ltt_ust_event *uevent;
944
945 rcu_read_lock();
946
947 if (usess == NULL) {
948 DBG2("No UST session on global update. Returning");
949 goto error;
950 }
951
952 DBG2("UST app global update for app sock %d for session uid %d", sock,
953 usess->uid);
954
955 app = find_app_by_sock(sock);
956 if (app == NULL) {
957 ERR("Failed to update app sock %d", sock);
958 goto error;
959 }
960
961 ua_sess = create_ust_app_session(usess, app);
962 if (ua_sess == NULL) {
963 goto error;
964 }
965
966 hashtable_get_first(usess->domain_global.channels, &iter);
967 while ((node = hashtable_iter_get_node(&iter)) != NULL) {
968 uchan = caa_container_of(node, struct ltt_ust_channel, node);
969
970 ua_chan = create_ust_app_channel(ua_sess, uchan, app);
971 if (ua_chan == NULL) {
972 goto next_chan;
973 }
974
975 hashtable_get_first(uchan->events, &iter);
976 while ((node = hashtable_iter_get_node(&iter)) != NULL) {
977 uevent = caa_container_of(node, struct ltt_ust_event, node);
978
979 ua_event = create_ust_app_event(ua_sess, ua_chan, uevent, app);
980 if (ua_event == NULL) {
981 goto next_event;
982 }
983
984 next_event:
985 hashtable_get_next(uchan->events, &iter);
986 }
987
988 next_chan:
989 /* Next item in hash table */
990 hashtable_get_next(usess->domain_global.channels, &iter);
991 }
992
993 if (usess->start_trace) {
994 ret = ust_app_start_trace(usess, app);
995 if (ret < 0) {
996 goto error;
997 }
998
999 DBG2("UST trace started for app pid %d", app->key.pid);
1000 }
1001
1002 error:
1003 rcu_read_unlock();
1004 return;
1005 }
This page took 0.049844 seconds and 5 git commands to generate.