]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udev-rules: update log messages
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 15 Jan 2025 14:47:05 +0000 (23:47 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 17 Jan 2025 19:22:23 +0000 (04:22 +0900)
This also adds trace logs about token result, and skipping assignment
caused by final value already assigned.

src/udev/udev-rules.c

index 3ea1a2346b0ededf72e97f57ba5da076716ca66b..f973985321c6131df7cd3bf7d655ada2584727b3 100644 (file)
@@ -298,6 +298,37 @@ static bool token_is_for_parents(UdevRuleToken *token) {
 #define log_event_trace(event, ...)                                     \
         _log_event_trace(event, UNIQ_T(e, UNIQ), __VA_ARGS__)
 
+#define _log_event_result(event, token, result, result_u)               \
+        ({                                                              \
+                bool result_u = (result);                               \
+                                                                        \
+                log_event_trace(event, token, "%s",                     \
+                                result_u ? "PASS" : "FAIL");            \
+                result_u;                                               \
+        })
+
+#define log_event_result(event, token, result)                          \
+        _log_event_result(event, token, result, UNIQ_T(r, UNIQ))
+
+#define log_event_done(event, token)                                    \
+        ({                                                              \
+                log_event_trace(event, token, "DONE");                  \
+                true;                                                   \
+        })
+
+#define _log_event_final_set(event, token, token_u)                     \
+        ({                                                              \
+                UdevRuleToken *token_u = ASSERT_PTR(token);             \
+                                                                        \
+                log_event_trace(event, token_u,                         \
+                                "Already assigned final value, ignoring further %s.", \
+                                token_u->op == OP_REMOVE ? "modification" : "assignment"); \
+                true;                                                   \
+        })
+
+#define log_event_final_set(event, token)                       \
+        _log_event_final_set(event, token, UNIQ_T(t, UNIQ))
+
 #define _log_event_truncated(event, token, token_u, what, format)       \
         ({                                                              \
                 UdevRuleToken *token_u = ASSERT_PTR(token);             \
@@ -359,16 +390,6 @@ static bool token_is_for_parents(UdevRuleToken *token) {
                              "Invalid value \"%s\" for %s (char %zu: %s), ignoring.", \
                              value, key, offset, hint)
 
-static void log_unknown_owner(sd_device *dev, UdevRuleLine *line, int error, const char *entity, const char *name) {
-        assert(line);
-        ASSERT_NON_ZERO(error);
-
-        if (IN_SET(abs(error), ENOENT, ESRCH))
-                log_udev_rule_line_full(dev, line, LOG_ERR, error, "Unknown %s '%s', ignoring.", entity, name);
-        else
-                log_udev_rule_line_full(dev, line, LOG_ERR, error, "Failed to resolve %s '%s', ignoring: %m", entity, name);
-}
-
 /*** Other functions ***/
 
 static UdevRuleToken* udev_rule_token_free(UdevRuleToken *token) {
@@ -453,7 +474,11 @@ static int rule_resolve_user(UdevRuleLine *rule_line, const char *name, uid_t *r
 
         r = get_user_creds(&name, &uid, NULL, NULL, NULL, USER_CREDS_ALLOW_MISSING);
         if (r < 0) {
-                log_unknown_owner(NULL, rule_line, r, "user", name);
+                if (IN_SET(r, -ENOENT, -ESRCH))
+                        log_line_error_errno(rule_line, r, "Unknown user '%s', ignoring.", name);
+                else
+                        log_line_error_errno(rule_line, r, "Failed to resolve user '%s', ignoring: %m", name);
+
                 *ret = UID_INVALID;
                 return 0;
         }
@@ -489,7 +514,11 @@ static int rule_resolve_group(UdevRuleLine *rule_line, const char *name, gid_t *
 
         r = get_group_creds(&name, &gid, USER_CREDS_ALLOW_MISSING);
         if (r < 0) {
-                log_unknown_owner(NULL, rule_line, r, "group", name);
+                if (IN_SET(r, -ENOENT, -ESRCH))
+                        log_line_error_errno(rule_line, r, "Unknown group '%s', ignoring.", name);
+                else
+                        log_line_error_errno(rule_line, r, "Failed to resolve group '%s', ignoring: %m", name);
+
                 *ret = GID_INVALID;
                 return 0;
         }
@@ -2012,30 +2041,6 @@ static int get_property_from_string(char *line, char **ret_key, char **ret_value
         return 1;
 }
 
-static int import_parent_into_properties(sd_device *dev, const char *filter) {
-        sd_device *parent;
-        int r;
-
-        assert(dev);
-        assert(filter);
-
-        r = sd_device_get_parent(dev, &parent);
-        if (r == -ENOENT)
-                return 0;
-        if (r < 0)
-                return r;
-
-        FOREACH_DEVICE_PROPERTY(parent, key, val) {
-                if (fnmatch(filter, key, 0) != 0)
-                        continue;
-                r = device_add_property(dev, key, val);
-                if (r < 0)
-                        return r;
-        }
-
-        return 1;
-}
-
 static int attr_subst_subdir(char attr[static UDEV_PATH_SIZE]) {
         _cleanup_closedir_ DIR *dir = NULL;
         char buf[UDEV_PATH_SIZE], *p;
@@ -2173,8 +2178,8 @@ static int udev_rule_apply_token_to_event(
         case TK_M_DEVLINK:
                 FOREACH_DEVICE_DEVLINK(dev, val)
                         if (token_match_string(event, token, strempty(startswith(val, "/dev/")), /* log_result = */ false) == (token->op == OP_MATCH))
-                                return token->op == OP_MATCH;
-                return token->op == OP_NOMATCH;
+                                return log_event_result(event, token, token->op == OP_MATCH);
+                return log_event_result(event, token, token->op == OP_NOMATCH);
 
         case TK_M_NAME:
                 return token_match_string(event, token, event->name, /* log_result = */ true);
@@ -2203,8 +2208,8 @@ static int udev_rule_apply_token_to_event(
         case TK_M_PARENTS_TAG:
                 FOREACH_DEVICE_CURRENT_TAG(dev, val)
                         if (token_match_string(event, token, val, /* log_result = */ false) == (token->op == OP_MATCH))
-                                return token->op == OP_MATCH;
-                return token->op == OP_NOMATCH;
+                                return log_event_result(event, token, token->op == OP_MATCH);
+                return log_event_result(event, token, token->op == OP_NOMATCH);
 
         case TK_M_SUBSYSTEM:
         case TK_M_PARENTS_SUBSYSTEM: {
@@ -2243,7 +2248,7 @@ static int udev_rule_apply_token_to_event(
 
                 r = sysctl_read(sysctl_normalize(buf), &value);
                 if (r < 0 && r != -ENOENT)
-                        return log_event_error_errno(event, token, r, "Failed to read sysctl '%s': %m", buf);
+                        return log_event_error_errno(event, token, r, "Failed to read sysctl \"%s\": %m", buf);
 
                 return token_match_string(event, token, strstrip(value), /* log_result = */ true);
         }
@@ -2270,23 +2275,26 @@ static int udev_rule_apply_token_to_event(
                         assert(!truncated);
                         strscpyl_full(buf, sizeof(buf), &truncated, val, "/", tmp, NULL);
                         if (truncated)
-                                return false;
+                                return log_event_result(event, token, false);
                 }
 
                 r = attr_subst_subdir(buf);
                 if (r == -ENOENT)
-                        return token->op == OP_NOMATCH;
+                        return log_event_result(event, token, token->op == OP_NOMATCH);
                 if (r < 0)
-                        return log_event_error_errno(event, token, r, "Failed to test for the existence of '%s': %m", buf);
+                        return log_event_error_errno(event, token, r, "Failed to test for the existence of \"%s\": %m", buf);
 
-                if (stat(buf, &statbuf) < 0)
-                        return token->op == OP_NOMATCH;
+                if (stat(buf, &statbuf) < 0) {
+                        if (errno != ENOENT)
+                                log_event_warning_errno(event, token, errno, "Failed to stat \"%s\", ignoring: %m", buf);
+                        return log_event_result(event, token, token->op == OP_NOMATCH);
+                }
 
                 if (mode == MODE_INVALID)
-                        return token->op == OP_MATCH;
+                        return log_event_result(event, token, token->op == OP_MATCH);
 
                 match = (statbuf.st_mode & mode) > 0;
-                return token->op == (match ? OP_MATCH : OP_NOMATCH);
+                return log_event_result(event, token, token->op == (match ? OP_MATCH : OP_NOMATCH));
         }
         case TK_M_PROGRAM: {
                 char buf[UDEV_LINE_SIZE], result[UDEV_LINE_SIZE];
@@ -2296,7 +2304,7 @@ static int udev_rule_apply_token_to_event(
                 if (!apply_format_value(event, token, buf, sizeof(buf), "command"))
                         return false;
 
-                log_event_debug(event, token, "Running PROGRAM=\"%s\"", buf);
+                log_event_debug(event, token, "Running command \"%s\"", buf);
 
                 r = udev_event_spawn(event, /* accept_failure = */ true, buf, result, sizeof(result), NULL);
                 if (r != 0) {
@@ -2304,14 +2312,14 @@ static int udev_rule_apply_token_to_event(
                                 log_event_warning_errno(event, token, r, "Failed to execute \"%s\": %m", buf);
                         else /* returned value is positive when program fails */
                                 log_event_debug(event, token, "Command \"%s\" returned %d (error)", buf, r);
-                        return token->op == OP_NOMATCH;
+                        return log_event_result(event, token, token->op == OP_NOMATCH);
                 }
 
                 delete_trailing_chars(result, "\n");
                 udev_replace_chars_and_log(event, token, result, UDEV_ALLOWED_CHARS_INPUT, "command output");
 
                 event->program_result = strdup(result);
-                return token->op == OP_MATCH;
+                return log_event_result(event, token, token->op == OP_MATCH);
         }
         case TK_M_IMPORT_FILE: {
                 _cleanup_fclose_ FILE *f = NULL;
@@ -2320,13 +2328,13 @@ static int udev_rule_apply_token_to_event(
                 if (!apply_format_value(event, token, buf, sizeof(buf), "file name to be imported"))
                         return false;
 
-                log_event_debug(event, token, "Importing properties from '%s'", buf);
+                log_event_debug(event, token, "Importing properties from \"%s\"", buf);
 
                 f = fopen(buf, "re");
                 if (!f) {
                         if (errno != ENOENT)
-                                return log_event_error_errno(event, token, errno, "Failed to open '%s': %m", buf);
-                        return token->op == OP_NOMATCH;
+                                return log_event_error_errno(event, token, errno, "Failed to open \"%s\": %m", buf);
+                        return log_event_result(event, token, token->op == OP_NOMATCH);
                 }
 
                 for (;;) {
@@ -2335,16 +2343,16 @@ static int udev_rule_apply_token_to_event(
 
                         r = read_line(f, LONG_LINE_MAX, &line);
                         if (r < 0) {
-                                log_event_debug_errno(event, token, r, "Failed to read '%s', ignoring: %m", buf);
-                                return token->op == OP_NOMATCH;
+                                log_event_debug_errno(event, token, r, "Failed to read \"%s\", ignoring: %m", buf);
+                                return log_event_result(event, token, token->op == OP_NOMATCH);
                         }
                         if (r == 0)
-                                break;
+                                return log_event_result(event, token, token->op == OP_MATCH);
 
                         r = get_property_from_string(line, &key, &value);
                         if (r < 0) {
                                 log_event_debug_errno(event, token, r,
-                                                      "Failed to parse key and value from '%s', ignoring: %m",
+                                                      "Failed to parse key and value from \"%s\", ignoring: %m",
                                                       line);
                                 continue;
                         }
@@ -2356,9 +2364,10 @@ static int udev_rule_apply_token_to_event(
                                 return log_event_error_errno(event, token, r,
                                                              "Failed to add property %s=%s: %m",
                                                              key, value);
+                        log_event_trace(event, token, "Imported property \"%s=%s\".", key, value);
                 }
 
-                return token->op == OP_MATCH;
+                assert_not_reached();
         }
         case TK_M_IMPORT_PROGRAM: {
                 _cleanup_strv_free_ char **lines = NULL;
@@ -2368,15 +2377,15 @@ static int udev_rule_apply_token_to_event(
                 if (!apply_format_value(event, token, buf, sizeof(buf), "command"))
                         return false;
 
-                log_event_debug(event, token, "Importing properties from results of '%s'", buf);
+                log_event_debug(event, token, "Importing properties from results of \"%s\"", buf);
 
                 r = udev_event_spawn(event, /* accept_failure = */ true, buf, result, sizeof result, &truncated);
                 if (r != 0) {
                         if (r < 0)
-                                log_event_warning_errno(event, token, r, "Failed to execute '%s', ignoring: %m", buf);
+                                log_event_warning_errno(event, token, r, "Failed to execute \"%s\", ignoring: %m", buf);
                         else /* returned value is positive when program fails */
                                 log_event_debug(event, token, "Command \"%s\" returned %d (error), ignoring", buf, r);
-                        return token->op == OP_NOMATCH;
+                        return log_event_result(event, token, token->op == OP_NOMATCH);
                 }
 
                 if (truncated) {
@@ -2400,7 +2409,7 @@ static int udev_rule_apply_token_to_event(
                 if (r < 0) {
                         log_event_warning_errno(event, token, r,
                                                 "Failed to extract lines from result of command \"%s\", ignoring: %m", buf);
-                        return false;
+                        return log_event_result(event, token, false);
                 }
 
                 STRV_FOREACH(line, lines) {
@@ -2409,7 +2418,7 @@ static int udev_rule_apply_token_to_event(
                         r = get_property_from_string(*line, &key, &value);
                         if (r < 0) {
                                 log_event_debug_errno(event, token, r,
-                                                      "Failed to parse key and value from '%s', ignoring: %m",
+                                                      "Failed to parse key and value from \"%s\", ignoring: %m",
                                                       *line);
                                 continue;
                         }
@@ -2421,9 +2430,10 @@ static int udev_rule_apply_token_to_event(
                                 return log_event_error_errno(event, token, r,
                                                              "Failed to add property %s=%s: %m",
                                                              key, value);
+                        log_event_trace(event, token, "Imported property \"%s=%s\".", key, value);
                 }
 
-                return token->op == OP_MATCH;
+                return log_event_result(event, token, token->op == OP_MATCH);
         }
         case TK_M_IMPORT_BUILTIN: {
                 UdevBuiltinCommand cmd = PTR_TO_UDEV_BUILTIN_CMD(token->data);
@@ -2434,10 +2444,10 @@ static int udev_rule_apply_token_to_event(
                 if (udev_builtin_run_once(cmd)) {
                         /* check if we ran already */
                         if (event->builtin_run & mask) {
-                                log_event_debug(event, token, "Skipping builtin '%s' in IMPORT key",
+                                log_event_debug(event, token, "Builtin command \"%s\" has already run, skipping.",
                                                 udev_builtin_name(cmd));
                                 /* return the result from earlier run */
-                                return token->op == (event->builtin_ret & mask ? OP_NOMATCH : OP_MATCH);
+                                return log_event_result(event, token, token->op == (event->builtin_ret & mask ? OP_NOMATCH : OP_MATCH));
                         }
                         /* mark as ran */
                         event->builtin_run |= mask;
@@ -2446,34 +2456,36 @@ static int udev_rule_apply_token_to_event(
                 if (!apply_format_value(event, token, buf, sizeof(buf), "builtin command"))
                         return false;
 
-                log_event_debug(event, token, "Importing properties from results of builtin command '%s'", buf);
+                log_event_debug(event, token, "Importing properties from results of builtin command \"%s\".", buf);
 
                 r = udev_builtin_run(event, cmd, buf);
                 if (r < 0) {
                         /* remember failure */
-                        log_event_debug_errno(event, token, r, "Failed to run builtin '%s': %m", buf);
+                        log_event_debug_errno(event, token, r, "Failed to run builtin \"%s\": %m", buf);
                         event->builtin_ret |= mask;
                 }
-                return token->op == (r >= 0 ? OP_MATCH : OP_NOMATCH);
+                return log_event_result(event, token, token->op == (r >= 0 ? OP_MATCH : OP_NOMATCH));
         }
         case TK_M_IMPORT_DB: {
                 const char *val;
 
                 if (!event->dev_db_clone)
-                        return token->op == OP_NOMATCH;
+                        return log_event_result(event, token, token->op == OP_NOMATCH);
                 r = sd_device_get_property_value(event->dev_db_clone, token->value, &val);
                 if (r == -ENOENT)
-                        return token->op == OP_NOMATCH;
+                        return log_event_result(event, token, token->op == OP_NOMATCH);
                 if (r < 0)
                         return log_event_error_errno(event, token, r,
-                                                     "Failed to get property '%s' from database: %m",
+                                                     "Failed to get property \"%s\" from database: %m",
                                                      token->value);
 
                 r = device_add_property(dev, token->value, val);
                 if (r < 0)
-                        return log_event_error_errno(event, token, r, "Failed to add property '%s=%s': %m",
+                        return log_event_error_errno(event, token, r, "Failed to add property \"%s=%s\": %m",
                                                      token->value, val);
-                return token->op == OP_MATCH;
+                log_event_trace(event, token, "Imported property \"%s=%s\".", token->value, val);
+
+                return log_event_result(event, token, token->op == OP_MATCH);
         }
         case TK_M_IMPORT_CMDLINE: {
                 _cleanup_free_ char *value = NULL;
@@ -2481,16 +2493,19 @@ static int udev_rule_apply_token_to_event(
                 r = proc_cmdline_get_key(token->value, PROC_CMDLINE_VALUE_OPTIONAL|PROC_CMDLINE_IGNORE_EFI_OPTIONS, &value);
                 if (r < 0)
                         return log_event_error_errno(event, token, r,
-                                                     "Failed to read '%s' option from /proc/cmdline: %m",
+                                                     "Failed to read \"%s\" option from /proc/cmdline: %m",
                                                      token->value);
                 if (r == 0)
-                        return token->op == OP_NOMATCH;
+                        return log_event_result(event, token, token->op == OP_NOMATCH);
 
-                r = device_add_property(dev, token->value, value ?: "1");
+                const char *val = value ?: "1";
+                r = device_add_property(dev, token->value, val);
                 if (r < 0)
-                        return log_event_error_errno(event, token, r, "Failed to add property '%s=%s': %m",
-                                                     token->value, value ?: "1");
-                return token->op == OP_MATCH;
+                        return log_event_error_errno(event, token, r, "Failed to add property \"%s=%s\": %m",
+                                                     token->value, val);
+                log_event_trace(event, token, "Imported property \"%s=%s\".", token->value, val);
+
+                return log_event_result(event, token, token->op == OP_MATCH);
         }
         case TK_M_IMPORT_PARENT: {
                 char buf[UDEV_PATH_SIZE];
@@ -2498,35 +2513,56 @@ static int udev_rule_apply_token_to_event(
                 if (!apply_format_value(event, token, buf, sizeof(buf), "property name"))
                         return false;
 
-                r = import_parent_into_properties(dev, buf);
+                sd_device *parent;
+                r = sd_device_get_parent(dev, &parent);
+                if (ERRNO_IS_NEG_DEVICE_ABSENT(r))
+                        return log_event_result(event, token, token->op == OP_NOMATCH);
                 if (r < 0)
-                        return log_event_error_errno(event, token, r,
-                                                     "Failed to import properties '%s' from parent: %m",
-                                                     buf);
-                return token->op == (r > 0 ? OP_MATCH : OP_NOMATCH);
+                        return log_event_error_errno(event, token, r, "Failed to get parent device: %m");
+
+                bool have = false;
+                FOREACH_DEVICE_PROPERTY(parent, key, val) {
+                        if (fnmatch(buf, key, 0) != 0)
+                                continue;
+
+                        r = device_add_property(dev, key, val);
+                        if (r < 0)
+                                return log_event_error_errno(event, token, r, "Failed to add property \"%s=%s\": %m", key, val);
+                        log_event_trace(event, token, "Imported property \"%s=%s\".", key, val);
+                        have = true;
+                }
+
+                return log_event_result(event, token, token->op == (have ? OP_MATCH : OP_NOMATCH));
         }
         case TK_M_RESULT:
                 return token_match_string(event, token, event->program_result, /* log_result = */ true);
+
         case TK_A_OPTIONS_STRING_ESCAPE_NONE:
                 event->esc = ESCAPE_NONE;
-                break;
+                return log_event_done(event, token);
+
         case TK_A_OPTIONS_STRING_ESCAPE_REPLACE:
                 event->esc = ESCAPE_REPLACE;
-                break;
+                return log_event_done(event, token);
+
         case TK_A_OPTIONS_DB_PERSIST:
                 device_set_db_persist(dev);
-                break;
+                return log_event_done(event, token);
+
         case TK_A_OPTIONS_INOTIFY_WATCH:
                 if (event->inotify_watch_final)
-                        break;
+                        return log_event_final_set(event, token);
+
                 if (token->op == OP_ASSIGN_FINAL)
                         event->inotify_watch_final = true;
 
                 event->inotify_watch = token->data;
-                break;
+                return log_event_done(event, token);
+
         case TK_A_OPTIONS_DEVLINK_PRIORITY:
                 device_set_devlink_priority(dev, PTR_TO_INT(token->data));
-                break;
+                return log_event_done(event, token);
+
         case TK_A_OPTIONS_LOG_LEVEL: {
                 int level = PTR_TO_INT(token->data);
 
@@ -2548,14 +2584,15 @@ static int udev_rule_apply_token_to_event(
                         event->log_level_was_debug = true;
                 }
 
-                break;
+                return log_event_done(event, token);
         }
         case TK_A_OWNER: {
                 char owner[UDEV_NAME_SIZE];
                 const char *ow = owner;
 
                 if (event->owner_final)
-                        break;
+                        return log_event_final_set(event, token);
+
                 if (token->op == OP_ASSIGN_FINAL)
                         event->owner_final = true;
 
@@ -2563,18 +2600,21 @@ static int udev_rule_apply_token_to_event(
                         return true;
 
                 r = get_user_creds(&ow, &event->uid, NULL, NULL, NULL, USER_CREDS_ALLOW_MISSING);
-                if (r < 0)
-                        log_unknown_owner(dev, token->rule_line, r, "user", owner);
+                if (IN_SET(r, -ENOENT, -ESRCH))
+                        log_event_error_errno(event, token, r, "Unknown user \"%s\", ignoring.", owner);
+                else if (r < 0)
+                        log_event_error_errno(event, token, r, "Failed to resolve user \"%s\", ignoring: %m", owner);
                 else
-                        log_event_debug(event, token, "OWNER %s(%u)", owner, event->uid);
-                break;
+                        log_event_debug(event, token, "Set owner: %s(%u)", owner, event->uid);
+                return true;
         }
         case TK_A_GROUP: {
                 char group[UDEV_NAME_SIZE];
                 const char *gr = group;
 
                 if (event->group_final)
-                        break;
+                        return log_event_final_set(event, token);
+
                 if (token->op == OP_ASSIGN_FINAL)
                         event->group_final = true;
 
@@ -2582,17 +2622,20 @@ static int udev_rule_apply_token_to_event(
                         return true;
 
                 r = get_group_creds(&gr, &event->gid, USER_CREDS_ALLOW_MISSING);
-                if (r < 0)
-                        log_unknown_owner(dev, token->rule_line, r, "group", group);
+                if (IN_SET(r, -ENOENT, -ESRCH))
+                        log_event_error_errno(event, token, r, "Unknown group \"%s\", ignoring.", group);
+                else if (r < 0)
+                        log_event_error_errno(event, token, r, "Failed to resolve group \"%s\", ignoring: %m", group);
                 else
-                        log_event_debug(event, token, "GROUP %s(%u)", group, event->gid);
-                break;
+                        log_event_debug(event, token, "Set group: %s(%u)", group, event->gid);
+                return true;
         }
         case TK_A_MODE: {
                 char mode_str[UDEV_NAME_SIZE];
 
                 if (event->mode_final)
-                        break;
+                        return log_event_final_set(event, token);
+
                 if (token->op == OP_ASSIGN_FINAL)
                         event->mode_final = true;
 
@@ -2601,41 +2644,44 @@ static int udev_rule_apply_token_to_event(
 
                 r = parse_mode(mode_str, &event->mode);
                 if (r < 0)
-                        log_event_error_errno(event, token, r, "Failed to parse mode '%s', ignoring: %m", mode_str);
+                        log_event_error_errno(event, token, r, "Failed to parse mode \"%s\", ignoring: %m", mode_str);
                 else
-                        log_event_debug(event, token, "MODE %#o", event->mode);
-                break;
+                        log_event_debug(event, token, "Set mode: %#o", event->mode);
+                return true;
         }
         case TK_A_OWNER_ID:
                 if (event->owner_final)
-                        break;
+                        return log_event_final_set(event, token);
+
                 if (token->op == OP_ASSIGN_FINAL)
                         event->owner_final = true;
-                if (!token->data)
-                        break;
-                event->uid = PTR_TO_UID(token->data);
-                log_event_debug(event, token, "OWNER %u", event->uid);
-                break;
+
+                event->uid = PTR_TO_UID(ASSERT_PTR(token->data));
+                log_event_debug(event, token, "Set owner ID: %u", event->uid);
+                return true;
+
         case TK_A_GROUP_ID:
                 if (event->group_final)
-                        break;
+                        return log_event_final_set(event, token);
+
                 if (token->op == OP_ASSIGN_FINAL)
                         event->group_final = true;
-                if (!token->data)
-                        break;
-                event->gid = PTR_TO_GID(token->data);
-                log_event_debug(event, token, "GROUP %u", event->gid);
-                break;
+
+                event->gid = PTR_TO_GID(ASSERT_PTR(token->data));
+                log_event_debug(event, token, "Set group ID: %u", event->gid);
+                return true;
+
         case TK_A_MODE_ID:
                 if (event->mode_final)
-                        break;
+                        return log_event_final_set(event, token);
+
                 if (token->op == OP_ASSIGN_FINAL)
                         event->mode_final = true;
-                if (!token->data)
-                        break;
-                event->mode = PTR_TO_MODE(token->data);
-                log_event_debug(event, token, "MODE %#o", event->mode);
-                break;
+
+                event->mode = PTR_TO_MODE(ASSERT_PTR(token->data));
+                log_event_debug(event, token, "Set mode: %#o", event->mode);
+                return true;
+
         case TK_A_SECLABEL: {
                 _cleanup_free_ char *name = NULL, *label = NULL;
                 char label_str[UDEV_LINE_SIZE] = {};
@@ -2661,13 +2707,13 @@ static int udev_rule_apply_token_to_event(
                 if (r == -ENOMEM)
                         return log_oom();
                 if (r < 0)
-                        return log_event_error_errno(event, token, r, "Failed to store SECLABEL{%s}='%s': %m", name, label);
+                        return log_event_error_errno(event, token, r, "Failed to store security label \"%s=%s\": %m", name, label);
 
-                log_event_debug(event, token, "SECLABEL{%s}='%s'", name, label);
+                log_event_debug(event, token, "Set security label: %s=%s", name, label);
 
                 TAKE_PTR(name);
                 TAKE_PTR(label);
-                break;
+                return true;
         }
         case TK_A_ENV: {
                 const char *val, *name = token->data;
@@ -2676,11 +2722,13 @@ static int udev_rule_apply_token_to_event(
 
                 if (isempty(token->value)) {
                         if (token->op == OP_ADD)
-                                break;
+                                return log_event_done(event, token);
+
                         r = device_add_property(dev, name, NULL);
                         if (r < 0)
-                                return log_event_error_errno(event, token, r, "Failed to remove property '%s': %m", name);
-                        break;
+                                return log_event_error_errno(event, token, r, "Failed to remove property \"%s\": %m", name);
+                        log_event_trace(event, token, "Removed property \"%s\".", name);
+                        return true;
                 }
 
                 if (token->op == OP_ADD &&
@@ -2689,9 +2737,9 @@ static int udev_rule_apply_token_to_event(
                         l = strpcpyl_full(&p, l, &truncated, val, " ", NULL);
                         if (truncated) {
                                 log_event_warning(event, token,
-                                                  "The buffer for the property '%s' is full, "
-                                                  "refusing to append the new value '%s'.", name, token->value);
-                                break;
+                                                  "The buffer for the property is full, refusing to append new property \"%s=%s\".",
+                                                  name, token->value);
+                                return true;
                         }
                 }
 
@@ -2703,8 +2751,9 @@ static int udev_rule_apply_token_to_event(
 
                 r = device_add_property(dev, name, value_new);
                 if (r < 0)
-                        return log_event_error_errno(event, token, r, "Failed to add property '%s=%s': %m", name, value_new);
-                break;
+                        return log_event_error_errno(event, token, r, "Failed to set property \"%s=%s\": %m", name, value_new);
+                log_event_trace(event, token, "Set property \"%s=%s\".", name, value_new);
+                return true;
         }
         case TK_A_TAG: {
                 char buf[UDEV_PATH_SIZE];
@@ -2712,33 +2761,39 @@ static int udev_rule_apply_token_to_event(
                 if (!apply_format_value(event, token, buf, sizeof(buf), "tag name"))
                         return true;
 
+                if (token->op == OP_REMOVE) {
+                        device_remove_tag(dev, buf);
+                        log_event_trace(event, token, "Removed tag \"%s\".", buf);
+                        return true;
+                }
+
+                assert(IN_SET(token->op, OP_ASSIGN, OP_ADD));
+
                 if (token->op == OP_ASSIGN)
                         device_cleanup_tags(dev);
 
-                if (token->op == OP_REMOVE)
-                        device_remove_tag(dev, buf);
-                else {
-                        r = device_add_tag(dev, buf, true);
-                        if (r == -ENOMEM)
-                                return log_oom();
-                        if (r < 0)
-                                log_event_warning_errno(event, token, r, "Failed to add tag '%s', ignoring: %m", buf);
-                }
-                break;
+                r = device_add_tag(dev, buf, /* both = */ true);
+                if (r == -ENOMEM)
+                        return log_oom();
+                if (r < 0)
+                        log_event_warning_errno(event, token, r, "Failed to %s tag \"%s\", ignoring: %m",
+                                                token->op == OP_ASSIGN ? "set" : "add", buf);
+                else
+                        log_event_trace(event, token, "%s tag \"%s\".", token->op == OP_ASSIGN ? "Set" : "Added", buf);
+                return true;
         }
         case TK_A_NAME: {
                 char buf[UDEV_PATH_SIZE];
 
                 if (event->name_final)
-                        break;
+                        return log_event_final_set(event, token);
+
                 if (token->op == OP_ASSIGN_FINAL)
                         event->name_final = true;
 
                 if (sd_device_get_ifindex(dev, NULL) < 0) {
-                        log_event_error(event, token,
-                                        "Only network interfaces can be renamed, ignoring NAME=\"%s\".",
-                                        token->value);
-                        break;
+                        log_event_warning(event, token, "Only network interfaces can be renamed, ignoring.");
+                        return true;
                 }
 
                 if (!apply_format_value(event, token, buf, sizeof(buf), "network interface name"))
@@ -2751,18 +2806,23 @@ static int udev_rule_apply_token_to_event(
                 if (r < 0)
                         return r;
 
-                log_event_debug(event, token, "NAME '%s'", event->name);
-                break;
+                log_event_debug(event, token, "Set network interface name: %s", event->name);
+                return true;
         }
         case TK_A_DEVLINK: {
                 char buf[UDEV_PATH_SIZE];
 
                 if (event->devlink_final)
-                        break;
-                if (sd_device_get_devnum(dev, NULL) < 0)
-                        break;
+                        return log_event_final_set(event, token);
+
+                if (sd_device_get_devnum(dev, NULL) < 0) {
+                        log_event_debug(event, token, "Device does not have device node, ignoring to manage device node symlink.");
+                        return true;
+                }
+
                 if (token->op == OP_ASSIGN_FINAL)
                         event->devlink_final = true;
+
                 if (IN_SET(token->op, OP_ASSIGN, OP_ASSIGN_FINAL))
                         device_cleanup_devlinks(dev);
 
@@ -2784,31 +2844,31 @@ static int udev_rule_apply_token_to_event(
                         if (r == -ENOMEM)
                                 return log_oom();
                         if (r < 0) {
-                                log_warning_errno(r, "Failed to extract first path in SYMLINK=, ignoring: %m");
-                                break;
+                                log_warning_errno(r, "Failed to extract first path in device node symlinks, ignoring: %m");
+                                return true;
                         }
                         if (r == 0)
-                                break;
+                                return true;
 
                         if (token->op == OP_REMOVE) {
                                 r = device_remove_devlink(dev, path);
                                 if (r == -ENOMEM)
                                         return log_oom();
                                 if (r < 0)
-                                        log_event_warning_errno(event, token, r, "Failed to remove devlink '%s', ignoring: %m", path);
+                                        log_event_warning_errno(event, token, r, "Failed to remove device node symlink \"%s\", ignoring: %m", path);
                                 else if (r > 0)
-                                        log_event_debug(event, token, "Dropped SYMLINK '%s'", path);
+                                        log_event_debug(event, token, "Removed device node symlink \"%s\"", path);
                         } else {
                                 r = device_add_devlink(dev, path);
                                 if (r == -ENOMEM)
                                         return log_oom();
                                 if (r < 0)
-                                        log_event_warning_errno(event, token, r, "Failed to add devlink '%s', ignoring: %m", path);
+                                        log_event_warning_errno(event, token, r, "Failed to add device node symlink \"%s\", ignoring: %m", path);
                                 else if (r > 0)
-                                        log_event_debug(event, token, "Added SYMLINK '%s'", path);
+                                        log_event_debug(event, token, "Added device node symlink \"%s\".", path);
                         }
                 }
-                break;
+                assert_not_reached();
         }
         case TK_A_ATTR: {
                 char buf[UDEV_PATH_SIZE], value[UDEV_NAME_SIZE];
@@ -2820,34 +2880,36 @@ static int udev_rule_apply_token_to_event(
                         strscpyl_full(buf, sizeof(buf), &truncated, val, "/", key_name, NULL);
                         if (truncated) {
                                 log_event_warning(event, token,
-                                                  "The path to the attribute '%s/%s' is too long, refusing to set the attribute.",
+                                                  "The path to the attribute \"%s/%s\" is too long, refusing to set the attribute.",
                                                   val, key_name);
-                                break;
+                                return true;
                         }
                 }
 
                 r = attr_subst_subdir(buf);
                 if (r < 0) {
-                        log_event_error_errno(event, token, r, "Could not find file matches '%s', ignoring: %m", buf);
-                        break;
+                        log_event_error_errno(event, token, r, "Could not find file matches \"%s\", ignoring: %m", buf);
+                        return true;
                 }
 
                 if (!apply_format_value(event, token, value, sizeof(value), "attribute value"))
                         return true;
 
                 if (EVENT_MODE_DESTRUCTIVE(event)) {
-                        log_event_debug(event, token, "Writing ATTR{'%s'}=\"%s\".", buf, value);
+                        log_event_debug(event, token, "Writing \"%s\" to sysfs attribute \"%s\".", value, buf);
                         r = write_string_file(buf, value,
                                               WRITE_STRING_FILE_VERIFY_ON_FAILURE |
                                               WRITE_STRING_FILE_DISABLE_BUFFER |
                                               WRITE_STRING_FILE_AVOID_NEWLINE |
                                               WRITE_STRING_FILE_VERIFY_IGNORE_NEWLINE);
                         if (r < 0)
-                                log_event_error_errno(event, token, r, "Failed to write ATTR{%s}=\"%s\", ignoring: %m", buf, value);
+                                log_event_error_errno(event, token, r, "Failed to write \"%s\" to sysfs attribute \"%s\", ignoring: %m", value, buf);
+                        else
+                                log_event_done(event, token);
                 } else
-                        log_event_debug(event, token, "Running in test mode, skipping writing ATTR{%s}=\"%s\".", buf, value);
+                        log_event_debug(event, token, "Running in test mode, skipping writing \"%s\" to sysfs attribute \"%s\".", value, buf);
 
-                break;
+                return true;
         }
         case TK_A_SYSCTL: {
                 char buf[UDEV_PATH_SIZE], value[UDEV_NAME_SIZE];
@@ -2861,14 +2923,16 @@ static int udev_rule_apply_token_to_event(
                 sysctl_normalize(buf);
 
                 if (EVENT_MODE_DESTRUCTIVE(event)) {
-                        log_event_debug(event, token, "Writing SYSCTL{%s}=\"%s\".", buf, value);
+                        log_event_debug(event, token, "Writing \"%s\" to sysctl entry \"%s\".", value, buf);
                         r = sysctl_write(buf, value);
                         if (r < 0)
-                                log_event_error_errno(event, token, r, "Failed to write SYSCTL{%s}=\"%s\", ignoring: %m", buf, value);
+                                log_event_error_errno(event, token, r, "Failed to write \"%s\" to sysctl entry \"%s\", ignoring: %m", value, buf);
+                        else
+                                log_event_done(event, token);
                 } else
-                        log_event_debug(event, token, "Running in test mode, skipping writing SYSCTL{%s}=\"%s\".", buf, value);
+                        log_event_debug(event, token, "Running in test mode, skipping writing \"%s\" to sysctl entry \"%s\".", value, buf);
 
-                break;
+                return true;
         }
         case TK_A_RUN_BUILTIN:
         case TK_A_RUN_PROGRAM: {
@@ -2876,7 +2940,8 @@ static int udev_rule_apply_token_to_event(
                 char buf[UDEV_LINE_SIZE];
 
                 if (event->run_final)
-                        break;
+                        return log_event_final_set(event, token);
+
                 if (token->op == OP_ASSIGN_FINAL)
                         event->run_final = true;
 
@@ -2891,24 +2956,22 @@ static int udev_rule_apply_token_to_event(
                         return log_oom();
 
                 r = ordered_hashmap_ensure_put(&event->run_list, NULL, cmd, token->data);
-                if (r == -ENOMEM)
-                        return log_oom();
                 if (r < 0)
-                        return log_event_error_errno(event, token, r, "Failed to store command '%s': %m", cmd);
+                        return log_event_error_errno(event, token, r, "Failed to store command \"%s\": %m", cmd);
 
+                log_event_debug(event, token, "Set command: %s", cmd);
                 TAKE_PTR(cmd);
-
-                log_event_debug(event, token, "RUN '%s'", token->value);
-                break;
+                return true;
         }
         case TK_A_OPTIONS_STATIC_NODE:
                 /* do nothing for events. */
-                break;
+                return true;
+
         default:
                 assert_not_reached();
         }
 
-        return true;
+        assert_not_reached();
 }
 
 static int udev_rule_apply_parent_token_to_event(UdevRuleToken *head_token, UdevEvent *event) {