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