Commit | Line | Data |
---|---|---|
54d01ffb DG |
1 | /* |
2 | * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca> | |
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 as published by the Free | |
6 | * Software Foundation; only version 2 of the License. | |
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., 59 Temple | |
15 | * Place - Suite 330, Boston, MA 02111-1307, USA. | |
16 | */ | |
17 | ||
56fff090 | 18 | #include <string.h> |
54d01ffb DG |
19 | #include <unistd.h> |
20 | ||
21 | #include <lttng/lttng.h> | |
22 | #include <lttng-sessiond-comm.h> | |
23 | #include <lttngerr.h> | |
2bdd86d4 MD |
24 | #ifdef CONFIG_LTTNG_TOOLS_HAVE_UST |
25 | #include <ust/lttng-ust-ctl.h> | |
26 | #include <ust/lttng-ust-abi.h> | |
27 | #else | |
28 | #include "lttng-ust-ctl.h" | |
29 | #include "lttng-ust-abi.h" | |
30 | #endif | |
54d01ffb DG |
31 | |
32 | #include "channel.h" | |
33 | #include "kernel-ctl.h" | |
44d3bd01 | 34 | #include "ust-ctl.h" |
54d01ffb DG |
35 | #include "utils.h" |
36 | ||
37 | /* | |
38 | * Return allocated channel attributes. | |
39 | */ | |
f6cd6b0f | 40 | struct lttng_channel *channel_new_default_attr(int dom) |
54d01ffb DG |
41 | { |
42 | struct lttng_channel *chan; | |
43 | ||
44 | chan = zmalloc(sizeof(struct lttng_channel)); | |
45 | if (chan == NULL) { | |
46 | perror("malloc channel init"); | |
47 | goto error_alloc; | |
48 | } | |
49 | ||
44d3bd01 DG |
50 | if (snprintf(chan->name, sizeof(chan->name), "%s", |
51 | DEFAULT_CHANNEL_NAME) < 0) { | |
52 | perror("snprintf default channel name"); | |
54d01ffb DG |
53 | goto error; |
54 | } | |
55 | ||
56 | chan->attr.overwrite = DEFAULT_CHANNEL_OVERWRITE; | |
57 | chan->attr.switch_timer_interval = DEFAULT_CHANNEL_SWITCH_TIMER; | |
58 | chan->attr.read_timer_interval = DEFAULT_CHANNEL_READ_TIMER; | |
59 | ||
60 | switch (dom) { | |
61 | case LTTNG_DOMAIN_KERNEL: | |
62 | chan->attr.subbuf_size = DEFAULT_KERNEL_CHANNEL_SUBBUF_SIZE; | |
63 | chan->attr.num_subbuf = DEFAULT_KERNEL_CHANNEL_SUBBUF_NUM; | |
64 | chan->attr.output = DEFAULT_KERNEL_CHANNEL_OUTPUT; | |
65 | break; | |
2bdd86d4 | 66 | case LTTNG_DOMAIN_UST: |
44d3bd01 DG |
67 | case LTTNG_DOMAIN_UST_PID: |
68 | chan->attr.subbuf_size = DEFAULT_UST_CHANNEL_SUBBUF_SIZE; | |
69 | chan->attr.num_subbuf = DEFAULT_UST_CHANNEL_SUBBUF_NUM; | |
70 | chan->attr.output = DEFAULT_UST_CHANNEL_OUTPUT; | |
71 | break; | |
54d01ffb DG |
72 | default: |
73 | goto error; /* Not implemented */ | |
74 | } | |
75 | ||
76 | return chan; | |
77 | ||
78 | error: | |
79 | free(chan); | |
80 | error_alloc: | |
81 | return NULL; | |
82 | } | |
83 | ||
56fff090 DG |
84 | /* |
85 | * Copy two ltt ust channel. Dst and src must be already allocated. | |
86 | */ | |
87 | int channel_ust_copy(struct ltt_ust_channel *dst, | |
88 | struct ltt_ust_channel *src) | |
89 | { | |
90 | struct ltt_ust_event *uevent, *new_uevent; | |
91 | ||
92 | memcpy(dst, src, sizeof(struct ltt_ust_channel)); | |
93 | CDS_INIT_LIST_HEAD(&dst->events.head); | |
94 | ||
95 | cds_list_for_each_entry(uevent, &src->events.head, list) { | |
96 | new_uevent = malloc(sizeof(struct ltt_ust_event)); | |
97 | if (new_uevent == NULL) { | |
98 | perror("malloc ltt_ust_event"); | |
99 | goto error; | |
100 | } | |
101 | ||
102 | memcpy(new_uevent, uevent, sizeof(struct ltt_ust_event)); | |
103 | cds_list_add(&new_uevent->list, &dst->events.head); | |
104 | dst->events.count++; | |
105 | } | |
106 | ||
107 | return 0; | |
108 | ||
109 | error: | |
110 | return -1; | |
111 | } | |
112 | ||
54d01ffb DG |
113 | /* |
114 | * Disable kernel channel of the kernel session. | |
115 | */ | |
116 | int channel_kernel_disable(struct ltt_kernel_session *ksession, | |
117 | char *channel_name) | |
118 | { | |
119 | int ret; | |
120 | struct ltt_kernel_channel *kchan; | |
121 | ||
122 | kchan = trace_kernel_get_channel_by_name(channel_name, ksession); | |
123 | if (kchan == NULL) { | |
124 | ret = LTTCOMM_KERN_CHAN_NOT_FOUND; | |
125 | goto error; | |
126 | } else if (kchan->enabled == 1) { | |
127 | ret = kernel_disable_channel(kchan); | |
128 | if (ret < 0) { | |
129 | if (ret != EEXIST) { | |
130 | ret = LTTCOMM_KERN_CHAN_DISABLE_FAIL; | |
131 | } | |
132 | goto error; | |
133 | } | |
134 | } | |
135 | ||
136 | ret = LTTCOMM_OK; | |
137 | ||
138 | error: | |
139 | return ret; | |
140 | } | |
141 | ||
142 | /* | |
143 | * Enable kernel channel of the kernel session. | |
144 | */ | |
145 | int channel_kernel_enable(struct ltt_kernel_session *ksession, | |
146 | struct ltt_kernel_channel *kchan) | |
147 | { | |
148 | int ret; | |
149 | ||
150 | if (kchan->enabled == 0) { | |
151 | ret = kernel_enable_channel(kchan); | |
152 | if (ret < 0) { | |
153 | ret = LTTCOMM_KERN_CHAN_ENABLE_FAIL; | |
154 | goto error; | |
155 | } | |
156 | } | |
157 | ||
158 | ret = LTTCOMM_OK; | |
159 | ||
160 | error: | |
161 | return ret; | |
162 | } | |
163 | ||
164 | /* | |
165 | * Create kernel channel of the kernel session and notify kernel thread. | |
166 | */ | |
167 | int channel_kernel_create(struct ltt_kernel_session *ksession, | |
44d3bd01 | 168 | struct lttng_channel *chan, int kernel_pipe) |
54d01ffb DG |
169 | { |
170 | int ret; | |
171 | struct lttng_channel *attr = chan; | |
172 | ||
173 | /* Creating channel attributes if needed */ | |
174 | if (attr == NULL) { | |
2bdd86d4 | 175 | /* FIXME: this appears to be a memory leak */ |
f6cd6b0f | 176 | attr = channel_new_default_attr(LTTNG_DOMAIN_KERNEL); |
54d01ffb DG |
177 | if (attr == NULL) { |
178 | ret = LTTCOMM_FATAL; | |
179 | goto error; | |
180 | } | |
181 | } | |
182 | ||
183 | /* Channel not found, creating it */ | |
184 | ret = kernel_create_channel(ksession, attr, ksession->trace_path); | |
185 | if (ret < 0) { | |
186 | ret = LTTCOMM_KERN_CHAN_FAIL; | |
187 | goto error; | |
188 | } | |
189 | ||
190 | /* Notify kernel thread that there is a new channel */ | |
191 | ret = notify_thread_pipe(kernel_pipe); | |
192 | if (ret < 0) { | |
193 | ret = LTTCOMM_FATAL; | |
194 | goto error; | |
195 | } | |
196 | ||
197 | ret = LTTCOMM_OK; | |
198 | ||
199 | error: | |
200 | return ret; | |
201 | } | |
44d3bd01 DG |
202 | |
203 | /* | |
204 | * Create UST channel and enable it on the tracer. | |
205 | */ | |
206 | int channel_ust_create(struct ltt_ust_session *usession, | |
207 | struct lttng_channel *chan, int sock) | |
208 | { | |
209 | int ret; | |
210 | struct lttng_channel *attr = chan; | |
2bdd86d4 MD |
211 | struct ltt_ust_channel *suchan; |
212 | struct lttng_ust_channel_attr uattr; | |
213 | struct object_data *obj; | |
44d3bd01 DG |
214 | |
215 | /* Creating channel attributes if needed */ | |
216 | if (attr == NULL) { | |
2bdd86d4 MD |
217 | /* FIXME: this appears to be a memory leak */ |
218 | /* TODO: get default for other UST domains */ | |
219 | attr = channel_new_default_attr(LTTNG_DOMAIN_UST); | |
44d3bd01 DG |
220 | if (attr == NULL) { |
221 | ret = LTTCOMM_FATAL; | |
222 | goto error; | |
223 | } | |
224 | } | |
225 | ||
2bdd86d4 MD |
226 | suchan = trace_ust_create_channel(attr, usession->path); |
227 | if (suchan == NULL) { | |
228 | ret = LTTCOMM_FATAL; | |
229 | goto error; | |
230 | } | |
231 | uattr.overwrite = attr->attr.overwrite; | |
232 | uattr.subbuf_size = attr->attr.subbuf_size; | |
233 | uattr.num_subbuf = attr->attr.num_subbuf; | |
234 | uattr.switch_timer_interval = attr->attr.switch_timer_interval; | |
235 | uattr.read_timer_interval = attr->attr.read_timer_interval; | |
236 | uattr.output = attr->attr.output; | |
237 | ret = ustctl_create_channel(sock, usession->handle, | |
238 | &uattr, &obj); | |
44d3bd01 DG |
239 | if (ret < 0) { |
240 | ret = LTTCOMM_UST_CHAN_FAIL; | |
241 | goto error; | |
242 | } | |
2bdd86d4 MD |
243 | suchan->attr.overwrite = uattr.overwrite; |
244 | suchan->attr.subbuf_size = uattr.subbuf_size; | |
245 | suchan->attr.num_subbuf = uattr.num_subbuf; | |
246 | suchan->attr.switch_timer_interval = uattr.switch_timer_interval; | |
247 | suchan->attr.read_timer_interval = uattr.read_timer_interval; | |
248 | suchan->attr.output = uattr.output; | |
249 | suchan->handle = obj->handle; | |
250 | suchan->attr.shm_fd = obj->shm_fd; | |
251 | suchan->attr.wait_fd = obj->wait_fd; | |
252 | suchan->attr.memory_map_size = obj->memory_map_size; | |
253 | suchan->obj = obj; | |
254 | ||
255 | /* Add channel to session */ | |
256 | cds_list_add(&suchan->list, &usession->channels.head); | |
257 | usession->channels.count++; | |
258 | ||
259 | DBG2("Channel %s UST create successfully for sock:%d", suchan->name, sock); | |
44d3bd01 DG |
260 | |
261 | ret = LTTCOMM_OK; | |
262 | ||
263 | error: | |
264 | return ret; | |
265 | } | |
266 | ||
267 | /* | |
268 | * Enable UST channel on the tracer. | |
269 | */ | |
270 | int channel_ust_enable(struct ltt_ust_session *usession, | |
271 | struct ltt_ust_channel *uchan, int sock) | |
272 | { | |
2bdd86d4 MD |
273 | int ret = LTTCOMM_OK; |
274 | struct object_data obj; | |
275 | ||
276 | obj.handle = uchan->handle; | |
277 | obj.shm_fd = uchan->attr.shm_fd; | |
278 | obj.wait_fd = uchan->attr.wait_fd; | |
279 | obj.memory_map_size = uchan->attr.memory_map_size; | |
280 | ret = ustctl_enable(sock, &obj); | |
44d3bd01 DG |
281 | if (ret < 0) { |
282 | ret = LTTCOMM_UST_CHAN_FAIL; | |
2bdd86d4 | 283 | goto end; |
44d3bd01 | 284 | } |
44d3bd01 | 285 | ret = LTTCOMM_OK; |
2bdd86d4 | 286 | end: |
44d3bd01 DG |
287 | return ret; |
288 | } | |
289 | ||
290 | /* | |
291 | * Disable UST channel on the tracer. | |
292 | */ | |
293 | int channel_ust_disable(struct ltt_ust_session *usession, | |
294 | struct ltt_ust_channel *uchan, int sock) | |
295 | { | |
2bdd86d4 MD |
296 | int ret = LTTCOMM_OK; |
297 | struct object_data obj; | |
298 | ||
299 | obj.handle = uchan->handle; | |
300 | obj.shm_fd = uchan->attr.shm_fd; | |
301 | obj.wait_fd = uchan->attr.wait_fd; | |
302 | obj.memory_map_size = uchan->attr.memory_map_size; | |
303 | ret = ustctl_disable(sock, &obj); | |
44d3bd01 DG |
304 | if (ret < 0) { |
305 | ret = LTTCOMM_UST_CHAN_FAIL; | |
2bdd86d4 | 306 | goto end; |
44d3bd01 | 307 | } |
44d3bd01 | 308 | ret = LTTCOMM_OK; |
2bdd86d4 | 309 | end: |
44d3bd01 DG |
310 | return ret; |
311 | } |