+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,
+ struct lttng_tracker_id *id)
+{
+ int ret, value;
+ struct lttng_tracker_list *tracker_list;
+
+ ret = lttng_tracker_id_lookup_string(tracker_type,
+ id, &value);
+ if (ret != LTTNG_OK) {
+ return ret;
+ }
+
+ /* Add to list. */
+ tracker_list = get_id_tracker_list(session, tracker_type);
+ if (!tracker_list) {
+ return LTTNG_ERR_INVALID;
+ }
+ ret = lttng_tracker_list_add(tracker_list, id);
+ if (ret != LTTNG_OK) {
+ return ret;
+ }
+
+ 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) {
+ return LTTNG_OK;
+ }
+ 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) {
+ return LTTNG_OK;
+ }
+ 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) {
+ return LTTNG_OK;
+ }
+ 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) {
+ return LTTNG_OK;
+ }
+ 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) {
+ return LTTNG_OK;
+ }
+ 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) {
+ return LTTNG_OK;
+ }
+ break;
+ default:
+ return LTTNG_ERR_INVALID;
+ }
+ switch (-ret) {
+ case EINVAL:
+ return LTTNG_ERR_INVALID;
+ case ENOMEM:
+ return LTTNG_ERR_NOMEM;
+ case EEXIST:
+ return LTTNG_ERR_ID_TRACKED;
+ default:
+ return LTTNG_ERR_UNK;
+ }
+}
+
+int kernel_untrack_id(enum lttng_tracker_type tracker_type,
+ struct ltt_kernel_session *session,
+ struct lttng_tracker_id *id)
+{
+ int ret, value;
+ struct lttng_tracker_list *tracker_list;
+
+ ret = lttng_tracker_id_lookup_string(tracker_type,
+ id, &value);
+ if (ret != LTTNG_OK) {
+ return ret;
+ }
+
+ /* Remove from list. */
+ tracker_list = get_id_tracker_list(session, tracker_type);
+ if (!tracker_list) {
+ return LTTNG_ERR_INVALID;
+ }
+ ret = lttng_tracker_list_remove(tracker_list, id);
+ if (ret != LTTNG_OK) {
+ return ret;
+ }
+
+ 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) {
+ return LTTNG_OK;
+ }
+ 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) {
+ return LTTNG_OK;
+ }
+ 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) {
+ return LTTNG_OK;
+ }
+ 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) {
+ return LTTNG_OK;
+ }
+ 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) {
+ return LTTNG_OK;
+ }
+ 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) {
+ return LTTNG_OK;
+ }
+ break;
+ default:
+ return LTTNG_ERR_INVALID;
+ }
+
+ switch (-ret) {
+ case EINVAL:
+ return LTTNG_ERR_INVALID;
+ case ENOMEM:
+ return LTTNG_ERR_NOMEM;
+ case ENOENT:
+ return LTTNG_ERR_ID_NOT_TRACKED;
+ default:
+ return LTTNG_ERR_UNK;
+ }
+}
+
+/*
+ * Called with session lock held.
+ */
+ssize_t kernel_list_tracker_ids(enum lttng_tracker_type tracker_type,
+ struct ltt_kernel_session *session,
+ struct lttng_tracker_id **_ids)
+{
+ struct lttng_tracker_list *tracker_list;
+
+ tracker_list = get_id_tracker_list(session, tracker_type);
+ if (!tracker_list) {
+ return -LTTNG_ERR_INVALID;
+ }
+ return lttng_tracker_id_get_list(tracker_list, _ids);
+}
+