1
0
mirror of https://github.com/systemd/systemd synced 2025-09-26 23:34:44 +02:00

Compare commits

...

8 Commits

Author SHA1 Message Date
Jinyuan Si
239952e890 cryptsetup: Fix crypto device missing issue after bootup
Normally, the udev rules operate on "change" events. But when
coldplugging, there's an "add" event present. The udev rules have to
recognize this and do some actions in this particular situation, too.
Also, we don't want the nodes to be created prematurely on "add"
events while not coldplugging. The udev rules will check
DM_UDEV_PRIMARY_SOURCE_FLAG to see if the device was activated
correctly before and if not, it ignore the "add" event totally.
This way the udev rules can support udev triggers generating "add"
events (e.g. "udevadm trigger --action=add" or
"echo add > /sys/block/<dm_device>/uevent").

In this case, the udevd service is started after
systemd-cryptsetup@config.service, is started, which will cause udevd
service to miss the "change" uevent with DM_UDEV_PRIMARY_SOURCE_FLAG
flag generated by systemd-cryptsetup@config.service. To solve this
issue, we let the cryptsetup service be started after the udevd
service.
2020-12-10 20:46:00 +01:00
Lennart Poettering
4add63c79e
Merge pull request #17903 from yuwata/udev-options-log-level
udev: introduce OPTIONS="log_level=xxx" rule
2020-12-10 20:45:32 +01:00
Zbigniew Jędrzejewski-Szmek
3c94f71472 Drop compat "gateway" name
Back in 5248e7e1f11aba6859de0b28f0dd3778b22842f2 (July 2017) we moved over to
"_gateway", with the old name declared to be temporary measure. Since we're
doing a bunch of changes to resolved now, it seems to be a good moment to make
this simplification and not add support for the compat name in new code.
2020-12-10 20:44:41 +01:00
Lennart Poettering
8374bf4fa2 veritysetup: also place udev socket dep
In light of #17848, also place udev socket dep in veritysetup, it's the
same issue after all.
2020-12-10 20:44:12 +01:00
Yu Watanabe
563a94d080 man: mention new OPTIONS=log_level= udev rule 2020-12-10 12:33:34 +09:00
Yu Watanabe
1a0bd01529 udev: introduce new OPTIONS="log_level=" udev rule 2020-12-10 12:31:45 +09:00
Yu Watanabe
b2d9e58f78 udev: introduce log_device_uevent() helper function
And this drops duplicated check for seqnum and device action.
2020-12-10 12:26:19 +09:00
Yu Watanabe
481f24d1f6 udev: drop meaningless size optimization
These objects are not allocated multiple times simultaneously per
single process.
2020-12-10 12:18:30 +09:00
17 changed files with 107 additions and 79 deletions

View File

@ -647,6 +647,24 @@
on the transition from initramfs.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>log_level=<replaceable>level</replaceable></option></term>
<listitem>
<para>Takes a log level name like <literal>debug</literal> or
<literal>info</literal>, or a special value <literal>reset</literal>. When a log
level name is specified, the maximum log level is changed to that level. When
<literal>reset</literal> is set, then the previously specified log level is
revoked. Defaults to the log level of the main process of
<command>systemd-udevd</command>.</para>
<para>This may be useful when debugging events for certain devices. Note that the
log level is applied when the line including this rule is processed. So, for
debugging, it is recommended that this is specified at earlier place, e.g., the
first line of <filename>00-debug.rules</filename>.</para>
<para>Example for debugging uevent processing for network interfaces.
<programlisting># /etc/udev/rules.d/00-debug-net.rules
SUBSYSTEM=="net", OPTIONS="log_level=debug"</programlisting></para>
</listitem>
</varlistentry>
</variablelist>
</listitem>
</varlistentry>

View File

@ -667,9 +667,6 @@ if fallback_hostname == '' or fallback_hostname[0] == '.' or fallback_hostname[0
endif
conf.set_quoted('FALLBACK_HOSTNAME', fallback_hostname)
conf.set10('ENABLE_COMPAT_GATEWAY_HOSTNAME', get_option('compat-gateway-hostname'))
gateway_hostnames = ['_gateway'] + (conf.get('ENABLE_COMPAT_GATEWAY_HOSTNAME') == 1 ? ['gateway'] : [])
default_hierarchy = get_option('default-hierarchy')
conf.set_quoted('DEFAULT_HIERARCHY_NAME', default_hierarchy,
description : 'default cgroup hierarchy as string')
@ -3688,7 +3685,6 @@ status = [
'nobody user name: @0@'.format(nobody_user),
'nobody group name: @0@'.format(nobody_group),
'fallback hostname: @0@'.format(get_option('fallback-hostname')),
'symbolic gateway hostnames: @0@'.format(', '.join(gateway_hostnames)),
'default DNSSEC mode: @0@'.format(default_dnssec),
'default DNS-over-TLS mode: @0@'.format(default_dns_over_tls),

View File

@ -187,8 +187,6 @@ option('install-sysconfdir', type : 'boolean', value : true,
option('fallback-hostname', type : 'string', value : 'localhost',
description : 'the hostname used if none configured')
option('compat-gateway-hostname', type : 'boolean', value : 'false',
description : 'allow "gateway" as the symbolic name for default gateway')
option('default-hierarchy', type : 'combo',
choices : ['legacy', 'hybrid', 'unified'], value : 'unified',
description : 'default cgroup hierarchy')

View File

@ -212,20 +212,6 @@ bool is_localhost(const char *hostname) {
endswith_no_case(hostname, ".localhost.localdomain.");
}
bool is_gateway_hostname(const char *hostname) {
assert(hostname);
/* This tries to identify the valid syntaxes for the our
* synthetic "gateway" host. */
return
strcaseeq(hostname, "_gateway") || strcaseeq(hostname, "_gateway.")
#if ENABLE_COMPAT_GATEWAY_HOSTNAME
|| strcaseeq(hostname, "gateway") || strcaseeq(hostname, "gateway.")
#endif
;
}
int sethostname_idempotent(const char *s) {
char buf[HOST_NAME_MAX + 1] = {};

View File

@ -5,6 +5,7 @@
#include <stdio.h>
#include "macro.h"
#include "strv.h"
bool hostname_is_set(void);
@ -19,7 +20,11 @@ char* hostname_cleanup(char *s);
#define machine_name_is_valid(s) hostname_is_valid(s, false)
bool is_localhost(const char *hostname);
bool is_gateway_hostname(const char *hostname);
static inline bool is_gateway_hostname(const char *hostname) {
/* This tries to identify the valid syntaxes for the our synthetic "gateway" host. */
return STRCASE_IN_SET(hostname, "_gateway", "_gateway.");
}
int sethostname_idempotent(const char *s);

View File

@ -522,13 +522,8 @@ DnsScopeMatch dns_scope_good_domain(
if (dns_name_endswith(domain, "invalid") > 0)
return DNS_SCOPE_NO;
/* Never go to network for the _gateway domain, it's something special, synthesized locally. Note
* that we don't use is_gateway_hostname() here, since that has support for the legacy "gateway"
* hostname (without the prefix underscore), which we don't want to filter on all protocols. i.e. we
* don't want to filter "gateway" on classic DNS, since there might very well be such a host inside
* some search domain, and we shouldn't block that. We do filter it in LLMNR however (and on mDNS by
* side-effect, since it's a single-label name which mDNS doesn't accept anyway). */
if (dns_name_equal(domain, "_gateway") > 0)
/* Never go to network for the _gateway domain, it's something special, synthesized locally. */
if (is_gateway_hostname(domain))
return DNS_SCOPE_NO;
switch (s->protocol) {

View File

@ -564,7 +564,7 @@ int generator_write_cryptsetup_unit_section(
fprintf(f,
"DefaultDependencies=no\n"
"IgnoreOnIsolate=true\n"
"After=cryptsetup-pre.target\n"
"After=cryptsetup-pre.target systemd-udevd-kernel.socket\n"
"Before=blockdev@dev-mapper-%%i.target\n"
"Wants=blockdev@dev-mapper-%%i.target\n");

View File

@ -324,6 +324,20 @@ bool device_for_action(sd_device *dev, DeviceAction action) {
return a == action;
}
void log_device_uevent(sd_device *device, const char *str) {
DeviceAction action = _DEVICE_ACTION_INVALID;
uint64_t seqnum = 0;
if (!DEBUG_LOGGING)
return;
(void) device_get_seqnum(device, &seqnum);
(void) device_get_action(device, &action);
log_device_debug(device, "%s%s(SEQNUM=%"PRIu64", ACTION=%s)",
strempty(str), isempty(str) ? "" : " ",
seqnum, strna(device_action_to_string(action)));
}
int udev_rule_parse_value(char *str, char **ret_value, char **ret_endpos) {
char *i, *j;
int r;

View File

@ -33,4 +33,6 @@ int device_wait_for_devlink(const char *path, const char *subsystem, usec_t dead
int device_is_renaming(sd_device *dev);
bool device_for_action(sd_device *dev, DeviceAction action);
void log_device_uevent(sd_device *device, const char *str);
int udev_rule_parse_value(char *str, char **ret_value, char **ret_endpos);

View 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);

View File

@ -44,10 +44,10 @@ struct udev_ctrl {
int sock_connect;
union sockaddr_union saddr;
socklen_t addrlen;
bool bound:1;
bool cleanup_socket:1;
bool connected:1;
bool maybe_disconnected:1;
bool bound;
bool cleanup_socket;
bool connected;
bool maybe_disconnected;
sd_event *event;
sd_event_source *event_source;
sd_event_source *event_source_connect;

View 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;

View File

@ -34,17 +34,19 @@ typedef struct UdevEvent {
unsigned builtin_run;
unsigned builtin_ret;
UdevRuleEscapeType esc:8;
bool inotify_watch:1;
bool inotify_watch_final:1;
bool group_final:1;
bool owner_final:1;
bool mode_final:1;
bool name_final:1;
bool devlink_final:1;
bool run_final:1;
bool inotify_watch;
bool inotify_watch_final;
bool group_final;
bool owner_final;
bool mode_final;
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);

View 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;

View 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);

View 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;
@ -100,8 +101,8 @@ typedef struct Manager {
usec_t last_usec;
bool stop_exec_queue:1;
bool exit:1;
bool stop_exec_queue;
bool exit;
} Manager;
enum event_state {
@ -436,25 +437,14 @@ static int worker_mark_block_device_read_only(sd_device *dev) {
static int worker_process_device(Manager *manager, sd_device *dev) {
_cleanup_(udev_event_freep) UdevEvent *udev_event = NULL;
_cleanup_close_ int fd_lock = -1;
DeviceAction action;
uint64_t seqnum;
int r;
assert(manager);
assert(dev);
r = device_get_seqnum(dev, &seqnum);
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to get SEQNUM: %m");
log_device_uevent(dev, "Processing device");
r = device_get_action(dev, &action);
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to get ACTION: %m");
log_device_debug(dev, "Processing device (SEQNUM=%"PRIu64", ACTION=%s)",
seqnum, device_action_to_string(action));
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;
@ -521,9 +511,7 @@ static int worker_process_device(Manager *manager, sd_device *dev) {
} else
(void) udev_watch_end(dev);
log_device_debug(dev, "Device (SEQNUM=%"PRIu64", ACTION=%s) processed",
seqnum, device_action_to_string(action));
log_device_uevent(dev, "Device processed");
return 0;
}
@ -553,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;
}
@ -655,13 +646,7 @@ static void event_run(Manager *manager, struct event *event) {
assert(manager);
assert(event);
if (DEBUG_LOGGING) {
DeviceAction action;
r = device_get_action(event->dev, &action);
log_device_debug(event->dev, "Device (SEQNUM=%"PRIu64", ACTION=%s) ready for processing",
event->seqnum, r >= 0 ? device_action_to_string(action) : "<unknown>");
}
log_device_uevent(event->dev, "Device ready for processing");
HASHMAP_FOREACH(worker, manager->workers) {
if (worker->state != WORKER_IDLE)
@ -704,7 +689,6 @@ static void event_run(Manager *manager, struct event *event) {
static int event_queue_insert(Manager *manager, sd_device *dev) {
_cleanup_(sd_device_unrefp) sd_device *clone = NULL;
struct event *event;
DeviceAction action;
uint64_t seqnum;
int r;
@ -719,11 +703,6 @@ static int event_queue_insert(Manager *manager, sd_device *dev) {
if (r < 0)
return r;
/* Refuse devices do not have ACTION property. */
r = device_get_action(dev, &action);
if (r < 0)
return r;
/* Save original device to restore the state on failures. */
r = device_shallow_clone(dev, &clone);
if (r < 0)
@ -753,8 +732,7 @@ static int event_queue_insert(Manager *manager, sd_device *dev) {
LIST_APPEND(event, manager->events, event);
log_device_debug(dev, "Device (SEQNUM=%"PRIu64", ACTION=%s) is queued",
seqnum, device_action_to_string(action));
log_device_uevent(dev, "Device is queued");
return 0;
}
@ -1090,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:
@ -1734,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;

View File

@ -97,7 +97,7 @@ static int create_device(void) {
"Conflicts=umount.target\n"
"BindsTo=%s %s\n"
"IgnoreOnIsolate=true\n"
"After=cryptsetup-pre.target %s %s\n"
"After=cryptsetup-pre.target systemd-udevd-kernel.socket %s %s\n"
"Before=cryptsetup.target umount.target\n"
"\n[Service]\n"
"Type=oneshot\n"