3368da6c1ba8a5d6e2c89ac09d0679793fc04867
[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.h"
30 #include "kernel-consumer.h"
31
32 /*
33 * Sending a single channel to the consumer with command ADD_CHANNEL.
34 */
35 int kernel_consumer_add_channel(struct consumer_socket *sock,
36 struct ltt_kernel_channel *channel, struct ltt_kernel_session *session)
37 {
38 int ret;
39 char tmp_path[PATH_MAX];
40 const char *pathname;
41 struct lttcomm_consumer_msg lkm;
42 struct consumer_output *consumer;
43
44 /* Safety net */
45 assert(channel);
46 assert(session);
47 assert(session->consumer);
48
49 consumer = session->consumer;
50
51 DBG("Kernel consumer adding channel %s to kernel consumer",
52 channel->channel->name);
53
54 /* Get the right path name destination */
55 if (consumer->type == CONSUMER_DST_LOCAL) {
56 /* Set application path to the destination path */
57 ret = snprintf(tmp_path, sizeof(tmp_path), "%s/%s",
58 consumer->dst.trace_path, consumer->subdir);
59 if (ret < 0) {
60 PERROR("snprintf metadata path");
61 goto error;
62 }
63 pathname = tmp_path;
64
65 /* Create directory */
66 ret = run_as_mkdir_recursive(pathname, S_IRWXU | S_IRWXG,
67 session->uid, session->gid);
68 if (ret < 0) {
69 if (ret != -EEXIST) {
70 ERR("Trace directory creation error");
71 goto error;
72 }
73 }
74 DBG3("Kernel local consumer tracefile path: %s", pathname);
75 } else {
76 ret = snprintf(tmp_path, sizeof(tmp_path), "%s", consumer->subdir);
77 if (ret < 0) {
78 PERROR("snprintf metadata path");
79 goto error;
80 }
81 pathname = tmp_path;
82 DBG3("Kernel network consumer subdir path: %s", pathname);
83 }
84
85 /* Prep channel message structure */
86 consumer_init_channel_comm_msg(&lkm,
87 LTTNG_CONSUMER_ADD_CHANNEL,
88 channel->fd,
89 session->id,
90 pathname,
91 session->uid,
92 session->gid,
93 consumer->net_seq_index,
94 channel->channel->name,
95 channel->stream_count,
96 channel->channel->attr.output,
97 CONSUMER_CHANNEL_TYPE_DATA);
98
99 health_code_update();
100
101 ret = consumer_send_channel(sock, &lkm);
102 if (ret < 0) {
103 goto error;
104 }
105
106 health_code_update();
107
108 error:
109 return ret;
110 }
111
112 /*
113 * Sending metadata to the consumer with command ADD_CHANNEL and ADD_STREAM.
114 */
115 int kernel_consumer_add_metadata(struct consumer_socket *sock,
116 struct ltt_kernel_session *session)
117 {
118 int ret;
119 char tmp_path[PATH_MAX];
120 const char *pathname;
121 struct lttcomm_consumer_msg lkm;
122 struct consumer_output *consumer;
123
124 /* Safety net */
125 assert(session);
126 assert(session->consumer);
127 assert(sock);
128
129 DBG("Sending metadata %d to kernel consumer", session->metadata_stream_fd);
130
131 /* Get consumer output pointer */
132 consumer = session->consumer;
133
134 /* Get the right path name destination */
135 if (consumer->type == CONSUMER_DST_LOCAL) {
136 /* Set application path to the destination path */
137 ret = snprintf(tmp_path, sizeof(tmp_path), "%s/%s",
138 consumer->dst.trace_path, consumer->subdir);
139 if (ret < 0) {
140 PERROR("snprintf metadata path");
141 goto error;
142 }
143 pathname = tmp_path;
144
145 /* Create directory */
146 ret = run_as_mkdir_recursive(pathname, S_IRWXU | S_IRWXG,
147 session->uid, session->gid);
148 if (ret < 0) {
149 if (ret != -EEXIST) {
150 ERR("Trace directory creation error");
151 goto error;
152 }
153 }
154 DBG3("Kernel local consumer tracefile path: %s", pathname);
155 } else {
156 ret = snprintf(tmp_path, sizeof(tmp_path), "%s", consumer->subdir);
157 if (ret < 0) {
158 PERROR("snprintf metadata path");
159 goto error;
160 }
161 pathname = tmp_path;
162 DBG3("Kernel network consumer subdir path: %s", pathname);
163 }
164
165 /* Prep channel message structure */
166 consumer_init_channel_comm_msg(&lkm,
167 LTTNG_CONSUMER_ADD_CHANNEL,
168 session->metadata->fd,
169 session->id,
170 pathname,
171 session->uid,
172 session->gid,
173 consumer->net_seq_index,
174 DEFAULT_METADATA_NAME,
175 1,
176 DEFAULT_KERNEL_CHANNEL_OUTPUT,
177 CONSUMER_CHANNEL_TYPE_METADATA);
178
179 health_code_update();
180
181 ret = consumer_send_channel(sock, &lkm);
182 if (ret < 0) {
183 goto error;
184 }
185
186 health_code_update();
187
188 /* Prep stream message structure */
189 consumer_init_stream_comm_msg(&lkm,
190 LTTNG_CONSUMER_ADD_STREAM,
191 session->metadata->fd,
192 session->metadata_stream_fd,
193 0); /* CPU: 0 for metadata. */
194
195 health_code_update();
196
197 /* Send stream and file descriptor */
198 ret = consumer_send_stream(sock, consumer, &lkm,
199 &session->metadata_stream_fd, 1);
200 if (ret < 0) {
201 goto error;
202 }
203
204 health_code_update();
205
206 error:
207 return ret;
208 }
209
210 /*
211 * Sending a single stream to the consumer with command ADD_STREAM.
212 */
213 int kernel_consumer_add_stream(struct consumer_socket *sock,
214 struct ltt_kernel_channel *channel, struct ltt_kernel_stream *stream,
215 struct ltt_kernel_session *session)
216 {
217 int ret;
218 struct lttcomm_consumer_msg lkm;
219 struct consumer_output *consumer;
220
221 assert(channel);
222 assert(stream);
223 assert(session);
224 assert(session->consumer);
225 assert(sock);
226
227 DBG("Sending stream %d of channel %s to kernel consumer",
228 stream->fd, channel->channel->name);
229
230 /* Get consumer output pointer */
231 consumer = session->consumer;
232
233 /* Prep stream consumer message */
234 consumer_init_stream_comm_msg(&lkm,
235 LTTNG_CONSUMER_ADD_STREAM,
236 channel->fd,
237 stream->fd,
238 stream->cpu);
239
240 health_code_update();
241
242 /* Send stream and file descriptor */
243 ret = consumer_send_stream(sock, consumer, &lkm, &stream->fd, 1);
244 if (ret < 0) {
245 goto error;
246 }
247
248 health_code_update();
249
250 error:
251 return ret;
252 }
253
254 /*
255 * Send all stream fds of kernel channel to the consumer.
256 */
257 int kernel_consumer_send_channel_stream(struct consumer_socket *sock,
258 struct ltt_kernel_channel *channel, struct ltt_kernel_session *session)
259 {
260 int ret;
261 struct ltt_kernel_stream *stream;
262
263 /* Safety net */
264 assert(channel);
265 assert(session);
266 assert(session->consumer);
267 assert(sock);
268
269 /* Bail out if consumer is disabled */
270 if (!session->consumer->enabled) {
271 ret = LTTNG_OK;
272 goto error;
273 }
274
275 DBG("Sending streams of channel %s to kernel consumer",
276 channel->channel->name);
277
278 ret = kernel_consumer_add_channel(sock, channel, session);
279 if (ret < 0) {
280 goto error;
281 }
282
283 /* Send streams */
284 cds_list_for_each_entry(stream, &channel->stream_list.head, list) {
285 if (!stream->fd) {
286 continue;
287 }
288
289 /* Add stream on the kernel consumer side. */
290 ret = kernel_consumer_add_stream(sock, channel, stream, session);
291 if (ret < 0) {
292 goto error;
293 }
294 }
295
296 error:
297 return ret;
298 }
299
300 /*
301 * Send all stream fds of the kernel session to the consumer.
302 */
303 int kernel_consumer_send_session(struct consumer_socket *sock,
304 struct ltt_kernel_session *session)
305 {
306 int ret;
307 struct ltt_kernel_channel *chan;
308
309 /* Safety net */
310 assert(session);
311 assert(session->consumer);
312 assert(sock);
313
314 /* Bail out if consumer is disabled */
315 if (!session->consumer->enabled) {
316 ret = LTTNG_OK;
317 goto error;
318 }
319
320 DBG("Sending session stream to kernel consumer");
321
322 if (session->metadata_stream_fd >= 0) {
323 ret = kernel_consumer_add_metadata(sock, session);
324 if (ret < 0) {
325 goto error;
326 }
327
328 /* Flag that at least the metadata has been sent to the consumer. */
329 session->consumer_fds_sent = 1;
330 }
331
332 /* Send channel and streams of it */
333 cds_list_for_each_entry(chan, &session->channel_list.head, list) {
334 ret = kernel_consumer_send_channel_stream(sock, chan, session);
335 if (ret < 0) {
336 goto error;
337 }
338 }
339
340 DBG("Kernel consumer FDs of metadata and channel streams sent");
341
342 return 0;
343
344 error:
345 return ret;
346 }
This page took 0.035001 seconds and 3 git commands to generate.