70759fb36d90149d8964967d3b20608c60bcc9ff
[lttng-tools.git] / src / bin / lttng-sessiond / kernel-consumer.c
1 /*
2 * Copyright (C) 2012 - David Goulet <dgoulet@efficios.com>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17
18 #define _GNU_SOURCE
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <sys/stat.h>
23 #include <unistd.h>
24
25 #include <common/common.h>
26 #include <common/defaults.h>
27
28 #include "consumer.h"
29 #include "health-sessiond.h"
30 #include "kernel-consumer.h"
31
32 static char *create_channel_path(struct consumer_output *consumer,
33 uid_t uid, gid_t gid)
34 {
35 int ret;
36 char tmp_path[PATH_MAX];
37 char *pathname = NULL;
38
39 assert(consumer);
40
41 /* Get the right path name destination */
42 if (consumer->type == CONSUMER_DST_LOCAL) {
43 /* Set application path to the destination path */
44 ret = snprintf(tmp_path, sizeof(tmp_path), "%s%s",
45 consumer->dst.trace_path, consumer->subdir);
46 if (ret < 0) {
47 PERROR("snprintf kernel channel path");
48 goto error;
49 }
50 pathname = strndup(tmp_path, sizeof(tmp_path));
51
52 /* Create directory */
53 ret = run_as_mkdir_recursive(pathname, S_IRWXU | S_IRWXG, uid, gid);
54 if (ret < 0) {
55 if (ret != -EEXIST) {
56 ERR("Trace directory creation error");
57 goto error;
58 }
59 }
60 DBG3("Kernel local consumer tracefile path: %s", pathname);
61 } else {
62 ret = snprintf(tmp_path, sizeof(tmp_path), "%s", consumer->subdir);
63 if (ret < 0) {
64 PERROR("snprintf kernel metadata path");
65 goto error;
66 }
67 pathname = strndup(tmp_path, sizeof(tmp_path));
68 DBG3("Kernel network consumer subdir path: %s", pathname);
69 }
70
71 return pathname;
72
73 error:
74 free(pathname);
75 return NULL;
76 }
77
78 /*
79 * Sending a single channel to the consumer with command ADD_CHANNEL.
80 */
81 int kernel_consumer_add_channel(struct consumer_socket *sock,
82 struct ltt_kernel_channel *channel, struct ltt_kernel_session *session,
83 unsigned int monitor)
84 {
85 int ret;
86 char *pathname;
87 struct lttcomm_consumer_msg lkm;
88 struct consumer_output *consumer;
89
90 /* Safety net */
91 assert(channel);
92 assert(session);
93 assert(session->consumer);
94
95 consumer = session->consumer;
96
97 DBG("Kernel consumer adding channel %s to kernel consumer",
98 channel->channel->name);
99
100 if (monitor) {
101 pathname = create_channel_path(consumer, session->uid, session->gid);
102 if (!pathname) {
103 ret = -1;
104 goto error;
105 }
106 } else {
107 /* Empty path. */
108 pathname = "";
109 }
110
111 /* Prep channel message structure */
112 consumer_init_channel_comm_msg(&lkm,
113 LTTNG_CONSUMER_ADD_CHANNEL,
114 channel->fd,
115 session->id,
116 pathname,
117 session->uid,
118 session->gid,
119 consumer->net_seq_index,
120 channel->channel->name,
121 channel->stream_count,
122 channel->channel->attr.output,
123 CONSUMER_CHANNEL_TYPE_DATA,
124 channel->channel->attr.tracefile_size,
125 channel->channel->attr.tracefile_count,
126 monitor,
127 channel->channel->attr.live_timer_interval);
128
129 health_code_update();
130
131 ret = consumer_send_channel(sock, &lkm);
132 if (ret < 0) {
133 goto error;
134 }
135
136 health_code_update();
137
138 error:
139 return ret;
140 }
141
142 /*
143 * Sending metadata to the consumer with command ADD_CHANNEL and ADD_STREAM.
144 */
145 int kernel_consumer_add_metadata(struct consumer_socket *sock,
146 struct ltt_kernel_session *session, unsigned int monitor)
147 {
148 int ret;
149 char *pathname;
150 struct lttcomm_consumer_msg lkm;
151 struct consumer_output *consumer;
152
153 /* Safety net */
154 assert(session);
155 assert(session->consumer);
156 assert(sock);
157
158 DBG("Sending metadata %d to kernel consumer", session->metadata_stream_fd);
159
160 /* Get consumer output pointer */
161 consumer = session->consumer;
162
163 if (monitor) {
164 pathname = create_channel_path(consumer, session->uid, session->gid);
165 if (!pathname) {
166 ret = -1;
167 goto error;
168 }
169 } else {
170 /* Empty path. */
171 pathname = "";
172 }
173
174 /* Prep channel message structure */
175 consumer_init_channel_comm_msg(&lkm,
176 LTTNG_CONSUMER_ADD_CHANNEL,
177 session->metadata->fd,
178 session->id,
179 pathname,
180 session->uid,
181 session->gid,
182 consumer->net_seq_index,
183 DEFAULT_METADATA_NAME,
184 1,
185 DEFAULT_KERNEL_CHANNEL_OUTPUT,
186 CONSUMER_CHANNEL_TYPE_METADATA,
187 0, 0,
188 monitor, 0);
189
190 health_code_update();
191
192 ret = consumer_send_channel(sock, &lkm);
193 if (ret < 0) {
194 goto error;
195 }
196
197 health_code_update();
198
199 /* Prep stream message structure */
200 consumer_init_stream_comm_msg(&lkm,
201 LTTNG_CONSUMER_ADD_STREAM,
202 session->metadata->fd,
203 session->metadata_stream_fd,
204 0); /* CPU: 0 for metadata. */
205
206 health_code_update();
207
208 /* Send stream and file descriptor */
209 ret = consumer_send_stream(sock, consumer, &lkm,
210 &session->metadata_stream_fd, 1);
211 if (ret < 0) {
212 goto error;
213 }
214
215 health_code_update();
216
217 error:
218 return ret;
219 }
220
221 /*
222 * Sending a single stream to the consumer with command ADD_STREAM.
223 */
224 int kernel_consumer_add_stream(struct consumer_socket *sock,
225 struct ltt_kernel_channel *channel, struct ltt_kernel_stream *stream,
226 struct ltt_kernel_session *session, unsigned int monitor)
227 {
228 int ret;
229 struct lttcomm_consumer_msg lkm;
230 struct consumer_output *consumer;
231
232 assert(channel);
233 assert(stream);
234 assert(session);
235 assert(session->consumer);
236 assert(sock);
237
238 DBG("Sending stream %d of channel %s to kernel consumer",
239 stream->fd, channel->channel->name);
240
241 /* Get consumer output pointer */
242 consumer = session->consumer;
243
244 /* Prep stream consumer message */
245 consumer_init_stream_comm_msg(&lkm,
246 LTTNG_CONSUMER_ADD_STREAM,
247 channel->fd,
248 stream->fd,
249 stream->cpu);
250
251 health_code_update();
252
253 /* Send stream and file descriptor */
254 ret = consumer_send_stream(sock, consumer, &lkm, &stream->fd, 1);
255 if (ret < 0) {
256 goto error;
257 }
258
259 health_code_update();
260
261 error:
262 return ret;
263 }
264
265 /*
266 * Send all stream fds of kernel channel to the consumer.
267 */
268 int kernel_consumer_send_channel_stream(struct consumer_socket *sock,
269 struct ltt_kernel_channel *channel, struct ltt_kernel_session *session,
270 unsigned int monitor)
271 {
272 int ret;
273 struct ltt_kernel_stream *stream;
274
275 /* Safety net */
276 assert(channel);
277 assert(session);
278 assert(session->consumer);
279 assert(sock);
280
281 /* Bail out if consumer is disabled */
282 if (!session->consumer->enabled) {
283 ret = LTTNG_OK;
284 goto error;
285 }
286
287 DBG("Sending streams of channel %s to kernel consumer",
288 channel->channel->name);
289
290 ret = kernel_consumer_add_channel(sock, channel, session, monitor);
291 if (ret < 0) {
292 goto error;
293 }
294
295 /* Send streams */
296 cds_list_for_each_entry(stream, &channel->stream_list.head, list) {
297 if (!stream->fd) {
298 continue;
299 }
300
301 /* Add stream on the kernel consumer side. */
302 ret = kernel_consumer_add_stream(sock, channel, stream, session,
303 monitor);
304 if (ret < 0) {
305 goto error;
306 }
307 }
308
309 error:
310 return ret;
311 }
312
313 /*
314 * Send all stream fds of the kernel session to the consumer.
315 */
316 int kernel_consumer_send_session(struct consumer_socket *sock,
317 struct ltt_kernel_session *session)
318 {
319 int ret, monitor = 0;
320 struct ltt_kernel_channel *chan;
321
322 /* Safety net */
323 assert(session);
324 assert(session->consumer);
325 assert(sock);
326
327 /* Bail out if consumer is disabled */
328 if (!session->consumer->enabled) {
329 ret = LTTNG_OK;
330 goto error;
331 }
332
333 /* Don't monitor the streams on the consumer if in flight recorder. */
334 if (session->output_traces) {
335 monitor = 1;
336 }
337
338 DBG("Sending session stream to kernel consumer");
339
340 if (session->metadata_stream_fd >= 0) {
341 ret = kernel_consumer_add_metadata(sock, session, monitor);
342 if (ret < 0) {
343 goto error;
344 }
345
346 /* Flag that at least the metadata has been sent to the consumer. */
347 session->consumer_fds_sent = 1;
348 }
349
350 /* Send channel and streams of it */
351 cds_list_for_each_entry(chan, &session->channel_list.head, list) {
352 ret = kernel_consumer_send_channel_stream(sock, chan, session,
353 monitor);
354 if (ret < 0) {
355 goto error;
356 }
357 }
358
359 DBG("Kernel consumer FDs of metadata and channel streams sent");
360
361 return 0;
362
363 error:
364 return ret;
365 }
366
367 int kernel_consumer_destroy_channel(struct consumer_socket *socket,
368 struct ltt_kernel_channel *channel)
369 {
370 int ret;
371 struct lttcomm_consumer_msg msg;
372
373 assert(channel);
374 assert(socket);
375
376 DBG("Sending kernel consumer destroy channel key %d", channel->fd);
377
378 msg.cmd_type = LTTNG_CONSUMER_DESTROY_CHANNEL;
379 msg.u.destroy_channel.key = channel->fd;
380
381 pthread_mutex_lock(socket->lock);
382 health_code_update();
383
384 ret = consumer_send_msg(socket, &msg);
385 if (ret < 0) {
386 goto error;
387 }
388
389 error:
390 health_code_update();
391 pthread_mutex_unlock(socket->lock);
392 return ret;
393 }
394
395 int kernel_consumer_destroy_metadata(struct consumer_socket *socket,
396 struct ltt_kernel_metadata *metadata)
397 {
398 int ret;
399 struct lttcomm_consumer_msg msg;
400
401 assert(metadata);
402 assert(socket);
403
404 DBG("Sending kernel consumer destroy channel key %d", metadata->fd);
405
406 msg.cmd_type = LTTNG_CONSUMER_DESTROY_CHANNEL;
407 msg.u.destroy_channel.key = metadata->fd;
408
409 pthread_mutex_lock(socket->lock);
410 health_code_update();
411
412 ret = consumer_send_msg(socket, &msg);
413 if (ret < 0) {
414 goto error;
415 }
416
417 error:
418 health_code_update();
419 pthread_mutex_unlock(socket->lock);
420 return ret;
421 }
This page took 0.036346 seconds and 3 git commands to generate.