Add EEXIST support for kernel event on the tracer side
[lttng-tools.git] / ltt-sessiond / event.c
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
18 #include <errno.h>
19 #include <urcu/list.h>
20
21 #include <lttng/lttng.h>
22 #include <lttng-sessiond-comm.h>
23 #include <lttngerr.h>
24
25 #include "channel.h"
26 #include "event.h"
27 #include "kernel-ctl.h"
28
29 /*
30 * Setup a lttng_event used to enable *all* syscall tracing.
31 */
32 static void init_syscalls_kernel_event(struct lttng_event *event)
33 {
34 event->name[0] = '\0';
35 /*
36 * We use LTTNG_EVENT* here since the trace kernel creation will make the
37 * right changes for the kernel.
38 */
39 event->type = LTTNG_EVENT_SYSCALL;
40 }
41
42 /*
43 * Disable kernel tracepoint event for a channel from the kernel session.
44 */
45 int event_kernel_disable_tracepoint(struct ltt_kernel_session *ksession,
46 struct ltt_kernel_channel *kchan, char *event_name)
47 {
48 int ret;
49 struct ltt_kernel_event *kevent;
50
51 kevent = trace_kernel_get_event_by_name(event_name, kchan);
52 if (kevent == NULL) {
53 ret = LTTCOMM_NO_EVENT;
54 goto error;
55 }
56
57 ret = kernel_disable_event(kevent);
58 if (ret < 0) {
59 ret = LTTCOMM_KERN_DISABLE_FAIL;
60 goto error;
61 }
62
63 DBG("Kernel event %s disable for channel %s.",
64 kevent->event->name, kchan->channel->name);
65
66 ret = LTTCOMM_OK;
67
68 error:
69 return ret;
70 }
71
72 /*
73 * Disable kernel tracepoint events for a channel from the kernel session.
74 */
75 int event_kernel_disable_all_tracepoints(struct ltt_kernel_session *ksession,
76 struct ltt_kernel_channel *kchan)
77 {
78 int ret;
79 struct ltt_kernel_event *kevent;
80
81 /* For each event in the kernel session */
82 cds_list_for_each_entry(kevent, &kchan->events_list.head, list) {
83 ret = kernel_disable_event(kevent);
84 if (ret < 0) {
85 /* We continue disabling the rest */
86 continue;
87 }
88 }
89 ret = LTTCOMM_OK;
90 return ret;
91 }
92
93 /*
94 * Disable kernel syscall events for a channel from the kernel session.
95 */
96 int event_kernel_disable_all_syscalls(struct ltt_kernel_session *ksession,
97 struct ltt_kernel_channel *kchan)
98 {
99 ERR("Cannot disable syscall tracing for existing session. Please destroy session instead.");
100 return LTTCOMM_OK; /* Return OK so disable all succeeds */
101 }
102
103 /*
104 * Disable all kernel event for a channel from the kernel session.
105 */
106 int event_kernel_disable_all(struct ltt_kernel_session *ksession,
107 struct ltt_kernel_channel *kchan)
108 {
109 int ret;
110
111 ret = event_kernel_disable_all_tracepoints(ksession, kchan);
112 if (ret != LTTCOMM_OK)
113 return ret;
114 ret = event_kernel_disable_all_syscalls(ksession, kchan);
115 return ret;
116 }
117
118 /*
119 * Enable kernel tracepoint event for a channel from the kernel session.
120 */
121 int event_kernel_enable_tracepoint(struct ltt_kernel_session *ksession,
122 struct ltt_kernel_channel *kchan, struct lttng_event *event)
123 {
124 int ret;
125 struct ltt_kernel_event *kevent;
126
127 kevent = trace_kernel_get_event_by_name(event->name, kchan);
128 if (kevent == NULL) {
129 ret = kernel_create_event(event, kchan);
130 if (ret < 0) {
131 if (ret == -EEXIST) {
132 ret = LTTCOMM_KERN_EVENT_EXIST;
133 } else {
134 ret = LTTCOMM_KERN_ENABLE_FAIL;
135 }
136 goto end;
137 }
138 } else if (kevent->enabled == 0) {
139 ret = kernel_enable_event(kevent);
140 if (ret < 0) {
141 ret = LTTCOMM_KERN_ENABLE_FAIL;
142 goto end;
143 }
144 }
145 ret = LTTCOMM_OK;
146 end:
147 return ret;
148 }
149
150 /*
151 * Enable all kernel tracepoint events of a channel of the kernel session.
152 */
153 int event_kernel_enable_all_tracepoints(struct ltt_kernel_session *ksession,
154 struct ltt_kernel_channel *kchan, int kernel_tracer_fd)
155 {
156 int size, i, ret;
157 struct ltt_kernel_event *kevent;
158 struct lttng_event *event_list;
159
160 /* For each event in the kernel session */
161 cds_list_for_each_entry(kevent, &kchan->events_list.head, list) {
162 ret = kernel_enable_event(kevent);
163 if (ret < 0) {
164 /* Enable failed but still continue */
165 continue;
166 }
167 }
168
169 size = kernel_list_events(kernel_tracer_fd, &event_list);
170 if (size < 0) {
171 ret = LTTCOMM_KERN_LIST_FAIL;
172 goto end;
173 }
174
175 for (i = 0; i < size; i++) {
176 kevent = trace_kernel_get_event_by_name(event_list[i].name, kchan);
177 if (kevent == NULL) {
178 /* Default event type for enable all */
179 event_list[i].type = LTTNG_EVENT_TRACEPOINT;
180 /* Enable each single tracepoint event */
181 ret = kernel_create_event(&event_list[i], kchan);
182 if (ret < 0) {
183 /* Ignore error here and continue */
184 }
185 }
186 }
187 free(event_list);
188 ret = LTTCOMM_OK;
189 end:
190 return ret;
191
192 }
193
194 /*
195 * Enable all kernel tracepoint events of a channel of the kernel session.
196 */
197 int event_kernel_enable_all_syscalls(struct ltt_kernel_session *ksession,
198 struct ltt_kernel_channel *kchan, int kernel_tracer_fd)
199 {
200 int ret;
201 struct lttng_event event;
202
203 init_syscalls_kernel_event(&event);
204
205 DBG("Enabling all syscall tracing");
206
207 ret = kernel_create_event(&event, kchan);
208 if (ret < 0) {
209 goto end;
210 }
211 ret = LTTCOMM_OK;
212 end:
213 return ret;
214 }
215
216 /*
217 * Enable all kernel events of a channel of the kernel session.
218 */
219 int event_kernel_enable_all(struct ltt_kernel_session *ksession,
220 struct ltt_kernel_channel *kchan, int kernel_tracer_fd)
221 {
222 int ret;
223
224 ret = event_kernel_enable_all_tracepoints(ksession, kchan, kernel_tracer_fd);
225 if (ret != LTTCOMM_OK) {
226 goto end;
227 }
228 ret = event_kernel_enable_all_syscalls(ksession, kchan, kernel_tracer_fd);
229 end:
230 return ret;
231 }
This page took 0.033341 seconds and 4 git commands to generate.