1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-21 02:50:18 +03:00

udev: allow to enable trace logging in systemd-udevd (#36070)

split out of #35968.
This commit is contained in:
Lennart Poettering 2025-01-20 22:02:13 +01:00 committed by GitHub
commit 169b0d4eb0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 132 additions and 10 deletions

View File

@ -318,6 +318,8 @@
<varlistentry>
<term><varname>udev.log_level=</varname></term>
<term><varname>rd.udev.log_level=</varname></term>
<term><varname>udev.trace=</varname></term>
<term><varname>rd.udev.trace=</varname></term>
<term><varname>udev.children_max=</varname></term>
<term><varname>rd.udev.children_max=</varname></term>
<term><varname>udev.exec_delay=</varname></term>

View File

@ -167,6 +167,16 @@
<xi:include href="version-info.xml" xpointer="v247"/>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>udev.trace[=<replaceable>BOOL</replaceable>]</varname></term>
<term><varname>rd.udev.trace[=<replaceable>BOOL</replaceable>]</varname></term>
<listitem>
<para>Enable/disable trace logging. When enabled, <varname>udev.log_level=</varname> will be
ignored, and <literal>debug</literal> level is assumed.</para>
<xi:include href="version-info.xml" xpointer="v258"/>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>udev.children_max=</varname></term>
<term><varname>rd.udev.children_max=</varname></term>

View File

@ -743,6 +743,14 @@
<xi:include href="version-info.xml" xpointer="v241"/>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--trace=<replaceable>BOOL</replaceable></option></term>
<listitem>
<para>Enable/disable trace logging in <command>systemd-udevd</command>.</para>
<xi:include href="version-info.xml" xpointer="v258"/>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-t</option></term>
<term><option>--timeout=<replaceable>seconds</replaceable></option></term>

View File

@ -66,7 +66,7 @@ _udevadm() {
[SETTLE]='-t --timeout -E --exit-if-exists'
[CONTROL_STANDALONE]='-e --exit -s --stop-exec-queue -S --start-exec-queue -R --reload --ping
--load-credentials'
[CONTROL_ARG]='-l --log-priority -p --property -m --children-max -t --timeout'
[CONTROL_ARG]='-l --log-priority -p --property -m --children-max -t --timeout --trace'
[MONITOR_STANDALONE]='-k --kernel -u --udev -p --property'
[MONITOR_ARG]='-s --subsystem-match -t --tag-match'
[TEST_STANDALONE]='-v --verbose'
@ -191,6 +191,9 @@ _udevadm() {
-l|--log-priority)
comps='alert crit debug emerg err info notice warning'
;;
--trace)
comps='yes no'
;;
*)
comps=''
;;

View File

@ -66,6 +66,7 @@ _udevadm_control(){
'(-R --reload)'{-R,--reload}'[Signal systemd-udevd to reload the rules files and other databases like the kernel module index.]' \
'(-p --property)'{-p,--property=}'[Set a global property for all events.]:KEY=VALUE' \
'(-m --children-max=)'{-m,--children-max=}'[Set the maximum number of events.]:N' \
'--trace=[Enable/disable trace logging.]:BOOL' \
'(-t --timeout=)'{-t,--timeout=}'[The maximum number of seconds to wait for a reply from systemd-udevd.]:SECONDS'
}

View File

@ -2,6 +2,11 @@
#include "varlink-io.systemd.Udev.h"
static SD_VARLINK_DEFINE_METHOD(
SetTrace,
SD_VARLINK_FIELD_COMMENT("Enable/disable."),
SD_VARLINK_DEFINE_INPUT(enable, SD_VARLINK_BOOL, 0));
static SD_VARLINK_DEFINE_METHOD(
SetChildrenMax,
SD_VARLINK_FIELD_COMMENT("The maximum number of child processes. When 0 is specified, the maximum is determined based on the system resources."),
@ -22,6 +27,8 @@ SD_VARLINK_DEFINE_INTERFACE(
io_systemd_Udev,
"io.systemd.Udev",
SD_VARLINK_INTERFACE_COMMENT("An interface for controlling systemd-udevd."),
SD_VARLINK_SYMBOL_COMMENT("Enable/disable trace logging."),
&vl_method_SetTrace,
SD_VARLINK_SYMBOL_COMMENT("Sets the maximum number of child processes."),
&vl_method_SetChildrenMax,
SD_VARLINK_SYMBOL_COMMENT("Sets the global udev properties."),

View File

@ -112,6 +112,20 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
return 0;
} else if (proc_cmdline_key_streq(key, "udev.trace")) {
if (!value)
config->trace = true;
else {
r = parse_boolean(value);
if (r < 0)
log_warning_errno(r, "Failed to parse udev.trace argument, ignoring: %s", value);
else
config->trace = r;
}
return 0;
} else {
if (startswith(key, "udev."))
log_warning("Unknown udev kernel command line option \"%s\", ignoring.", key);
@ -257,13 +271,24 @@ static int parse_argv(int argc, char *argv[], UdevConfig *config) {
manager->config_by_command.name || \
manager->config_by_udev_conf.name;
static void manager_merge_config_log_level(Manager *manager) {
assert(manager);
MERGE_BOOL(trace);
if (manager->config.trace)
manager->config.log_level = LOG_DEBUG;
else
MERGE_NON_NEGATIVE(log_level, log_get_max_level());
}
static void manager_merge_config(Manager *manager) {
assert(manager);
/* udev.conf has the lowest priority, then followed by command line arguments, kernel command line
options, and values set by udev control. */
MERGE_NON_NEGATIVE(log_level, log_get_max_level());
manager_merge_config_log_level(manager);
MERGE_NON_NEGATIVE(resolve_name_timing, RESOLVE_NAME_EARLY);
MERGE_NON_ZERO(exec_delay_usec, 0);
MERGE_NON_ZERO(timeout_usec, DEFAULT_WORKER_TIMEOUT_USEC);
@ -310,16 +335,36 @@ void manager_set_log_level(Manager *manager, int log_level) {
int old = log_get_max_level();
log_set_max_level(log_level);
manager->config.log_level = manager->config_by_control.log_level = log_level;
manager->config_by_control.log_level = log_level;
manager_merge_config_log_level(manager);
if (log_level != old)
manager_kill_workers(manager, /* force = */ false);
if (manager->config.log_level == old)
return;
log_set_max_level(manager->config.log_level);
manager_kill_workers(manager, /* force = */ false);
}
void manager_set_trace(Manager *manager, bool enable) {
assert(manager);
bool old = manager->config.trace;
manager->config_by_control.trace = enable;
manager_merge_config_log_level(manager);
if (manager->config.trace == old)
return;
log_set_max_level(manager->config.log_level);
manager_kill_workers(manager, /* force = */ false);
}
static void manager_adjust_config(UdevConfig *config) {
assert(config);
log_set_max_level(config->log_level);
if (config->timeout_usec < MIN_WORKER_TIMEOUT_USEC) {
log_debug("Timeout (%s) for processing event is too small, using the default: %s",
FORMAT_TIMESPAN(config->timeout_usec, 1),
@ -411,7 +456,6 @@ int manager_load(Manager *manager, int argc, char *argv[]) {
if (arg_debug)
log_set_target(LOG_TARGET_CONSOLE);
log_set_max_level(manager->config.log_level);
manager_adjust_config(&manager->config);
return 1;
}
@ -424,7 +468,6 @@ UdevReloadFlags manager_reload_config(Manager *manager) {
manager->config_by_udev_conf = UDEV_CONFIG_INIT;
manager_parse_udev_config(&manager->config_by_udev_conf);
manager_merge_config(manager);
log_set_max_level(manager->config.log_level);
manager_adjust_config(&manager->config);
if (manager->config.resolve_name_timing != old.resolve_name_timing)
@ -434,7 +477,8 @@ UdevReloadFlags manager_reload_config(Manager *manager) {
manager->config.exec_delay_usec != old.exec_delay_usec ||
manager->config.timeout_usec != old.timeout_usec ||
manager->config.timeout_signal != old.timeout_signal ||
manager->config.blockdev_read_only != old.blockdev_read_only)
manager->config.blockdev_read_only != old.blockdev_read_only ||
manager->config.trace != old.trace)
return UDEV_RELOAD_KILL_WORKERS;
return 0;

View File

@ -18,6 +18,7 @@ typedef struct UdevConfig {
usec_t timeout_usec;
int timeout_signal;
bool blockdev_read_only;
bool trace;
} UdevConfig;
#define UDEV_CONFIG_INIT \
@ -28,6 +29,7 @@ typedef struct UdevConfig {
void manager_set_children_max(Manager *manager, unsigned n);
void manager_set_log_level(Manager *manager, int log_level);
void manager_set_trace(Manager *manager, bool enable);
void manager_set_environment(Manager *manager, char * const *v);
int manager_load(Manager *manager, int argc, char *argv[]);

View File

@ -43,6 +43,26 @@ static int vl_method_set_log_level(sd_varlink *link, sd_json_variant *parameters
return sd_varlink_reply(link, NULL);
}
static int vl_method_set_trace(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
bool enable;
int r;
static const sd_json_dispatch_field dispatch_table[] = {
{ "enable", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, 0, SD_JSON_MANDATORY },
{}
};
assert(link);
r = sd_varlink_dispatch(link, parameters, dispatch_table, &enable);
if (r != 0)
return r;
log_debug("Received io.systemd.service.SetTrace(%s)", yes_no(enable));
manager_set_trace(userdata, enable);
return sd_varlink_reply(link, NULL);
}
static int vl_method_set_children_max(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
unsigned n;
int r;
@ -160,6 +180,7 @@ int manager_start_varlink_server(Manager *manager) {
"io.systemd.service.Reload", vl_method_reload,
"io.systemd.service.SetLogLevel", vl_method_set_log_level,
"io.systemd.service.GetEnvironment", varlink_method_get_environment,
"io.systemd.Udev.SetTrace", vl_method_set_trace,
"io.systemd.Udev.SetChildrenMax", vl_method_set_children_max,
"io.systemd.Udev.SetEnvironment", vl_method_set_environment,
"io.systemd.Udev.StartExecQueue", vl_method_start_stop_exec_queue,

View File

@ -182,6 +182,7 @@ static int worker_process_device(UdevWorker *worker, sd_device *dev) {
udev_event = udev_event_new(dev, worker, EVENT_UDEV_WORKER);
if (!udev_event)
return -ENOMEM;
udev_event->trace = worker->config.trace;
/* If this is a block device and the device is locked currently via the BSD advisory locks,
* someone else is using it exclusively. We don't run our udev rules now to not interfere.

View File

@ -10,6 +10,7 @@
#include "creds-util.h"
#include "errno-util.h"
#include "parse-argument.h"
#include "parse-util.h"
#include "process-util.h"
#include "static-destruct.h"
@ -30,6 +31,7 @@ static bool arg_exit = false;
static int arg_max_children = -1;
static int arg_log_level = -1;
static int arg_start_exec_queue = -1;
static int arg_trace = -1;
static bool arg_load_credentials = false;
STATIC_DESTRUCTOR_REGISTER(arg_env, strv_freep);
@ -42,7 +44,8 @@ static bool arg_has_control_commands(void) {
arg_reload ||
!strv_isempty(arg_env) ||
arg_max_children >= 0 ||
arg_ping;
arg_ping ||
arg_trace >= 0;
}
static int help(void) {
@ -58,6 +61,7 @@ static int help(void) {
" -p --property=KEY=VALUE Set a global property for all events\n"
" -m --children-max=N Maximum number of children\n"
" --ping Wait for udev to respond to a ping message\n"
" --trace=BOOL Enable/disable trace logging\n"
" -t --timeout=SECONDS Maximum time to block for a reply\n"
" --load-credentials Load udev rules from credentials\n",
program_invocation_short_name);
@ -68,6 +72,7 @@ static int help(void) {
static int parse_argv(int argc, char *argv[]) {
enum {
ARG_PING = 0x100,
ARG_TRACE,
ARG_LOAD_CREDENTIALS,
};
@ -83,6 +88,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "env", required_argument, NULL, 'p' }, /* alias for -p */
{ "children-max", required_argument, NULL, 'm' },
{ "ping", no_argument, NULL, ARG_PING },
{ "trace", required_argument, NULL, ARG_TRACE },
{ "timeout", required_argument, NULL, 't' },
{ "load-credentials", no_argument, NULL, ARG_LOAD_CREDENTIALS },
{ "version", no_argument, NULL, 'V' },
@ -143,6 +149,14 @@ static int parse_argv(int argc, char *argv[]) {
arg_ping = true;
break;
case ARG_TRACE:
r = parse_boolean_argument("--trace=", optarg, NULL);
if (r < 0)
return r;
arg_trace = r;
break;
case 't':
r = parse_sec(optarg, &arg_timeout);
if (r < 0)
@ -296,6 +310,13 @@ static int send_control_commands(void) {
return r;
}
if (arg_trace >= 0) {
r = varlink_callbo_and_log(link, "io.systemd.Udev.SetTrace", /* reply = */ NULL,
SD_JSON_BUILD_PAIR_BOOLEAN("enable", arg_trace));
if (r < 0)
return r;
}
return 0;
}

View File

@ -52,6 +52,8 @@ udevadm control -R
udevadm control -p HELLO=world
udevadm control -m 42
udevadm control --ping -t 5
udevadm control --trace yes
udevadm control --trace no
udevadm control --load-credentials
udevadm control -h