When the periodic RA timer fires, any error returned by sendmsg()
currently propagates up through sd_radv_send() into radv_timeout(),
which then calls sd_radv_stop(). The RA engine is never started again
until the next carrier transition.
On an 802.3ad bond there is a window right after carrier-up where the
link is administratively up but no aggregator has been selected yet, so
sendmsg() returns ENOBUFS. If the very first RA after a flap lands in
that window, radv stops permanently and all clients lose their SLAAC
addresses, on-link/PD prefixes, and default router once the previously
advertised lifetimes expire, while IPv4 keeps working, leading to a very
confusing situation with v4 up and v6 down.
Handle this the same way solicited RAs already do (see
radv_process_packet()): log the failure and reschedule the timer instead
of giving up. ra_sent is left untouched on failure so we stay in the
fast initial-advertisement regime until a send actually succeeds.
link_radv_enabled() and link_ndisc_enabled() use
link_ipv6ll_enabled_harder(), which considers a static fe80:: address
in [Address] sufficient to run radv/ndisc even when LinkLocalAddressing=
(or IPv6LinkLocalAddressGenerationMode=none, which network_verify()
folds into the same flag) disables the kernel-generated link-local.
network_adjust_radv()/ndisc()/dhcp() however only check the raw
link_local flag and zero router_prefix_delegation / ndisc / dhcp&IPV6
at parse time, so the runtime gate never gets a chance to fire.
Factor the static-LL lookup out of link_ipv6ll_enabled_harder() into a
Network-level helper and use it in the three network_adjust_*()
functions, bringing parse-time and runtime behaviour in line.
Device enumeration may encounter transient errors such as ENXIO when devices
appear or disappear concurrently. These conditions represent expected "device absent"
races and should be treated uniformly across the enumeration logic.
This change replaces the ENODEV-specific check with ERRNO_IS_NEG_DEVICE_ABSENT(),
ensuring that all expected disappearance conditions are handled consistently.
Unexpected errors are still propagated, while expected races are ignored without
aborting the enumeration.
I had those prepared before but I didn't submit them because the
automatic layout didn't work well. In two cases now the sync of widths
between verbs and options is disabled and one case is left with the
automatic alignment. I think it'd good enough to merge.
Checking for pefile required that module to be made available for the
Python used to build systemd, even though it's only used at runtime,
potentially via a different Python installation.
Furthermore, Meson's Python module doesn't do the right thing when cross
compiling and looking up a Python for the host system, so this would end
up uselessly checking whether the build Python had the pefile module,
which is not needed. Even if it were made to check the host Python using
find_program, it still relies on being able to run its Python, which in
a cross scenario it probably wouldn't be able to do.
All in all, this check does more harm than good, and prevents building
ukify in valid configurations, so remove it.
Implement support for the --json= flag in the info subcommand
(issue #38844). Previously, coredumpctl info always produced
human-readable text output regardless of --json=.
Add a CoredumpFields struct that holds all journal fields extracted
for a coredump entry, along with coredump_fields_done() to release
member resources and coredump_fields_load() to populate the struct
from a journal entry. Both print_info() and the new print_info_json()
use this shared loader, eliminating the duplicate RETRIEVE loop.
print_info_json() builds a JSON object with the same fields shown by
print_info(). Missing fields are omitted via SD_JSON_BUILD_PAIR_CONDITION,
matching the tolerant behavior of print_info() rather than skipping the
entry entirely. Signal/Reason handling mirrors print_info(): normal
coredumps (MESSAGE_ID == SD_MESSAGE_COREDUMP_STR) emit a numeric Signal
field; non-normal entries (kernel oops, etc.) emit a Reason field with
the raw text from COREDUMP_SIGNAL.
Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
When the kernel hands the command line to PID 1, any KEY=VALUE assignment
whose KEY does not contain a '.' is exported as an environment variable
(with '-' replaced by '_') rather than passed as an argument. Mimic the
same split in --boot mode so kernel-cmdline-style arguments passed after
the container path behave as they would on a real boot.
When running test_xopenat_auto_rw_ro under a non-root user with the
CAP_DAC_OVERRIDE capability, the test currently fails.
As the comment already says, root bypasses mode bits via CAP_DAC_OVERRIDE so
let's check for that instead of the effective user ID.
Signed-off-by: Emanuele Rocca <emanuele.rocca@arm.com>
As pointed out in review, parse_path_argument can fail for non-oom reasons.
But the function already logs, so the correct thing to do is to just
propagate the error.
The conversion doesn't work great, because some of the verbs take many
arguments and the first column is extermely wide. So similarly to
kernel-install, I dropped the sync of column widths. This allows the
help for options to use most of the available space.
-C/--capsule is now documented, fixup for
00431b2b66.
Verb functions are renamed to match verb names.
The missing first param is added to the synopsis of "wait".
It now matches the man page.
Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
The verb synopses are long, so they got broken up:
===============================================================================
> localectl [OPTIONS…] COMMAND …
Query or change system locale and keyboard settings.
Commands:
[status] Show current locale settings
set-locale LOCALE... Set system locale
list-locales Show known locales
set-keymap MAP [MAP] Set console and X11 keyboard mappings
list-keymaps Show known virtual console keyboard mappings
set-x11-keymap LAYOUT [MODEL Set X11 and console keyboard mappings
[VARIANT [OPTIONS]]]
list-x11-keymap-models Show known X11 keyboard mapping models
list-x11-keymap-layouts Show known X11 keyboard mapping layouts
list-x11-keymap-variants Show known X11 keyboard mapping variants
[LAYOUT]
list-x11-keymap-options Show known X11 keyboard mapping options
Options:
-h --help Show this help
--version Show package version
-l --full Do not ellipsize output
--no-pager Do not start a pager
--no-ask-password Do not prompt for password
-H --host=[USER@]HOST Operate on remote host
-M --machine=CONTAINER Operate on local container
--no-convert Don't convert keyboard mappings
See the localectl(1) man page for details.
===============================================================================
But I think this is OK. Everything is readable. On a more normal terminal,
everything fits nicely.
Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
The verb synopses are very long because of the many parameters.
Previously were shown without help and occupied all available columns.
With the autogenerated help format, this doesn't work great. So the
verbs and options tables are not synced, so that help for options can
use more columns. I think in this case this is better than the
alternatives.
Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Add support for configuring cpuset partition type via the
CPUSetPartition= unit file setting. This controls the kernel's
cpuset.cpus.partition cgroup attribute.
The setting takes one of "member", "root", or "isolated". This is
useful for real-time workloads that require dedicated CPU resources
without interference from other processes.
When set, systemd will write the partition type to the
cpuset.cpus.partition cgroup file. If the kernel rejects the value
(e.g., due to partition hierarchy rules), a warning is logged and the
unit continues with the kernel's default partition type.
Co-developed-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Signed-off-by: Gabriele Monaco <gmonaco@redhat.com>
The help tests would not pass because in cases where the verb synopsis
is very long, we'd format the table badly if the terminal is fairly
narrow. I experimented with a few solutions, but overall, it's hard to
achieve very good layout with the automatic formatting. I think the
approach in this commit works the best: we end up with an two- or
three-line verb synopis, which is similar to what we did manually
before.
$ COLUMNS=80 build/localectl -h
...
Commands:
[status] Show current locale settings
set-locale LOCALE... Set system locale
list-locales Show known locales
set-keymap MAP [MAP] Set console and X11 keyboard mappings
list-keymaps Show known virtual console keyboard mappings
set-x11-keymap LAYOUT [MODEL Set X11 and console keyboard mappings
[VARIANT [OPTIONS]]]
list-x11-keymap-models Show known X11 keyboard mapping models
list-x11-keymap-layouts Show known X11 keyboard mapping layouts
list-x11-keymap-variants Show known X11 keyboard mapping variants
[LAYOUT]
list-x11-keymap-options Show known X11 keyboard mapping options
I think that almost nobody actually uses an 80 column terminal, and if
they do, they probably don't spend too much time looking at our --help
output there. So the goal here is to do something reasonable and robust
and get the tests to pass.
We can use strjoina here because the strings are fully under our
control.
Looking at the corpus examples, I'm not sure the fuzzer even went into
the compat parsers. None of the files have argv[0] that'd cause
invoked_as() to go into the compat paths. So add the files to provide
a quick test and possibly bias the fuzzer search into the right
direction.
All log messages during option parsing are emitted using log_full,
and the level is set as LOG_ERR + state->log_level_shift. The default
shift is 0, but if set to e.g. 4, we log at LOG_DEBUG, and if set
to 5 or higher, logging is effectively suppressed. (Unless compiled
with LOG_TRACE, when it'd be suppressed if the shift if set to 6
or higher.) So this gives something like 'opterr', except that
without global state and potentially more flexible.
systemctl_main() is moved to systemctl.c to allow fuzz-systemctl-parse-argv
to compile. It needs systemctl_help(), which needs the verb table, with the
expected groups. Once we provide that, the linker needs all the verb_*
functions. So add dummy implementations in fuzz-systemctl-parse-argv to
allow the link to happen.
The alternative would be to provide an empty option table, but that
seems to be more complicated, and also can simulate parsing of the whole
command line with the full verb set, so it seems better to test with the
real verb table.
$ nm build/fuzz-systemctl-parse-argv | rg 0000000000418885
0000000000418885 T verb_add_dependency
0000000000418885 T verb_bind
0000000000418885 T verb_cancel
0000000000418885 T verb_cat
0000000000418885 T verb_clean_or_freeze
0000000000418885 T verb_edit
0000000000418885 T verb_enable
0000000000418885 T verb_get_default
0000000000418885 T verb_import_environment
0000000000418885 T verb_is_active
0000000000418885 T verb_is_enabled
0000000000418885 T verb_is_failed
0000000000418885 T verb_is_system_running
0000000000418885 T verb_kill
0000000000418885 T verb_list_automounts
0000000000418885 T verb_list_dependencies
0000000000418885 T verb_list_jobs
0000000000418885 T verb_list_machines
0000000000418885 T verb_list_paths
0000000000418885 T verb_list_sockets
0000000000418885 T verb_list_timers
0000000000418885 T verb_list_unit_files
0000000000418885 T verb_list_units
0000000000418885 T verb_log_setting
0000000000418885 T verb_mount_image
0000000000418885 t verb_noop
0000000000418885 T verb_preset_all
0000000000418885 T verb_reset_failed
0000000000418885 T verb_service_log_setting
0000000000418885 T verb_service_watchdogs
0000000000418885 T verb_set_default
0000000000418885 T verb_set_environment
0000000000418885 T verb_set_property
0000000000418885 T verb_show
0000000000418885 T verb_show_environment
0000000000418885 T verb_start_special
0000000000418885 T verb_start_system_special
0000000000418885 T verb_switch_root
0000000000418885 T verb_trivial_method
0000000000418885 T verb_whoami
The verbs[] table still lives in systemctl-main.c — only the option parsing
side is migrated. systemctl_dispatch_parse_argv() gains a remaining_args
out-param so run() can pass the parsed positional args to systemctl_main(),
which dispatches via _dispatch_verb_with_args() instead of dispatch_verb().
The Options section of --help now renders from the OPTION declarations; the
verb sections still use raw printfs and will be converted alongside the
verbs[] migration.
Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
Compatibility-only options (--fail, --irreversible, --ignore-dependencies,
--no-legend) are grouped at the end alongside the '.' / '?' error handlers.
The case 'P': … _fallthrough_; case 'p': pair is kept intact and placed at
-p's slot in --help, so -P sits immediately before -p in the source.
Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
So far we'd reject --state=, but it seems nicer to make it reset the
setting as we generally do. The output variable is modified in place…
Option parsing isn't atomic anyway, so I think it's fine to to that.
Add support for configuring cpuset partition type via the
CPUSetPartition= unit file setting. This controls the kernel's
cpuset.cpus.partition cgroup attribute.
The setting takes one of "member", "root", or "isolated". This is
useful for real-time workloads that require dedicated CPU resources
without interference from other processes.
When set, systemd will write the partition type to the
cpuset.cpus.partition cgroup file. If the kernel rejects the value
(e.g., due to partition hierarchy rules), a warning is logged and the
unit continues with the kernel's default partition type.
Co-developed-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Signed-off-by: Gabriele Monaco <gmonaco@redhat.com>
The pre-allocated pcie-root-port block in run_virtual_machine() places
every port directly on pcie.0 with an auto-assigned PCI address. A
minimal VM already costs 4 builtin + 10 hotplug spares = 14 pcie.0
slots, on top of 3 implicit virtio devices (virtio-rng-pci,
virtio-balloon, virtio-serial-pci) for another 3.
pcie.0 has 32 device-numbers; q35 reserves 0x00 (host bridge) and 0x1f
(ICH9 LPC), leaving ~30 auto-assignable slots. TEST-64-UDEV-STORAGE-
nvme_basic pushes 20 '-device nvme' lines through
$SYSTEMD_VMSPAWN_QEMU_EXTRA, which vmspawn does not see — total demand
14 + 3 + 20 = 37 > 30. Bus realization fails after QEMU's chardev has
already emitted the QMP greeting, and the monitor socket POLLHUPs while
we are mid-feature-probe, reported as 'QMP connection dropped during
feature probing'.
Pack the root ports as multifunction devices, 8 per pcie.0 device-
number (QEMU docs/pcie.txt:84, 117-120, 255-258). Function 0 of each
group carries multifunction=on; functions 1-7 ride the same slot via
addr=N.F. Each function remains independently hot-pluggable so vmspawn's
QMP device_add machinery is unaffected. 14 ports collapse to 2 pcie.0
slots; the nvme_basic budget becomes 2 + 3 + 20 = 25.
The chassis/slot properties (used for ACPI hotplug identity) stay as i+1
— they live in a uint8_t namespace independent of the PCI BDF and are
still unique. Base PCI slot 0x10 sits above the auto-assigned virtio
devices (which land at 0x01-0x03 in config order) and below the q35 LPC
reservation at 0x1f.
While here, rebuild the slot-count formula to match what
assign_pcie_ports() actually allocates. The +1 'SCSI controller' term
was bogus — virtio-scsi-pci comes from the hotplug-spares pool via
hotplug_port_owner[] in vmspawn-qmp.c, never from a builtin port (see
the comment in assign_pcie_ports()). The +1 'network' and +1 'vsock'
terms are now conditional on arg_network_stack and use_vsock. Bind
volumes were missing entirely. And the per-drive accounting now mirrors
assign_pcie_ports()'s skip-SCSI behaviour: non-SCSI drives (root +
extras + bind volumes) take one builtin port each, SCSI drives take none
— they share a controller drawn from the hotplug pool at device-add
time. Tighten the cap from UINT8_MAX to 192 (24 packed device-numbers ×
8) so we cannot claim more than 24 slots on pcie.0 regardless of how
many extras/runtime-mounts a caller asks for.
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Add a helper that tries to determine the number of installed CPUs. This
borrows heavily from physical_memory(), i.e. uses the physical number,
but caps by per-container cpuset.
userns_registry_remove() restores a sub-delegated UID range by writing
the previous owner's data to u<UID>.delegate with WRITE_STRING_FILE_ATOMIC.
Atomic writes go via a temp file and rename, which replaces the directory
entry with a fresh inode and severs the hardlink to g<GID>.delegate. The
stale GID side then keeps pointing at the prior inode with outdated owner
and ancestor data, so subsequent lookups via GID return wrong results.
Re-create the hardlink after the atomic write so the two views stay in
sync, matching what userns_registry_store() already does after writing
a new delegation.
We don't use it, the kernel ignores it, let's just drop
the argument. Saves callers from having to ensure the name
they pass in fits in the 64 char buffer.
The pre-allocated pcie-root-port block in run_virtual_machine() places
every port directly on pcie.0 with an auto-assigned PCI address. A
minimal VM already costs 4 builtin + 10 hotplug spares = 14 pcie.0
slots, on top of 3 implicit virtio devices (virtio-rng-pci,
virtio-balloon, virtio-serial-pci) for another 3.
pcie.0 has 32 device-numbers; q35 reserves 0x00 (host bridge) and 0x1f
(ICH9 LPC), leaving ~30 auto-assignable slots. TEST-64-UDEV-STORAGE-
nvme_basic pushes 20 '-device nvme' lines through
$SYSTEMD_VMSPAWN_QEMU_EXTRA, which vmspawn does not see — total demand
14 + 3 + 20 = 37 > 30. Bus realization fails after QEMU's chardev has
already emitted the QMP greeting, and the monitor socket POLLHUPs
while we are mid-feature-probe, reported as 'QMP connection dropped
during feature probing'.
Pack the root ports as multifunction devices, 8 per pcie.0 device-
number (QEMU docs/pcie.txt:84, 117-120, 255-258). Function 0 of each
group carries multifunction=on; functions 1-7 ride the same slot via
addr=N.F. Each function remains independently hot-pluggable so
vmspawn's QMP device_add machinery is unaffected. 14 ports collapse to
2 pcie.0 slots; the nvme_basic budget becomes 2 + 3 + 20 = 25.
The chassis/slot properties (used for ACPI hotplug identity) stay as
i+1 — they live in a uint8_t namespace independent of the PCI BDF and
are still unique. Base PCI slot 0x10 sits above the auto-assigned
virtio devices (which land at 0x01-0x03 in config order) and below
the q35 LPC reservation at 0x1f.
While here, rebuild the slot-count formula to match what
assign_pcie_ports() actually allocates. The +1 'SCSI controller' term
was bogus — virtio-scsi-pci comes from the hotplug-spares pool via
hotplug_port_owner[] in vmspawn-qmp.c, never from a builtin port (see
the comment in assign_pcie_ports()). The +1 'network' and +1 'vsock'
terms are now conditional on arg_network_stack and use_vsock. Bind
volumes were missing entirely. And the per-drive accounting now
mirrors assign_pcie_ports()'s skip-SCSI behaviour: non-SCSI drives
(root + extras + bind volumes) take one builtin port each, SCSI
drives take none — they share a controller drawn from the hotplug
pool at device-add time. Cap at 120 ports (15 device-numbers × 8) so
we cannot run off the end of the 5-bit PCI device-number space — the
usable range starting at 0x10 ends at 0x1e because ICH9 LPC sits at
0x1f.0 single-function, blocking the rest of that slot for
multifunction packing.
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
As per https://github.com/systemd/systemd/pull/41986#pullrequestreview-4281939586
This also corrects the list of unit types a bit:
1. this removes the mount/automount unit type from the list, since for these types
we do not allow aliases/renaming anyway.
2. this adds socket + swap units to the list, since they can change
name, and for both of them we actually do fork off processes hence
track resources.
Follow-up for: #41986
* 8b9ea8981e Install new files for upstream build
* b230cf0490 use dh-cruft to register & purge volatile files
* 8f9b9952e1 Install new files for upstream build