Add important DEBUG statement
[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 24#include <string.h>
aba8e916
DG
25#include <sys/stat.h>
26#include <sys/types.h>
099e26bd 27#include <unistd.h>
91d76f53 28
1e307fab 29#include <lttngerr.h>
48842b30 30#include <lttng-share.h>
1e307fab 31
f6a9efaa 32#include "hashtable.h"
56fff090 33#include "ust-app.h"
48842b30 34#include "ust-consumer.h"
d80a6244
DG
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}
91d76f53
DG
135
136/*
099e26bd 137 * Delete a traceable application structure from the global list.
91d76f53 138 */
f6a9efaa 139static void delete_ust_app(struct ust_app *lta)
91d76f53 140{
f6a9efaa
DG
141 int ret;
142 struct cds_lfht_node *node;
143 struct cds_lfht_iter iter;
d80a6244 144 struct ust_app_session *lts;
44d3bd01 145
f6a9efaa 146 rcu_read_lock();
44d3bd01 147
f6a9efaa
DG
148 /* Remove from apps hash table */
149 node = hashtable_lookup(ust_app_ht,
150 (void *) ((unsigned long) lta->key.pid), sizeof(void *), &iter);
151 if (node == NULL) {
152 ERR("UST app pid %d not found in hash table", lta->key.pid);
d80a6244 153 goto end;
f6a9efaa
DG
154 } else {
155 ret = hashtable_del(ust_app_ht, &iter);
156 if (ret) {
157 ERR("UST app unable to delete app %d from hash table",
158 lta->key.pid);
159 } else {
160 DBG2("UST app pid %d deleted", lta->key.pid);
56fff090
DG
161 }
162 }
163
f6a9efaa
DG
164 /* Remove from key hash table */
165 node = hashtable_lookup(ust_app_sock_key_map,
166 (void *) ((unsigned long) lta->key.sock), sizeof(void *), &iter);
167 if (node == NULL) {
168 ERR("UST app key %d not found in key hash table", lta->key.sock);
d80a6244 169 goto end;
f6a9efaa
DG
170 } else {
171 ret = hashtable_del(ust_app_sock_key_map, &iter);
172 if (ret) {
173 ERR("UST app unable to delete app sock %d from key hash table",
174 lta->key.sock);
175 } else {
176 DBG2("UST app pair sock %d key %d deleted",
177 lta->key.sock, lta->key.pid);
178 }
179 }
180
d80a6244
DG
181 /* Socket is already closed at this point */
182
183 /* Delete ust app sessions info */
184 if (lta->sock_closed) {
185 lta->key.sock = -1;
186 }
187
188 cds_lfht_for_each_entry(lta->sessions, &iter, lts, node) {
189 hashtable_del(lta->sessions, &iter);
190 delete_ust_app_session(lta->key.sock, lts);
191 }
f6a9efaa 192
d80a6244
DG
193 ret = hashtable_destroy(lta->sessions);
194 if (ret < 0) {
195 ERR("UST app destroy session hashtable failed");
196 goto end;
197 }
198
199 if (lta->key.sock >= 0) {
200 close(lta->key.sock);
201 }
202
203 free(lta);
204end:
f6a9efaa 205 rcu_read_unlock();
099e26bd
DG
206}
207
208/*
f6a9efaa 209 * URCU intermediate call to delete an UST app.
099e26bd 210 */
f6a9efaa 211static void delete_ust_app_rcu(struct rcu_head *head)
099e26bd 212{
f6a9efaa
DG
213 struct cds_lfht_node *node =
214 caa_container_of(head, struct cds_lfht_node, head);
215 struct ust_app *app =
216 caa_container_of(node, struct ust_app, node);
217
218 delete_ust_app(app);
099e26bd
DG
219}
220
221/*
421cb601
DG
222 * Find an ust_app using the sock and return it. RCU read side lock must be
223 * held before calling this helper function.
099e26bd 224 */
f6a9efaa 225static struct ust_app *find_app_by_sock(int sock)
099e26bd 226{
f6a9efaa
DG
227 struct cds_lfht_node *node;
228 struct ust_app_key *key;
229 struct cds_lfht_iter iter;
f6a9efaa 230
f6a9efaa
DG
231 node = hashtable_lookup(ust_app_sock_key_map,
232 (void *)((unsigned long) sock), sizeof(void *), &iter);
233 if (node == NULL) {
234 DBG2("UST app find by sock %d key not found", sock);
f6a9efaa
DG
235 goto error;
236 }
237
238 key = caa_container_of(node, struct ust_app_key, node);
239
240 node = hashtable_lookup(ust_app_ht,
241 (void *)((unsigned long) key->pid), sizeof(void *), &iter);
242 if (node == NULL) {
243 DBG2("UST app find by sock %d not found", sock);
f6a9efaa
DG
244 goto error;
245 }
f6a9efaa
DG
246 return caa_container_of(node, struct ust_app, node);
247
248error:
249 return NULL;
099e26bd
DG
250}
251
252/*
f6a9efaa 253 * Return pointer to traceable apps list.
099e26bd 254 */
f6a9efaa 255struct cds_lfht *ust_app_get_ht(void)
099e26bd 256{
f6a9efaa 257 return ust_app_ht;
91d76f53
DG
258}
259
0177d773 260/*
f6a9efaa 261 * Return ust app pointer or NULL if not found.
0177d773 262 */
f6a9efaa 263struct ust_app *ust_app_find_by_pid(pid_t pid)
0177d773 264{
f6a9efaa
DG
265 struct cds_lfht_node *node;
266 struct cds_lfht_iter iter;
0177d773 267
f6a9efaa
DG
268 rcu_read_lock();
269 node = hashtable_lookup(ust_app_ht,
270 (void *)((unsigned long) pid), sizeof(void *), &iter);
271 if (node == NULL) {
f6a9efaa
DG
272 DBG2("UST app no found with pid %d", pid);
273 goto error;
0177d773 274 }
f6a9efaa 275 rcu_read_unlock();
0177d773 276
f6a9efaa 277 DBG2("Found UST app by pid %d", pid);
44d3bd01 278
f6a9efaa
DG
279 return caa_container_of(node, struct ust_app, node);
280
281error:
ee2fd646 282 rcu_read_unlock();
0177d773
DG
283 return NULL;
284}
285
91d76f53 286/*
56fff090 287 * Using pid and uid (of the app), allocate a new ust_app struct and
050349bb 288 * add it to the global traceable app list.
91d76f53 289 *
050349bb 290 * On success, return 0, else return malloc ENOMEM.
91d76f53 291 */
56fff090 292int ust_app_register(struct ust_register_msg *msg, int sock)
91d76f53 293{
56fff090 294 struct ust_app *lta;
91d76f53 295
d80a6244 296 lta = zmalloc(sizeof(struct ust_app));
91d76f53 297 if (lta == NULL) {
48842b30 298 PERROR("malloc");
91d76f53
DG
299 return -ENOMEM;
300 }
301
099e26bd
DG
302 lta->uid = msg->uid;
303 lta->gid = msg->gid;
f6a9efaa 304 lta->key.pid = msg->pid;
099e26bd
DG
305 lta->ppid = msg->ppid;
306 lta->v_major = msg->major;
307 lta->v_minor = msg->minor;
f6a9efaa 308 lta->key.sock = sock;
099e26bd
DG
309 strncpy(lta->name, msg->name, sizeof(lta->name));
310 lta->name[16] = '\0';
f6a9efaa
DG
311 hashtable_node_init(&lta->node, (void *)((unsigned long)lta->key.pid),
312 sizeof(void *));
48842b30
DG
313
314 /* Session hashtable */
315 lta->sessions = hashtable_new(0);
f6a9efaa
DG
316
317 /* Set sock key map */
318 hashtable_node_init(&lta->key.node, (void *)((unsigned long)lta->key.sock),
319 sizeof(void *));
099e26bd 320
f6a9efaa
DG
321 rcu_read_lock();
322 hashtable_add_unique(ust_app_ht, &lta->node);
323 hashtable_add_unique(ust_app_sock_key_map, &lta->key.node);
324 rcu_read_unlock();
099e26bd
DG
325
326 DBG("App registered with pid:%d ppid:%d uid:%d gid:%d sock:%d name:%s"
f6a9efaa
DG
327 " (version %d.%d)", lta->key.pid, lta->ppid, lta->uid, lta->gid,
328 lta->key.sock, lta->name, lta->v_major, lta->v_minor);
91d76f53
DG
329
330 return 0;
331}
332
333/*
050349bb
DG
334 * Unregister app by removing it from the global traceable app list and freeing
335 * the data struct.
099e26bd
DG
336 *
337 * The socket is already closed at this point so no close to sock.
91d76f53 338 */
56fff090 339void ust_app_unregister(int sock)
91d76f53 340{
56fff090 341 struct ust_app *lta;
421cb601
DG
342 struct cds_lfht_node *node;
343 struct cds_lfht_iter iter;
91d76f53 344
421cb601 345 rcu_read_lock();
099e26bd 346 lta = find_app_by_sock(sock);
421cb601
DG
347 if (lta == NULL) {
348 ERR("Unregister app sock %d not found!", sock);
349 goto error;
350 }
351
352 DBG("PID %d unregistering with sock %d", lta->key.pid, sock);
353
354 /* Get the node reference for a call_rcu */
355 node = hashtable_lookup(ust_app_ht,
356 (void *)((unsigned long) lta->key.pid), sizeof(void *), &iter);
357 if (node == NULL) {
358 ERR("Unable to find app sock %d by pid %d", sock, lta->key.pid);
359 goto error;
91d76f53 360 }
421cb601 361
d80a6244
DG
362 /* We got called because the socket was closed on the remote end. */
363 close(sock);
364 /* Using a flag because we still need "sock" as a key. */
365 lta->sock_closed = 1;
421cb601 366 call_rcu(&node->head, delete_ust_app_rcu);
421cb601
DG
367error:
368 rcu_read_unlock();
369 return;
91d76f53
DG
370}
371
372/*
050349bb 373 * Return traceable_app_count
91d76f53 374 */
f6a9efaa 375unsigned long ust_app_list_count(void)
91d76f53 376{
f6a9efaa 377 unsigned long count;
91d76f53 378
f6a9efaa
DG
379 rcu_read_lock();
380 count = hashtable_get_count(ust_app_ht);
381 rcu_read_unlock();
91d76f53 382
099e26bd 383 return count;
91d76f53
DG
384}
385
b551a063
DG
386/*
387 * Fill events array with all events name of all registered apps.
388 */
389int ust_app_list_events(struct lttng_event **events)
390{
391 int ret, handle;
392 size_t nbmem, count = 0;
393 struct cds_lfht_iter iter;
394 struct ust_app *app;
395 struct lttng_event *tmp;
396
397 nbmem = UST_APP_EVENT_LIST_SIZE;
398 tmp = zmalloc(nbmem * sizeof(struct lttng_event));
399 if (tmp == NULL) {
400 PERROR("zmalloc ust app events");
401 ret = -ENOMEM;
402 goto error;
403 }
404
405 rcu_read_lock();
406
407 cds_lfht_for_each_entry(ust_app_ht, &iter, app, node) {
408 handle = ustctl_tracepoint_list(app->key.sock);
409 if (handle < 0) {
410 ERR("UST app list events getting handle failed for app pid %d",
411 app->key.pid);
412 continue;
413 }
414
415 while ((ret = ustctl_tracepoint_list_get(app->key.sock, handle,
416 tmp[count].name)) != -ENOENT) {
417 if (count > nbmem) {
418 DBG2("Reallocating event list from %zu to %zu bytes", nbmem,
419 nbmem + UST_APP_EVENT_LIST_SIZE);
420 nbmem += UST_APP_EVENT_LIST_SIZE;
421 tmp = realloc(tmp, nbmem);
422 if (tmp == NULL) {
423 PERROR("realloc ust app events");
424 ret = -ENOMEM;
425 goto rcu_error;
426 }
427 }
428
429 tmp[count].type = LTTNG_UST_TRACEPOINT;
430 tmp[count].pid = app->key.pid;
431 count++;
432 }
433 }
434
435 ret = count;
436 *events = tmp;
437
438 DBG2("UST app list events done (%zu events)", count);
439
440rcu_error:
441 rcu_read_unlock();
442error:
443 return ret;
444}
445
91d76f53 446/*
099e26bd 447 * Free and clean all traceable apps of the global list.
91d76f53 448 */
56fff090 449void ust_app_clean_list(void)
91d76f53 450{
f6a9efaa
DG
451 int ret;
452 struct cds_lfht_node *node;
453 struct cds_lfht_iter iter;
454
455 DBG2("UST app clean hash table");
456
457 rcu_read_lock();
458
459 hashtable_get_first(ust_app_ht, &iter);
460 while ((node = hashtable_iter_get_node(&iter)) != NULL) {
461 ret = hashtable_del(ust_app_ht, &iter);
462 if (!ret) {
463 call_rcu(&node->head, delete_ust_app_rcu);
464 }
465 hashtable_get_next(ust_app_ht, &iter);
91d76f53 466 }
f6a9efaa
DG
467
468 rcu_read_unlock();
469}
470
471/*
472 * Init UST app hash table.
473 */
474void ust_app_ht_alloc(void)
475{
476 ust_app_ht = hashtable_new(0);
477 ust_app_sock_key_map = hashtable_new(0);
91d76f53 478}
48842b30
DG
479
480/*
481 * Alloc new UST app session.
482 */
421cb601 483static struct ust_app_session *alloc_ust_app_session(void)
48842b30
DG
484{
485 struct ust_app_session *ua_sess;
486
421cb601 487 /* Init most of the default value by allocating and zeroing */
48842b30
DG
488 ua_sess = zmalloc(sizeof(struct ust_app_session));
489 if (ua_sess == NULL) {
490 PERROR("malloc");
491 goto error;
492 }
493
48842b30
DG
494 ua_sess->handle = -1;
495 ua_sess->channels = hashtable_new_str(0);
48842b30
DG
496
497 return ua_sess;
498
499error:
500 return NULL;
501}
502
421cb601
DG
503/*
504 * Alloc new UST app channel.
505 */
506static struct ust_app_channel *alloc_ust_app_channel(char *name)
48842b30
DG
507{
508 struct ust_app_channel *ua_chan;
509
421cb601 510 /* Init most of the default value by allocating and zeroing */
48842b30
DG
511 ua_chan = zmalloc(sizeof(struct ust_app_channel));
512 if (ua_chan == NULL) {
513 PERROR("malloc");
514 goto error;
515 }
516
517 strncpy(ua_chan->name, name, sizeof(ua_chan->name));
518 ua_chan->name[sizeof(ua_chan->name) - 1] = '\0';
48842b30 519 ua_chan->handle = -1;
48842b30 520 ua_chan->ctx = hashtable_new(0);
5af2f756 521 CDS_INIT_LIST_HEAD(&ua_chan->streams.head);
48842b30
DG
522 ua_chan->events = hashtable_new_str(0);
523 hashtable_node_init(&ua_chan->node, (void *) ua_chan->name,
524 strlen(ua_chan->name));
525
526 DBG3("UST app channel %s allocated", ua_chan->name);
527
528 return ua_chan;
529
530error:
531 return NULL;
532}
533
421cb601
DG
534/*
535 * Alloc new UST app event.
536 */
537static struct ust_app_event *alloc_ust_app_event(char *name)
48842b30
DG
538{
539 struct ust_app_event *ua_event;
540
421cb601 541 /* Init most of the default value by allocating and zeroing */
48842b30
DG
542 ua_event = zmalloc(sizeof(struct ust_app_event));
543 if (ua_event == NULL) {
544 PERROR("malloc");
545 goto error;
546 }
547
548 strncpy(ua_event->name, name, sizeof(ua_event->name));
549 ua_event->name[sizeof(ua_event->name) - 1] = '\0';
550 ua_event->ctx = hashtable_new(0);
551 hashtable_node_init(&ua_event->node, (void *) ua_event->name,
552 strlen(ua_event->name));
553
554 DBG3("UST app event %s allocated", ua_event->name);
555
556 return ua_event;
557
558error:
559 return NULL;
560}
561
421cb601 562static void shadow_copy_event(struct ust_app_event *ua_event,
48842b30
DG
563 struct ltt_ust_event *uevent)
564{
565 strncpy(ua_event->name, uevent->attr.name, sizeof(ua_event->name));
566 ua_event->name[sizeof(ua_event->name) - 1] = '\0';
567
568 /* TODO: support copy context */
569}
570
421cb601 571static void shadow_copy_channel(struct ust_app_channel *ua_chan,
48842b30
DG
572 struct ltt_ust_channel *uchan)
573{
574 struct cds_lfht_iter iter;
575 struct cds_lfht_node *node, *ua_event_node;
576 struct ltt_ust_event *uevent;
577 struct ust_app_event *ua_event;
578
421cb601 579 DBG2("Shadow copy of UST app channel %s", ua_chan->name);
48842b30
DG
580
581 strncpy(ua_chan->name, uchan->name, sizeof(ua_chan->name));
582 ua_chan->name[sizeof(ua_chan->name) - 1] = '\0';
583
584 /* TODO: support copy context */
585
421cb601 586 /* Copy all events from ltt ust channel to ust app channel */
48842b30
DG
587 hashtable_get_first(uchan->events, &iter);
588 while ((node = hashtable_iter_get_node(&iter)) != NULL) {
589 uevent = caa_container_of(node, struct ltt_ust_event, node);
590
591 ua_event_node = hashtable_lookup(ua_chan->events,
592 (void *) uevent->attr.name, strlen(uevent->attr.name), &iter);
593 if (ua_event_node == NULL) {
421cb601 594 DBG2("UST event %s not found on shadow copy channel",
48842b30 595 uevent->attr.name);
421cb601 596 ua_event = alloc_ust_app_event(uevent->attr.name);
48842b30 597 if (ua_event == NULL) {
421cb601 598 goto next;
48842b30 599 }
421cb601 600 shadow_copy_event(ua_event, uevent);
48842b30 601 hashtable_add_unique(ua_chan->events, &ua_event->node);
48842b30
DG
602 }
603
421cb601 604next:
48842b30
DG
605 /* Get next UST events */
606 hashtable_get_next(uchan->events, &iter);
607 }
608
421cb601 609 DBG3("Shadow copy channel done");
48842b30
DG
610}
611
421cb601 612static void shadow_copy_session(struct ust_app_session *ua_sess,
48842b30
DG
613 struct ltt_ust_session *usess)
614{
615 struct cds_lfht_node *node, *ua_chan_node;
616 struct cds_lfht_iter iter;
617 struct ltt_ust_channel *uchan;
618 struct ust_app_channel *ua_chan;
619
421cb601 620 DBG2("Shadow copy of session handle %d", ua_sess->handle);
48842b30
DG
621
622 ua_sess->uid = usess->uid;
623
624 /* TODO: support all UST domain */
625
626 /* Iterate over all channels in global domain. */
627 hashtable_get_first(usess->domain_global.channels, &iter);
628 while ((node = hashtable_iter_get_node(&iter)) != NULL) {
629 uchan = caa_container_of(node, struct ltt_ust_channel, node);
630
631 ua_chan_node = hashtable_lookup(ua_sess->channels,
421cb601 632 (void *)uchan->name, strlen(uchan->name), &iter);
48842b30 633 if (ua_chan_node == NULL) {
421cb601 634 DBG2("Channel %s not found on shadow session copy, creating it",
48842b30 635 uchan->name);
421cb601 636 ua_chan = alloc_ust_app_channel(uchan->name);
48842b30
DG
637 if (ua_chan == NULL) {
638 /* malloc failed... continuing */
421cb601 639 goto next;
48842b30 640 }
421cb601
DG
641
642 shadow_copy_channel(ua_chan, uchan);
48842b30 643 hashtable_add_unique(ua_sess->channels, &ua_chan->node);
48842b30
DG
644 }
645
421cb601 646next:
48842b30
DG
647 /* Next item in hash table */
648 hashtable_get_next(usess->domain_global.channels, &iter);
649 }
650}
651
421cb601
DG
652/*
653 * Return ust app session from the app session hashtable using the UST session
654 * uid.
655 */
48842b30
DG
656static struct ust_app_session *lookup_session_by_app(
657 struct ltt_ust_session *usess, struct ust_app *app)
658{
659 struct cds_lfht_iter iter;
660 struct cds_lfht_node *node;
661
662 /* Get right UST app session from app */
663 node = hashtable_lookup(app->sessions,
421cb601 664 (void *) ((unsigned long) usess->uid), sizeof(void *), &iter);
48842b30
DG
665 if (node == NULL) {
666 goto error;
667 }
668
669 return caa_container_of(node, struct ust_app_session, node);
670
671error:
672 return NULL;
673}
674
421cb601
DG
675/*
676 * Create a UST session onto the tracer of app and add it the session
677 * hashtable.
678 *
679 * Return ust app session or NULL on error.
680 */
681static struct ust_app_session *create_ust_app_session(
682 struct ltt_ust_session *usess, struct ust_app *app)
683{
684 int ret;
685 struct ust_app_session *ua_sess;
686
687 ua_sess = lookup_session_by_app(usess, app);
688 if (ua_sess == NULL) {
689 DBG2("UST app pid: %d session uid %d not found, creating it",
690 app->key.pid, usess->uid);
691 ua_sess = alloc_ust_app_session();
692 if (ua_sess == NULL) {
693 /* Only malloc can failed so something is really wrong */
694 goto error;
695 }
696 shadow_copy_session(ua_sess, usess);
697 }
698
699 if (ua_sess->handle == -1) {
700 ret = ustctl_create_session(app->key.sock);
701 if (ret < 0) {
702 ERR("Error creating session for app pid %d, sock %d",
703 app->key.pid, app->key.sock);
704 /* TODO: free() ua_sess */
705 goto error;
706 }
707
708 DBG2("UST app ustctl create session handle %d", ret);
709 ua_sess->handle = ret;
710
711 /* Add ust app session to app's HT */
712 hashtable_node_init(&ua_sess->node,
713 (void *)((unsigned long) ua_sess->uid), sizeof(void *));
714 hashtable_add_unique(app->sessions, &ua_sess->node);
715
716 DBG2("UST app session created successfully with handle %d", ret);
717 }
718
719 return ua_sess;
720
721error:
722 return NULL;
723}
724
725static struct ust_app_channel *create_ust_app_channel(
726 struct ust_app_session *ua_sess, struct ltt_ust_channel *uchan,
727 struct ust_app *app)
728{
729 int ret = 0;
730 struct cds_lfht_iter iter;
731 struct cds_lfht_node *ua_chan_node;
732 struct ust_app_channel *ua_chan;
733
734 /* Lookup channel in the ust app session */
735 ua_chan_node = hashtable_lookup(ua_sess->channels,
736 (void *)uchan->name, strlen(uchan->name), &iter);
737 if (ua_chan_node == NULL) {
738 DBG2("Unable to find channel %s in ust session uid %u",
739 uchan->name, ua_sess->uid);
740 ua_chan = alloc_ust_app_channel(uchan->name);
741 if (ua_chan == NULL) {
742 goto error;
743 }
744 shadow_copy_channel(ua_chan, uchan);
745 hashtable_add_unique(ua_sess->channels, &ua_chan->node);
746 } else {
747 ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node);
748 }
749
750 /* TODO: remove cast and use lttng-ust-abi.h */
751 ret = ustctl_create_channel(app->key.sock, ua_sess->handle,
752 (struct lttng_ust_channel_attr *)&uchan->attr, &ua_chan->obj);
753 if (ret < 0) {
754 DBG("Error creating channel %s for app (pid: %d, sock: %d) "
755 "and session handle %d with ret %d",
756 ua_chan->name, app->key.pid, app->key.sock,
757 ua_sess->handle, ret);
758 goto error;
759 }
760
761 ua_chan->handle = ua_chan->obj->handle;
762 ua_chan->attr.shm_fd = ua_chan->obj->shm_fd;
763 ua_chan->attr.wait_fd = ua_chan->obj->wait_fd;
764 ua_chan->attr.memory_map_size = ua_chan->obj->memory_map_size;
765
766 DBG2("Channel %s UST create successfully for pid:%d and sock:%d",
767 ua_chan->name, app->key.pid, app->key.sock);
768
769 return ua_chan;
770
771error:
772 return NULL;
773}
774
775static struct ust_app_event *create_ust_app_event(
776 struct ust_app_session *ua_sess, struct ust_app_channel *ua_chan,
777 struct ltt_ust_event *uevent, struct ust_app *app)
778{
779 int ret;
780 struct cds_lfht_iter iter;
781 struct cds_lfht_node *ua_event_node;
782 struct ust_app_event *ua_event;
783
784 /* Get event node */
785 ua_event_node = hashtable_lookup(ua_chan->events,
786 (void *)uevent->attr.name, strlen(uevent->attr.name), &iter);
787 if (ua_event_node == NULL) {
788 DBG2("UST app event %s not found, creating it", uevent->attr.name);
789 /* Does not exist so create one */
790 ua_event = alloc_ust_app_event(uevent->attr.name);
791 if (ua_event == NULL) {
792 /* Only malloc can failed so something is really wrong */
793 goto error;
794 }
795 shadow_copy_event(ua_event, uevent);
796
797 hashtable_add_unique(ua_chan->events, &ua_event->node);
798 } else {
799 ua_event = caa_container_of(ua_event_node, struct ust_app_event, node);
800 }
801
802 /* Create UST event on tracer */
803 ret = ustctl_create_event(app->key.sock, &uevent->attr, ua_chan->obj,
804 &ua_event->obj);
805 if (ret < 0) {
806 ERR("Error ustctl create event %s for app pid: %d with ret %d",
807 uevent->attr.name, app->key.pid, ret);
808 /* TODO: free() ua_event */
809 goto error;
810 }
811 ua_event->handle = ua_event->obj->handle;
812 ua_event->enabled = 1;
813
814
815 DBG2("Event %s UST create successfully for pid:%d", uevent->attr.name,
816 app->key.pid);
817
818 return ua_event;
819
820error:
821 return NULL;
822}
823
824static int create_ust_app_metadata(struct ust_app_session *ua_sess,
825 char *pathname, struct ust_app *app)
826{
827 int ret = 0;
828 struct lttng_ust_channel_attr uattr;
829
830 if (ua_sess->metadata == NULL) {
831 /* Allocate UST metadata */
832 ua_sess->metadata = trace_ust_create_metadata(pathname);
833 if (ua_sess->metadata == NULL) {
834 ERR("UST app session %d creating metadata failed",
835 ua_sess->handle);
836 goto error;
837 }
838
839 uattr.overwrite = ua_sess->metadata->attr.overwrite;
840 uattr.subbuf_size = ua_sess->metadata->attr.subbuf_size;
841 uattr.num_subbuf = ua_sess->metadata->attr.num_subbuf;
842 uattr.switch_timer_interval =
843 ua_sess->metadata->attr.switch_timer_interval;
844 uattr.read_timer_interval =
845 ua_sess->metadata->attr.read_timer_interval;
846 uattr.output = ua_sess->metadata->attr.output;
847
848 /* UST tracer metadata creation */
849 ret = ustctl_open_metadata(app->key.sock, ua_sess->handle, &uattr,
850 &ua_sess->metadata->obj);
851 if (ret < 0) {
852 ERR("UST app open metadata failed for app pid:%d",
853 app->key.pid);
854 goto error;
855 }
856
857 DBG2("UST metadata opened for app pid %d", app->key.pid);
858 }
859
860 /* Open UST metadata stream */
861 if (ua_sess->metadata->stream_obj == NULL) {
862 ret = ustctl_create_stream(app->key.sock, ua_sess->metadata->obj,
863 &ua_sess->metadata->stream_obj);
864 if (ret < 0) {
865 ERR("UST create metadata stream failed");
866 goto error;
867 }
868
869 ret = snprintf(ua_sess->metadata->pathname, PATH_MAX, "%s/%s-%d",
870 pathname, app->name, app->key.pid);
871 if (ret < 0) {
872 PERROR("asprintf UST create stream");
873 goto error;
874 }
875
876 ret = mkdir(ua_sess->metadata->pathname, S_IRWXU | S_IRWXG);
877 if (ret < 0) {
878 PERROR("mkdir UST metadata");
879 goto error;
880 }
881
882 ret = snprintf(ua_sess->metadata->pathname, PATH_MAX, "%s/%s-%d/metadata",
883 pathname, app->name, app->key.pid);
884 if (ret < 0) {
885 PERROR("asprintf UST create stream");
886 goto error;
887 }
888
889 DBG2("UST metadata stream object created for app pid %d",
890 app->key.pid);
891 }
892
893 return 0;
894
895error:
896 return -1;
897}
898
899/*
900 * Add channel to all ust app session.
901 */
902int ust_app_add_channel_all(struct ltt_ust_session *usess,
48842b30
DG
903 struct ltt_ust_channel *uchan)
904{
905 int ret = 0;
906 struct cds_lfht_iter iter;
421cb601 907 struct cds_lfht_node *node;
48842b30
DG
908 struct ust_app *app;
909 struct ust_app_session *ua_sess;
910 struct ust_app_channel *ua_chan;
911
421cb601
DG
912 if (usess == NULL || uchan == NULL) {
913 ERR("Adding UST global channel to NULL values");
914 ret = -1;
915 goto error;
916 }
917
48842b30
DG
918 DBG2("UST app adding channel %s to global domain for session uid %d",
919 uchan->name, usess->uid);
920
921 rcu_read_lock();
421cb601
DG
922
923 /* For every UST applications registered */
48842b30
DG
924 hashtable_get_first(ust_app_ht, &iter);
925 while ((node = hashtable_iter_get_node(&iter)) != NULL) {
926 app = caa_container_of(node, struct ust_app, node);
927
421cb601
DG
928 /* Create session on the tracer side and add it to app session HT */
929 ua_sess = create_ust_app_session(usess, app);
509cbaf8 930 if (ua_sess == NULL) {
48842b30
DG
931 goto next;
932 }
933
421cb601
DG
934 /* Create channel onto application */
935 ua_chan = create_ust_app_channel(ua_sess, uchan, app);
936 if (ua_chan == NULL) {
48842b30
DG
937 goto next;
938 }
939
48842b30
DG
940next:
941 /* Next applications */
942 hashtable_get_next(ust_app_ht, &iter);
943 }
944 rcu_read_unlock();
945
421cb601 946error:
48842b30
DG
947 return ret;
948}
949
421cb601 950int ust_app_add_event_all(struct ltt_ust_session *usess,
48842b30
DG
951 struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent)
952{
953 int ret = 0;
954 struct cds_lfht_iter iter;
421cb601 955 struct cds_lfht_node *node, *ua_chan_node;
48842b30
DG
956 struct ust_app *app;
957 struct ust_app_session *ua_sess;
958 struct ust_app_channel *ua_chan;
959 struct ust_app_event *ua_event;
48842b30
DG
960
961 DBG2("UST app adding event %s to global domain for session uid %d",
962 uevent->attr.name, usess->uid);
963
964 rcu_read_lock();
421cb601
DG
965
966 /* For all registered applications */
48842b30
DG
967 hashtable_get_first(ust_app_ht, &iter);
968 while ((node = hashtable_iter_get_node(&iter)) != NULL) {
969 app = caa_container_of(node, struct ust_app, node);
970
421cb601
DG
971 /* Create session on the tracer side and add it to app session HT */
972 ua_sess = create_ust_app_session(usess, app);
509cbaf8 973 if (ua_sess == NULL) {
421cb601 974 goto next;
48842b30
DG
975 }
976
977 /* Lookup channel in the ust app session */
978 ua_chan_node = hashtable_lookup(ua_sess->channels,
421cb601 979 (void *)uchan->name, strlen(uchan->name), &iter);
48842b30 980 if (ua_chan_node == NULL) {
421cb601
DG
981 ERR("Channel %s not found in session uid %d. Skipping",
982 uchan->name, usess->uid);
48842b30
DG
983 goto next;
984 }
48842b30
DG
985 ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node);
986
421cb601
DG
987 ua_event = create_ust_app_event(ua_sess, ua_chan, uevent, app);
988 if (ua_event == NULL) {
989 goto next;
48842b30
DG
990 }
991
48842b30
DG
992next:
993 /* Next applications */
994 hashtable_get_next(ust_app_ht, &iter);
995 }
996 rcu_read_unlock();
997
998 return ret;
999}
1000
421cb601 1001int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *app)
48842b30
DG
1002{
1003 int ret = 0;
1004 struct cds_lfht_iter iter;
421cb601 1005 struct cds_lfht_node *node;
48842b30
DG
1006 struct ust_app_session *ua_sess;
1007 struct ust_app_channel *ua_chan;
48842b30 1008
421cb601 1009 DBG("Starting tracing for ust app pid %d", app->key.pid);
5cf5d0e7 1010
509cbaf8
MD
1011 rcu_read_lock();
1012
421cb601
DG
1013 ua_sess = lookup_session_by_app(usess, app);
1014 if (ua_sess == NULL) {
1015 /* Only malloc can failed so something is really wrong */
509cbaf8 1016 goto error_rcu_unlock;
421cb601 1017 }
48842b30 1018
421cb601
DG
1019 ret = create_ust_app_metadata(ua_sess, usess->pathname, app);
1020 if (ret < 0) {
509cbaf8 1021 goto error_rcu_unlock;
421cb601 1022 }
48842b30 1023
421cb601
DG
1024 /* For each channel */
1025 hashtable_get_first(ua_sess->channels, &iter);
1026 while ((node = hashtable_iter_get_node(&iter)) != NULL) {
1027 ua_chan = caa_container_of(node, struct ust_app_channel, node);
48842b30 1028
421cb601
DG
1029 /* Create all streams */
1030 while (1) {
1031 struct ltt_ust_stream *ustream;
48842b30 1032
421cb601
DG
1033 ustream = zmalloc(sizeof(*ustream));
1034 if (ustream == NULL) {
1035 PERROR("zmalloc ust stream");
509cbaf8 1036 goto error_rcu_unlock;
421cb601 1037 }
48842b30 1038
421cb601
DG
1039 ret = ustctl_create_stream(app->key.sock, ua_chan->obj,
1040 &ustream->obj);
48842b30 1041 if (ret < 0) {
421cb601
DG
1042 /* Got all streams */
1043 break;
48842b30 1044 }
421cb601 1045 ustream->handle = ustream->obj->handle;
48842b30 1046
421cb601
DG
1047 /* Order is important */
1048 cds_list_add_tail(&ustream->list, &ua_chan->streams.head);
1049 ret = snprintf(ustream->pathname, PATH_MAX, "%s/%s-%d/%s_%u",
1050 usess->pathname, app->name, app->key.pid,
1051 ua_chan->name, ua_chan->streams.count++);
aba8e916
DG
1052 if (ret < 0) {
1053 PERROR("asprintf UST create stream");
421cb601 1054 continue;
aba8e916 1055 }
421cb601
DG
1056 DBG2("UST stream %d ready at %s", ua_chan->streams.count,
1057 ustream->pathname);
1058 }
aba8e916 1059
421cb601
DG
1060 /* Next applications */
1061 hashtable_get_next(ua_sess->channels, &iter);
1062 }
aba8e916 1063
421cb601
DG
1064 /* Setup UST consumer socket and send fds to it */
1065 ret = ust_consumer_send_session(usess->consumer_fd, ua_sess);
1066 if (ret < 0) {
509cbaf8 1067 goto error_rcu_unlock;
421cb601 1068 }
48842b30 1069
421cb601
DG
1070 /* This start the UST tracing */
1071 ret = ustctl_start_session(app->key.sock, ua_sess->handle);
1072 if (ret < 0) {
1073 ERR("Error starting tracing for app pid: %d", app->key.pid);
509cbaf8 1074 goto error_rcu_unlock;
421cb601 1075 }
509cbaf8 1076 rcu_read_unlock();
48842b30 1077
421cb601
DG
1078 /* Quiescent wait after starting trace */
1079 ustctl_wait_quiescent(app->key.sock);
48842b30 1080
421cb601 1081 return 0;
48842b30 1082
509cbaf8
MD
1083error_rcu_unlock:
1084 rcu_read_unlock();
421cb601
DG
1085 return -1;
1086}
48842b30 1087
421cb601
DG
1088int ust_app_start_trace_all(struct ltt_ust_session *usess)
1089{
1090 int ret = 0;
1091 struct cds_lfht_iter iter;
1092 struct cds_lfht_node *node;
1093 struct ust_app *app;
48842b30 1094
421cb601
DG
1095 DBG("Starting all UST traces");
1096
1097 rcu_read_lock();
1098 hashtable_get_first(ust_app_ht, &iter);
1099 while ((node = hashtable_iter_get_node(&iter)) != NULL) {
1100 app = caa_container_of(node, struct ust_app, node);
1101
1102 ret = ust_app_start_trace(usess, app);
48842b30 1103 if (ret < 0) {
48842b30
DG
1104 goto next;
1105 }
1106
48842b30
DG
1107next:
1108 /* Next applications */
1109 hashtable_get_next(ust_app_ht, &iter);
1110 }
1111 rcu_read_unlock();
1112
1113 return 0;
1114}
487cf67c
DG
1115
1116void ust_app_global_update(struct ltt_ust_session *usess, int sock)
1117{
1118 int ret = 0;
487cf67c 1119 struct cds_lfht_iter iter;
421cb601 1120 struct cds_lfht_node *node;
487cf67c
DG
1121 struct ust_app *app;
1122 struct ust_app_session *ua_sess;
1123 struct ust_app_channel *ua_chan;
1124 struct ust_app_event *ua_event;
487cf67c 1125 struct ltt_ust_channel *uchan;
421cb601 1126 struct ltt_ust_event *uevent;
487cf67c 1127
1f3580c7
DG
1128 rcu_read_lock();
1129
1130 if (usess == NULL) {
1131 DBG2("No UST session on global update. Returning");
1132 goto error;
1133 }
1134
487cf67c
DG
1135 DBG2("UST app global update for app sock %d for session uid %d", sock,
1136 usess->uid);
1137
487cf67c
DG
1138 app = find_app_by_sock(sock);
1139 if (app == NULL) {
1140 ERR("Failed to update app sock %d", sock);
1141 goto error;
1142 }
1143
421cb601 1144 ua_sess = create_ust_app_session(usess, app);
487cf67c 1145 if (ua_sess == NULL) {
487cf67c
DG
1146 goto error;
1147 }
1148
487cf67c
DG
1149 hashtable_get_first(usess->domain_global.channels, &iter);
1150 while ((node = hashtable_iter_get_node(&iter)) != NULL) {
1151 uchan = caa_container_of(node, struct ltt_ust_channel, node);
1152
421cb601
DG
1153 ua_chan = create_ust_app_channel(ua_sess, uchan, app);
1154 if (ua_chan == NULL) {
487cf67c
DG
1155 goto next_chan;
1156 }
1157
421cb601 1158 hashtable_get_first(uchan->events, &iter);
487cf67c 1159 while ((node = hashtable_iter_get_node(&iter)) != NULL) {
421cb601 1160 uevent = caa_container_of(node, struct ltt_ust_event, node);
487cf67c 1161
421cb601
DG
1162 ua_event = create_ust_app_event(ua_sess, ua_chan, uevent, app);
1163 if (ua_event == NULL) {
487cf67c
DG
1164 goto next_event;
1165 }
1166
487cf67c 1167next_event:
421cb601 1168 hashtable_get_next(uchan->events, &iter);
36dc12cc
DG
1169 }
1170
487cf67c 1171next_chan:
421cb601
DG
1172 /* Next item in hash table */
1173 hashtable_get_next(usess->domain_global.channels, &iter);
487cf67c
DG
1174 }
1175
36dc12cc 1176 if (usess->start_trace) {
421cb601 1177 ret = ust_app_start_trace(usess, app);
36dc12cc 1178 if (ret < 0) {
36dc12cc
DG
1179 goto error;
1180 }
1181
36dc12cc
DG
1182 DBG2("UST trace started for app pid %d", app->key.pid);
1183 }
1184
487cf67c
DG
1185error:
1186 rcu_read_unlock();
1187 return;
1188}
This page took 0.132995 seconds and 4 git commands to generate.