+static struct lttng_tracker_list *get_id_tracker_list(
+ struct ltt_kernel_session *session,
+ enum lttng_tracker_type tracker_type)
+{
+ switch (tracker_type) {
+ case LTTNG_TRACKER_PID:
+ return session->tracker_list_pid;
+ case LTTNG_TRACKER_VPID:
+ return session->tracker_list_vpid;
+ case LTTNG_TRACKER_UID:
+ return session->tracker_list_uid;
+ case LTTNG_TRACKER_VUID:
+ return session->tracker_list_vuid;
+ case LTTNG_TRACKER_GID:
+ return session->tracker_list_gid;
+ case LTTNG_TRACKER_VGID:
+ return session->tracker_list_vgid;
+ default:
+ return NULL;
+ }
+}
+
+int kernel_track_id(enum lttng_tracker_type tracker_type,
+ struct ltt_kernel_session *session,
+ const struct lttng_tracker_id *id)
+{
+ int ret, value;
+ struct lttng_tracker_list *tracker_list;
+ struct lttng_tracker_ids *saved_ids;
+
+ ret = lttng_tracker_id_lookup_string(tracker_type, id, &value);
+ if (ret != LTTNG_OK) {
+ return ret;
+ }
+
+ tracker_list = get_id_tracker_list(session, tracker_type);
+ if (!tracker_list) {
+ return LTTNG_ERR_INVALID;
+ }
+
+ /* Save list for restore on error. */
+ ret = lttng_tracker_id_get_list(tracker_list, &saved_ids);
+ if (ret != LTTNG_OK) {
+ return LTTNG_ERR_INVALID;
+ }
+
+ /* Add to list. */
+ ret = lttng_tracker_list_add(tracker_list, id);
+ if (ret != LTTNG_OK) {
+ goto end;
+ }
+
+ switch (tracker_type) {
+ case LTTNG_TRACKER_PID:
+ DBG("Kernel track PID %d for session id %" PRIu64 ".", value,
+ session->id);
+ ret = kernctl_track_pid(session->fd, value);
+ if (!ret) {
+ ret = LTTNG_OK;
+ goto end;
+ }
+ break;
+ case LTTNG_TRACKER_VPID:
+ DBG("Kernel track VPID %d for session id %" PRIu64 ".", value,
+ session->id);
+ ret = kernctl_track_id(session->fd, LTTNG_TRACKER_VPID, value);
+ if (!ret) {
+ ret = LTTNG_OK;
+ goto end;
+ }
+ break;
+ case LTTNG_TRACKER_UID:
+ DBG("Kernel track UID %d for session id %" PRIu64 ".", value,
+ session->id);
+ ret = kernctl_track_id(session->fd, LTTNG_TRACKER_UID, value);
+ if (!ret) {
+ ret = LTTNG_OK;
+ goto end;
+ }
+ break;
+ case LTTNG_TRACKER_GID:
+ DBG("Kernel track GID %d for session id %" PRIu64 ".", value,
+ session->id);
+ ret = kernctl_track_id(session->fd, LTTNG_TRACKER_GID, value);
+ if (!ret) {
+ ret = LTTNG_OK;
+ goto end;
+ }
+ break;
+ case LTTNG_TRACKER_VUID:
+ DBG("Kernel track VUID %d for session id %" PRIu64 ".", value,
+ session->id);
+ ret = kernctl_track_id(session->fd, LTTNG_TRACKER_VUID, value);
+ if (!ret) {
+ ret = LTTNG_OK;
+ goto end;
+ }
+ break;
+ case LTTNG_TRACKER_VGID:
+ DBG("Kernel track VGID %d for session id %" PRIu64 ".", value,
+ session->id);
+ ret = kernctl_track_id(session->fd, LTTNG_TRACKER_VGID, value);
+ if (!ret) {
+ ret = LTTNG_OK;
+ goto end;
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ /* Error handling. */
+ switch (-ret) {
+ case EINVAL:
+ ret = LTTNG_ERR_INVALID;
+ break;
+ case ENOMEM:
+ ret = LTTNG_ERR_NOMEM;
+ break;
+ case EEXIST:
+ ret = LTTNG_ERR_ID_TRACKED;
+ break;
+ default:
+ ret = LTTNG_ERR_UNK;
+ break;
+ }
+
+ if (lttng_tracker_id_set_list(tracker_list, saved_ids) != LTTNG_OK) {
+ ERR("Error on tracker add error handling.\n");
+ }
+end:
+ lttng_tracker_ids_destroy(saved_ids);
+ return ret;
+}
+
+int kernel_untrack_id(enum lttng_tracker_type tracker_type,
+ struct ltt_kernel_session *session,
+ const struct lttng_tracker_id *id)
+{
+ int ret, value;
+ struct lttng_tracker_list *tracker_list;
+ struct lttng_tracker_ids *saved_ids;
+
+ ret = lttng_tracker_id_lookup_string(tracker_type, id, &value);
+ if (ret != LTTNG_OK) {
+ return ret;
+ }
+
+ tracker_list = get_id_tracker_list(session, tracker_type);
+ if (!tracker_list) {
+ return LTTNG_ERR_INVALID;
+ }
+ /* Save list for restore on error. */
+ ret = lttng_tracker_id_get_list(tracker_list, &saved_ids);
+ if (ret != LTTNG_OK) {
+ return LTTNG_ERR_INVALID;
+ }
+ /* Remove from list. */
+ ret = lttng_tracker_list_remove(tracker_list, id);
+ if (ret != LTTNG_OK) {
+ goto end;
+ }
+
+ switch (tracker_type) {
+ case LTTNG_TRACKER_PID:
+ DBG("Kernel untrack PID %d for session id %" PRIu64 ".", value,
+ session->id);
+ ret = kernctl_untrack_pid(session->fd, value);
+ if (!ret) {
+ ret = LTTNG_OK;
+ goto end;
+ }
+ break;
+ case LTTNG_TRACKER_VPID:
+ DBG("Kernel untrack VPID %d for session id %" PRIu64 ".", value,
+ session->id);
+ ret = kernctl_untrack_id(
+ session->fd, LTTNG_TRACKER_VPID, value);
+ if (!ret) {
+ ret = LTTNG_OK;
+ goto end;
+ }
+ break;
+ case LTTNG_TRACKER_UID:
+ DBG("Kernel untrack UID %d for session id %" PRIu64 ".", value,
+ session->id);
+ ret = kernctl_untrack_id(session->fd, LTTNG_TRACKER_UID, value);
+ if (!ret) {
+ ret = LTTNG_OK;
+ goto end;
+ }
+ break;
+ case LTTNG_TRACKER_GID:
+ DBG("Kernel untrack GID %d for session id %" PRIu64 ".", value,
+ session->id);
+ ret = kernctl_untrack_id(session->fd, LTTNG_TRACKER_GID, value);
+ if (!ret) {
+ ret = LTTNG_OK;
+ goto end;
+ }
+ break;
+ case LTTNG_TRACKER_VUID:
+ DBG("Kernel untrack VUID %d for session id %" PRIu64 ".", value,
+ session->id);
+ ret = kernctl_untrack_id(
+ session->fd, LTTNG_TRACKER_VUID, value);
+ if (!ret) {
+ ret = LTTNG_OK;
+ goto end;
+ }
+ break;
+ case LTTNG_TRACKER_VGID:
+ DBG("Kernel untrack VGID %d for session id %" PRIu64 ".", value,
+ session->id);
+ ret = kernctl_untrack_id(
+ session->fd, LTTNG_TRACKER_VGID, value);
+ if (!ret) {
+ ret = LTTNG_OK;
+ goto end;
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ /* Error handling. */
+ switch (-ret) {
+ case EINVAL:
+ ret = LTTNG_ERR_INVALID;
+ break;
+ case ENOMEM:
+ ret = LTTNG_ERR_NOMEM;
+ break;
+ case EEXIST:
+ ret = LTTNG_ERR_ID_TRACKED;
+ break;
+ default:
+ ret = LTTNG_ERR_UNK;
+ break;
+ }
+
+ if (lttng_tracker_id_set_list(tracker_list, saved_ids) != LTTNG_OK) {
+ ERR("Error on tracker remove error handling.\n");
+ }
+end:
+ lttng_tracker_ids_destroy(saved_ids);
+ return ret;
+}
+
+/*
+ * Called with session lock held.
+ */
+int kernel_list_tracker_ids(enum lttng_tracker_type tracker_type,
+ struct ltt_kernel_session *session,
+ struct lttng_tracker_ids **_ids)
+{
+ int ret = 0;
+ struct lttng_tracker_list *tracker_list;
+
+ tracker_list = get_id_tracker_list(session, tracker_type);
+ if (!tracker_list) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = lttng_tracker_id_get_list(tracker_list, _ids);
+ if (ret != LTTNG_OK) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+end:
+ return ret;
+}
+