4f720ead80a5f1e8e72aea72c17833f680848c6b
[lttng-tools.git] / src / lib / lttng-ctl / tracker.c
1 /*
2 * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8 #include "lttng-ctl-helper.h"
9 #include "lttng/domain.h"
10 #include "lttng/lttng-error.h"
11 #include <common/sessiond-comm/sessiond-comm.h>
12 #include <common/tracker.h>
13 #include <lttng/tracker.h>
14
15 struct lttng_process_attr_tracker_handle {
16 char *session_name;
17 enum lttng_domain_type domain;
18 enum lttng_process_attr process_attr;
19 struct lttng_process_attr_values *inclusion_set;
20 };
21
22 void lttng_process_attr_tracker_handle_destroy(
23 struct lttng_process_attr_tracker_handle *tracker)
24 {
25 if (!tracker) {
26 return;
27 }
28
29 lttng_process_attr_values_destroy(tracker->inclusion_set);
30 free(tracker->session_name);
31 free(tracker);
32 }
33
34 enum lttng_error_code lttng_session_get_tracker_handle(const char *session_name,
35 enum lttng_domain_type domain,
36 enum lttng_process_attr process_attr,
37 struct lttng_process_attr_tracker_handle **out_tracker_handle)
38 {
39 enum lttng_error_code ret_code = LTTNG_OK;
40 struct lttng_process_attr_tracker_handle *handle = NULL;
41 enum lttng_process_attr_tracker_handle_status status;
42 enum lttng_tracking_policy policy;
43
44 if (!session_name || !out_tracker_handle) {
45 ret_code = LTTNG_ERR_INVALID;
46 goto error;
47 }
48
49 if (domain != LTTNG_DOMAIN_KERNEL && domain != LTTNG_DOMAIN_UST) {
50 ret_code = LTTNG_ERR_UNSUPPORTED_DOMAIN;
51 goto error;
52 }
53
54 handle = zmalloc(sizeof(*handle));
55 if (!handle) {
56 ret_code = LTTNG_ERR_NOMEM;
57 goto error;
58 }
59
60 handle->session_name = strdup(session_name);
61 if (!handle->session_name) {
62 ret_code = LTTNG_ERR_NOMEM;
63 goto error;
64 }
65
66 handle->domain = domain;
67 handle->process_attr = process_attr;
68
69 /*
70 * Use the `get_tracking_policy` command to validate the tracker's
71 * existance.
72 */
73 status = lttng_process_attr_tracker_handle_get_tracking_policy(
74 handle, &policy);
75 switch (status) {
76 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK:
77 break;
78 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST:
79 ret_code = LTTNG_ERR_SESSION_NOT_EXIST;
80 goto error;
81 default:
82 ret_code = LTTNG_ERR_UNK;
83 goto error;
84 }
85
86 *out_tracker_handle = handle;
87 return ret_code;
88 error:
89 lttng_process_attr_tracker_handle_destroy(handle);
90 return ret_code;
91 }
92
93 enum lttng_process_attr_tracker_handle_status
94 lttng_process_attr_tracker_handle_get_tracking_policy(
95 const struct lttng_process_attr_tracker_handle *tracker,
96 enum lttng_tracking_policy *policy)
97 {
98 void *reply = NULL;
99 int reply_ret;
100 enum lttng_process_attr_tracker_handle_status status =
101 LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK;
102 struct lttcomm_session_msg lsm = {
103 .cmd_type = LTTNG_PROCESS_ATTR_TRACKER_GET_POLICY,
104 };
105
106 if (!tracker || !policy) {
107 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID;
108 goto end;
109 }
110
111 lttng_ctl_copy_string(lsm.session.name, tracker->session_name,
112 sizeof(lsm.session.name));
113 lsm.domain.type = tracker->domain;
114 lsm.u.process_attr_tracker_get_tracking_policy.process_attr =
115 (int32_t) tracker->process_attr;
116
117 /* Command returns a session descriptor on success. */
118 reply_ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(
119 &lsm, NULL, 0, &reply);
120 if (reply_ret != sizeof(uint32_t)) {
121 if (reply_ret == -LTTNG_ERR_SESSION_NOT_EXIST ||
122 reply_ret == -LTTNG_ERR_SESS_NOT_FOUND) {
123 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST;
124 } else {
125 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR;
126 }
127 goto end;
128 }
129
130 *policy = (enum lttng_tracking_policy)(*((const uint32_t *) reply));
131 end:
132 free(reply);
133 return status;
134 }
135
136 enum lttng_process_attr_tracker_handle_status
137 lttng_process_attr_tracker_handle_set_tracking_policy(
138 const struct lttng_process_attr_tracker_handle *tracker,
139 enum lttng_tracking_policy policy)
140 {
141 int reply_ret;
142 enum lttng_process_attr_tracker_handle_status status =
143 LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK;
144 struct lttcomm_session_msg lsm = {
145 .cmd_type = LTTNG_PROCESS_ATTR_TRACKER_SET_POLICY,
146 };
147
148 if (!tracker) {
149 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID;
150 goto end;
151 }
152
153 lttng_ctl_copy_string(lsm.session.name, tracker->session_name,
154 sizeof(lsm.session.name));
155 lsm.domain.type = tracker->domain;
156 lsm.u.process_attr_tracker_set_tracking_policy.process_attr =
157 (int32_t) tracker->process_attr;
158 lsm.u.process_attr_tracker_set_tracking_policy.tracking_policy =
159 (int32_t) policy;
160
161 /* Command returns a session descriptor on success. */
162 reply_ret = lttng_ctl_ask_sessiond(&lsm, NULL);
163 if (reply_ret < 0) {
164 if (reply_ret == -LTTNG_ERR_SESSION_NOT_EXIST) {
165 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST;
166 } else {
167 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR;
168 }
169 goto end;
170 }
171 end:
172 return status;
173 }
174
175 #define DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(command_upper, \
176 command_lower, process_attr_name, value_type_name, \
177 value_type_c, value_type_enum) \
178 enum lttng_process_attr_tracker_handle_status \
179 lttng_process_attr_##process_attr_name##_tracker_handle_##command_lower##_##value_type_name( \
180 const struct lttng_process_attr_tracker_handle \
181 *tracker, \
182 value_type_c value) \
183 { \
184 int ret; \
185 enum lttng_process_attr_tracker_handle_status status = \
186 LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK; \
187 struct lttcomm_session_msg lsm = { \
188 .cmd_type = LTTNG_PROCESS_ATTR_TRACKER_##command_upper##_INCLUDE_VALUE}; \
189 \
190 if (!tracker) { \
191 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID; \
192 goto end; \
193 } \
194 \
195 lttng_ctl_copy_string(lsm.session.name, tracker->session_name, \
196 sizeof(lsm.session.name)); \
197 lsm.domain.type = tracker->domain; \
198 lsm.u.process_attr_tracker_add_remove_include_value \
199 .process_attr = \
200 (int32_t) tracker->process_attr; \
201 lsm.u.process_attr_tracker_add_remove_include_value \
202 .value_type = (uint32_t) \
203 LTTNG_PROCESS_ATTR_VALUE_TYPE_##value_type_enum; \
204 \
205 if (is_signed(value_type_c)) { \
206 lsm.u.process_attr_tracker_add_remove_include_value \
207 .integral_value.u._signed = value; \
208 } else { \
209 lsm.u.process_attr_tracker_add_remove_include_value \
210 .integral_value.u._unsigned = value; \
211 } \
212 \
213 ret = lttng_ctl_ask_sessiond(&lsm, NULL); \
214 if (ret < 0) { \
215 switch (-ret) { \
216 case LTTNG_ERR_PROCESS_ATTR_EXISTS: \
217 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_EXISTS; \
218 break; \
219 case LTTNG_ERR_PROCESS_ATTR_MISSING: \
220 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_MISSING; \
221 break; \
222 case LTTNG_ERR_PROCESS_ATTR_TRACKER_INVALID_TRACKING_POLICY: \
223 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY; \
224 break; \
225 default: \
226 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR; \
227 } \
228 } \
229 end: \
230 return status; \
231 }
232
233 #define DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(command_upper, \
234 command_lower, process_attr_name, value_type_name, \
235 value_type_enum) \
236 enum lttng_process_attr_tracker_handle_status \
237 lttng_process_attr_##process_attr_name##_tracker_handle_##command_lower##_##value_type_name( \
238 const struct lttng_process_attr_tracker_handle \
239 *tracker, \
240 const char *value) \
241 { \
242 int ret; \
243 enum lttng_process_attr_tracker_handle_status status = \
244 LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK; \
245 struct lttcomm_session_msg lsm = { \
246 .cmd_type = LTTNG_PROCESS_ATTR_TRACKER_##command_upper##_INCLUDE_VALUE}; \
247 const size_t len = value ? strlen(value) + 1 : 0; \
248 \
249 if (!tracker || !value) { \
250 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID; \
251 goto end; \
252 } \
253 \
254 lttng_ctl_copy_string(lsm.session.name, tracker->session_name, \
255 sizeof(lsm.session.name)); \
256 lsm.domain.type = tracker->domain; \
257 lsm.u.process_attr_tracker_add_remove_include_value \
258 .process_attr = \
259 (int32_t) tracker->process_attr; \
260 lsm.u.process_attr_tracker_add_remove_include_value.name_len = \
261 (uint32_t) len; \
262 lsm.u.process_attr_tracker_add_remove_include_value \
263 .value_type = (uint32_t) \
264 LTTNG_PROCESS_ATTR_VALUE_TYPE_##value_type_enum; \
265 \
266 ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header( \
267 &lsm, value, len, NULL); \
268 if (ret < 0) { \
269 switch (-ret) { \
270 case LTTNG_ERR_PROCESS_ATTR_EXISTS: \
271 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_EXISTS; \
272 break; \
273 case LTTNG_ERR_PROCESS_ATTR_MISSING: \
274 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_MISSING; \
275 break; \
276 case LTTNG_ERR_PROCESS_ATTR_TRACKER_INVALID_TRACKING_POLICY: \
277 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY; \
278 break; \
279 case LTTNG_ERR_USER_NOT_FOUND: \
280 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_USER_NOT_FOUND; \
281 break; \
282 case LTTNG_ERR_GROUP_NOT_FOUND: \
283 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_GROUP_NOT_FOUND; \
284 break; \
285 default: \
286 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR; \
287 } \
288 } \
289 end: \
290 return status; \
291 }
292
293 /* PID */
294 DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
295 ADD, add, process_id, pid, pid_t, PID);
296 DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
297 REMOVE, remove, process_id, pid, pid_t, PID);
298
299 /* VPID */
300 DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
301 ADD, add, virtual_process_id, pid, pid_t, PID);
302 DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
303 REMOVE, remove, virtual_process_id, pid, pid_t, PID);
304
305 /* UID */
306 DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
307 ADD, add, user_id, uid, uid_t, UID);
308 DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
309 REMOVE, remove, user_id, uid, uid_t, UID);
310 DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
311 ADD, add, user_id, user_name, USER_NAME);
312 DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
313 REMOVE, remove, user_id, user_name, USER_NAME);
314
315 /* VUID */
316 DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
317 ADD, add, virtual_user_id, uid, uid_t, UID);
318 DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
319 REMOVE, remove, virtual_user_id, uid, uid_t, UID);
320 DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
321 ADD, add, virtual_user_id, user_name, USER_NAME);
322 DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
323 REMOVE, remove, virtual_user_id, user_name, USER_NAME);
324
325 /* GID */
326 DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
327 ADD, add, group_id, gid, gid_t, GID);
328 DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
329 REMOVE, remove, group_id, gid, gid_t, GID);
330 DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
331 ADD, add, group_id, group_name, GROUP_NAME);
332 DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
333 REMOVE, remove, group_id, group_name, GROUP_NAME);
334
335 /* VGID */
336 DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
337 ADD, add, virtual_group_id, gid, gid_t, GID);
338 DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
339 REMOVE, remove, virtual_group_id, gid, gid_t, GID);
340 DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
341 ADD, add, virtual_group_id, group_name, GROUP_NAME);
342 DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
343 REMOVE, remove, virtual_group_id, group_name, GROUP_NAME);
344
345 enum lttng_process_attr_tracker_handle_status
346 lttng_process_attr_tracker_handle_get_inclusion_set(
347 struct lttng_process_attr_tracker_handle *tracker,
348 const struct lttng_process_attr_values **values)
349 {
350 void *reply = NULL;
351 int reply_ret;
352 enum lttng_process_attr_tracker_handle_status status =
353 LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK;
354 struct lttcomm_session_msg lsm = {
355 .cmd_type = LTTNG_PROCESS_ATTR_TRACKER_GET_INCLUSION_SET,
356 };
357 struct lttng_buffer_view inclusion_set_view;
358 ssize_t inclusion_set_ret;
359
360 if (!tracker || !values) {
361 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID;
362 goto end;
363 }
364
365 lttng_process_attr_values_destroy(tracker->inclusion_set);
366 tracker->inclusion_set = NULL;
367
368 lttng_ctl_copy_string(lsm.session.name, tracker->session_name,
369 sizeof(lsm.session.name));
370 lsm.domain.type = tracker->domain;
371 lsm.u.process_attr_tracker_get_tracking_policy.process_attr =
372 (int32_t) tracker->process_attr;
373
374 /* Command returns a session descriptor on success. */
375 reply_ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(
376 &lsm, NULL, 0, &reply);
377 if (reply_ret < 0) {
378 if (reply_ret == -LTTNG_ERR_SESSION_NOT_EXIST) {
379 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST;
380 } else if (reply_ret ==
381 -LTTNG_ERR_PROCESS_ATTR_TRACKER_INVALID_TRACKING_POLICY) {
382 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY;
383 } else {
384 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR;
385 }
386 goto end;
387 } else if (reply_ret == 0) {
388 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR;
389 goto end;
390 }
391
392 inclusion_set_view = lttng_buffer_view_init(reply, 0, reply_ret);
393 if (!inclusion_set_view.data) {
394 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR;
395 goto end;
396 }
397
398 inclusion_set_ret = lttng_process_attr_values_create_from_buffer(
399 tracker->domain, tracker->process_attr,
400 &inclusion_set_view, &tracker->inclusion_set);
401 if (inclusion_set_ret < 0) {
402 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR;
403 goto end;
404 }
405 *values = tracker->inclusion_set;
406 end:
407 free(reply);
408 return status;
409 }
410
411 enum lttng_process_attr_values_status lttng_process_attr_values_get_count(
412 const struct lttng_process_attr_values *values,
413 unsigned int *count)
414 {
415 enum lttng_process_attr_values_status status =
416 LTTNG_PROCESS_ATTR_VALUES_STATUS_OK;
417
418 if (!values || !count) {
419 status = LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID;
420 goto end;
421 }
422
423 *count = _lttng_process_attr_values_get_count(values);
424 end:
425 return status;
426 }
427
428 enum lttng_process_attr_value_type lttng_process_attr_values_get_type_at_index(
429 const struct lttng_process_attr_values *values,
430 unsigned int index)
431 {
432 enum lttng_process_attr_value_type type;
433 const struct process_attr_value *value;
434
435 if (!values) {
436 type = LTTNG_PROCESS_ATTR_VALUE_TYPE_INVALID;
437 goto end;
438 }
439
440 if (_lttng_process_attr_values_get_count(values) <= index) {
441 type = LTTNG_PROCESS_ATTR_VALUE_TYPE_INVALID;
442 goto end;
443 }
444
445 value = lttng_process_attr_tracker_values_get_at_index(values, index);
446 type = value->type;
447 end:
448 return type;
449 }
450
451 #define DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER( \
452 value_type_name, value_type, expected_value_type) \
453 enum lttng_process_attr_values_status \
454 lttng_process_attr_values_get_##value_type_name##_at_index( \
455 const struct lttng_process_attr_values \
456 *values, \
457 unsigned int index, \
458 value_type *out_value) \
459 { \
460 enum lttng_process_attr_values_status status = \
461 LTTNG_PROCESS_ATTR_VALUES_STATUS_OK; \
462 const struct process_attr_value *value; \
463 \
464 if (!values) { \
465 status = LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID; \
466 goto end; \
467 } \
468 \
469 if (_lttng_process_attr_values_get_count(values) <= index) { \
470 status = LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID; \
471 goto end; \
472 } \
473 \
474 value = lttng_process_attr_tracker_values_get_at_index( \
475 values, index); \
476 if (value->type != \
477 LTTNG_PROCESS_ATTR_VALUE_TYPE_##expected_value_type) { \
478 status = LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID_TYPE; \
479 goto end; \
480 } \
481 *out_value = value->value.value_type_name; \
482 end: \
483 return status; \
484 }
485
486 DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER(pid, pid_t, PID);
487 DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER(uid, uid_t, UID);
488 DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER(gid, gid_t, GID);
489 DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER(user_name, const char *, USER_NAME);
490 DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER(group_name, const char *, GROUP_NAME);
491
492 static enum lttng_error_code handle_status_to_error_code(
493 enum lttng_process_attr_tracker_handle_status handle_status)
494 {
495 switch (handle_status) {
496 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY:
497 return LTTNG_ERR_INVALID;
498 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST:
499 return LTTNG_ERR_SESSION_NOT_EXIST;
500 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR:
501 return LTTNG_ERR_INVALID_PROTOCOL;
502 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_EXISTS:
503 return LTTNG_ERR_PID_TRACKED;
504 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_MISSING:
505 return LTTNG_ERR_PID_NOT_TRACKED;
506 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK:
507 return LTTNG_OK;
508 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR:
509 default:
510 /* fall-through. */
511 return LTTNG_ERR_UNK;
512 }
513 }
514
515 /*
516 * Add PID to session tracker.
517 * Return 0 on success else a negative LTTng error code.
518 */
519 int lttng_track_pid(struct lttng_handle *handle, int pid)
520 {
521 enum lttng_error_code ret_code;
522 struct lttng_process_attr_tracker_handle *tracker_handle = NULL;
523 enum lttng_process_attr_tracker_handle_status handle_status;
524 enum lttng_tracking_policy policy;
525 enum lttng_process_attr process_attr;
526
527 if (!handle) {
528 ret_code = LTTNG_ERR_INVALID;
529 goto end;
530 }
531
532 process_attr = handle->domain.type == LTTNG_DOMAIN_KERNEL ?
533 LTTNG_PROCESS_ATTR_PROCESS_ID :
534 LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID;
535
536 ret_code = lttng_session_get_tracker_handle(handle->session_name,
537 handle->domain.type,
538 process_attr, &tracker_handle);
539 if (ret_code != LTTNG_OK) {
540 goto end;
541 }
542
543 if (pid == -1) {
544 handle_status = lttng_process_attr_tracker_handle_set_tracking_policy(
545 tracker_handle,
546 LTTNG_TRACKING_POLICY_INCLUDE_ALL);
547 ret_code = handle_status_to_error_code(handle_status);
548 goto end;
549 }
550
551 handle_status = lttng_process_attr_tracker_handle_get_tracking_policy(
552 tracker_handle, &policy);
553 if (handle_status != LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) {
554 ret_code = handle_status_to_error_code(handle_status);
555 goto end;
556 }
557
558 if (policy != LTTNG_TRACKING_POLICY_INCLUDE_SET) {
559 handle_status = lttng_process_attr_tracker_handle_set_tracking_policy(
560 tracker_handle,
561 LTTNG_TRACKING_POLICY_INCLUDE_SET);
562 if (handle_status != LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) {
563 ret_code = handle_status_to_error_code(handle_status);
564 goto end;
565 }
566 }
567
568 handle_status = process_attr == LTTNG_PROCESS_ATTR_PROCESS_ID ?
569 lttng_process_attr_process_id_tracker_handle_add_pid(
570 tracker_handle,
571 (pid_t) pid) :
572 lttng_process_attr_virtual_process_id_tracker_handle_add_pid(
573 tracker_handle,
574 (pid_t) pid);
575 ret_code = handle_status_to_error_code(handle_status);
576 end:
577 lttng_process_attr_tracker_handle_destroy(tracker_handle);
578 return ret_code == LTTNG_OK ? 0 : -ret_code;
579 }
580
581 /*
582 * Remove PID from session tracker.
583 * Return 0 on success else a negative LTTng error code.
584 */
585 int lttng_untrack_pid(struct lttng_handle *handle, int pid)
586 {
587 enum lttng_error_code ret_code;
588 struct lttng_process_attr_tracker_handle *tracker_handle = NULL;
589 enum lttng_process_attr_tracker_handle_status handle_status;
590 enum lttng_tracking_policy policy;
591 enum lttng_process_attr process_attr;
592
593 if (!handle) {
594 ret_code = LTTNG_ERR_INVALID;
595 goto end;
596 }
597
598 process_attr = handle->domain.type == LTTNG_DOMAIN_KERNEL ?
599 LTTNG_PROCESS_ATTR_PROCESS_ID :
600 LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID;
601 ret_code = lttng_session_get_tracker_handle(handle->session_name,
602 handle->domain.type, process_attr, &tracker_handle);
603 if (ret_code != LTTNG_OK) {
604 goto end;
605 }
606
607 if (pid == -1) {
608 handle_status = lttng_process_attr_tracker_handle_set_tracking_policy(
609 tracker_handle,
610 LTTNG_TRACKING_POLICY_EXCLUDE_ALL);
611 ret_code = handle_status_to_error_code(handle_status);
612 goto end;
613 }
614
615 handle_status = lttng_process_attr_tracker_handle_get_tracking_policy(
616 tracker_handle, &policy);
617 if (handle_status != LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) {
618 ret_code = handle_status_to_error_code(handle_status);
619 goto end;
620 }
621
622 if (policy == LTTNG_TRACKING_POLICY_EXCLUDE_ALL) {
623 ret_code = LTTNG_ERR_PID_NOT_TRACKED;
624 goto end;
625 } else if (policy == LTTNG_TRACKING_POLICY_INCLUDE_ALL) {
626 ret_code = LTTNG_ERR_INVALID;
627 goto end;
628 }
629
630 handle_status = process_attr == LTTNG_PROCESS_ATTR_PROCESS_ID ?
631 lttng_process_attr_process_id_tracker_handle_remove_pid(
632 tracker_handle,
633 (pid_t) pid) :
634 lttng_process_attr_virtual_process_id_tracker_handle_remove_pid(
635 tracker_handle,
636 (pid_t) pid);
637 if (handle_status == LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY) {
638 ret_code = LTTNG_ERR_PID_NOT_TRACKED;
639 }
640 end:
641 lttng_process_attr_tracker_handle_destroy(tracker_handle);
642 return ret_code == LTTNG_OK ? 0 : -ret_code;
643 }
644
645 /*
646 * List PIDs in the tracker.
647 *
648 * enabled is set to whether the PID tracker is enabled.
649 * pids is set to an allocated array of PIDs currently tracked. On
650 * success, pids must be freed by the caller.
651 * nr_pids is set to the number of entries contained by the pids array.
652 *
653 * Returns 0 on success, else a negative LTTng error code.
654 */
655 int lttng_list_tracker_pids(struct lttng_handle *handle,
656 int *_enabled,
657 int32_t **_pids,
658 size_t *_nr_pids)
659 {
660 enum lttng_error_code ret_code;
661 struct lttng_process_attr_tracker_handle *tracker_handle = NULL;
662 enum lttng_process_attr_tracker_handle_status handle_status;
663 const struct lttng_process_attr_values *values;
664 enum lttng_tracking_policy policy;
665 unsigned int pid_count, i;
666 int32_t *pid_array = NULL;
667
668 if (!handle || !_enabled || !_pids || !_nr_pids) {
669 ret_code = LTTNG_ERR_INVALID;
670 goto end;
671 }
672
673 ret_code = lttng_session_get_tracker_handle(handle->session_name,
674 handle->domain.type,
675 LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID, &tracker_handle);
676 if (ret_code != LTTNG_OK) {
677 goto end;
678 }
679
680 while (true) {
681 handle_status = lttng_process_attr_tracker_handle_get_inclusion_set(
682 tracker_handle, &values);
683 if (handle_status ==
684 LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) {
685 policy = LTTNG_TRACKING_POLICY_INCLUDE_SET;
686 break;
687 } else if (handle_status !=
688 LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY) {
689 ret_code = handle_status_to_error_code(handle_status);
690 goto end;
691 }
692
693 handle_status = lttng_process_attr_tracker_handle_get_tracking_policy(
694 tracker_handle, &policy);
695 if (handle_status !=
696 LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) {
697 ret_code = handle_status_to_error_code(handle_status);
698 goto end;
699 }
700
701 /* Tracking policy changed in the meantime, retry. */
702 if (policy == LTTNG_TRACKING_POLICY_INCLUDE_SET) {
703 continue;
704 }
705 break;
706 }
707
708 switch (policy) {
709 case LTTNG_TRACKING_POLICY_INCLUDE_ALL:
710 *_enabled = 0;
711 goto end;
712 case LTTNG_TRACKING_POLICY_EXCLUDE_ALL:
713 *_enabled = 1;
714 pid_count = 0;
715 break;
716 case LTTNG_TRACKING_POLICY_INCLUDE_SET:
717 {
718 const enum lttng_process_attr_values_status values_status =
719 lttng_process_attr_values_get_count(
720 values, &pid_count);
721
722 if (values_status != LTTNG_PROCESS_ATTR_VALUES_STATUS_OK) {
723 ret_code = LTTNG_ERR_UNK;
724 goto end;
725 }
726 break;
727 }
728 default:
729 ret_code = LTTNG_ERR_INVALID_PROTOCOL;
730 goto end;
731 }
732
733 pid_array = zmalloc(pid_count * sizeof(int32_t));
734 if (!pid_array) {
735 ret_code = LTTNG_ERR_NOMEM;
736 goto end;
737 }
738
739 /* Extract values to a raw array. */
740 for (i = 0; i < pid_count; i++) {
741 pid_t pid;
742 const enum lttng_process_attr_values_status values_status =
743 lttng_process_attr_values_get_pid_at_index(
744 values, i, &pid);
745
746 if (values_status != LTTNG_PROCESS_ATTR_VALUES_STATUS_OK) {
747 ret_code = LTTNG_ERR_UNK;
748 goto end;
749 }
750 pid_array[i] = (int32_t) pid;
751 }
752 *_nr_pids = (size_t) pid_count;
753 *_pids = pid_array;
754 pid_array = NULL;
755 end:
756 lttng_process_attr_tracker_handle_destroy(tracker_handle);
757 free(pid_array);
758 return ret_code == LTTNG_OK ? 0 : -ret_code;
759 }
This page took 0.067501 seconds and 3 git commands to generate.