From de04bbc88637bb336255f6cc7c7e4f4ea179f40d Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Wed, 4 Jul 2018 17:51:47 -0400 Subject: [PATCH] Backport: Fix: tracker: ensure consistency of tracker states On error when adding/removing from either UST or kernel trackers, we need to roll back the state of our internal lists. Signed-off-by: Mathieu Desnoyers --- src/bin/lttng-sessiond/kernel.c | 111 ++++++++++++++++++++++------- src/bin/lttng-sessiond/trace-ust.c | 55 +++++++++++--- 2 files changed, 128 insertions(+), 38 deletions(-) diff --git a/src/bin/lttng-sessiond/kernel.c b/src/bin/lttng-sessiond/kernel.c index ea0e75d7f..a72fe7f5c 100644 --- a/src/bin/lttng-sessiond/kernel.c +++ b/src/bin/lttng-sessiond/kernel.c @@ -412,6 +412,8 @@ int kernel_track_id(enum lttng_tracker_type tracker_type, { int ret, value; struct lttng_tracker_list *tracker_list; + struct lttng_tracker_id *saved_ids; + ssize_t saved_ids_count, i; ret = lttng_tracker_id_lookup_string(tracker_type, id, &value); @@ -419,14 +421,19 @@ int kernel_track_id(enum lttng_tracker_type tracker_type, return ret; } - /* Add to list. */ tracker_list = get_id_tracker_list(session, tracker_type); if (!tracker_list) { return LTTNG_ERR_INVALID; } + /* Save list for restore on error. */ + saved_ids_count = lttng_tracker_id_get_list(tracker_list, &saved_ids); + if (saved_ids_count < 0) { + return LTTNG_ERR_INVALID; + } + /* Add to list. */ ret = lttng_tracker_list_add(tracker_list, id); if (ret != LTTNG_OK) { - return ret; + goto end; } switch (tracker_type) { @@ -435,7 +442,8 @@ int kernel_track_id(enum lttng_tracker_type tracker_type, value, session->id); ret = kernctl_track_pid(session->fd, value); if (!ret) { - return LTTNG_OK; + ret = LTTNG_OK; + goto end; } break; case LTTNG_TRACKER_VPID: @@ -443,7 +451,8 @@ int kernel_track_id(enum lttng_tracker_type tracker_type, value, session->id); ret = kernctl_track_id(session->fd, LTTNG_TRACKER_VPID, value); if (!ret) { - return LTTNG_OK; + ret = LTTNG_OK; + goto end; } break; case LTTNG_TRACKER_UID: @@ -451,7 +460,8 @@ int kernel_track_id(enum lttng_tracker_type tracker_type, value, session->id); ret = kernctl_track_id(session->fd, LTTNG_TRACKER_UID, value); if (!ret) { - return LTTNG_OK; + ret = LTTNG_OK; + goto end; } break; case LTTNG_TRACKER_GID: @@ -459,7 +469,8 @@ int kernel_track_id(enum lttng_tracker_type tracker_type, value, session->id); ret = kernctl_track_id(session->fd, LTTNG_TRACKER_GID, value); if (!ret) { - return LTTNG_OK; + ret = LTTNG_OK; + goto end; } break; case LTTNG_TRACKER_VUID: @@ -467,7 +478,8 @@ int kernel_track_id(enum lttng_tracker_type tracker_type, value, session->id); ret = kernctl_track_id(session->fd, LTTNG_TRACKER_VUID, value); if (!ret) { - return LTTNG_OK; + ret = LTTNG_OK; + goto end; } break; case LTTNG_TRACKER_VGID: @@ -475,22 +487,38 @@ int kernel_track_id(enum lttng_tracker_type tracker_type, value, session->id); ret = kernctl_track_id(session->fd, LTTNG_TRACKER_VGID, value); if (!ret) { - return LTTNG_OK; + ret = LTTNG_OK; + goto end; } break; default: - return LTTNG_ERR_INVALID; + ret = -EINVAL; + break; } + /* Error handling. */ switch (-ret) { case EINVAL: - return LTTNG_ERR_INVALID; + ret = LTTNG_ERR_INVALID; + break; case ENOMEM: - return LTTNG_ERR_NOMEM; + ret = LTTNG_ERR_NOMEM; + break; case EEXIST: - return LTTNG_ERR_ID_TRACKED; + ret = LTTNG_ERR_ID_TRACKED; + break; default: - return LTTNG_ERR_UNK; + ret = LTTNG_ERR_UNK; + break; + } + if (lttng_tracker_id_set_list(tracker_list, saved_ids, saved_ids_count) != LTTNG_OK) { + ERR("Error on tracker add error handling.\n"); + } +end: + for (i = 0; i < saved_ids_count; i++) { + free(saved_ids[i].string); } + free(saved_ids); + return ret; } int kernel_untrack_id(enum lttng_tracker_type tracker_type, @@ -499,6 +527,8 @@ int kernel_untrack_id(enum lttng_tracker_type tracker_type, { int ret, value; struct lttng_tracker_list *tracker_list; + struct lttng_tracker_id *saved_ids; + ssize_t saved_ids_count, i; ret = lttng_tracker_id_lookup_string(tracker_type, id, &value); @@ -506,14 +536,19 @@ int kernel_untrack_id(enum lttng_tracker_type tracker_type, return ret; } - /* Remove from list. */ tracker_list = get_id_tracker_list(session, tracker_type); if (!tracker_list) { return LTTNG_ERR_INVALID; } + /* Save list for restore on error. */ + saved_ids_count = lttng_tracker_id_get_list(tracker_list, &saved_ids); + if (saved_ids_count < 0) { + return LTTNG_ERR_INVALID; + } + /* Remove from list. */ ret = lttng_tracker_list_remove(tracker_list, id); if (ret != LTTNG_OK) { - return ret; + goto end; } switch (tracker_type) { @@ -522,7 +557,8 @@ int kernel_untrack_id(enum lttng_tracker_type tracker_type, value, session->id); ret = kernctl_untrack_pid(session->fd, value); if (!ret) { - return LTTNG_OK; + ret = LTTNG_OK; + goto end; } break; case LTTNG_TRACKER_VPID: @@ -530,7 +566,8 @@ int kernel_untrack_id(enum lttng_tracker_type tracker_type, value, session->id); ret = kernctl_untrack_id(session->fd, LTTNG_TRACKER_VPID, value); if (!ret) { - return LTTNG_OK; + ret = LTTNG_OK; + goto end; } break; case LTTNG_TRACKER_UID: @@ -538,7 +575,8 @@ int kernel_untrack_id(enum lttng_tracker_type tracker_type, value, session->id); ret = kernctl_untrack_id(session->fd, LTTNG_TRACKER_UID, value); if (!ret) { - return LTTNG_OK; + ret = LTTNG_OK; + goto end; } break; case LTTNG_TRACKER_GID: @@ -546,7 +584,8 @@ int kernel_untrack_id(enum lttng_tracker_type tracker_type, value, session->id); ret = kernctl_untrack_id(session->fd, LTTNG_TRACKER_GID, value); if (!ret) { - return LTTNG_OK; + ret = LTTNG_OK; + goto end; } break; case LTTNG_TRACKER_VUID: @@ -554,7 +593,8 @@ int kernel_untrack_id(enum lttng_tracker_type tracker_type, value, session->id); ret = kernctl_untrack_id(session->fd, LTTNG_TRACKER_VUID, value); if (!ret) { - return LTTNG_OK; + ret = LTTNG_OK; + goto end; } break; case LTTNG_TRACKER_VGID: @@ -562,23 +602,40 @@ int kernel_untrack_id(enum lttng_tracker_type tracker_type, value, session->id); ret = kernctl_untrack_id(session->fd, LTTNG_TRACKER_VGID, value); if (!ret) { - return LTTNG_OK; + ret = LTTNG_OK; + goto end; } break; default: - return LTTNG_ERR_INVALID; + ret = -EINVAL; + break; } + /* Error handling. */ switch (-ret) { case EINVAL: - return LTTNG_ERR_INVALID; + ret = LTTNG_ERR_INVALID; + break; case ENOMEM: - return LTTNG_ERR_NOMEM; - case ENOENT: - return LTTNG_ERR_ID_NOT_TRACKED; + ret = LTTNG_ERR_NOMEM; + break; + case EEXIST: + ret = LTTNG_ERR_ID_TRACKED; + break; default: - return LTTNG_ERR_UNK; + ret = LTTNG_ERR_UNK; + break; + } + + if (lttng_tracker_id_set_list(tracker_list, saved_ids, saved_ids_count) != LTTNG_OK) { + ERR("Error on tracker remove error handling.\n"); } +end: + for (i = 0; i < saved_ids_count; i++) { + free(saved_ids[i].string); + } + free(saved_ids); + return ret; } /* diff --git a/src/bin/lttng-sessiond/trace-ust.c b/src/bin/lttng-sessiond/trace-ust.c index 10af67e37..29263e7c8 100644 --- a/src/bin/lttng-sessiond/trace-ust.c +++ b/src/bin/lttng-sessiond/trace-ust.c @@ -874,6 +874,8 @@ int trace_ust_track_id(enum lttng_tracker_type tracker_type, struct ust_id_tracker *id_tracker; struct lttng_tracker_list *tracker_list; int value; + struct lttng_tracker_id *saved_ids; + ssize_t saved_ids_count, i; if (tracker_type == LTTNG_TRACKER_PID) { DBG("Backward compatible behavior: translate PID tracker to VPID tracker for UST domain."); @@ -885,15 +887,19 @@ int trace_ust_track_id(enum lttng_tracker_type tracker_type, if (retval != LTTNG_OK) { return retval; } - - /* Add to list. */ tracker_list = get_id_tracker_list(session, tracker_type); if (!tracker_list) { return LTTNG_ERR_INVALID; } + /* Save list for restore on error. */ + saved_ids_count = lttng_tracker_id_get_list(tracker_list, &saved_ids); + if (saved_ids_count < 0) { + return LTTNG_ERR_INVALID; + } + /* Add to list. */ retval = lttng_tracker_list_add(tracker_list, id); if (retval != LTTNG_OK) { - return retval; + goto end; } id_tracker = get_id_tracker(session, tracker_type); @@ -913,12 +919,12 @@ int trace_ust_track_id(enum lttng_tracker_type tracker_type, retval = init_id_tracker(id_tracker); if (retval != LTTNG_OK) { ERR("Error initializing ID tracker"); - goto end; + goto end_restore; } retval = id_tracker_add_id(id_tracker, value); if (retval != LTTNG_OK) { fini_id_tracker(id_tracker); - goto end; + goto end_restore; } /* Keep only apps matching ID. */ ust_app_global_update_all(session); @@ -927,7 +933,7 @@ int trace_ust_track_id(enum lttng_tracker_type tracker_type, retval = id_tracker_add_id(id_tracker, value); if (retval != LTTNG_OK) { - goto end; + goto end_restore; } /* Add session to application */ switch (tracker_type) { @@ -943,7 +949,17 @@ int trace_ust_track_id(enum lttng_tracker_type tracker_type, } } } + goto end; + +end_restore: + if (lttng_tracker_id_set_list(tracker_list, saved_ids, saved_ids_count) != LTTNG_OK) { + ERR("Error on tracker add error handling.\n"); + } end: + for (i = 0; i < saved_ids_count; i++) { + free(saved_ids[i].string); + } + free(saved_ids); return retval; } @@ -957,6 +973,8 @@ int trace_ust_untrack_id(enum lttng_tracker_type tracker_type, struct ust_id_tracker *id_tracker; struct lttng_tracker_list *tracker_list; int value; + struct lttng_tracker_id *saved_ids; + ssize_t saved_ids_count, i; if (tracker_type == LTTNG_TRACKER_PID) { DBG("Backward compatible behavior: translate PID tracker to VPID tracker for UST domain."); @@ -969,14 +987,19 @@ int trace_ust_untrack_id(enum lttng_tracker_type tracker_type, return retval; } - /* Remove from list. */ tracker_list = get_id_tracker_list(session, tracker_type); if (!tracker_list) { return LTTNG_ERR_INVALID; } + /* Save list for restore on error. */ + saved_ids_count = lttng_tracker_id_get_list(tracker_list, &saved_ids); + if (saved_ids_count < 0) { + return LTTNG_ERR_INVALID; + } + /* Remove from list. */ retval = lttng_tracker_list_remove(tracker_list, id); if (retval != LTTNG_OK) { - return retval; + goto end; } id_tracker = get_id_tracker(session, tracker_type); @@ -994,7 +1017,7 @@ int trace_ust_untrack_id(enum lttng_tracker_type tracker_type, ERR("Error initializing ID tracker"); /* Rollback operation. */ *id_tracker = tmp_tracker; - goto end; + goto end_restore; } fini_id_tracker(&tmp_tracker); @@ -1006,12 +1029,12 @@ int trace_ust_untrack_id(enum lttng_tracker_type tracker_type, if (!id_tracker->ht) { /* No ID being tracked. */ retval = LTTNG_ERR_ID_NOT_TRACKED; - goto end; + goto end_restore; } /* Remove ID from tracker */ retval = id_tracker_del_id(id_tracker, value); if (retval != LTTNG_OK) { - goto end; + goto end_restore; } switch (tracker_type) { case LTTNG_TRACKER_VPID: @@ -1026,7 +1049,17 @@ int trace_ust_untrack_id(enum lttng_tracker_type tracker_type, ust_app_global_update_all(session); } } + goto end; + +end_restore: + if (lttng_tracker_id_set_list(tracker_list, saved_ids, saved_ids_count) != LTTNG_OK) { + ERR("Error on tracker remove error handling.\n"); + } end: + for (i = 0; i < saved_ids_count; i++) { + free(saved_ids[i].string); + } + free(saved_ids); return retval; } -- 2.34.1