Install UST comm lib
[lttng-ust.git] / libustctl / ustctl.c
CommitLineData
57773204
MD
1/*
2 * Copyright (C) 2011 - Julien Desfossez <julien.desfossez@polymtl.ca>
3 * Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; only version 2
8 * of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20#include <string.h>
21#include <ust/lttng-ust-ctl.h>
22#include <ust/lttng-ust-abi.h>
23#include <ust/usterr-signal-safe.h>
e41474be 24#include <ust/lttng-ust-comm.h>
57773204
MD
25
26#include "../libringbuffer/backend.h"
27#include "../libringbuffer/frontend.h"
28
6b120308
MD
29volatile enum ust_loglevel ust_loglevel;
30
57773204
MD
31static
32void init_object(struct object_data *data)
33{
34 data->handle = -1;
35 data->shm_fd = -1;
36 data->wait_fd = -1;
37 data->memory_map_size = 0;
38}
39
40void release_object(int sock, struct object_data *data)
41{
42 struct ustcomm_ust_msg lum;
43 struct ustcomm_ust_reply lur;
44 int ret;
45
46 if (data->shm_fd >= 0)
47 close(data->shm_fd);
48 if (data->wait_fd >= 0)
49 close(data->wait_fd);
50 memset(&lum, 0, sizeof(lum));
51 lum.handle = data->handle;
52 lum.cmd = LTTNG_UST_RELEASE;
53 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
54 assert(!ret);
55 free(data);
56}
57
58/*
59 * returns session handle.
60 */
61int ustctl_create_session(int sock)
62{
63 struct ustcomm_ust_msg lum;
64 struct ustcomm_ust_reply lur;
65 int ret, session_handle;
66
67 /* Create session */
68 memset(&lum, 0, sizeof(lum));
69 lum.handle = LTTNG_UST_ROOT_HANDLE;
70 lum.cmd = LTTNG_UST_SESSION;
71 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
72 if (ret)
73 return ret;
74 session_handle = lur.ret_val;
75 DBG("received session handle %u", session_handle);
76 return session_handle;
77}
78
79/* open the metadata global channel */
80int ustctl_open_metadata(int sock, int session_handle,
81 struct lttng_ust_channel_attr *chops,
82 struct object_data **_metadata_data)
83{
84 struct ustcomm_ust_msg lum;
85 struct ustcomm_ust_reply lur;
86 struct object_data *metadata_data;
87 int ret;
88
89 metadata_data = malloc(sizeof(*metadata_data));
90 if (!metadata_data)
91 return -ENOMEM;
92 init_object(metadata_data);
93 /* Create metadata channel */
94 memset(&lum, 0, sizeof(lum));
95 lum.handle = session_handle;
96 lum.cmd = LTTNG_UST_METADATA;
97 lum.u.channel.overwrite = chops->overwrite;
98 lum.u.channel.subbuf_size = chops->subbuf_size;
99 lum.u.channel.num_subbuf = chops->num_subbuf;
100 lum.u.channel.switch_timer_interval = chops->switch_timer_interval;
101 lum.u.channel.read_timer_interval = chops->read_timer_interval;
102 lum.u.channel.output = chops->output;
103 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
104 if (ret) {
105 free(metadata_data);
106 return ret;
107 }
108 if (lur.ret_code != USTCOMM_OK) {
109 free(metadata_data);
110 return lur.ret_code;
111 }
112 metadata_data->handle = lur.ret_val;
113 DBG("received metadata handle %u", metadata_data->handle);
114 metadata_data->memory_map_size = lur.u.channel.memory_map_size;
115 /* get shm fd */
116 ret = ustcomm_recv_fd(sock);
117 if (ret < 0)
118 goto error;
119 metadata_data->shm_fd = ret;
120 /* get wait fd */
121 ret = ustcomm_recv_fd(sock);
122 if (ret < 0)
123 goto error;
124 metadata_data->wait_fd = ret;
125 *_metadata_data = metadata_data;
126 return 0;
127
128error:
129 release_object(sock, metadata_data);
130 return -EINVAL;
131}
132
133int ustctl_create_channel(int sock, int session_handle,
134 struct lttng_ust_channel_attr *chops,
135 struct object_data **_channel_data)
136{
137 struct ustcomm_ust_msg lum;
138 struct ustcomm_ust_reply lur;
139 struct object_data *channel_data;
140 int ret;
141
142 channel_data = malloc(sizeof(*channel_data));
143 if (!channel_data)
144 return -ENOMEM;
145 init_object(channel_data);
146 /* Create metadata channel */
147 memset(&lum, 0, sizeof(lum));
148 lum.handle = session_handle;
149 lum.cmd = LTTNG_UST_CHANNEL;
150 lum.u.channel.overwrite = chops->overwrite;
151 lum.u.channel.subbuf_size = chops->subbuf_size;
152 lum.u.channel.num_subbuf = chops->num_subbuf;
153 lum.u.channel.switch_timer_interval = chops->switch_timer_interval;
154 lum.u.channel.read_timer_interval = chops->read_timer_interval;
155 lum.u.channel.output = chops->output;
156 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
157 if (ret) {
158 free(channel_data);
159 return ret;
160 }
161 if (lur.ret_code != USTCOMM_OK) {
162 free(channel_data);
163 return lur.ret_code;
164 }
165 channel_data->handle = lur.ret_val;
166 DBG("received channel handle %u", channel_data->handle);
167 channel_data->memory_map_size = lur.u.channel.memory_map_size;
168 /* get shm fd */
169 ret = ustcomm_recv_fd(sock);
170 if (ret < 0)
171 goto error;
172 channel_data->shm_fd = ret;
173 /* get wait fd */
174 ret = ustcomm_recv_fd(sock);
175 if (ret < 0)
176 goto error;
177 channel_data->wait_fd = ret;
178 *_channel_data = channel_data;
179 return 0;
180
181error:
182 release_object(sock, channel_data);
183 return -EINVAL;
184}
185
186/*
187 * Return -ENOENT if no more stream is available for creation.
188 * Return 0 on success.
189 * Return negative error value on error.
190 */
191int ustctl_create_stream(int sock, struct object_data *channel_data,
192 struct object_data **_stream_data)
193{
194 struct ustcomm_ust_msg lum;
195 struct ustcomm_ust_reply lur;
196 struct object_data *stream_data;
197 int ret, fd;
198
199 stream_data = malloc(sizeof(*stream_data));
200 if (!stream_data)
201 return -ENOMEM;
202 init_object(stream_data);
203 memset(&lum, 0, sizeof(lum));
204 lum.handle = channel_data->handle;
205 lum.cmd = LTTNG_UST_STREAM;
206 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
207 if (ret) {
208 free(stream_data);
209 return ret;
210 }
211 if (lur.ret_code != USTCOMM_OK) {
212 free(stream_data);
213 return lur.ret_code;
214 }
215
216 stream_data->handle = lur.ret_val;
217 DBG("received stream handle %u", stream_data->handle);
218 stream_data->memory_map_size = lur.u.stream.memory_map_size;
219 /* get shm fd */
220 fd = ustcomm_recv_fd(sock);
221 if (fd < 0)
222 goto error;
223 stream_data->shm_fd = fd;
224 /* get wait fd */
225 fd = ustcomm_recv_fd(sock);
226 if (fd < 0)
227 goto error;
228 stream_data->wait_fd = fd;
229 *_stream_data = stream_data;
230 return ret;
231
232error:
233 release_object(sock, stream_data);
234 return -EINVAL;
235}
236
237int ustctl_create_event(int sock, struct lttng_ust_event *ev,
238 struct object_data *channel_data,
239 struct object_data **_event_data)
240{
241 struct ustcomm_ust_msg lum;
242 struct ustcomm_ust_reply lur;
243 struct object_data *event_data;
244 int ret;
245
246 event_data = malloc(sizeof(*event_data));
247 if (!event_data)
248 return -ENOMEM;
249 init_object(event_data);
250 memset(&lum, 0, sizeof(lum));
251 lum.handle = channel_data->handle;
252 lum.cmd = LTTNG_UST_EVENT;
253 strncpy(lum.u.event.name, ev->name,
254 LTTNG_UST_SYM_NAME_LEN);
255 lum.u.event.instrumentation = ev->instrumentation;
256 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
257 if (ret) {
258 free(event_data);
259 return ret;
260 }
261 event_data->handle = lur.ret_val;
262 DBG("received event handle %u", event_data->handle);
263 *_event_data = event_data;
264 return 0;
265}
266
267int ustctl_add_context(int sock, struct lttng_ust_context *ctx,
268 struct object_data *channel_data,
269 struct object_data **_context_data)
270{
271 struct ustcomm_ust_msg lum;
272 struct ustcomm_ust_reply lur;
273 struct object_data *context_data;
274 int ret;
275
276 context_data = malloc(sizeof(*context_data));
277 if (!context_data)
278 return -ENOMEM;
279 init_object(context_data);
280 memset(&lum, 0, sizeof(lum));
281 lum.handle = channel_data->handle;
282 lum.cmd = LTTNG_UST_CONTEXT;
283 lum.u.context.ctx = ctx->ctx;
284 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
285 if (ret) {
286 free(context_data);
287 return ret;
288 }
289 context_data->handle = lur.ret_val;
290 DBG("received context handle %u", context_data->handle);
291 *_context_data = context_data;
292 return ret;
293}
294
295/* Enable event, channel and session ioctl */
296int ustctl_enable(int sock, struct object_data *object)
297{
298 struct ustcomm_ust_msg lum;
299 struct ustcomm_ust_reply lur;
300 int ret;
301
302 memset(&lum, 0, sizeof(lum));
303 lum.handle = object->handle;
304 lum.cmd = LTTNG_UST_ENABLE;
305 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
306 if (ret)
307 return ret;
308 DBG("enabled handle %u", object->handle);
309 return 0;
310}
311
312/* Disable event, channel and session ioctl */
313int ustctl_disable(int sock, struct object_data *object)
314{
315 struct ustcomm_ust_msg lum;
316 struct ustcomm_ust_reply lur;
317 int ret;
318
319 memset(&lum, 0, sizeof(lum));
320 lum.handle = object->handle;
321 lum.cmd = LTTNG_UST_DISABLE;
322 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
323 if (ret)
324 return ret;
325 DBG("disable handle %u", object->handle);
326 return 0;
327}
328
329int ustctl_start_session(int sock, struct object_data *object)
330{
331 return ustctl_enable(sock, object);
332}
333
334int ustctl_stop_session(int sock, struct object_data *object)
335{
336 return ustctl_disable(sock, object);
337}
338
339
340int ustctl_tracepoint_list(int sock)
341{
342 return -ENOSYS; /* not implemented */
343}
344
345int ustctl_tracer_version(int sock, struct lttng_ust_tracer_version *v)
346{
347 struct ustcomm_ust_msg lum;
348 struct ustcomm_ust_reply lur;
349 int ret;
350
351 memset(&lum, 0, sizeof(lum));
352 lum.handle = LTTNG_UST_ROOT_HANDLE;
353 lum.cmd = LTTNG_UST_TRACER_VERSION;
354 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
355 if (ret)
356 return ret;
357 memcpy(v, &lur.u.version, sizeof(*v));
358 DBG("received tracer version");
359 return 0;
360}
361
362int ustctl_wait_quiescent(int sock)
363{
364 struct ustcomm_ust_msg lum;
365 struct ustcomm_ust_reply lur;
366 int ret;
367
368 memset(&lum, 0, sizeof(lum));
369 lum.handle = LTTNG_UST_ROOT_HANDLE;
370 lum.cmd = LTTNG_UST_WAIT_QUIESCENT;
371 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
372 if (ret)
373 return ret;
374 DBG("waited for quiescent state");
375 return 0;
376}
377
378int ustctl_calibrate(int sock, struct lttng_ust_calibrate *calibrate)
379{
380 return -ENOSYS;
381}
382
383/* Buffer operations */
384
385/* Map channel shm into process memory */
386struct shm_handle *ustctl_map_channel(struct object_data *chan_data)
387{
388 struct shm_handle *handle;
389 struct channel *chan;
390 size_t chan_size;
391
392 handle = channel_handle_create(chan_data->shm_fd,
393 chan_data->wait_fd,
394 chan_data->memory_map_size);
395 if (!handle) {
396 ERR("create handle error");
397 return NULL;
398 }
399 /*
400 * Set to -1 because the shm_handle destruction will take care
401 * of closing shm_fd and wait_fd.
402 */
403 chan_data->shm_fd = -1;
404 chan_data->wait_fd = -1;
405
406 /*
407 * TODO: add consistency checks to be resilient if the
408 * application try to feed us with incoherent channel structure
409 * values.
410 */
411 chan = shmp(handle, handle->chan);
412 /* chan is object 0. This is hardcoded. */
413 chan_size = handle->table->objects[0].allocated_len;
414 handle->shadow_chan = malloc(chan_size);
415 if (!handle->shadow_chan) {
416 channel_destroy(chan, handle, 1);
417 return NULL;
418 }
419 memcpy(handle->shadow_chan, chan, chan_size);
420 return handle;
421}
422
423/* Add stream to channel shm and map its shm into process memory */
424int ustctl_add_stream(struct shm_handle *handle,
425 struct object_data *stream_data)
426{
427 int ret;
428
429 if (!stream_data->handle)
430 return -ENOENT;
431 /* map stream */
432 ret = channel_handle_add_stream(handle,
433 stream_data->shm_fd,
434 stream_data->wait_fd,
435 stream_data->memory_map_size);
436 if (ret) {
437 ERR("add stream error\n");
438 return ret;
439 }
440 /*
441 * Set to -1 because the shm_handle destruction will take care
442 * of closing shm_fd and wait_fd.
443 */
444 stream_data->shm_fd = -1;
445 stream_data->wait_fd = -1;
446 return 0;
447}
448
5224b5c8
MD
449void ustctl_unmap_channel(struct shm_handle *handle)
450{
451 struct channel *chan;
452
453 chan = shmp(handle, handle->chan);
454 channel_destroy(chan, handle, 1);
455}
456
6e922b24
MD
457struct lib_ring_buffer *ustctl_open_stream_read(struct shm_handle *handle,
458 int cpu)
459{
460 struct channel *chan = handle->shadow_chan;
461 int shm_fd, wait_fd;
462 uint64_t memory_map_size;
463 struct lib_ring_buffer *buf;
464 int ret;
465
466 buf = channel_get_ring_buffer(&chan->backend.config,
467 chan, cpu, handle, &shm_fd, &wait_fd, &memory_map_size);
468 if (!buf)
469 return NULL;
470 ret = lib_ring_buffer_open_read(buf, handle, 1);
471 if (ret)
472 return NULL;
473 return buf;
474}
475
476void ustctl_close_stream_read(struct shm_handle *handle,
477 struct lib_ring_buffer *buf)
478{
479 lib_ring_buffer_release_read(buf, handle, 1);
480}
481
57773204
MD
482/* For mmap mode, readable without "get" operation */
483
9095efe9
MD
484void *ustctl_get_mmap_base(struct shm_handle *handle,
485 struct lib_ring_buffer *buf)
486{
487 return shmp(handle, buf->backend.memory_map);
488}
489
57773204
MD
490/* returns the length to mmap. */
491int ustctl_get_mmap_len(struct shm_handle *handle,
492 struct lib_ring_buffer *buf,
493 unsigned long *len)
494{
495 unsigned long mmap_buf_len;
496 struct channel *chan = handle->shadow_chan;
497
498 if (chan->backend.config.output != RING_BUFFER_MMAP)
499 return -EINVAL;
500 mmap_buf_len = chan->backend.buf_size;
501 if (chan->backend.extra_reader_sb)
502 mmap_buf_len += chan->backend.subbuf_size;
503 if (mmap_buf_len > INT_MAX)
504 return -EFBIG;
505 *len = mmap_buf_len;
506 return 0;
507}
508
509/* returns the maximum size for sub-buffers. */
510int ustctl_get_max_subbuf_size(struct shm_handle *handle,
511 struct lib_ring_buffer *buf,
512 unsigned long *len)
513{
514 struct channel *chan = handle->shadow_chan;
515
516 *len = chan->backend.subbuf_size;
517 return 0;
518}
519
520/*
521 * For mmap mode, operate on the current packet (between get/put or
522 * get_next/put_next).
523 */
524
525/* returns the offset of the subbuffer belonging to the mmap reader. */
526int ustctl_get_mmap_read_offset(struct shm_handle *handle,
527 struct lib_ring_buffer *buf, unsigned long *off)
528{
529 struct channel *chan = handle->shadow_chan;
530 unsigned long sb_bindex;
531
532 if (chan->backend.config.output != RING_BUFFER_MMAP)
533 return -EINVAL;
534 sb_bindex = subbuffer_id_get_index(&chan->backend.config,
535 buf->backend.buf_rsb.id);
536 *off = shmp(handle, shmp_index(handle, buf->backend.array, sb_bindex)->shmp)->mmap_offset;
537 return 0;
538}
539
540/* returns the size of the current sub-buffer, without padding (for mmap). */
541int ustctl_get_subbuf_size(struct shm_handle *handle,
542 struct lib_ring_buffer *buf, unsigned long *len)
543{
544 struct channel *chan = handle->shadow_chan;
545
546 *len = lib_ring_buffer_get_read_data_size(&chan->backend.config, buf,
547 handle);
548 return 0;
549}
550
551/* returns the size of the current sub-buffer, without padding (for mmap). */
552int ustctl_get_padded_subbuf_size(struct shm_handle *handle,
553 struct lib_ring_buffer *buf, unsigned long *len)
554{
555 struct channel *chan = handle->shadow_chan;
556
557 *len = lib_ring_buffer_get_read_data_size(&chan->backend.config, buf,
558 handle);
559 *len = PAGE_ALIGN(*len);
560 return 0;
561}
562
563/* Get exclusive read access to the next sub-buffer that can be read. */
564int ustctl_get_next_subbuf(struct shm_handle *handle,
565 struct lib_ring_buffer *buf)
566{
567 return lib_ring_buffer_get_next_subbuf(buf, handle);
568}
569
570
571/* Release exclusive sub-buffer access, move consumer forward. */
572int ustctl_put_next_subbuf(struct shm_handle *handle,
573 struct lib_ring_buffer *buf)
574{
575 lib_ring_buffer_put_next_subbuf(buf, handle);
576 return 0;
577}
578
579/* snapshot */
580
581/* Get a snapshot of the current ring buffer producer and consumer positions */
582int ustctl_snapshot(struct shm_handle *handle,
583 struct lib_ring_buffer *buf)
584{
585 return lib_ring_buffer_snapshot(buf, &buf->cons_snapshot,
586 &buf->prod_snapshot, handle);
587}
588
589/* Get the consumer position (iteration start) */
590int ustctl_snapshot_get_consumed(struct shm_handle *handle,
591 struct lib_ring_buffer *buf, unsigned long *pos)
592{
593 *pos = buf->cons_snapshot;
594 return 0;
595}
596
597/* Get the producer position (iteration end) */
598int ustctl_snapshot_get_produced(struct shm_handle *handle,
599 struct lib_ring_buffer *buf, unsigned long *pos)
600{
601 *pos = buf->prod_snapshot;
602 return 0;
603}
604
605/* Get exclusive read access to the specified sub-buffer position */
606int ustctl_get_subbuf(struct shm_handle *handle,
607 struct lib_ring_buffer *buf, unsigned long *pos)
608{
609 return lib_ring_buffer_get_subbuf(buf, *pos, handle);
610}
611
612/* Release exclusive sub-buffer access */
613int ustctl_put_subbuf(struct shm_handle *handle,
614 struct lib_ring_buffer *buf)
615{
616 lib_ring_buffer_put_subbuf(buf, handle);
617 return 0;
618}
619
620int ustctl_buffer_flush(struct shm_handle *handle,
621 struct lib_ring_buffer *buf)
622{
623 lib_ring_buffer_switch_slow(buf, SWITCH_ACTIVE, handle);
624 return 0;
625}
This page took 0.046799 seconds and 4 git commands to generate.