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