Fix: tracker: ensure consistency of tracker states
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 4 Jul 2018 21:51:47 +0000 (17:51 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 4 Jul 2018 21:51:47 +0000 (17:51 -0400)
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 <mathieu.desnoyers@efficios.com>
src/bin/lttng-sessiond/kernel.c
src/bin/lttng-sessiond/trace-ust.c

index e223bcc075cd524b6c0633828084296b1d5bbf20..241ff1576c669e433ea71adea316d41bc13bfefb 100644 (file)
@@ -424,6 +424,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);
@@ -431,14 +433,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) {
@@ -447,7 +454,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:
@@ -455,7 +463,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:
@@ -463,7 +472,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:
@@ -471,7 +481,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:
@@ -479,7 +490,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:
@@ -487,22 +499,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,
@@ -511,6 +539,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);
@@ -518,14 +548,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) {
@@ -534,7 +569,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:
@@ -542,7 +578,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:
@@ -550,7 +587,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:
@@ -558,7 +596,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:
@@ -566,7 +605,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:
@@ -574,23 +614,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;
 }
 
 /*
index ff0c9751374dd861fba6c1b1ac9e5e312bd23195..629d57c42d28f080527a88abc3bbbbf9b4e77638 100644 (file)
@@ -877,6 +877,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.");
@@ -888,15 +890,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);
@@ -916,12 +922,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);
@@ -930,7 +936,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) {
@@ -946,7 +952,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;
 }
 
@@ -960,6 +976,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.");
@@ -972,14 +990,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);
@@ -997,7 +1020,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);
 
@@ -1009,12 +1032,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:
@@ -1029,7 +1052,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;
 }
 
This page took 0.034992 seconds and 5 git commands to generate.