]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udev: introduce new OPTIONS="log_level=" udev rule
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 8 Dec 2020 13:37:12 +0000 (22:37 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 10 Dec 2020 03:31:45 +0000 (12:31 +0900)
src/test/test-udev.c
src/udev/udev-event.c
src/udev/udev-event.h
src/udev/udev-rules.c
src/udev/udevadm-test.c
src/udev/udevd.c

index 8acf86da37785f4d57c787f0c8dc63c7d2ac4fb8..488b965c822b7663de965de5c197e5df92f079d4 100644 (file)
@@ -102,7 +102,7 @@ static int run(int argc, char *argv[]) {
         if (r < 0)
                 return log_debug_errno(r, "Failed to open device '%s'", devpath);
 
-        assert_se(event = udev_event_new(dev, 0, NULL));
+        assert_se(event = udev_event_new(dev, 0, NULL, log_get_max_level()));
 
         assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGHUP, SIGCHLD, -1) >= 0);
 
index 5159d19a3825d6d6b58e09642eb02b058b615403..307f949fde5f1dd87c6626343ad0a94ead25751f 100644 (file)
@@ -51,7 +51,7 @@ typedef struct Spawn {
         size_t result_len;
 } Spawn;
 
-UdevEvent *udev_event_new(sd_device *dev, usec_t exec_delay_usec, sd_netlink *rtnl) {
+UdevEvent *udev_event_new(sd_device *dev, usec_t exec_delay_usec, sd_netlink *rtnl, int log_level) {
         UdevEvent *event;
 
         assert(dev);
@@ -68,6 +68,8 @@ UdevEvent *udev_event_new(sd_device *dev, usec_t exec_delay_usec, sd_netlink *rt
                 .uid = UID_INVALID,
                 .gid = GID_INVALID,
                 .mode = MODE_INVALID,
+                .log_level_was_debug = log_level == LOG_DEBUG,
+                .default_log_level = log_level,
         };
 
         return event;
index a34b85176d8b35c0c56f1390f10ca0348a2d7673..27bf8f9372bc6c80ffafe8b1222a9e76515f0b33 100644 (file)
@@ -42,9 +42,11 @@ typedef struct UdevEvent {
         bool name_final;
         bool devlink_final;
         bool run_final;
+        bool log_level_was_debug;
+        int default_log_level;
 } UdevEvent;
 
-UdevEvent *udev_event_new(sd_device *dev, usec_t exec_delay_usec, sd_netlink *rtnl);
+UdevEvent *udev_event_new(sd_device *dev, usec_t exec_delay_usec, sd_netlink *rtnl, int log_level);
 UdevEvent *udev_event_free(UdevEvent *event);
 DEFINE_TRIVIAL_CLEANUP_FUNC(UdevEvent*, udev_event_free);
 
index ef6a0c112cb1f8c33c0cb7da7d8a538c171e7f20..48fd33fdedd22b3b2a4fffde60f5acf147364097 100644 (file)
@@ -25,6 +25,7 @@
 #include "strv.h"
 #include "strxcpyx.h"
 #include "sysctl-util.h"
+#include "syslog-util.h"
 #include "udev-builtin.h"
 #include "udev-event.h"
 #include "udev-rules.h"
@@ -104,6 +105,7 @@ typedef enum {
         TK_A_OPTIONS_DB_PERSIST,            /* no argument */
         TK_A_OPTIONS_INOTIFY_WATCH,         /* boolean */
         TK_A_OPTIONS_DEVLINK_PRIORITY,      /* int */
+        TK_A_OPTIONS_LOG_LEVEL,             /* string of log level or "reset" */
         TK_A_OWNER,                         /* user name */
         TK_A_GROUP,                         /* group name */
         TK_A_MODE,                          /* mode string */
@@ -834,6 +836,17 @@ static int parse_token(UdevRules *rules, const char *key, char *attr, UdevRuleOp
                         if (r < 0)
                                 return log_token_error_errno(rules, r, "Failed to parse link priority '%s': %m", tmp);
                         r = rule_line_add_token(rule_line, TK_A_OPTIONS_DEVLINK_PRIORITY, op, NULL, INT_TO_PTR(prio));
+                } else if ((tmp = startswith(value, "log_level="))) {
+                        int level;
+
+                        if (streq(tmp, "reset"))
+                                level = -1;
+                        else {
+                                level = log_level_from_string(tmp);
+                                if (level < 0)
+                                        return log_token_error_errno(rules, level, "Failed to parse log level '%s': %m", tmp);
+                        }
+                        r = rule_line_add_token(rule_line, TK_A_OPTIONS_LOG_LEVEL, op, NULL, INT_TO_PTR(level));
                 } else {
                         log_token_warning(rules, "Invalid value for OPTIONS key, ignoring: '%s'", value);
                         return 0;
@@ -1858,6 +1871,22 @@ static int udev_rule_apply_token_to_event(
         case TK_A_OPTIONS_DEVLINK_PRIORITY:
                 device_set_devlink_priority(dev, PTR_TO_INT(token->data));
                 break;
+        case TK_A_OPTIONS_LOG_LEVEL: {
+                int level = PTR_TO_INT(token->data);
+
+                if (level < 0)
+                        level = event->default_log_level;
+
+                log_set_max_level_all_realms(level);
+
+                if (level == LOG_DEBUG && !event->log_level_was_debug) {
+                        /* The log level becomes LOG_DEBUG at first time. Let's log basic information. */
+                        log_device_uevent(dev, "The log level is changed to 'debug' while processing device");
+                        event->log_level_was_debug = true;
+                }
+
+                break;
+        }
         case TK_A_OWNER: {
                 char owner[UTIL_NAME_SIZE];
                 const char *ow = owner;
index a029622af9dab240491dbb1beb9badb1e4ec6094..747047dac87657a6deb8b0f98aaf9a73d426244e 100644 (file)
@@ -138,7 +138,7 @@ int test_main(int argc, char *argv[], void *userdata) {
         /* don't read info from the db */
         device_seal(dev);
 
-        event = udev_event_new(dev, 0, NULL);
+        event = udev_event_new(dev, 0, NULL, LOG_DEBUG);
 
         assert_se(sigfillset(&mask) >= 0);
         assert_se(sigprocmask(SIG_SETMASK, &mask, &sigmask_orig) >= 0);
index 3961e763059a92a2120a6d1cf26f42df702532d6..5d02a9d27ce4da755bb954bb0d373797151e0be7 100644 (file)
@@ -84,6 +84,7 @@ typedef struct Manager {
         LIST_HEAD(struct event, events);
         const char *cgroup;
         pid_t pid; /* the process that originally allocated the manager object */
+        int log_level;
 
         UdevRules *rules;
         Hashmap *properties;
@@ -443,7 +444,7 @@ static int worker_process_device(Manager *manager, sd_device *dev) {
 
         log_device_uevent(dev, "Processing device");
 
-        udev_event = udev_event_new(dev, arg_exec_delay_usec, manager->rtnl);
+        udev_event = udev_event_new(dev, arg_exec_delay_usec, manager->rtnl, manager->log_level);
         if (!udev_event)
                 return -ENOMEM;
 
@@ -540,6 +541,9 @@ static int worker_device_monitor_handler(sd_device_monitor *monitor, sd_device *
         if (r < 0)
                 log_device_warning_errno(dev, r, "Failed to send signal to main daemon, ignoring: %m");
 
+        /* Reset the log level, as it might be changed by "OPTIONS=log_level=". */
+        log_set_max_level_all_realms(manager->log_level);
+
         return 1;
 }
 
@@ -1064,6 +1068,7 @@ static int on_ctrl_msg(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, co
         case UDEV_CTRL_SET_LOG_LEVEL:
                 log_debug("Received udev control message (SET_LOG_LEVEL), setting log_level=%i", value->intval);
                 log_set_max_level_all_realms(value->intval);
+                manager->log_level = value->intval;
                 manager_kill_workers(manager);
                 break;
         case UDEV_CTRL_STOP_EXEC_QUEUE:
@@ -1708,6 +1713,8 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg
         if (r < 0)
                 return log_error_errno(r, "Failed to bind netlink socket: %m");
 
+        manager->log_level = log_get_max_level();
+
         *ret = TAKE_PTR(manager);
 
         return 0;