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