Make connect error retry wait 5 seconds
[lttng-ust.git] / libust / lttng-ust-abi.c
CommitLineData
f4681817
MD
1/*
2 * lttng-ust-abi.c
3 *
4 * Copyright 2010-2011 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 *
6 * LTTng UST ABI
7 *
8 * Mimic system calls for:
9 * - session creation, returns an object descriptor or failure.
10 * - channel creation, returns an object descriptor or failure.
11 * - Operates on a session object descriptor
12 * - Takes all channel options as parameters.
13 * - stream get, returns an object descriptor or failure.
14 * - Operates on a channel object descriptor.
15 * - stream notifier get, returns an object descriptor or failure.
16 * - Operates on a channel object descriptor.
17 * - event creation, returns an object descriptor or failure.
18 * - Operates on a channel object descriptor
19 * - Takes an event name as parameter
20 * - Takes an instrumentation source as parameter
21 * - e.g. tracepoints, dynamic_probes...
22 * - Takes instrumentation source specific arguments.
23 *
24 * Dual LGPL v2.1/GPL v2 license.
25 */
26
27#include <ust/lttng-ust-abi.h>
28#include <urcu/compiler.h>
29#include <urcu/list.h>
30#include <ust/lttng-events.h>
1dbfff0c 31#include <ust/usterr-signal-safe.h>
f4681817
MD
32#include "ust/core.h"
33#include "ltt-tracer.h"
34
35/*
36 * Object descriptor table. Should be protected from concurrent access
37 * by the caller.
38 */
39
40struct obj;
41
42struct objd_ops {
43 long (*cmd)(int objd, unsigned int cmd, unsigned long arg);
44 int (*release)(int objd);
45};
46
47struct obj {
48 union {
49 struct {
50 void *private_data;
51 const struct objd_ops *ops;
52 int f_count;
53 } s;
54 int freelist_next; /* offset freelist. end is -1. */
55 } u;
56};
57
58struct objd_table {
59 struct obj *array;
60 unsigned int len, allocated_len;
61 int freelist_head; /* offset freelist head. end is -1 */
62};
63
64static struct objd_table objd_table = {
65 .freelist_head = -1,
66};
67
68static
69int objd_alloc(void *private_data, const struct objd_ops *ops)
70{
71 struct obj *obj;
72
73 if (objd_table.freelist_head != -1) {
74 obj = &objd_table.array[objd_table.freelist_head];
75 objd_table.freelist_head = obj->u.freelist_next;
76 goto end;
77 }
78
79 if (objd_table.len >= objd_table.allocated_len) {
80 unsigned int new_allocated_len, old_allocated_len;
81 struct obj *new_table, *old_table;
82
83 old_allocated_len = objd_table.allocated_len;
84 old_table = objd_table.array;
85 if (!old_allocated_len)
86 new_allocated_len = 1;
87 else
88 new_allocated_len = old_allocated_len << 1;
89 new_table = zmalloc(sizeof(struct obj) * new_allocated_len);
90 if (!new_table)
91 return -ENOMEM;
92 memcpy(new_table, old_table,
93 sizeof(struct obj) * old_allocated_len);
94 free(old_table);
95 objd_table.array = new_table;
96 objd_table.allocated_len = new_allocated_len;
97 }
98 obj = &objd_table.array[objd_table.len];
99 objd_table.len++;
100end:
101 obj->u.s.private_data = private_data;
102 obj->u.s.ops = ops;
103 obj->u.s.f_count = 1;
104 return obj - objd_table.array;
105}
106
107static
108struct obj *_objd_get(int id)
109{
110 if (id >= objd_table.len)
111 return NULL;
112 return &objd_table.array[id];
113}
114
115static
116void *objd_private(int id)
117{
118 struct obj *obj = _objd_get(id);
119 assert(obj);
120 return obj->u.s.private_data;
121}
122
123static
124void objd_set_private(int id, void *private_data)
125{
126 struct obj *obj = _objd_get(id);
127 assert(obj);
128 obj->u.s.private_data = private_data;
129}
130
131static
132const struct objd_ops *objd_ops(int id)
133{
134 struct obj *obj = _objd_get(id);
135 assert(obj);
136 return obj->u.s.ops;
137}
138
139static
140void objd_free(int id)
141{
142 struct obj *obj = _objd_get(id);
143
144 assert(obj);
145 obj->u.freelist_next = objd_table.freelist_head;
146 objd_table.freelist_head = obj - objd_table.array;
147}
148
149static
150void objd_ref(int id)
151{
152 struct obj *obj = _objd_get(id);
153 obj->u.s.f_count++;
154}
155
1ea11eab 156int objd_unref(int id)
f4681817
MD
157{
158 struct obj *obj = _objd_get(id);
159
1ea11eab
MD
160 if (!obj)
161 return -EINVAL;
f4681817
MD
162 if (!(--obj->u.s.f_count)) {
163 const struct objd_ops *ops = objd_ops(id);
164
165 if (ops->release)
166 ops->release(id);
167 objd_free(id);
168 }
1ea11eab 169 return 0;
f4681817
MD
170}
171
172static
173void objd_table_destroy(void)
174{
175 free(objd_table.array);
176}
177
178/*
179 * This is LTTng's own personal way to create an ABI for sessiond.
180 * We send commands over a socket.
181 */
182
183static const struct objd_ops lttng_ops;
184static const struct objd_ops lttng_session_ops;
185static const struct objd_ops lttng_channel_ops;
186static const struct objd_ops lttng_metadata_ops;
187static const struct objd_ops lttng_event_ops;
188
189enum channel_type {
190 PER_CPU_CHANNEL,
191 METADATA_CHANNEL,
192};
193
f4681817
MD
194int lttng_abi_create_session(void)
195{
196 struct ltt_session *session;
197 int session_objd, ret;
198
199 session = ltt_session_create();
200 if (!session)
201 return -ENOMEM;
202 session_objd = objd_alloc(session, &lttng_session_ops);
203 if (session_objd < 0) {
204 ret = session_objd;
205 goto objd_error;
206 }
207 session->objd = session_objd;
208 return session_objd;
209
210objd_error:
211 ltt_session_destroy(session);
212 return ret;
213}
214
215#if 0
216static
217int lttng_abi_tracepoint_list(void)
218{
219 int list_objd, ret;
220
221 /* TODO: Create list private data */
222 list_objd = objd_alloc(NULL, &lttng_tracepoint_list_ops);
223 if (list_objd < 0) {
224 ret = list_objd;
225 goto objd_error;
226 }
227
228 return list_objd;
229
230objd_error:
231 return ret;
232}
233#endif //0
234
235static
236long lttng_abi_tracer_version(int objd,
237 struct lttng_ust_tracer_version *v)
238{
239 v->version = LTTNG_UST_VERSION;
240 v->patchlevel = LTTNG_UST_PATCHLEVEL;
241 v->sublevel = LTTNG_UST_SUBLEVEL;
242 return 0;
243}
244
245static
246long lttng_abi_add_context(int objd,
247 struct lttng_ust_context *context_param,
248 struct lttng_ctx **ctx, struct ltt_session *session)
249{
250 if (session->been_active)
251 return -EPERM;
252
253 switch (context_param->ctx) {
254 case LTTNG_UST_CONTEXT_VTID:
438bc215 255 //TODO return lttng_add_vtid_to_ctx(ctx);
f4681817
MD
256 default:
257 return -EINVAL;
258 }
259}
260
261/**
262 * lttng_cmd - lttng control through socket commands
263 *
264 * @objd: the object descriptor
265 * @cmd: the command
266 * @arg: command arg
267 *
268 * This descriptor implements lttng commands:
269 * LTTNG_UST_SESSION
270 * Returns a LTTng trace session object descriptor
271 * LTTNG_UST_TRACER_VERSION
272 * Returns the LTTng kernel tracer version
273 * LTTNG_UST_TRACEPOINT_LIST
274 * Returns a file descriptor listing available tracepoints
275 * LTTNG_UST_WAIT_QUIESCENT
276 * Returns after all previously running probes have completed
277 *
278 * The returned session will be deleted when its file descriptor is closed.
279 */
280static
281long lttng_cmd(int objd, unsigned int cmd, unsigned long arg)
282{
283 switch (cmd) {
284 case LTTNG_UST_SESSION:
285 return lttng_abi_create_session();
286 case LTTNG_UST_TRACER_VERSION:
287 return lttng_abi_tracer_version(objd,
288 (struct lttng_ust_tracer_version *) arg);
289 case LTTNG_UST_TRACEPOINT_LIST:
290 return -ENOSYS; //TODO
291 //return lttng_abi_tracepoint_list();
292 case LTTNG_UST_WAIT_QUIESCENT:
293 synchronize_trace();
294 return 0;
295 default:
296 return -EINVAL;
297 }
298}
299
300static const struct objd_ops lttng_ops = {
301 .cmd = lttng_cmd,
302};
303
304/*
305 * We tolerate no failure in this function (if one happens, we print a dmesg
306 * error, but cannot return any error, because the channel information is
307 * invariant.
308 */
309static
310void lttng_metadata_create_events(int channel_objd)
311{
312 struct ltt_channel *channel = objd_private(channel_objd);
313 static struct lttng_ust_event metadata_params = {
314 .instrumentation = LTTNG_UST_TRACEPOINT,
315 .name = "lttng_metadata",
316 };
317 struct ltt_event *event;
318 int ret;
319
320 /*
321 * We tolerate no failure path after event creation. It will stay
322 * invariant for the rest of the session.
323 */
324 event = ltt_event_create(channel, &metadata_params, NULL);
325 if (!event) {
326 ret = -EINVAL;
327 goto create_error;
328 }
329 return;
330
331create_error:
332 WARN_ON(1);
333 return; /* not allowed to return error */
334}
335
336static
337int lttng_abi_create_channel(int session_objd,
338 struct lttng_ust_channel *chan_param,
339 enum channel_type channel_type)
340{
341 struct ltt_session *session = objd_private(session_objd);
342 const struct objd_ops *ops;
343 const char *transport_name;
344 struct ltt_channel *chan;
345 int chan_objd;
346 int ret = 0;
347
348 chan_objd = objd_alloc(NULL, &lttng_channel_ops);
349 if (chan_objd < 0) {
350 ret = chan_objd;
351 goto objd_error;
352 }
353 switch (channel_type) {
354 case PER_CPU_CHANNEL:
355 if (chan_param->output == LTTNG_UST_MMAP) {
356 transport_name = chan_param->overwrite ?
357 "relay-overwrite-mmap" : "relay-discard-mmap";
358 } else {
359 return -EINVAL;
360 }
361 ops = &lttng_channel_ops;
362 break;
363 case METADATA_CHANNEL:
364 if (chan_param->output == LTTNG_UST_MMAP)
365 transport_name = "relay-metadata-mmap";
366 else
367 return -EINVAL;
368 ops = &lttng_metadata_ops;
369 break;
370 default:
371 transport_name = "<unknown>";
372 break;
373 }
374 /*
375 * We tolerate no failure path after channel creation. It will stay
376 * invariant for the rest of the session.
377 */
378 chan = ltt_channel_create(session, transport_name, NULL,
379 chan_param->subbuf_size,
380 chan_param->num_subbuf,
381 chan_param->switch_timer_interval,
382 chan_param->read_timer_interval);
383 if (!chan) {
384 ret = -EINVAL;
385 goto chan_error;
386 }
387 objd_set_private(chan_objd, chan);
388 chan->objd = chan_objd;
389 if (channel_type == METADATA_CHANNEL) {
390 session->metadata = chan;
391 lttng_metadata_create_events(chan_objd);
392 }
393
394 /* The channel created holds a reference on the session */
395 objd_ref(session_objd);
396
397 return chan_objd;
398
399chan_error:
1ea11eab
MD
400 {
401 int err;
402
403 err = objd_unref(chan_objd);
404 assert(!err);
405 }
f4681817
MD
406objd_error:
407 return ret;
408}
409
410/**
411 * lttng_session_cmd - lttng session object command
412 *
413 * @obj: the object
414 * @cmd: the command
415 * @arg: command arg
416 *
417 * This descriptor implements lttng commands:
418 * LTTNG_UST_CHANNEL
419 * Returns a LTTng channel object descriptor
420 * LTTNG_UST_ENABLE
421 * Enables tracing for a session (weak enable)
422 * LTTNG_UST_DISABLE
423 * Disables tracing for a session (strong disable)
424 * LTTNG_UST_METADATA
425 * Returns a LTTng metadata object descriptor
426 *
427 * The returned channel will be deleted when its file descriptor is closed.
428 */
429static
430long lttng_session_cmd(int objd, unsigned int cmd, unsigned long arg)
431{
432 struct ltt_session *session = objd_private(objd);
433
434 switch (cmd) {
435 case LTTNG_UST_CHANNEL:
436 return lttng_abi_create_channel(objd,
437 (struct lttng_ust_channel *) arg,
438 PER_CPU_CHANNEL);
439 case LTTNG_UST_SESSION_START:
440 case LTTNG_UST_ENABLE:
441 return ltt_session_enable(session);
442 case LTTNG_UST_SESSION_STOP:
443 case LTTNG_UST_DISABLE:
444 return ltt_session_disable(session);
445 case LTTNG_UST_METADATA:
446 return lttng_abi_create_channel(objd,
447 (struct lttng_ust_channel *) arg,
448 METADATA_CHANNEL);
449 default:
450 return -EINVAL;
451 }
452}
453
454/*
455 * Called when the last file reference is dropped.
456 *
457 * Big fat note: channels and events are invariant for the whole session after
458 * their creation. So this session destruction also destroys all channel and
459 * event structures specific to this session (they are not destroyed when their
460 * individual file is released).
461 */
462static
1ea11eab 463int lttng_release_session(int objd)
f4681817
MD
464{
465 struct ltt_session *session = objd_private(objd);
466
1ea11eab 467 if (session) {
f4681817 468 ltt_session_destroy(session);
1ea11eab
MD
469 return 0;
470 } else {
471 return -EINVAL;
472 }
f4681817
MD
473}
474
475static const struct objd_ops lttng_session_ops = {
1ea11eab 476 .release = lttng_release_session,
f4681817
MD
477 .cmd = lttng_session_cmd,
478};
479
480#if 0
481static
482int lttng_abi_open_stream(int channel_objd)
483{
484 struct ltt_channel *channel = objd_private(channel_objd);
485 struct lib_ring_buffer *buf;
486 int stream_objd, ret;
487
488 buf = channel->ops->buffer_read_open(channel->chan);
489 if (!buf)
490 return -ENOENT;
491
492 stream_objd = objd_alloc(buf, &lib_ring_buffer_objd_ops);
493 if (stream_objd < 0) {
494 ret = stream_objd;
495 goto objd_error;
496 }
497 /*
498 * The stream holds a reference to the channel within the generic ring
499 * buffer library, so no need to hold a refcount on the channel and
500 * session files here.
501 */
502 return stream_objd;
503
504objd_error:
505 channel->ops->buffer_read_close(buf);
506 return ret;
507}
508#endif //0
509
510static
511int lttng_abi_create_event(int channel_objd,
512 struct lttng_ust_event *event_param)
513{
514 struct ltt_channel *channel = objd_private(channel_objd);
515 struct ltt_event *event;
516 int event_objd, ret;
517
518 event_param->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
519 event_objd = objd_alloc(NULL, &lttng_event_ops);
520 if (event_objd < 0) {
521 ret = event_objd;
522 goto objd_error;
523 }
524 /*
525 * We tolerate no failure path after event creation. It will stay
526 * invariant for the rest of the session.
527 */
528 event = ltt_event_create(channel, event_param, NULL);
529 if (!event) {
530 ret = -EINVAL;
531 goto event_error;
532 }
533 objd_set_private(event_objd, event);
534 /* The event holds a reference on the channel */
535 objd_ref(channel_objd);
536 return event_objd;
537
538event_error:
1ea11eab
MD
539 {
540 int err;
541
542 err = objd_unref(event_objd);
543 assert(!err);
544 }
f4681817
MD
545objd_error:
546 return ret;
547}
548
549/**
550 * lttng_channel_cmd - lttng control through object descriptors
551 *
552 * @objd: the object descriptor
553 * @cmd: the command
554 * @arg: command arg
555 *
556 * This object descriptor implements lttng commands:
557 * LTTNG_UST_STREAM
558 * Returns an event stream object descriptor or failure.
559 * (typically, one event stream records events from one CPU)
560 * LTTNG_UST_EVENT
561 * Returns an event object descriptor or failure.
562 * LTTNG_UST_CONTEXT
563 * Prepend a context field to each event in the channel
564 * LTTNG_UST_ENABLE
565 * Enable recording for events in this channel (weak enable)
566 * LTTNG_UST_DISABLE
567 * Disable recording for events in this channel (strong disable)
568 *
569 * Channel and event file descriptors also hold a reference on the session.
570 */
571static
572long lttng_channel_cmd(int objd, unsigned int cmd, unsigned long arg)
573{
574 struct ltt_channel *channel = objd_private(objd);
575
576 switch (cmd) {
577 case LTTNG_UST_STREAM:
578 return -ENOSYS; //TODO
579 //return lttng_abi_open_stream(objd);
580 case LTTNG_UST_EVENT:
581 return lttng_abi_create_event(objd, (struct lttng_ust_event *) arg);
582 case LTTNG_UST_CONTEXT:
583 return lttng_abi_add_context(objd,
584 (struct lttng_ust_context *) arg,
585 &channel->ctx, channel->session);
586 case LTTNG_UST_ENABLE:
587 return ltt_channel_enable(channel);
588 case LTTNG_UST_DISABLE:
589 return ltt_channel_disable(channel);
590 default:
591 return -EINVAL;
592 }
593}
594
595/**
596 * lttng_metadata_cmd - lttng control through object descriptors
597 *
598 * @objd: the object descriptor
599 * @cmd: the command
600 * @arg: command arg
601 *
602 * This object descriptor implements lttng commands:
603 * LTTNG_UST_STREAM
604 * Returns an event stream file descriptor or failure.
605 *
606 * Channel and event file descriptors also hold a reference on the session.
607 */
608static
609long lttng_metadata_cmd(int objd, unsigned int cmd, unsigned long arg)
610{
611 switch (cmd) {
612 case LTTNG_UST_STREAM:
613 return -ENOSYS; //TODO
614 //return lttng_abi_open_stream(objd);
615 default:
616 return -EINVAL;
617 }
618}
619
620#if 0
621/**
622 * lttng_channel_poll - lttng stream addition/removal monitoring
623 *
624 * @file: the file
625 * @wait: poll table
626 */
627unsigned int lttng_channel_poll(struct file *file, poll_table *wait)
628{
629 struct ltt_channel *channel = file->private_data;
630 unsigned int mask = 0;
631
632 if (file->f_mode & FMODE_READ) {
633 poll_wait_set_exclusive(wait);
634 poll_wait(file, channel->ops->get_hp_wait_queue(channel->chan),
635 wait);
636
637 if (channel->ops->is_disabled(channel->chan))
638 return POLLERR;
639 if (channel->ops->is_finalized(channel->chan))
640 return POLLHUP;
641 if (channel->ops->buffer_has_read_closed_stream(channel->chan))
642 return POLLIN | POLLRDNORM;
643 return 0;
644 }
645 return mask;
646
647}
648#endif //0
649
650static
651int lttng_channel_release(int objd)
652{
653 struct ltt_channel *channel = objd_private(objd);
654
655 if (channel)
1ea11eab 656 return objd_unref(channel->session->objd);
f4681817
MD
657 return 0;
658}
659
660static const struct objd_ops lttng_channel_ops = {
661 .release = lttng_channel_release,
662 //.poll = lttng_channel_poll,
663 .cmd = lttng_channel_cmd,
664};
665
666static const struct objd_ops lttng_metadata_ops = {
667 .release = lttng_channel_release,
668 .cmd = lttng_metadata_cmd,
669};
670
671/**
672 * lttng_event_cmd - lttng control through object descriptors
673 *
674 * @objd: the object descriptor
675 * @cmd: the command
676 * @arg: command arg
677 *
678 * This object descriptor implements lttng commands:
679 * LTTNG_UST_CONTEXT
680 * Prepend a context field to each record of this event
681 * LTTNG_UST_ENABLE
682 * Enable recording for this event (weak enable)
683 * LTTNG_UST_DISABLE
684 * Disable recording for this event (strong disable)
685 */
686static
687long lttng_event_cmd(int objd, unsigned int cmd, unsigned long arg)
688{
689 struct ltt_event *event = objd_private(objd);
690
691 switch (cmd) {
692 case LTTNG_UST_CONTEXT:
693 return lttng_abi_add_context(objd,
694 (struct lttng_ust_context *) arg,
695 &event->ctx, event->chan->session);
696 case LTTNG_UST_ENABLE:
697 return ltt_event_enable(event);
698 case LTTNG_UST_DISABLE:
699 return ltt_event_disable(event);
700 default:
701 return -EINVAL;
702 }
703}
704
705static
706int lttng_event_release(int objd)
707{
708 struct ltt_event *event = objd_private(objd);
709
710 if (event)
1ea11eab 711 return objd_unref(event->chan->objd);
f4681817
MD
712 return 0;
713}
714
715/* TODO: filter control ioctl */
716static const struct objd_ops lttng_event_ops = {
717 .release = lttng_event_release,
718 .cmd = lttng_event_cmd,
719};
720
b35d179d 721void lttng_ust_abi_exit(void)
f4681817 722{
f4681817
MD
723 objd_table_destroy();
724}
This page took 0.048884 seconds and 4 git commands to generate.