Commit | Line | Data |
---|---|---|
022349df MD |
1 | /* |
2 | * Copyright (C) 2019 - Jonathan Rajotte <jonathan.rajotte-julien@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 _LGPL_SOURCE | |
19 | #include <assert.h> | |
20 | #include <inttypes.h> | |
21 | #include <string.h> | |
22 | #include <unistd.h> | |
23 | ||
24 | #include <common/defaults.h> | |
25 | #include <common/error.h> | |
26 | #include <common/utils.h> | |
27 | ||
28 | #include "clear.h" | |
29 | #include "session.h" | |
30 | #include "ust-app.h" | |
31 | #include "kernel.h" | |
32 | #include "cmd.h" | |
33 | ||
34 | struct cmd_clear_session_reply_context { | |
35 | int reply_sock_fd; | |
36 | }; | |
37 | ||
38 | static | |
39 | void cmd_clear_session_reply(const struct ltt_session *session, | |
40 | void *_reply_context) | |
41 | { | |
42 | int ret; | |
43 | ssize_t comm_ret; | |
44 | const struct cmd_clear_session_reply_context *reply_context = | |
45 | _reply_context; | |
46 | struct lttcomm_lttng_msg llm = { | |
47 | .cmd_type = LTTNG_CLEAR_SESSION, | |
48 | .ret_code = LTTNG_OK, | |
49 | .pid = UINT32_MAX, | |
50 | .cmd_header_size = 0, | |
51 | .data_size = 0, | |
52 | }; | |
53 | ||
54 | DBG("End of clear command: replying to client"); | |
55 | comm_ret = lttcomm_send_unix_sock(reply_context->reply_sock_fd, | |
56 | &llm, sizeof(llm)); | |
57 | if (comm_ret != (ssize_t) sizeof(llm)) { | |
58 | ERR("Failed to send result of session \"%s\" clear to client", | |
59 | session->name); | |
60 | } | |
61 | ret = close(reply_context->reply_sock_fd); | |
62 | if (ret) { | |
63 | PERROR("Failed to close client socket in deferred session clear reply"); | |
64 | } | |
65 | free(_reply_context); | |
66 | } | |
67 | ||
68 | int cmd_clear_session(struct ltt_session *session, int *sock_fd) | |
69 | { | |
70 | int ret = LTTNG_OK; | |
71 | struct cmd_clear_session_reply_context *reply_context = NULL; | |
72 | bool session_was_active = false; | |
73 | struct ltt_kernel_session *ksession; | |
74 | struct ltt_ust_session *usess; | |
75 | ||
76 | ksession = session->kernel_session; | |
77 | usess = session->ust_session; | |
78 | ||
79 | if (sock_fd) { | |
80 | reply_context = zmalloc(sizeof(*reply_context)); | |
81 | if (!reply_context) { | |
82 | ret = LTTNG_ERR_NOMEM; | |
83 | goto end; | |
84 | } | |
85 | reply_context->reply_sock_fd = *sock_fd; | |
86 | } | |
87 | ||
88 | if (!session->has_been_started) { | |
89 | /* | |
90 | * Nothing to be cleared, this is not an error: there is | |
91 | * indeed nothing to do, and there is no reason why we | |
92 | * should return an error to the user. | |
93 | */ | |
94 | goto end; | |
95 | } | |
96 | ||
97 | /* Unsupported feature in lttng-relayd before 2.11. */ | |
98 | if (session->consumer->type == CONSUMER_DST_NET && | |
99 | (session->consumer->relay_major_version == 2 && | |
100 | session->consumer->relay_minor_version < 12)) { | |
101 | ret = LTTNG_ERR_CLEAR_NOT_AVAILABLE_RELAY; | |
102 | goto end; | |
103 | } | |
104 | if (session->consumer->type == CONSUMER_DST_NET && | |
105 | !session->consumer->relay_allows_clear) { | |
106 | ret = LTTNG_ERR_CLEAR_NOT_AVAILABLE_RELAY; | |
107 | goto end; | |
108 | } | |
109 | ||
110 | /* | |
111 | * After a stop followed by a clear, all subsequent clear are | |
112 | * effect-less until start is performed. | |
113 | */ | |
114 | if (session->cleared_after_last_stop) { | |
115 | ret = LTTNG_OK; | |
116 | goto end; | |
117 | } | |
118 | ||
119 | /* | |
120 | * After a stop followed by a rotation, all subsequent clear are effect-less | |
121 | * until start is performed. | |
122 | */ | |
123 | if (session->rotated_after_last_stop) { | |
124 | ret = LTTNG_OK; | |
125 | goto end; | |
126 | } | |
127 | ||
128 | session_was_active = session->active; | |
129 | if (session_was_active) { | |
130 | ret = stop_kernel_session(ksession); | |
131 | if (ret != LTTNG_OK) { | |
132 | goto end; | |
133 | } | |
134 | if (usess && usess->active) { | |
135 | ret = ust_app_stop_trace_all(usess); | |
136 | if (ret < 0) { | |
137 | ret = LTTNG_ERR_UST_STOP_FAIL; | |
138 | goto end; | |
139 | } | |
140 | } | |
141 | } | |
142 | ||
143 | /* | |
144 | * Clear active kernel and UST session buffers. | |
145 | */ | |
146 | if (session->kernel_session) { | |
147 | ret = kernel_clear_session(session); | |
148 | if (ret != LTTNG_OK) { | |
149 | goto end; | |
150 | } | |
151 | } | |
152 | if (session->ust_session) { | |
153 | ret = ust_app_clear_session(session); | |
154 | if (ret != LTTNG_OK) { | |
155 | goto end; | |
156 | } | |
157 | } | |
158 | ||
159 | if (session->output_traces) { | |
160 | /* | |
161 | * Use rotation to delete local and remote stream files. | |
162 | */ | |
163 | if (reply_context) { | |
164 | ret = session_add_clear_notifier(session, | |
165 | cmd_clear_session_reply, | |
166 | (void *) reply_context); | |
167 | if (ret) { | |
168 | ret = LTTNG_ERR_FATAL; | |
169 | goto end; | |
170 | } | |
171 | /* | |
172 | * On success, ownership of reply_context has been | |
173 | * passed to session_add_clear_notifier(). | |
174 | */ | |
175 | reply_context = NULL; | |
176 | *sock_fd = -1; | |
177 | } | |
178 | ret = cmd_rotate_session(session, NULL, true, | |
179 | LTTNG_TRACE_CHUNK_COMMAND_TYPE_DELETE); | |
180 | if (ret != LTTNG_OK) { | |
181 | goto end; | |
182 | } | |
183 | } | |
184 | if (!session->active) { | |
185 | session->cleared_after_last_stop = true; | |
186 | } | |
187 | if (session_was_active) { | |
188 | /* Kernel tracing */ | |
189 | if (ksession != NULL) { | |
190 | DBG("Start kernel tracing session \"%s\"", | |
191 | session->name); | |
192 | ret = start_kernel_session(ksession); | |
193 | if (ret != LTTNG_OK) { | |
194 | goto end; | |
195 | } | |
196 | } | |
197 | ||
198 | /* Flag session that trace should start automatically */ | |
199 | if (usess) { | |
200 | int int_ret = ust_app_start_trace_all(usess); | |
201 | ||
202 | if (int_ret < 0) { | |
203 | ret = LTTNG_ERR_UST_START_FAIL; | |
204 | goto end; | |
205 | } | |
206 | } | |
207 | } | |
208 | ret = LTTNG_OK; | |
209 | end: | |
210 | free(reply_context); | |
211 | return ret; | |
212 | } |