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