1
0
mirror of https://github.com/systemd/systemd synced 2026-04-24 16:04:51 +02:00

Compare commits

...

19 Commits

Author SHA1 Message Date
Lennart Poettering
c0da575a0e update TODO 2022-04-05 14:36:00 +02:00
Lennart Poettering
197be5324e fix TODO 2022-04-05 14:02:36 +02:00
Lennart Poettering
598e431500 update TODO 2022-04-05 13:59:39 +02:00
Luca Boccassi
18a02561f1
Merge pull request #22953 from yuwata/test-sd-device
test: several fixlets for test-sd-device
2022-04-05 11:10:20 +01:00
Lennart Poettering
3e3c49cbe7 update TODO 2022-04-05 10:44:52 +02:00
Lennart Poettering
2cf120f7cf update TODO 2022-04-05 10:44:04 +02:00
Zbigniew Jędrzejewski-Szmek
42ac3bf1a3
Merge pull request #22956 from yuwata/network-fix-permission-error
network: ignore all errors in loading .network files
2022-04-05 08:59:44 +02:00
Yu Watanabe
c7749367e3 test-sd-device: ignore several errors when running on non-host network namespace
Fixes 93e04eb43b (commitcomment-70387367).
2022-04-05 14:33:19 +09:00
Yu Watanabe
b1d723228e test-sd-device: allow several devices removed during running test
To make the test stabler.
2022-04-05 14:29:52 +09:00
Yu Watanabe
901fa9a4c9 test-sd-device: device ID requires subsystem 2022-04-05 14:29:49 +09:00
Yu Watanabe
04d1fbd564 test-sd-device: log earlier which device is handled
To make debugging the test easier.
2022-04-05 14:29:41 +09:00
Yu Watanabe
20742f92c1
Merge pull request #22951 from keszybz/fix-entry-selection-bootctl-status
Fix entry selection in bootctl status
2022-04-05 13:42:43 +09:00
Zbigniew Jędrzejewski-Szmek
e12335ba60 man: add annotated example for bootctl status & list
This is based on the output on my laptop, with various manual adjustments.
If people have other types of entries, it'd be useful to add them here. In
particular, some dual-boot entries would be nice.
2022-04-04 21:19:20 +02:00
Zbigniew Jędrzejewski-Szmek
db9eabd675 man: fix tag syntax
Strangely enough, having <varlistenetry>s outside of <variablelist> wasn't
causing visual problems. But having two <listitem>s in one <varlistentry>
resulted in the paragraphs running together in the rendered man page.
2022-04-04 21:19:20 +02:00
Zbigniew Jędrzejewski-Szmek
8214758bd5 bootctl: unify boot entry loading for "status" and "list"
We must be consistent in the two listings, so let's split out the loading code
and call it from both verb_status() and verb_list(). This effectively makes
verb_status() also call efi_loader_get_entries().

There is still some code duplicated, but that's hard to avoid. Error messages
are made identical for the same errors in various places.

Fixes #22580.
2022-04-04 21:18:14 +02:00
Yu Watanabe
5672bdd341 udev/net: always log error in link_load_one() 2022-04-05 02:03:22 +09:00
Yu Watanabe
61ec7beaf5 network: always log error in network_load_one() and netdev_load_one() 2022-04-05 02:02:42 +09:00
Yu Watanabe
036a8d503f network: ignore all errors in loading .network files
This partially reverts 9202b567bcdd0c1f6a1fc2a5f36602e619960813.

Fixes #22954.
2022-04-05 01:57:07 +09:00
Zbigniew Jędrzejewski-Szmek
957b242319 bootctl: do not call acquire_esp() twice
That function is nasty because it modifies global state. We should call it just
once in each call path.

Also drop 'return 1' which doesn't seem to have any use.
2022-04-04 10:46:13 +02:00
8 changed files with 366 additions and 194 deletions

38
TODO
View File

@ -78,6 +78,44 @@ Janitorial Clean-ups:
Features:
* systemd creds hookup with qemu fw_cfg. (Quite possibly might not need any
code at all, given the fw_cfg stuff are just files, but we should then
document how to use it). Goal: provide symmetric ways to pass creds to nspawn
containers and qemu VMs. (maybe also pick up env vars from fw_cfg?)
* beef up sd_notify() to support AV_VSOCK in $NOTIFY_SOCKET, so that VM
managers can get ready notifications from VMs, just like container managers
from their payload. Also pick up address from qemu/fw_cfg if set there.
(which has benefits, given SecureBoot and kernel cmdline are not necessarily
friends.)
* mirroring this: maybe support binding to AV_VSOCK in Type=notify services,
then passing $NOTIFY_SOCKET and $NOTIFY_GUESTCID with PID1's cid (typically
fixed to "2", i.e. the official host cid) and the expected guest cid, for the
two sides of the channe. The latter env var could then be used in an
appropriate qemu cmdline. That way qemu payloads could talk sd_notify()
directly to host service manager.
* maybe write a tool that binds an AF_VFSOCK socket, then invokes qemu,
extending the command line to enable vsock on the VM, and using fw_cfg to
configure socket address.
* sd-boot: rework random seed handling following recent kernel changes: always
pass seed to kernel, but credit only if secure boot is used
* sd-boot: hash data from GetNextHighMonotonicCount() into updated random seed,
so that we might even open up up the random seed logic to non-SecureBoot
systems?
* sd-boot: add menu item for shutdown? or hotkey?
* sd-device has an API to create an sd_device object from a device id, but has
no api to query the device id
* sd-device should return the devnum type (i.e. 'b' or 'c') via some API for an
sd_device object, so that data passed into sd_device_new_from_devnum() can
also be queried.
* udevadm: a new "tree" verb that shows tree of devices as syspath hierarchy,
along with their properties. uninitialized devices should be greyed out.

View File

@ -46,12 +46,14 @@
<varlistentry>
<term><option>status</option></term>
<listitem><para>Shows brief information about the system firmware, the boot loader that was used to boot the
system, the boot loaders currently available in the ESP, the boot loaders listed in the firmware's list of boot
loaders and the current default boot loader entry. If no command is specified, this is the implied
default.</para></listitem>
<listitem><para>Shows brief information about the system firmware, the boot loader that was used to
boot the system, the boot loaders currently available in the ESP, the boot loaders listed in the
firmware's list of boot loaders and the current default boot loader entry. If no command is
specified, this is the implied default.</para>
<para>See the example below for details of the output.</para>
</listitem>
</varlistentry>
</variablelist>
<varlistentry>
<term><option>reboot-to-firmware</option> <optional><replaceable>BOOL</replaceable></optional></term>
@ -59,20 +61,20 @@
<listitem><para>Query or set the "Reboot-Into-Firmware-Setup" flag of the EFI firmware. Takes a
boolean argument which controls whether to show the firmware setup on next system reboot. If the
argument is omitted shows the current status of the flag, or whether the flag is supported. This
controls the same flag as <command>systemctl reboot --firmware-setup</command>, but is more
low-level and allows setting the flag independently from actually requesting a
reboot.</para></listitem>
controls the same flag as <command>systemctl reboot --firmware-setup</command>, but is more low-level
and allows setting the flag independently from actually requesting a reboot.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>systemd-efi-options</option> <optional><replaceable>STRING</replaceable></optional></term>
<listitem><para>When called without the optional argument, prints the current value of the
<literal>SystemdOptions</literal> EFI variable. When called with an argument, sets the
variable to that value. See
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
for the meaning of that variable.</para></listitem>
<literal>SystemdOptions</literal> EFI variable. When called with an argument, sets the variable to
that value. See
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry> for the
meaning of that variable.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
@ -84,17 +86,16 @@
<command>systemd-boot</command>.</para>
<variablelist>
<varlistentry>
<term><option>list</option></term>
<listitem><para>Shows all available boot loader entries implementing the <ulink
url="https://systemd.io/BOOT_LOADER_SPECIFICATION">Boot Loader Specification</ulink>, as well as any
other entries discovered or automatically generated by a boot loader implementing the <ulink
url="https://systemd.io/BOOT_LOADER_INTERFACE">Boot Loader
Interface</ulink>.</para>
url="https://systemd.io/BOOT_LOADER_INTERFACE">Boot Loader Interface</ulink>.
JSON output may be requested with <option>--json=</option>.</para>
<para>JSON output may be requested with <option>--json=</option>.</para>
<para>See the example below for details of the output.</para>
</listitem>
</varlistentry>
@ -104,9 +105,9 @@
<listitem><para>Sets the default boot loader entry. Takes a single boot loader entry ID string or a glob
pattern as argument. The <option>set-oneshot</option> command will set the default entry only for the next boot,
the <option>set-default</option> will set it persistently for all future boots.</para></listitem>
the <option>set-default</option> will set it persistently for all future boots.</para>
<listitem><para>Optionally, the boot loader entry ID may be specified as one of: <option>@default</option>,
<para>Optionally, the boot loader entry ID may be specified as one of: <option>@default</option>,
<option>@oneshot</option> or <option>@current</option>, which correspond to the current default boot loader
entry for all future boots, the current default boot loader entry for the next boot, and the currently booted
boot loader entry. These special IDs are resolved to the current values of the EFI variables
@ -137,7 +138,6 @@
disables the timeout while always showing the menu. When an empty string ("") is specified the
bootloader will revert to its default menu timeout.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
@ -347,6 +347,111 @@
the Extended Boot Loader partition.</para>
</refsect1>
<refsect1>
<title>Examples</title>
<example>
<title>Output from <command>status</command> and <command>list</command></title>
<programlisting>$ <command>bootctl status</command>
System:
Firmware: UEFI 2.40 (<replaceable>firmware-version</replaceable>) ← firmware vendor and version
Secure Boot: disabled (setup) ← secure boot status
TPM2 Support: yes
Boot into FW: supported ← does the firmware support booting into itself
Current Boot Loader: ← details about sd-boot or another boot loader
Product: systemd-boot <replaceable>version</replaceable> implementing the <ulink
url="https://systemd.io/BOOT_LOADER_INTERFACE">Boot Loader Interface</ulink>
Features: ✓ Boot counting
✓ Menu timeout control
✓ One-shot menu timeout control
✓ Default entry control
✓ One-shot entry control
✓ Support for XBOOTLDR partition
✓ Support for passing random seed to OS
✓ Load drop-in drivers
✓ Boot loader sets ESP information
ESP: /dev/disk/by-partuuid/01234567-89ab-cdef-dead-beef00000000
File: └─/EFI/systemd/systemd-bootx64.efi
Random Seed: ← random seed used for entropy in early boot
Passed to OS: yes
System Token: set
Exists: yes
Available Boot Loaders on ESP:
ESP: /boot/efi (/dev/disk/by-partuuid/01234567-89ab-cdef-dead-beef00000000)
File: └─/EFI/systemd/systemd-bootx64.efi (systemd-boot 251
File: └─/EFI/BOOT/BOOTX64.EFI (systemd-boot 251
Boot Loaders Listed in EFI Variables:
Title: Linux Boot Manager
ID: 0x0001
Status: active, boot-order
Partition: /dev/disk/by-partuuid/…
File: └─/EFI/systemd/systemd-bootx64.efi
Title: Fedora
ID: 0x0000
Status: active, boot-order
Partition: /dev/disk/by-partuuid/…
File: └─/EFI/fedora/shimx64.efi
Title: Linux-Firmware-Updater
ID: 0x0002
Status: active, boot-order
Partition: /dev/disk/by-partuuid/…
File: └─/EFI/fedora/fwupdx64.efi
Boot Loader Entries:
$BOOT: /boot/efi (/dev/disk/by-partuuid/01234567-89ab-cdef-dead-beef00000000)
Default Boot Loader Entry:
type: Boot Loader Specification Type #1 (.conf)
title: Fedora Linux 36 (Workstation Edition)
id: …
source: /boot/efi/loader/entries/<replaceable>entry-token</replaceable>-<replaceable>kernel-version</replaceable>.conf
version: <replaceable>kernel-version</replaceable>
machine-id: …
linux: /<replaceable>entry-token</replaceable>/<replaceable>kernel-version</replaceable>/linux
initrd: /<replaceable>entry-token</replaceable>/<replaceable>kernel-version</replaceable>/initrd
options: root=…
</programlisting>
<programlisting>$ <command>bootctl list</command>
Boot Loader Entries:
type: Boot Loader Specification Type #1 (.conf)
title: Fedora Linux 36 (Workstation Edition) (default) (selected)
id: …
source: /boot/efi/loader/entries/<replaceable>entry-token</replaceable>-<replaceable>kernel-version</replaceable>.conf
version: <replaceable>kernel-version</replaceable>
machine-id: …
linux: /<replaceable>entry-token</replaceable>/<replaceable>kernel-version</replaceable>/linux
initrd: /<replaceable>entry-token</replaceable>/<replaceable>kernel-version</replaceable>/initrd
options: root=…
type: Boot Loader Specification Type #2 (.efi)
title: Fedora Linux 35 (Workstation Edition)
id: …
source: /boot/efi/EFI/Linux/fedora-<replaceable>kernel-version</replaceable>.efi
version: <replaceable>kernel-version</replaceable>
machine-id: …
linux: /EFI/Linux/fedora-<replaceable>kernel-version</replaceable>.efi
options: root=…
type: Automatic
title: Reboot Into Firmware Interface
id: auto-reboot-to-firmware-setup
source: /sys/firmware/efi/efivars/LoaderEntries-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f
</programlisting>
<para>In the listing, <literal>(default)</literal> specifies the entry that will be
used by default, and <literal>(selected)</literal> specifies the entry that was
selected the last time (i.e. is currently running).</para>
</example>
</refsect1>
<refsect1>
<title>See Also</title>
<para>

View File

@ -115,7 +115,7 @@ static int acquire_esp(
free_and_replace(arg_esp_path, np);
log_debug("Using EFI System Partition at %s.", arg_esp_path);
return 1;
return 0;
}
static int acquire_xbootldr(
@ -583,6 +583,35 @@ static const char* const boot_entry_type_table[_BOOT_ENTRY_TYPE_MAX] = {
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_type, BootEntryType);
static int boot_config_load_and_select(
BootConfig *config,
const char *esp_path,
dev_t esp_devid,
const char *xbootldr_path,
dev_t xbootldr_devid) {
_cleanup_strv_free_ char **efi_entries = NULL;
int r;
/* If XBOOTLDR and ESP actually refer to the same block device, suppress XBOOTLDR, since it would
* find the same entries twice. */
bool same = esp_path && xbootldr_path && devid_set_and_equal(esp_devid, xbootldr_devid);
r = boot_config_load(config, esp_path, same ? NULL : xbootldr_path);
if (r < 0)
return r;
r = efi_loader_get_entries(&efi_entries);
if (r == -ENOENT || ERRNO_IS_NOT_SUPPORTED(r))
log_debug_errno(r, "Boot loader reported no entries.");
else if (r < 0)
log_warning_errno(r, "Failed to determine entries reported by boot loader, ignoring: %m");
else
(void) boot_config_augment_from_loader(config, efi_entries, /* only_auto= */ false);
return boot_config_select_special_entries(config);
}
static int boot_entry_show(
const BootEntry *e,
bool show_as_default,
@ -682,16 +711,17 @@ static int boot_entry_show(
}
static int status_entries(
const BootConfig *config,
const char *esp_path,
sd_id128_t esp_partition_uuid,
const char *xbootldr_path,
sd_id128_t xbootldr_partition_uuid) {
_cleanup_(boot_config_free) BootConfig config = BOOT_CONFIG_NULL;
sd_id128_t dollar_boot_partition_uuid;
const char *dollar_boot_path;
int r;
assert(config);
assert(esp_path || xbootldr_path);
if (xbootldr_path) {
@ -709,21 +739,13 @@ static int status_entries(
SD_ID128_FORMAT_VAL(dollar_boot_partition_uuid));
printf("\n\n");
r = boot_config_load(&config, esp_path, xbootldr_path);
if (r < 0)
return r;
r = boot_config_select_special_entries(&config);
if (r < 0)
return r;
if (config.default_entry < 0)
printf("%zu entries, no entry could be determined as default.\n", config.n_entries);
if (config->default_entry < 0)
printf("%zu entries, no entry could be determined as default.\n", config->n_entries);
else {
printf("Default Boot Loader Entry:\n");
r = boot_entry_show(
boot_config_default_entry(&config),
boot_config_default_entry(config),
/* show_as_default= */ false,
/* show_as_selected= */ false,
/* show_discovered= */ false);
@ -1593,13 +1615,9 @@ static void print_yes_no_line(bool first, bool good, const char *name) {
name);
}
static int are_we_installed(void) {
static int are_we_installed(const char *esp_path) {
int r;
r = acquire_esp(/* privileged_mode= */ false, /* graceful= */ false, NULL, NULL, NULL, NULL, NULL);
if (r < 0)
return r;
/* Tests whether systemd-boot is installed. It's not obvious what to use as check here: we could
* check EFI variables, we could check what binary /EFI/BOOT/BOOT*.EFI points to, or whether the
* loader entries directory exists. Here we opted to check whether /EFI/systemd/ is non-empty, which
@ -1614,7 +1632,7 @@ static int are_we_installed(void) {
* It specifically checks for systemd-boot, not for other boot loaders (which a check for
* /boot/loader/entries would do). */
_cleanup_free_ char *p = path_join(arg_esp_path, "/EFI/systemd/");
_cleanup_free_ char *p = path_join(esp_path, "/EFI/systemd/");
if (!p)
return log_oom();
@ -1645,7 +1663,7 @@ static int verb_status(int argc, char *argv[], void *userdata) {
r = acquire_xbootldr(/* unprivileged_mode= */ geteuid() != 0, &xbootldr_uuid, &xbootldr_devid);
if (arg_print_dollar_boot_path) {
if (r == -EACCES)
return log_error_errno(r, "Failed to determine XBOOTLDR location: %m");
return log_error_errno(r, "Failed to determine XBOOTLDR partition: %m");
if (r < 0)
return r;
@ -1659,8 +1677,8 @@ static int verb_status(int argc, char *argv[], void *userdata) {
if (arg_print_esp_path || arg_print_dollar_boot_path)
return 0;
r = 0; /* If we couldn't determine the path, then don't consider that a problem from here on, just show what we
* can show */
r = 0; /* If we couldn't determine the path, then don't consider that a problem from here on, just
* show what we can show */
pager_open(arg_pager_flags);
@ -1776,16 +1794,20 @@ static int verb_status(int argc, char *argv[], void *userdata) {
}
if (arg_esp_path || arg_xbootldr_path) {
/* If XBOOTLDR and ESP actually refer to the same block device, suppress XBOOTLDR, since it would find the same entries twice */
bool same = arg_esp_path && arg_xbootldr_path && devid_set_and_equal(esp_devid, xbootldr_devid);
_cleanup_(boot_config_free) BootConfig config = BOOT_CONFIG_NULL;
k = status_entries(
arg_esp_path,
esp_uuid,
same ? NULL : arg_xbootldr_path,
same ? SD_ID128_NULL : xbootldr_uuid);
k = boot_config_load_and_select(&config,
arg_esp_path, esp_devid,
arg_xbootldr_path, xbootldr_devid);
if (k < 0)
r = k;
else {
k = status_entries(&config,
arg_esp_path, esp_uuid,
arg_xbootldr_path, xbootldr_uuid);
if (k < 0)
r = k;
}
}
return r;
@ -1793,17 +1815,17 @@ static int verb_status(int argc, char *argv[], void *userdata) {
static int verb_list(int argc, char *argv[], void *userdata) {
_cleanup_(boot_config_free) BootConfig config = BOOT_CONFIG_NULL;
_cleanup_strv_free_ char **efi_entries = NULL;
dev_t esp_devid = 0, xbootldr_devid = 0;
int r;
/* If we lack privileges we invoke find_esp_and_warn() in "unprivileged mode" here, which does two things: turn
* off logging about access errors and turn off potentially privileged device probing. Here we're interested in
* the latter but not the former, hence request the mode, and log about EACCES. */
/* If we lack privileges we invoke find_esp_and_warn() in "unprivileged mode" here, which does two
* things: turn off logging about access errors and turn off potentially privileged device probing.
* Here we're interested in the latter but not the former, hence request the mode, and log about
* EACCES. */
r = acquire_esp(/* unprivileged_mode= */ geteuid() != 0, /* graceful= */ false, NULL, NULL, NULL, NULL, &esp_devid);
if (r == -EACCES) /* We really need the ESP path for this call, hence also log about access errors */
return log_error_errno(r, "Failed to determine ESP: %m");
return log_error_errno(r, "Failed to determine ESP location: %m");
if (r < 0)
return r;
@ -1813,22 +1835,7 @@ static int verb_list(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
/* If XBOOTLDR and ESP actually refer to the same block device, suppress XBOOTLDR, since it would find the same entries twice */
bool same = arg_esp_path && arg_xbootldr_path && devid_set_and_equal(esp_devid, xbootldr_devid);
r = boot_config_load(&config, arg_esp_path, same ? NULL : arg_xbootldr_path);
if (r < 0)
return r;
r = efi_loader_get_entries(&efi_entries);
if (r == -ENOENT || ERRNO_IS_NOT_SUPPORTED(r))
log_debug_errno(r, "Boot loader reported no entries.");
else if (r < 0)
log_warning_errno(r, "Failed to determine entries reported by boot loader, ignoring: %m");
else
(void) boot_config_augment_from_loader(&config, efi_entries, /* only_auto= */ false);
r = boot_config_select_special_entries(&config);
r = boot_config_load_and_select(&config, arg_esp_path, esp_devid, arg_xbootldr_path, xbootldr_devid);
if (r < 0)
return r;
@ -2063,7 +2070,7 @@ static int verb_install(int argc, char *argv[], void *userdata) {
if (!install) {
/* If we are updating, don't do anything if sd-boot wasn't actually installed. */
r = are_we_installed();
r = are_we_installed(arg_esp_path);
if (r < 0)
return r;
if (r == 0) {
@ -2209,7 +2216,11 @@ static int verb_remove(int argc, char *argv[], void *userdata) {
static int verb_is_installed(int argc, char *argv[], void *userdata) {
int r;
r = are_we_installed();
r = acquire_esp(/* privileged_mode= */ false, /* graceful= */ false, NULL, NULL, NULL, NULL, NULL);
if (r < 0)
return r;
r = are_we_installed(arg_esp_path);
if (r < 0)
return r;

View File

@ -17,14 +17,18 @@
static void test_sd_device_one(sd_device *d) {
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
const char *syspath, *sysname, *subsystem = NULL, *id, *devname, *val;
const char *syspath, *sysname, *subsystem = NULL, *devname, *val;
bool is_block = false;
dev_t devnum;
usec_t usec;
int i, r;
int ifindex, r;
assert_se(sd_device_get_syspath(d, &syspath) >= 0);
assert_se(path_startswith(syspath, "/sys"));
assert_se(sd_device_get_sysname(d, &sysname) >= 0);
log_info("%s(%s)", __func__, syspath);
assert_se(sd_device_new_from_syspath(&dev, syspath) >= 0);
assert_se(sd_device_get_syspath(dev, &val) >= 0);
assert_se(streq(syspath, val));
@ -35,10 +39,34 @@ static void test_sd_device_one(sd_device *d) {
assert_se(streq(syspath, val));
dev = sd_device_unref(dev);
assert_se(sd_device_get_sysname(d, &sysname) >= 0);
r = sd_device_get_ifindex(d, &ifindex);
if (r >= 0) {
assert_se(ifindex > 0);
r = sd_device_new_from_ifindex(&dev, ifindex);
if (r == -ENODEV)
log_device_warning_errno(d, r,
"Failed to create sd-device object from ifindex %i. "
"Maybe running on a non-host network namespace.", ifindex);
else {
assert_se(r >= 0);
assert_se(sd_device_get_syspath(dev, &val) >= 0);
assert_se(streq(syspath, val));
dev = sd_device_unref(dev);
}
/* This does not require the interface really exists on the network namespace.
* Hence, this should always succeed. */
assert_se(sd_device_new_from_ifname(&dev, sysname) >= 0);
assert_se(sd_device_get_syspath(dev, &val) >= 0);
assert_se(streq(syspath, val));
dev = sd_device_unref(dev);
} else
assert_se(r == -ENOENT);
r = sd_device_get_subsystem(d, &subsystem);
if (r >= 0) {
const char *name;
const char *name, *id;
if (streq(subsystem, "drivers"))
name = strjoina(d->driver_subsystem, ":", sysname);
@ -48,6 +76,31 @@ static void test_sd_device_one(sd_device *d) {
assert_se(sd_device_get_syspath(dev, &val) >= 0);
assert_se(streq(syspath, val));
dev = sd_device_unref(dev);
/* The device ID depends on subsystem. */
assert_se(device_get_device_id(d, &id) >= 0);
r = sd_device_new_from_device_id(&dev, id);
if (r == -ENODEV && ifindex > 0)
log_device_warning_errno(d, r,
"Failed to create sd-device object from device ID \"%s\". "
"Maybe running on a non-host network namespace.", id);
else {
assert_se(r >= 0);
assert_se(sd_device_get_syspath(dev, &val) >= 0);
assert_se(streq(syspath, val));
dev = sd_device_unref(dev);
}
/* These require udev database, and reading database requires device ID. */
r = sd_device_get_is_initialized(d);
if (r > 0) {
r = sd_device_get_usec_since_initialized(d, &usec);
assert_se((r >= 0 && usec > 0) || r == -ENODATA);
} else
assert(r == 0);
r = sd_device_get_property_value(d, "ID_NET_DRIVER", &val);
assert_se(r >= 0 || r == -ENOENT);
} else
assert_se(r == -ENOENT);
@ -101,22 +154,6 @@ static void test_sd_device_one(sd_device *d) {
} else
assert_se(r == -ENOENT);
r = sd_device_get_ifindex(d, &i);
if (r >= 0) {
assert_se(i > 0);
assert_se(sd_device_new_from_ifindex(&dev, i) >= 0);
assert_se(sd_device_get_syspath(dev, &val) >= 0);
assert_se(streq(syspath, val));
dev = sd_device_unref(dev);
assert_se(sd_device_new_from_ifname(&dev, sysname) >= 0);
assert_se(sd_device_get_syspath(dev, &val) >= 0);
assert_se(streq(syspath, val));
dev = sd_device_unref(dev);
} else
assert_se(r == -ENOENT);
assert_se(sd_device_get_devpath(d, &val) >= 0);
r = sd_device_get_devtype(d, &val);
@ -128,25 +165,8 @@ static void test_sd_device_one(sd_device *d) {
r = sd_device_get_sysnum(d, &val);
assert_se(r >= 0 || r == -ENOENT);
r = sd_device_get_is_initialized(d);
if (r > 0) {
r = sd_device_get_usec_since_initialized(d, &usec);
assert_se((r >= 0 && usec > 0) || r == -ENODATA);
} else
assert(r == 0);
r = sd_device_get_sysattr_value(d, "name_assign_type", &val);
assert_se(r >= 0 || ERRNO_IS_PRIVILEGE(r) || IN_SET(r, -ENOENT, -EINVAL));
r = sd_device_get_property_value(d, "ID_NET_DRIVER", &val);
assert_se(r >= 0 || r == -ENOENT);
assert_se(device_get_device_id(d, &id) >= 0);
assert_se(sd_device_new_from_device_id(&dev, id) >= 0);
assert_se(sd_device_get_syspath(dev, &val) >= 0);
assert_se(streq(syspath, val));
log_info("syspath:%s subsystem:%s id:%s initialized:%s", syspath, strna(subsystem), id, yes_no(i));
}
TEST(sd_device_enumerator_devices) {
@ -169,39 +189,54 @@ TEST(sd_device_enumerator_subsystems) {
test_sd_device_one(d);
}
static unsigned test_sd_device_enumerator_filter_subsystem_one(const char *subsystem, Hashmap *h) {
static void test_sd_device_enumerator_filter_subsystem_one(
const char *subsystem,
Hashmap *h,
unsigned *ret_n_new_dev,
unsigned *ret_n_removed_dev) {
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
sd_device *d, *t;
unsigned n_new_dev = 0;
unsigned n_new_dev = 0, n_removed_dev = 0;
sd_device *d;
assert_se(sd_device_enumerator_new(&e) >= 0);
assert_se(sd_device_enumerator_add_match_subsystem(e, subsystem, true) >= 0);
FOREACH_DEVICE(e, d) {
const char *syspath;
sd_device *t;
assert_se(sd_device_get_syspath(d, &syspath) >= 0);
t = hashmap_remove(h, syspath);
assert_se(!sd_device_unref(t));
if (t)
log_debug("Removed subsystem:%s syspath:%s", subsystem, syspath);
else {
if (!t) {
log_warning("New device found: subsystem:%s syspath:%s", subsystem, syspath);
n_new_dev++;
}
assert_se(!sd_device_unref(t));
}
/* Assume no device is unplugged. */
assert_se(hashmap_isempty(h));
HASHMAP_FOREACH(d, h) {
const char *syspath;
return n_new_dev;
assert_se(sd_device_get_syspath(d, &syspath) >= 0);
log_warning("Device removed: subsystem:%s syspath:%s", subsystem, syspath);
n_removed_dev++;
assert_se(!sd_device_unref(d));
}
hashmap_free(h);
*ret_n_new_dev = n_new_dev;
*ret_n_removed_dev = n_removed_dev;
}
TEST(sd_device_enumerator_filter_subsystem) {
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
_cleanup_(hashmap_freep) Hashmap *subsystems;
unsigned n_new_dev = 0;
unsigned n_new_dev = 0, n_removed_dev = 0;
sd_device *d;
Hashmap *h;
char *s;
@ -235,16 +270,22 @@ TEST(sd_device_enumerator_filter_subsystem) {
}
while ((h = hashmap_steal_first_key_and_value(subsystems, (void**) &s))) {
n_new_dev += test_sd_device_enumerator_filter_subsystem_one(s, h);
hashmap_free(h);
unsigned n, m;
test_sd_device_enumerator_filter_subsystem_one(s, TAKE_PTR(h), &n, &m);
free(s);
n_new_dev += n;
n_removed_dev += m;
}
if (n_new_dev > 0)
log_warning("%u new device is found in re-scan", n_new_dev);
log_warning("%u new devices are found in re-scan", n_new_dev);
if (n_removed_dev > 0)
log_warning("%u devices removed in re-scan", n_removed_dev);
/* Assume that not so many devices are plugged. */
assert_se(n_new_dev <= 10);
/* Assume that not so many devices are plugged or unplugged. */
assert_se(n_new_dev + n_removed_dev <= 10);
}
TEST(sd_device_new_from_nulstr) {

View File

@ -749,10 +749,8 @@ int netdev_load_one(Manager *manager, const char *filename) {
assert(filename);
r = null_or_empty_path(filename);
if (r == -ENOENT)
return 0;
if (r < 0)
return r;
return log_warning_errno(r, "Failed to check if \"%s\" is empty: %m", filename);
if (r > 0) {
log_debug("Skipping empty file: %s", filename);
return 0;
@ -777,7 +775,7 @@ int netdev_load_one(Manager *manager, const char *filename) {
netdev_raw,
NULL);
if (r < 0)
return r;
return r; /* config_parse_many() logs internally. */
/* skip out early if configuration does not match the environment */
if (!condition_test_list(netdev_raw->conditions, environ, NULL, NULL, NULL)) {
@ -785,15 +783,11 @@ int netdev_load_one(Manager *manager, const char *filename) {
return 0;
}
if (netdev_raw->kind == _NETDEV_KIND_INVALID) {
log_warning("NetDev has no Kind= configured in %s. Ignoring", filename);
return 0;
}
if (netdev_raw->kind == _NETDEV_KIND_INVALID)
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "NetDev has no Kind= configured in \"%s\", ignoring.", filename);
if (!netdev_raw->ifname) {
log_warning("NetDev without Name= configured in %s. Ignoring", filename);
return 0;
}
if (!netdev_raw->ifname)
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "NetDev without Name= configured in \"%s\", ignoring.", filename);
netdev = malloc0(NETDEV_VTABLE(netdev_raw)->object_size);
if (!netdev)
@ -815,13 +809,13 @@ int netdev_load_one(Manager *manager, const char *filename) {
CONFIG_PARSE_WARN,
netdev, NULL);
if (r < 0)
return r;
return r; /* config_parse_many() logs internally. */
/* verify configuration */
if (NETDEV_VTABLE(netdev)->config_verify) {
r = NETDEV_VTABLE(netdev)->config_verify(netdev, filename);
if (r < 0)
return 0;
return r; /* config_verify() logs internally. */
}
netdev->filename = strdup(filename);
@ -837,22 +831,21 @@ int netdev_load_one(Manager *manager, const char *filename) {
assert(n);
if (!streq(netdev->filename, n->filename))
log_netdev_warning_errno(netdev, r,
"Device was already configured by file %s, ignoring %s.",
"Device was already configured by \"%s\", ignoring %s.",
n->filename, netdev->filename);
/* Clear ifname before netdev_free() is called. Otherwise, the NetDev object 'n' is
* removed from the hashmap 'manager->netdevs'. */
netdev->ifname = mfree(netdev->ifname);
return 0;
return -EEXIST;
}
if (r < 0)
return r;
assert(r > 0);
log_netdev_debug(netdev, "loaded %s", netdev_kind_to_string(netdev->kind));
log_netdev_debug(netdev, "loaded \"%s\"", netdev_kind_to_string(netdev->kind));
r = netdev_request_to_create(netdev);
if (r < 0)
return r;
return r; /* netdev_request_to_create() logs internally. */
TAKE_PTR(netdev);
return 0;
@ -871,11 +864,8 @@ int netdev_load(Manager *manager, bool reload) {
if (r < 0)
return log_error_errno(r, "Failed to enumerate netdev files: %m");
STRV_FOREACH(f, files) {
r = netdev_load_one(manager, *f);
if (r < 0)
log_error_errno(r, "Failed to load %s, ignoring: %m", *f);
}
STRV_FOREACH(f, files)
(void) netdev_load_one(manager, *f);
return 0;
}

View File

@ -313,7 +313,7 @@ int network_verify(Network *network) {
r = network_drop_invalid_addresses(network);
if (r < 0)
return r;
return r; /* network_drop_invalid_addresses() logs internally. */
network_drop_invalid_routes(network);
network_drop_invalid_nexthops(network);
network_drop_invalid_bridge_fdb_entries(network);
@ -327,7 +327,7 @@ int network_verify(Network *network) {
network_drop_invalid_tclass(network);
r = sr_iov_drop_invalid_sections(UINT32_MAX, network->sr_iov_by_section);
if (r < 0)
return r;
return r; /* sr_iov_drop_invalid_sections() logs internally. */
network_drop_invalid_static_leases(network);
network_adjust_dhcp_server(network);
@ -346,10 +346,8 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
assert(filename);
r = null_or_empty_path(filename);
if (r == -ENOENT)
return 0;
if (r < 0)
return r;
return log_warning_errno(r, "Failed to check if \"%s\" is empty: %m", filename);
if (r > 0) {
log_debug("Skipping empty file: %s", filename);
return 0;
@ -365,7 +363,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
d = strrchr(name, '.');
if (!d)
return -EINVAL;
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid file name: %s", filename);
*d = '\0';
@ -552,7 +550,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
network,
&network->stats_by_path);
if (r < 0)
return r;
return r; /* config_parse_many() logs internally. */
r = network_add_ipv4ll_route(network);
if (r < 0)
@ -564,15 +562,12 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
network->filename);
r = network_verify(network);
if (r == -ENOMEM)
return r;
if (r < 0)
/* Ignore .network files that do not match the conditions. */
return 0;
return r; /* network_verify() logs internally. */
r = ordered_hashmap_ensure_put(networks, &string_hash_ops, network->name, network);
if (r < 0)
return r;
return log_warning_errno(r, "%s: Failed to store configuration into hashmap: %m", filename);
TAKE_PTR(network);
return 0;
@ -590,11 +585,8 @@ int network_load(Manager *manager, OrderedHashmap **networks) {
if (r < 0)
return log_error_errno(r, "Failed to enumerate network files: %m");
STRV_FOREACH(f, files) {
r = network_load_one(manager, networks, *f);
if (r < 0)
return log_error_errno(r, "Failed to load %s: %m", *f);
}
STRV_FOREACH(f, files)
(void) network_load_one(manager, networks, *f);
return 0;
}

View File

@ -71,7 +71,7 @@ typedef struct BootConfig {
BootEntry* boot_config_find_entry(BootConfig *config, const char *id);
static inline BootEntry* boot_config_default_entry(BootConfig *config) {
static inline const BootEntry* boot_config_default_entry(const BootConfig *config) {
assert(config);
if (config->default_entry < 0)

View File

@ -218,10 +218,8 @@ int link_load_one(LinkConfigContext *ctx, const char *filename) {
assert(filename);
r = null_or_empty_path(filename);
if (r == -ENOENT)
return 0;
if (r < 0)
return r;
return log_warning_errno(r, "Failed to check if \"%s\" is empty: %m", filename);
if (r > 0) {
log_debug("Skipping empty file: %s", filename);
return 0;
@ -229,11 +227,11 @@ int link_load_one(LinkConfigContext *ctx, const char *filename) {
name = strdup(filename);
if (!name)
return -ENOMEM;
return log_oom();
config = new(LinkConfig, 1);
if (!config)
return -ENOMEM;
return log_oom();
*config = (LinkConfig) {
.filename = TAKE_PTR(name),
@ -266,7 +264,7 @@ int link_load_one(LinkConfigContext *ctx, const char *filename) {
config_item_perf_lookup, link_config_gperf_lookup,
CONFIG_PARSE_WARN, config, NULL);
if (r < 0)
return r;
return r; /* config_parse_many() logs internally. */
if (net_match_is_empty(&config->match) && !config->conditions) {
log_warning("%s: No valid settings found in the [Match] section, ignoring file. "
@ -288,13 +286,13 @@ int link_load_one(LinkConfigContext *ctx, const char *filename) {
r = link_adjust_wol_options(config);
if (r < 0)
return r;
return r; /* link_adjust_wol_options() logs internally. */
r = sr_iov_drop_invalid_sections(config->sr_iov_num_vfs, config->sr_iov_by_section);
if (r < 0)
return r;
return r; /* sr_iov_drop_invalid_sections() logs internally. */
log_debug("Parsed configuration file %s", filename);
log_debug("Parsed configuration file \"%s\"", filename);
LIST_PREPEND(configs, ctx->configs, TAKE_PTR(config));
return 0;
@ -340,11 +338,8 @@ int link_config_load(LinkConfigContext *ctx) {
if (r < 0)
return log_error_errno(r, "failed to enumerate link files: %m");
STRV_FOREACH_BACKWARDS(f, files) {
r = link_load_one(ctx, *f);
if (r < 0)
log_error_errno(r, "Failed to load %s, ignoring: %m", *f);
}
STRV_FOREACH_BACKWARDS(f, files)
(void) link_load_one(ctx, *f);
return 0;
}