Make connect error retry wait 5 seconds
[lttng-ust.git] / libust / lttng-ust-abi.c
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>
31 #include <ust/usterr-signal-safe.h>
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
40 struct obj;
41
42 struct objd_ops {
43 long (*cmd)(int objd, unsigned int cmd, unsigned long arg);
44 int (*release)(int objd);
45 };
46
47 struct 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
58 struct objd_table {
59 struct obj *array;
60 unsigned int len, allocated_len;
61 int freelist_head; /* offset freelist head. end is -1 */
62 };
63
64 static struct objd_table objd_table = {
65 .freelist_head = -1,
66 };
67
68 static
69 int 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++;
100 end:
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
107 static
108 struct obj *_objd_get(int id)
109 {
110 if (id >= objd_table.len)
111 return NULL;
112 return &objd_table.array[id];
113 }
114
115 static
116 void *objd_private(int id)
117 {
118 struct obj *obj = _objd_get(id);
119 assert(obj);
120 return obj->u.s.private_data;
121 }
122
123 static
124 void 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
131 static
132 const 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
139 static
140 void 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
149 static
150 void objd_ref(int id)
151 {
152 struct obj *obj = _objd_get(id);
153 obj->u.s.f_count++;
154 }
155
156 int objd_unref(int id)
157 {
158 struct obj *obj = _objd_get(id);
159
160 if (!obj)
161 return -EINVAL;
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 }
169 return 0;
170 }
171
172 static
173 void 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
183 static const struct objd_ops lttng_ops;
184 static const struct objd_ops lttng_session_ops;
185 static const struct objd_ops lttng_channel_ops;
186 static const struct objd_ops lttng_metadata_ops;
187 static const struct objd_ops lttng_event_ops;
188
189 enum channel_type {
190 PER_CPU_CHANNEL,
191 METADATA_CHANNEL,
192 };
193
194 int 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
210 objd_error:
211 ltt_session_destroy(session);
212 return ret;
213 }
214
215 #if 0
216 static
217 int 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
230 objd_error:
231 return ret;
232 }
233 #endif //0
234
235 static
236 long 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
245 static
246 long 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:
255 //TODO return lttng_add_vtid_to_ctx(ctx);
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 */
280 static
281 long 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
300 static 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 */
309 static
310 void 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
331 create_error:
332 WARN_ON(1);
333 return; /* not allowed to return error */
334 }
335
336 static
337 int 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
399 chan_error:
400 {
401 int err;
402
403 err = objd_unref(chan_objd);
404 assert(!err);
405 }
406 objd_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 */
429 static
430 long 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 */
462 static
463 int lttng_release_session(int objd)
464 {
465 struct ltt_session *session = objd_private(objd);
466
467 if (session) {
468 ltt_session_destroy(session);
469 return 0;
470 } else {
471 return -EINVAL;
472 }
473 }
474
475 static const struct objd_ops lttng_session_ops = {
476 .release = lttng_release_session,
477 .cmd = lttng_session_cmd,
478 };
479
480 #if 0
481 static
482 int 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
504 objd_error:
505 channel->ops->buffer_read_close(buf);
506 return ret;
507 }
508 #endif //0
509
510 static
511 int 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
538 event_error:
539 {
540 int err;
541
542 err = objd_unref(event_objd);
543 assert(!err);
544 }
545 objd_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 */
571 static
572 long 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 */
608 static
609 long 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 */
627 unsigned 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
650 static
651 int lttng_channel_release(int objd)
652 {
653 struct ltt_channel *channel = objd_private(objd);
654
655 if (channel)
656 return objd_unref(channel->session->objd);
657 return 0;
658 }
659
660 static const struct objd_ops lttng_channel_ops = {
661 .release = lttng_channel_release,
662 //.poll = lttng_channel_poll,
663 .cmd = lttng_channel_cmd,
664 };
665
666 static 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 */
686 static
687 long 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
705 static
706 int lttng_event_release(int objd)
707 {
708 struct ltt_event *event = objd_private(objd);
709
710 if (event)
711 return objd_unref(event->chan->objd);
712 return 0;
713 }
714
715 /* TODO: filter control ioctl */
716 static const struct objd_ops lttng_event_ops = {
717 .release = lttng_event_release,
718 .cmd = lttng_event_cmd,
719 };
720
721 void lttng_ust_abi_exit(void)
722 {
723 objd_table_destroy();
724 }
This page took 0.04418 seconds and 5 git commands to generate.