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);
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);
.uid = UID_INVALID,
.gid = GID_INVALID,
.mode = MODE_INVALID,
+ .log_level_was_debug = log_level == LOG_DEBUG,
+ .default_log_level = log_level,
};
return event;
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);
#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"
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 */
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;
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;
/* 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);
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;
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;
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;
}
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:
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;