]> git.ipfire.org Git - thirdparty/systemd.git/log
thirdparty/systemd.git
2 weeks agoman: add a brief note about type 1 extra lines 41863/head
Lennart Poettering [Wed, 29 Apr 2026 11:35:41 +0000 (13:35 +0200)] 
man: add a brief note about type 1 extra lines

2 weeks agoboot: downgrade log level for an error we ignore
Lennart Poettering [Wed, 29 Apr 2026 10:39:26 +0000 (12:39 +0200)] 
boot: downgrade log level for an error we ignore

2 weeks agoboot: load extra files for UKIs into memory and register as initrds
Lennart Poettering [Wed, 25 Mar 2026 17:15:38 +0000 (18:15 +0100)] 
boot: load extra files for UKIs into memory and register as initrds

This generates on-the-fly cpio initrds from 'extra' resources declared
in Type #1 entries and installs them via the Linux initrd protocol so
that they get passed to the Linux kernel.

Replaces: #39286

2 weeks agoboot: parse 'extra' type 1 stanza too
Lennart Poettering [Fri, 20 Mar 2026 16:46:15 +0000 (17:46 +0100)] 
boot: parse 'extra' type 1 stanza too

This loads the new 'extra' stanza, but doesn't actually do anything with
it yet. That's added in a later commit.

Replaces: #39286

Implements: https://github.com/uapi-group/specifications/pull/212

2 weeks agocpio: move TPM PCR info into CpioTarget
Lennart Poettering [Wed, 29 Apr 2026 10:01:59 +0000 (12:01 +0200)] 
cpio: move TPM PCR info into CpioTarget

The PR to measure into is closely associated with where we place a
resource in the initrd cpios. Hence, let's also track it in CpioTarget,
thus simplifying our function parameter lists that way.

No change in behaviour.

2 weeks agolibsystemd: Clean up meson.build
Daan De Meyer [Tue, 28 Apr 2026 17:47:14 +0000 (19:47 +0200)] 
libsystemd: Clean up meson.build

Merge the two blocks adding tests, since there seems to be
no obvious reason to have two separate blocks, as they both
contain tests from the same libraries.

2 weeks agomkosi: Install liburing
Daan De Meyer [Mon, 27 Apr 2026 21:46:37 +0000 (23:46 +0200)] 
mkosi: Install liburing

Make sure liburing is installed so it's available for
experimentation in sd-event integration.

2 weeks agocore: add io.systemd.Unit.StartTransient() to the varlink API (#41583)
Michael Vogt [Wed, 29 Apr 2026 06:20:56 +0000 (08:20 +0200)] 
core: add io.systemd.Unit.StartTransient() to the varlink API (#41583)

This commit adds a simple version of io.systemd.Unit.StartTransient
for varlink. It is similar to the dbus version, but there is a key
difference:
1. Instead of building the unit from key/value properties it
takes a structured json object "UnitContext" with a "Service" field
inside.
   It is also only implementing a minimal set of what can be done with a
   service.
2. No aux units (for now)
3. When called with --more the varlink socket can notify about
   state changes depending on the notify{Job,Unit}Changes parameter

This aligns to the json objects/format from
https://github.com/systemd/systemd/pull/39391
and to show how the format can be shared it adds a new
(minimal) `ServiceContext` that is now part of
`io.systemd.Unit.List()`.

2 weeks agoci: Reduce noise from claude-review workflow
Daan De Meyer [Tue, 28 Apr 2026 07:26:12 +0000 (09:26 +0200)] 
ci: Reduce noise from claude-review workflow

2 weeks agoAdd "namespaces" to option macros, convert systemd-run+run0 (#41844)
Zbigniew Jędrzejewski-Szmek [Tue, 28 Apr 2026 17:38:04 +0000 (19:38 +0200)] 
Add "namespaces" to option macros, convert systemd-run+run0 (#41844)

2 weeks agoupdate TODO
Lennart Poettering [Tue, 28 Apr 2026 10:04:20 +0000 (12:04 +0200)] 
update TODO

2 weeks agoshared/options: add an assert loop to verify ordering 41844/head
Zbigniew Jędrzejewski-Szmek [Tue, 28 Apr 2026 06:45:03 +0000 (08:45 +0200)] 
shared/options: add an assert loop to verify ordering

If things are misordered, we need to catch this. Use assert_se to make
the check also in custom builds that otherwise disable assertions.

2 weeks agorun: use a "named namespace" also for the main option parser
Zbigniew Jędrzejewski-Szmek [Tue, 28 Apr 2026 06:11:40 +0000 (08:11 +0200)] 
run: use a "named namespace" also for the main option parser

It seems that clang reorders the entries in the options array that
originate from different functions, but not within a function. Using
"named namespaces" exclusively should sidestep the issue.

(A bigger hammer would be to sort the array. We *can* do this, since the
options have the increasing .id field. But that'd require duplicating
the memory or making it writable. Let's avoid this until we know for
sure that it's needed.)

2 weeks agorun: convert run0 option parser to macros
Zbigniew Jędrzejewski-Szmek [Mon, 27 Apr 2026 22:30:08 +0000 (00:30 +0200)] 
run: convert run0 option parser to macros

This exercises the new option namespace code.

--help output is generally the same, except for the formatting changes
related to use of the new output helpers and the common option macros.

--same-root-dir is now documented (followup for
  475729b80532dfbbce98705dade6570ce5cc29f0).

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
2 weeks agorun: convert parse_argv() to OPTION macros
Zbigniew Jędrzejewski-Szmek [Mon, 27 Apr 2026 22:04:50 +0000 (00:04 +0200)] 
run: convert parse_argv() to OPTION macros

--system is now documented (fixup for 66b1e746055b9c56fd72c0451a4cfb2b06cf3f20).
--capsule is now documented (fixup for 759b3c082d463a488235592df45cbebefbe1ad5c).

--help output is generally the same, except for the formatting changes
related to use of the new output helpers and common option macros.

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
2 weeks agorun: reorder switch cases to match help() output order
Zbigniew Jędrzejewski-Szmek [Mon, 27 Apr 2026 21:58:24 +0000 (23:58 +0200)] 
run: reorder switch cases to match help() output order

Both parse_argv() and parse_argv_sudo_mode() handled options in an
order that no longer matched the help text. Reorder the case statements
so the source order mirrors what the user sees in --help.

In parse_argv_sudo_mode(), drop the case 'i' → ARG_VIA_SHELL fall-through
so the cases can be sequenced independently; 'i' now sets arg_via_shell
directly.

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
2 weeks agoshared/options: introduce "namespaces" for options
Zbigniew Jędrzejewski-Szmek [Mon, 27 Apr 2026 20:56:50 +0000 (22:56 +0200)] 
shared/options: introduce "namespaces" for options

This allows multiple option parsers to be defined in a single
compilation unit. We put the OPTION_NAMESPACE("name") to split
up the options. The basic implementation is similar to groups,
except that groups only matter for help display, while namespaces
matter for both help display and actual option parsing. When parsing,
we locate the appropriate range between the beginning of options
and the next namespace marker or between two namespace markers and
only look at that range.

2 weeks agoloop-util: don't reuse partition fd when partscan needed
Clayton Craft [Tue, 28 Apr 2026 02:38:26 +0000 (19:38 -0700)] 
loop-util: don't reuse partition fd when partscan needed

Some devices (e.g. android phones running pmOS) cannot have their OEM
partition table altered without breaking the firmware, so the distros's
partitions live inside a nested GPT carved into one of the OEM
partitions. Exposing these subpartitions requires wrapping the outer
partition in a loop device with partscan enabled, since the kernel does
not go into nested partition tables.

systemd already detects this case in udev-builtin-blkid
(ID_PART_GPT_AUTO_ROOT_DISK_NEEDS_LOOP) and acts on with
systemd-loop@.service, but this fails towards the end.
loop_device_make_internal has an optimization where if the input is
already a block device with a matching sector size, it skips creating
a loop and just hands back the original fd. That's fine for whole disks
but wrong for partitions, which don't support partscan, so this causes
dissect_image to fail with EPROTONOSUPPORT.

This patch changes the behavior to only take the shortcut when the input
is a whole disk, or when partscan was not requested.

Co-Authored-By: Clayton Craft <clayton@craftyguy.net>
2 weeks agoshared/options: fix --help indentation for long options
Zbigniew Jędrzejewski-Szmek [Tue, 28 Apr 2026 09:12:43 +0000 (11:12 +0200)] 
shared/options: fix --help indentation for long options

In 4339197f5d4f712bc900d8e09c892015d48b19bb the helper to format -o/--opt=
was split out, but the indentation was for --long-options was messed up.
We'd print:
Options:
  -h --help             Show this help
  --version             Show package version
  --no-ask-password     Do not prompt for password
  ...
But we want
  -h --help             Show this help
     --version          Show package version
     --no-ask-password  Do not prompt for password
  ...

The prefix argument was arguably ugly, even if it allowed one alloc to be
avoided. Let's get rid of it and let the handler prefix the string as
appropriate. This makes other callers nicer too.

Fixup for 4339197f5d4f712bc900d8e09c892015d48b19bb.

2 weeks agocore: ensure all types from execute.h start with Exec
Lennart Poettering [Tue, 28 Apr 2026 10:05:28 +0000 (12:05 +0200)] 
core: ensure all types from execute.h start with Exec

Until very recently all types defined by execute.h started with "Exec"
in the name. I think that was useful, since it made clear that the types
are associated with the ExecContext infrastructure. Let's hence restore
this.

(If we every move these types out of execute.h we should drop the "Exec"
prefix again. But today is not that day.)

No real code changes, just dumb renaming.

2 weeks agomeson: rerun 'update-man-rules'
Lennart Poettering [Tue, 28 Apr 2026 10:03:45 +0000 (12:03 +0200)] 
meson: rerun 'update-man-rules'

2 weeks agoA couple of sanitizer-related tweaks (#41808)
Luca Boccassi [Tue, 28 Apr 2026 11:04:45 +0000 (12:04 +0100)] 
A couple of sanitizer-related tweaks (#41808)

The sanitizer job was FUBAR on Fedora Rawhide (and RHEL 10 to some
extent) due to several changes:
- latest LLVM (v22) introduced a change that occasionally generates a
false-positive warning when running with sanitizers
  - several tools had to be "ASan-wrapped" because:
- util-linux started linking against libsystemd which propagated to
other tools depending on its shared libraries (like libmount)
- libssh started depending on libfido2, which depends on libudev; this
then translated to an interesting depedency chain where tpm2 utils got a
dependency on libudev through libcurl -> libssh -> libfido2
- polkit added MemoryMax= to its service file, which is incompatible
with ASan-runs (at least with the current limits)

See the commits for more detailed descriptions.

Also, one note: the santizer job is currently still FUBAR on Fedora
Rawhide (or, more specifically, the TEST-50-DISSECT and TEST-58-REPART),
because mkfs.erofs also gained a dependency on libudev (through libcurl,
see above), but the wrapping currently doesn't work as it also depends
on libqpl which is linked with libtsan (which is incompatible with other
sanitizers). This is currently tracked in
https://bugzilla.redhat.com/show_bug.cgi?id=2461146

2 weeks agopo: Translated using Weblate (German)
Dark Cronyx [Tue, 28 Apr 2026 08:59:17 +0000 (08:59 +0000)] 
po: Translated using Weblate (German)

Currently translated at 100.0% (266 of 266 strings)

Co-authored-by: Dark Cronyx <darkcronyx@protonmail.com>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/de/
Translation: systemd/main

2 weeks agofork-notify: Use callback instead of argv NULL code path with return (#41813)
Daan De Meyer [Tue, 28 Apr 2026 08:15:31 +0000 (10:15 +0200)] 
fork-notify: Use callback instead of argv NULL code path with return (#41813)

2 weeks agocore: transition job to JOB_FINISHED on uninstall 41583/head
Michael Vogt [Mon, 27 Apr 2026 11:12:30 +0000 (13:12 +0200)] 
core: transition job to JOB_FINISHED on uninstall

When a job reaches the job_uninstall() stage we used to set the
state to JOB_WAITING. However now that we have a JOB_FINISHED state [1]
we should use that instead. This is more accurate so when
varlink_job_send_removed_signal() is called the job is in the expected
state and that is what the user will see.

Note that this does not change the D-Bus API because there
bus_job_send_removed_signal() doesn't send the state, it only sends
the result.

[1] https://github.com/systemd/systemd/pull/41811

2 weeks agoudev: don't assert on worker cap after killing a broken idle worker 41758/head
Daan De Meyer [Tue, 21 Apr 2026 08:44:44 +0000 (08:44 +0000)] 
udev: don't assert on worker cap after killing a broken idle worker

manager_can_process_event() considers an event processable if either
there is room below children_max to spawn, or an idle worker exists.
When only the latter holds, event_run() picks the idle worker and
tries device_monitor_send(). If that send fails, event_run() SIGKILLs
the worker, marks it WORKER_KILLED and continues the loop. With no
other idle worker available, it falls through to worker_spawn(),
guarded by:

    assert(hashmap_size(manager->workers) < manager->config.children_max);

The just-killed worker is still in manager->workers until its SIGCHLD
is reaped by on_worker_exit(), so at the cap this assertion trips and
udevd aborts:

    Assertion 'hashmap_size(manager->workers) < manager->config.children_max'
    failed at src/udev/udev-manager.c:635, function event_run(). Aborting.

Instead of asserting, bail out when we are already at the worker
limit. The event remains in EVENT_QUEUED; once the killed worker's
SIGCHLD arrives and frees it from the hashmap, on_post() re-runs
event_queue_start() and the event is retried.

2 weeks agooptions: add a proper state machine field
Lennart Poettering [Fri, 24 Apr 2026 08:33:46 +0000 (10:33 +0200)] 
options: add a proper state machine field

Let's track the state of the option parser in an explicit 'state' field.

Benefits:

1. We can make sure that a parser that got into a failure state will
   be invalidated for good (i.e. further operations are guaranteed to
   fail too).

2. As a side effect this cleans up the option_parse() return parameter
   handling: we'll now always initialize ret_option/ret_arg when
   returning >= 0, as per coding style.

2 weeks agooptions: tighten validation of argc/argv
Lennart Poettering [Fri, 24 Apr 2026 08:37:48 +0000 (10:37 +0200)] 
options: tighten validation of argc/argv

If argc/argv do no match a lot of our assumptions are invalid, hence
let's check this explicitly once, instead of ignoring the issue.

2 weeks agooptions: drop redundant enum value declaration
Lennart Poettering [Fri, 24 Apr 2026 08:32:52 +0000 (10:32 +0200)] 
options: drop redundant enum value declaration

2 weeks agotree-wide: change option_parse() to return option and arg via internal state (#41833)
Zbigniew Jędrzejewski-Szmek [Mon, 27 Apr 2026 17:42:52 +0000 (19:42 +0200)] 
tree-wide: change option_parse() to return option and arg via internal state (#41833)

2 weeks agomachine-register: don't unref borrowed varlink reply 41813/head
Kai Lüke [Fri, 24 Apr 2026 16:49:09 +0000 (01:49 +0900)] 
machine-register: don't unref borrowed varlink reply

ASAN showed a use-after-free error for systemd-vmspawn's
machine_register call because the reply got accessed and freed again
through _cleanup. The same problem exists in two
verb_machine_control_one/unregister_machine.
Fix these call sites to not set up _cleanup.

2 weeks agonsresource: fix buffer overrun reported by ASAN
Kai Lüke [Fri, 24 Apr 2026 16:42:36 +0000 (01:42 +0900)] 
nsresource: fix buffer overrun reported by ASAN

This came up when running systemd-vmspawn with ASAN to fix another bug
and thus I had to fix this overrun here first: The dispatch tables were
missing the terminator, add it.

2 weeks agofork-notify: Use callback instead of argv NULL code path with return
Kai Lüke [Fri, 24 Apr 2026 15:18:56 +0000 (00:18 +0900)] 
fork-notify: Use callback instead of argv NULL code path with return

In 012d87c1fc/cc8f398202 it was made possible for fork_notify() to
return in the child but at that point all FDs were closed and the
_cleanup path from the return causes assertion failures due to invalid
FDs in notify_event_source/event, leading to a vmspawn failing to start
with a SIGABRT logged in coredump.
Instead of TAKE_PTR on a bunch of things which is fragile, rather avoid
the return and instead add an explicit callback handler and guarantee
to exit directly after it. A userdata argument is also added but not
used yet I think it's quite normal to have for a callback.

2 weeks agovmspawn-varlink: treat QMP disconnect as success for Terminate
Christian Brauner [Mon, 27 Apr 2026 10:34:27 +0000 (12:34 +0200)] 
vmspawn-varlink: treat QMP disconnect as success for Terminate

QMP "quit" tells QEMU to exit, which races the reply with the socket
EOF: sometimes the disconnect lands in qmp_client_fail_pending() with
-ECONNRESET before the reply has been parsed. The shared completion
callback then translates that into io.systemd.MachineInstance.NotConnected,
turning the desired outcome into a varlink error.

This is exactly what TEST-87-AUX-UTILS-VM exposes during its repeated
start/pause/resume/terminate stress loop: a successful Pause/Describe
followed milliseconds later by a Terminate that fails with NotConnected
when the disconnect path wins the race.

Give Terminate its own completion callback that treats disconnect-class
errors as success, since QEMU shutting down is the whole point of "quit".
The other simple commands (Pause, Resume, PowerOff, Reboot) keep the
existing semantics: they expect QMP to remain alive, so NotConnected is
the correct reply for them.

Link: https://github.com/systemd/systemd/actions/runs/24986080288/job/73159585425?pr=41835
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2 weeks agotest: add varlink io.systemd.Unit.StartTransient() test
Michael Vogt [Tue, 14 Apr 2026 15:04:31 +0000 (17:04 +0200)] 
test: add varlink io.systemd.Unit.StartTransient() test

This commit adds a bunch of integration tests for the new varlink
based io.systemd.Unit.StartTransient().

2 weeks agocore: add io.systemd.Unit.StartTransient() to the varlink API
Michael Vogt [Tue, 14 Apr 2026 15:04:15 +0000 (17:04 +0200)] 
core: add io.systemd.Unit.StartTransient() to the varlink API

This commit adds a simple version of io.systemd.Unit.StartTransient
for varlink. It is similar to the dbus version, but there is a key
difference:
1. Instead of building the unit from key/value properties it
   takes a json object in the "service" parameter. It is also
   only implementing a minimal set of what can be done with a
   service (for now)
2. No aux units (for now)
3. When called with --more the varlink socket can notify about
   unit job and state changes controlled via a bool on the
   varlink call inputs: notify{Job,Unit}Changes

We use the new io.systemd.Job interface when outputing the
io.systemd.Unit.StartTransient result as it makes the output
nice and mirrors the input.

Note that the property names follow the D-Bus naming to make a
future "systemctl show" transition from D-Bus -> varlink easier.

Because UnitContext is now also used for the inputs we need
to make a bunch of fields `SD_VARLINK_NULLABLE` so that the
input is even accepted. This does not affect the output, it
is still fully populated, just the schema. The ID of UnitContext
is still required.

Thanks to ikruglov and Lennart for their excellent feedback on
this.

2 weeks agocore: extract manager_setup_transient_unit() helper
Michael Vogt [Tue, 14 Apr 2026 14:24:07 +0000 (16:24 +0200)] 
core: extract manager_setup_transient_unit() helper

Extract the transient unit setup logic from transient_unit_from_message()
in dbus-manager.c into a shared helper.

This prepares for reuse by the varlink StartTransient implementation.

2 weeks agovarlink: add new io.systemd.Job interface
Michael Vogt [Tue, 21 Apr 2026 07:10:39 +0000 (09:10 +0200)] 
varlink: add new io.systemd.Job interface

This commit creates a new varlink-io.systemd.Job.c file and puts
the job related varlink types into this file. Those will be
used by the upcoming io.systemd.Unit.StartTransient.

Note that the property names follow the D-Bus naming to make a
future "systemctl show" transition from D-Bus -> varlink easier.

Thanks to @ikruglov for suggesting this preparation commit and
to Lennart for suggesting the D-Bus compatibility considerations.

2 weeks agoshared/options: add whitespace to OPTION_COMMON definitions 41833/head
Zbigniew Jędrzejewski-Szmek [Thu, 23 Apr 2026 18:04:35 +0000 (20:04 +0200)] 
shared/options: add whitespace to OPTION_COMMON definitions

Initially I thought that there'd be just a handful, but the list
has grown over time and all bunched up together they are hard to
read.

2 weeks agonspawn,vmspawn: fix state optarg uses
Zbigniew Jędrzejewski-Szmek [Mon, 27 Apr 2026 07:22:43 +0000 (09:22 +0200)] 
nspawn,vmspawn: fix state optarg uses

2 weeks agotree-wide: change option_parse() to return option and arg via internal state
Zbigniew Jędrzejewski-Szmek [Sun, 26 Apr 2026 21:22:27 +0000 (23:22 +0200)] 
tree-wide: change option_parse() to return option and arg via internal state

It was requested to make the 'c', 'opt', and 'arg' params the same, i.e.
defined through the FOREACH_OPTION macro. But we can't do that easily,
because 'c' was defined in the for loop definition, and we can only
define variables of the same type in that way. Also, in some cases we
need only 'c', in other cases with need 'c' and 'arg, in some cases 'c'
and 'opt', and in other cases all three. We'd need to either
conditionalize or mark those variables with _unused_ to deal with
compiler warnings. But a different approach works quite nicely: add
state.opt and state.arg to show the current option and it's argument.
(The short names are picked on purpose to reduce verbosity since those
are used a lot.)

2 weeks agoConvert udev helper programs to option macros (#41820)
Zbigniew Jędrzejewski-Szmek [Mon, 27 Apr 2026 09:22:23 +0000 (11:22 +0200)] 
Convert udev helper programs to option macros (#41820)

2 weeks agojob: add a "finished" state for jobs
Lennart Poettering [Fri, 24 Apr 2026 14:00:21 +0000 (16:00 +0200)] 
job: add a "finished" state for jobs

So far when a job completed we'd never transition into any new state,
we'd just do some final processing work (such as notifying clients) and
destroy it.

Let's change that, and briefly enter a final state: "finished". This is
useful so that code that notifies clients can generically send the
quadruplet of id, type, state, result for any change notification and
naturally can communicate job completion that way: by setting the state
field to "finished".

Prompted by the discussions in: #41583

2 weeks agoiocost: convert to the new option parser 41820/head
Zbigniew Jędrzejewski-Szmek [Sat, 25 Apr 2026 17:06:55 +0000 (19:06 +0200)] 
iocost: convert to the new option parser

--help output only has changes expected in the new style.

Co-developed-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2 weeks agoscsi_id: convert to the new option parser
Zbigniew Jędrzejewski-Szmek [Sat, 25 Apr 2026 11:01:13 +0000 (13:01 +0200)] 
scsi_id: convert to the new option parser

Common page-code parsing extracted into a parse_page_code() helper.

While at it, return real error values (-EINVAL, etc.) rather than -1,
and rename retval to r throughout for consistency.

The body of main is moved to new run. The closing of logging file
descriptors is dropped. They will be closed automatically anyway. Not
sure what the original purpose of that code was. The code is also
modernized in various places… though more changes could be made. The
return convention of help() and similar functions is changed to usual
negative/0/1, where 0 means that the caller should quit.

set_inq_values would return positive error values too, which was
previously ignored. It's not entirely clear, but that doesn't seem
to have been on purpose.

2 weeks agoformat-table: fix potential segfault
Yu Watanabe [Sun, 26 Apr 2026 17:04:38 +0000 (02:04 +0900)] 
format-table: fix potential segfault

In format-table.h, TABLE_IN_ADDR is commented as "Takes a union in_addr_union
(or a struct in_addr)". However, if we pass struct in_addr to table_add_many(),
the function reads more than the size of the struct.

2 weeks agopreparatory work for the storage provider work in #41776 (#41814)
Lennart Poettering [Sun, 26 Apr 2026 21:44:02 +0000 (23:44 +0200)] 
preparatory work for the storage provider work in #41776 (#41814)

nothing earth shattering, but generally useful. without #41776 it has no
immediate users though

2 weeks agovarious trivial tweaks (#41828)
Luca Boccassi [Sun, 26 Apr 2026 21:40:01 +0000 (22:40 +0100)] 
various trivial tweaks (#41828)

2 weeks agoblockdev-list: make BLOCKDEV_LIST_IGNORE_ROOT suppress all definitions of the root... 41814/head
Lennart Poettering [Thu, 23 Apr 2026 13:46:10 +0000 (15:46 +0200)] 
blockdev-list: make BLOCKDEV_LIST_IGNORE_ROOT suppress all definitions of the root disk

There are various definitions of the root disk, let's suppress them all if
the flag is set. So far only the outermost is suppressed, which is a bit
weird, given it's "further away" from the rootfs.

2 weeks agoblockdev-list: pick up read_only property
Lennart Poettering [Thu, 23 Apr 2026 06:58:48 +0000 (08:58 +0200)] 
blockdev-list: pick up read_only property

2 weeks agofs-util: add XO_AUTO_RW_RO
Lennart Poettering [Wed, 22 Apr 2026 08:17:19 +0000 (10:17 +0200)] 
fs-util: add XO_AUTO_RW_RO

2 weeks agoformat-table: add tristate field
Lennart Poettering [Wed, 22 Apr 2026 21:43:17 +0000 (23:43 +0200)] 
format-table: add tristate field

2 weeks agopath-lookup: add state_directory_generic() helper inspired by runtime_directory_generic()
Lennart Poettering [Thu, 23 Apr 2026 13:44:52 +0000 (15:44 +0200)] 
path-lookup: add state_directory_generic() helper inspired by runtime_directory_generic()

2 weeks agohelp-util: reword comment a bit 41828/head
Lennart Poettering [Sun, 26 Apr 2026 18:53:28 +0000 (20:53 +0200)] 
help-util: reword comment a bit

Based on comments here:

https://github.com/systemd/systemd/pull/41805#discussion_r3141746275

2 weeks agonotify: we typically say 'service manager' not 'init system', do so here too
Lennart Poettering [Sun, 26 Apr 2026 18:51:26 +0000 (20:51 +0200)] 
notify: we typically say 'service manager' not 'init system', do so here too

2 weeks agossh-proxy: add a missing dispatch table sentinel
Frantisek Sumsal [Sat, 25 Apr 2026 21:51:48 +0000 (23:51 +0200)] 
ssh-proxy: add a missing dispatch table sentinel

Which was accidentally dropped in e6be5fb7200fb02e78e4f27f49a4d734b7b850a0.

Follow-up for e6be5fb7200fb02e78e4f27f49a4d734b7b850a0.

2 weeks agovarlink: address some trivial points Claude found
Lennart Poettering [Sun, 26 Apr 2026 18:50:09 +0000 (20:50 +0200)] 
varlink: address some trivial points Claude found

Just addressing Claude's last review from #41815

2 weeks agovarlink-util: add generic code that calls out to a 'hook' directory o… (#41815)
Christian Brauner [Sun, 26 Apr 2026 15:31:52 +0000 (17:31 +0200)] 
varlink-util: add generic code that calls out to a 'hook' directory o… (#41815)

…f sockets

2 weeks agoshared/options: split out helper to format -o/--option=
Zbigniew Jędrzejewski-Szmek [Sat, 25 Apr 2026 11:31:43 +0000 (13:31 +0200)] 
shared/options: split out helper to format -o/--option=

2 weeks agoata_id: convert to the new option parser
Zbigniew Jędrzejewski-Szmek [Sat, 25 Apr 2026 10:43:12 +0000 (12:43 +0200)] 
ata_id: convert to the new option parser

The commandline check is tightened to reject extra arguments.

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
2 weeks agocdrom_id: convert to the new option parser
Zbigniew Jędrzejewski-Szmek [Sat, 25 Apr 2026 10:33:03 +0000 (12:33 +0200)] 
cdrom_id: convert to the new option parser

The commandline check is tightened to reject extra arguments.

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
2 weeks agodmi_memory_id: convert to the new option parser
Zbigniew Jędrzejewski-Szmek [Sat, 25 Apr 2026 10:17:27 +0000 (12:17 +0200)] 
dmi_memory_id: convert to the new option parser

For some reason, the old code had duplicate {"version", 'v'} entry in
the options table and a matching case that could not be reached.

Commandline parsing is tightened to reject any positional arguments.

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
2 weeks agofido_id: convert to the new option parser
Zbigniew Jędrzejewski-Szmek [Sat, 25 Apr 2026 10:09:05 +0000 (12:09 +0200)] 
fido_id: convert to the new option parser

The commandline check is tightened. Previously the program would
crash if called without an argument.

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
2 weeks agomtd_probe: convert to the new option parser
Zbigniew Jędrzejewski-Szmek [Sat, 25 Apr 2026 10:05:47 +0000 (12:05 +0200)] 
mtd_probe: convert to the new option parser

The commandline check is tightened. Previously the program would
crash if called without an argument.

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
2 weeks agovarlink-util: add generic code that calls out to a 'hook' directory of sockets 41815/head
Lennart Poettering [Thu, 23 Apr 2026 07:29:20 +0000 (09:29 +0200)] 
varlink-util: add generic code that calls out to a 'hook' directory of sockets

2 weeks agotest: don't strip directives from test units 41808/head
Frantisek Sumsal [Sat, 25 Apr 2026 21:39:47 +0000 (23:39 +0200)] 
test: don't strip directives from test units

The original find was matching even our test units, which caused issues
when the check was extended with Memory*= directives, as we stripped
them off from test units for TEST-55-OOMD where we certainly need them.
Since the stripping was meant primarily for "production-grade" units,
let's limit it to units under /etc/systemd/system/ and
/usr/lib/systemd/system/.

2 weeks agotest: slightly reduce the performance/memory overhead for wrapped binaries
Frantisek Sumsal [Sat, 25 Apr 2026 14:37:34 +0000 (16:37 +0200)] 
test: slightly reduce the performance/memory overhead for wrapped binaries

Let's drop the quarantine that ASan uses for use-after-free detection,
as it's pointless in wrapped binaries and can consume up to 256 MiB of
memory (with the default configuration). Also, don't keep any stack
traces for allocations & deallocations, which should (slightly) help
with both memory & performance overhead.

2 weeks agotest: temporarily ignore sanitizer warning about blocked ptrace()
Frantisek Sumsal [Thu, 23 Apr 2026 13:11:01 +0000 (15:11 +0200)] 
test: temporarily ignore sanitizer warning about blocked ptrace()

LLVM 22 introduced an additional check [0] for ptrace() syscall when
invoking sanitizers [0] which currently produces a false-positive
warning when running some of our units under sanitizers:

[   47.524680] systemd-timedated[740]: ==740==WARNING: ptrace appears to be blocked (is seccomp enabled?). LeakSanitizer may hang.
[   47.524680] systemd-timedated[740]: ==740==Child exited with signal 15.
...
[ 1555.734223] systemd-oomd[93]: ==93==WARNING: ptrace appears to be blocked (is seccomp enabled?). LeakSanitizer may hang.
[ 1555.734223] systemd-oomd[93]: ==93==Child exited with signal 15.
...

It is a false positive because we disable the seccomp filters
system-wide for our units in the sanitizer jobs.

Now, from what I've seen so far this happens only in
Type=notify(-reload) units that also utilize bus_event_loop_with_idle().
This, combined with the fact that the ptrace()-check child process from
[0] checks only if the child process was killed by _any_ signal, means
that if the systemd unit exits on its own after becoming idle and then
something sends it SIGTERM (either via explicit `systemctl stop` or
during system shutdown), this SIGTERM might hit the ptrace()-check child
process from the sanitizer handler (as we also send the signal to all
processes in the target cgroup), which the parent process then
mistakenly evaluates as a blocked ptrace() syscall, even though the
check process wasn't killed by SIGSYS.

I filed this as [1] to the LLVM project, but let's also temporarily
ignore the warning in the sanitizer report processing, as it currently
causes annoying test fails.

[0] https://github.com/llvm/llvm-project/commit/a708b4bf21d7c2298224cdacf7d424abc3c8fed4
[1] https://github.com/llvm/llvm-project/issues/193714

2 weeks agotest: drop any memory limits from units when running with sanitizers
Frantisek Sumsal [Fri, 24 Apr 2026 12:17:23 +0000 (14:17 +0200)] 
test: drop any memory limits from units when running with sanitizers

As the memory usage under sanitizers is quite unpredictable.

This is currently relevant mainly for Polkit, as it introduced memory
limits for its polkitd.service unit in the latest version [0] which are
very easy to trigger when running under sanitizers (as polkitd depends
on libsystemd which brings ASan into polkitd's address space).

[0] https://github.com/polkit-org/polkit/commit/7d9c06c58a957ee3f2a4383ade6f207b05207e3e

2 weeks agotest: wrap even more binaries when running with sanitizers
Frantisek Sumsal [Thu, 23 Apr 2026 11:44:59 +0000 (13:44 +0200)] 
test: wrap even more binaries when running with sanitizers

Turns out that the util-linux dep on libsystemd caused more fun than I
originally anticipated:

$ lddtree /usr/bin/dfuzzer
dfuzzer => /usr/bin/dfuzzer (interpreter => /lib64/ld-linux-x86-64.so.2)
    libgio-2.0.so.0 => /lib64/libgio-2.0.so.0
        libgmodule-2.0.so.0 => /lib64/libgmodule-2.0.so.0
        libz.so.1 => /lib64/libz.so.1
        libmount.so.1 => /lib64/libmount.so.1
            libblkid.so.1 => /lib64/libblkid.so.1
            libsystemd.so.0 => /lib64/libsystemd.so.0
                libm.so.6 => /lib64/libm.so.6
                    ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2
        libselinux.so.1 => /lib64/libselinux.so.1
            libpcre2-8.so.0 => /lib64/libpcre2-8.so.0
...

Also, the tpm2 utils now depend on libudev through libcurl -> libssh ->
libfido2 dep chain:

$ lddtree /usr/bin/tpm2_pcrread
tpm2_pcrread => /usr/bin/tpm2_pcrread (interpreter => /lib64/ld-linux-x86-64.so.2)
    ...
    libcurl.so.4 => /lib64/libcurl.so.4
    ...
        libssh.so.4 => /lib64/libssh.so.4
            libfido2.so.1 => /lib64/libfido2.so.1
                libcbor.so.0.13 => /lib64/libcbor.so.0.13
                libudev.so.1 => /lib64/libudev.so.1
                    libgcc_s.so.1 => /lib64/libgcc_s.so.1
...

Follow-up for 8030e0b19ef7c0e823d84dd08ad38a2d88e0a230.

2 weeks agov4l_id: convert to the new option parser
Zbigniew Jędrzejewski-Szmek [Sat, 25 Apr 2026 09:58:50 +0000 (11:58 +0200)] 
v4l_id: convert to the new option parser

The commandline check is tightened to reject extra arguments.

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
2 weeks agohwdb: sensor: add accel mount matrix for GPD WIN 5
fecet [Sat, 25 Apr 2026 06:48:19 +0000 (14:48 +0800)] 
hwdb: sensor: add accel mount matrix for GPD WIN 5

The WIN 5 (DMI product G1618-05) ships the same BMI0160
accelerometer with the same physical mounting as the Win Max 2
(G1619-04), so reuse its mount matrix. Verified on hardware:
without the matrix iio-sensor-proxy reports
AccelerometerOrientation=normal regardless of physical pose,
and applying the G1619-04 matrix makes orientation transitions
(normal / left-up / right-up / bottom-up) track the device
correctly.

2 weeks agoadd helpers for unified --help formatting (#41805)
Zbigniew Jędrzejewski-Szmek [Sat, 25 Apr 2026 09:23:18 +0000 (11:23 +0200)] 
add helpers for unified --help formatting (#41805)

I see --help output formatting as contiuation of @keszybz's work on
options.[ch], hence let's start to add some really basic infrastructure
to unify the --help output more.

2 weeks agoip-util: introduce several functions for IP packet handling (#41801)
Yu Watanabe [Sat, 25 Apr 2026 01:15:54 +0000 (10:15 +0900)] 
ip-util: introduce several functions for IP packet handling (#41801)

2 weeks agoip-util: define IPV4_MIN_REASSEMBLY_SIZE 41801/head
Yu Watanabe [Mon, 13 Apr 2026 23:12:49 +0000 (08:12 +0900)] 
ip-util: define IPV4_MIN_REASSEMBLY_SIZE

The number will be later used at several places.

2 weeks agoip-util: introduce udp_packet_verify()
Yu Watanabe [Mon, 16 Mar 2026 15:11:25 +0000 (00:11 +0900)] 
ip-util: introduce udp_packet_verify()

This is mostly equivalent to dhcp_packet_verify_headers(), but
- it optionally returns the UDP payload as iovec, and
- supports IP header with options,
- check packet length more strictly.

2 weeks agoip-util: introduce udp_packet_build()
Yu Watanabe [Sun, 15 Mar 2026 04:57:33 +0000 (13:57 +0900)] 
ip-util: introduce udp_packet_build()

Then make dhcp_packet_append_ip_headers() just a wrapper of the new
function. Currently, the wrapper is inefficient, but will be removed in
a later commit.

2 weeks agoip-util: introduce ip_checksum()
Yu Watanabe [Sun, 15 Mar 2026 04:30:38 +0000 (13:30 +0900)] 
ip-util: introduce ip_checksum()

It is equivalent to dhcp_packet_checksum(). It is generic
and not specific to DHCP. Hence, renamed to ip_checksum().

2 weeks agounits: order networkd resolve hook After=network-pre.target
Nick Rosbrook [Fri, 24 Apr 2026 13:38:42 +0000 (09:38 -0400)] 
units: order networkd resolve hook After=network-pre.target

Without this, the socket is available well before systemd-networkd.service
is able to start, because of its own After=network-pre.target ordering.
Then, if resolved handles queries before network-pre.target, it will
hang waiting for networkd to reply to hook queries.

This is currently happening in the wild with cloud-init.

2 weeks agonss-myhostname: fix maybe-uninitialized warning
Luca Boccassi [Fri, 24 Apr 2026 12:31:46 +0000 (13:31 +0100)] 
nss-myhostname: fix maybe-uninitialized warning

In resolute with gcc 15.2.0:

472s ../src/nss-myhostname/nss-myhostname.c: In function ‘_nss_myhostname_gethostbyname4_r’:
472s ../src/nss-myhostname/nss-myhostname.c:132:44: error: ‘local_address_ipv4’ may be used uninitialized [-Werror=maybe-uninitialized]
472s   132 |                 *(uint32_t*) r_tuple->addr = local_address_ipv4;
472s       |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
472s ../src/nss-myhostname/nss-myhostname.c:42:18: note: ‘local_address_ipv4’ was declared here
472s    42 |         uint32_t local_address_ipv4;
472s       |                  ^~~~~~~~~~~~~~~~~~

2 weeks agovmspawn: prepare QMP infrastructure for runtime block-device hotplug (#41763)
Christian Brauner [Fri, 24 Apr 2026 15:38:54 +0000 (17:38 +0200)] 
vmspawn: prepare QMP infrastructure for runtime block-device hotplug (#41763)

  The block-device hotplug work (#NNNNN) needs a number of cross-cutting
  changes to the QMP plumbing that aren't hotplug-specific in
  themselves: a refcounted DriveInfo so async stage callbacks can keep
  slot refs, a counter-based naming scheme so multiple drives can share
  the same backing path, pipelined remove-fd so QEMU's fdsets get
  released at blockdev-del time, and a generic-completion callback that
  doesn't tear the VM down on a runtime QMP error. None of these change
  behaviour from a user's point of view, none of them depend on the
  varlink hotplug methods landing, and several are wins on their own
  (the fdset leak in particular is observable today with --extra-drive
  under long-running VMs). Pulling them out of the hotplug PR keeps
  that PR focused on the IDL + server-side method handlers, and lets
  this preparatory work land on its own merits without waiting for the
  larger feature review.

  Cleanup pieces that fall out for free:

    qmp-client: widen next_fdset_id to uint64_t
    vmspawn: move VMSPAWN_PCIE_HOTPLUG_SPARES to vmspawn-qmp.h
    vmspawn-varlink: use error < 0 in async QMP completion callbacks
    vmspawn-varlink: simplify on_qmp_describe_complete result extraction
    vmspawn-varlink: extract notify_event_subscribers from on_qmp_event
    vmspawn-varlink: treat empty event subscription filter as catch-all
    vmspawn-qmp: pass bridge to on_cont_complete via invoke userdata

  Infrastructure the hotplug add path will sit on top of:

    vmspawn-qmp: convert DriveInfo to a refcounted object
    vmspawn-qmp: derive QMP node and device ids from a bridge counter
    vmspawn-qmp: pipeline remove-fd after each blockdev-add
    vmspawn-qmp: keep the event loop running on post-setup QMP failures
    vmspawn-qmp: add the hotplug-capable block-device add machinery
    vmspawn-qmp: add vmspawn_qmp_remove_block_device

  The two final commits introduce vmspawn_qmp_add_block_device() and
  vmspawn_qmp_remove_block_device() but leave them without varlink
  callers — the io.systemd.VirtualMachineInstance method handlers that
  forward into them land with the rest of the hotplug PR. Boot-time
  drive setup is rewritten on top of vmspawn_qmp_add_block_device() so
  the hotplug and boot paths share a single staged-add pipeline from
  day one.

2 weeks agojob: properly initialize all enum fields
Lennart Poettering [Fri, 24 Apr 2026 13:19:06 +0000 (15:19 +0200)] 
job: properly initialize all enum fields

This changes the .result field to invalid initially, which arguably
makes more sense than "done", which was previously the default.

This is a correctnes fix, and afaics has no effect on the API, since we
do not expose this 1:1 as D-Bus property: it's only seen on D-Bus as
part of the job completion signal, at which part it is correctly
initialized.

Noticed while reviewing: https://github.com/systemd/systemd/pull/41583

2 weeks agosystemd-cat does not connect the standard *input* of a process to the journal
Stephane Chazelas [Fri, 24 Apr 2026 12:53:02 +0000 (13:53 +0100)] 
systemd-cat does not connect the standard *input* of a process to the journal

The first paragraph of the description of the systemd-cat utility incorrectly referred to stdin when it obviously meant stderr: the other fd that it connects to the journal via a unix(7) domain socket, as clarified in the following paragraphs.

I've also replaced "process" with "command" as in that mode, systemd-cat executes a file and does not spawn a process.

2 weeks agoac-power,notify,systemctl: port 3 tools over to new --help APIs 41805/head
Lennart Poettering [Fri, 24 Apr 2026 06:10:43 +0000 (08:10 +0200)] 
ac-power,notify,systemctl: port 3 tools over to new --help APIs

Let's port over a few tools, to showcase the new logic.

2 weeks agohelp-util: add helpers for generating uniform --help texts
Lennart Poettering [Thu, 23 Apr 2026 22:09:00 +0000 (00:09 +0200)] 
help-util: add helpers for generating uniform --help texts

Let's introduce some helpers for generating uniform --help texts with
some minimal ANSI styling.

This shortens the help() functions generally, and allows us to change
the style at a single, central place.

This mostly just follows our current styling for --help, but it makes
two updates to it:

1. The command line summary at the very top of the --help text is now
   prefixes with a grey ">" character to indicate it's a command line.

2. The human language introductionary description/abstract right after
   that command line is set in italics, to emphasize it's not dry,
   technical, structural information, but more human friendly prose.

2 weeks agovmspawn-varlink: drop AcquireQMP stub and QemuMachineInstance interface 41763/head
Christian Brauner [Thu, 23 Apr 2026 08:22:17 +0000 (10:22 +0200)] 
vmspawn-varlink: drop AcquireQMP stub and QemuMachineInstance interface

The AcquireQMP() method was a placeholder that always returned
EOPNOTSUPP, reserving room for a future id-rewriting QMP multiplex
proxy. The broader direction is for systemd-vmspawn to remain the single
source of truth for VM control rather than exposing raw QMP to clients.

Since AcquireQMP was the only method on io.systemd.QemuMachineInstance
(and AlreadyAcquired was its only error), remove the whole interface
along with the stub, and update the controlAddress field comment in
io.systemd.Machine to stop referencing it.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2 weeks agovmspawn-qmp: add vmspawn_qmp_remove_block_device
Christian Brauner [Wed, 22 Apr 2026 08:19:09 +0000 (10:19 +0200)] 
vmspawn-qmp: add vmspawn_qmp_remove_block_device

Hot-remove counterpart to vmspawn_qmp_add_block_device. Looks the
drive up in the bridge's block_devices registry by caller-supplied
id and dispatches device_del using the internal qmp_device_id; the
varlink link gets the immediate ack/error reply once QEMU completes
the request.

Concurrency: a second remove for the same id while the first is in
flight (between device_del dispatch and DEVICE_DELETED) would
otherwise reach QEMU and earn a confusing 'already in the process of
unplug' reply. Track the in-flight state with a new
BLOCK_DEVICE_REMOVE_PENDING bit on the existing rollback_mask, and
short-circuit duplicate calls with -EBUSY. The bit is cleared on
device_del failure (the drive is still attached, so retries make
sense) and naturally vanishes on success when the registry entry is
dropped.

DEVICE_DELETED handling: the actual blockdev-del + registry removal
+ pcie-port release is deferred to vmspawn_qmp_dispatch_device_deleted,
which fires from on_qmp_event in vmspawn-varlink.c when the guest
acks the eject. Hooking it from the existing QMP event dispatcher
keeps the cleanup local to vmspawn-qmp.{c,h}.

The function has no varlink callers in this PR — the
io.systemd.VirtualMachineInstance method handler that forwards into
it lands with the rest of the hotplug PR.

Signed-off-by: Christian Brauner <brauner@kernel.org>
2 weeks agovmspawn-qmp: add the hotplug-capable block-device add machinery
Christian Brauner [Tue, 21 Apr 2026 22:34:50 +0000 (00:34 +0200)] 
vmspawn-qmp: add the hotplug-capable block-device add machinery

This is the bulk of the runtime block-device hotplug feature. The
boot-time qmp_setup_regular_drive() path is rewritten on top of a new
vmspawn_qmp_add_block_device() that owns the DriveInfo, drives a four
QMP-command pipeline (add-fd → blockdev-add → remove-fd → device_add)
through staged ref-counted callbacks, and registers the drive in a
per-bridge block-device registry on success.

New on the bridge:

  - block_devices: user-id → DriveInfo* registry (owned ref).
  - hotplug_port_owner[VMSPAWN_PCIE_HOTPLUG_SPARES]: per-port owner
    string for the spare pcie-root-ports, allocated/released through
    vmspawn_qmp_bridge_{allocate,release_pcie_port_by_idx}().
  - scsi_controller_port_idx / scsi_controller_created: track the
    on-demand virtio-scsi-pci controller so the first SCSI hotplug
    creates it (against an allocated spare port) and subsequent ones
    just attach.
  - next_block_counter: already in place from the previous commit, now
    actually consumed by add_block_device().

New on DriveInfo:

  - bridge (weak), id (varlink-visible — caller-supplied or auto-set
    to qmp_device_id), disk_type (for List replies later), counter,
    qmp_node_name / qmp_device_id (already added), fdset_path,
    pcie_port_idx (the hotplug port reserved by this drive — stays
    set across the add pipeline so drive_info_free releases it when
    the registry ref drops at DEVICE_DELETED time),
    rollback_mask (BlockDeviceAddStage bits of completed stages —
    plus a FAILED sentinel that suppresses cascading errors), and
    link (NULL ⇒ boot-time, sd_event_exit on fail; non-NULL ⇒
    hotplug, varlink reply on fail).

Helpers:

  - drive_info_unref() now releases any reserved hotplug port through
    the bridge and unrefs link.
  - drive_info_add_fail(): single failure entry point — fires the
    teardown for completed stages, sets the FAILED bit, and sends
    either the varlink error or sd_event_exit. Boot-time failures
    (link == NULL) always exit the loop, so late-arriving ephemeral
    continuation replies don't get silenced after cont.
  - vmspawn_qmp_block_device_teardown(): post-hoc blockdev-del when
    blockdev-add succeeded but a later stage failed.
  - reply_qmp_error: varlink reply helper — disconnect errors map to
    io.systemd.MachineInstance.NotConnected, everything else goes
    through sd_varlink_error_errno.
  - on_add_observe_stage / on_add_blockdev_stage /
    on_add_device_add_complete: the staged callbacks that drive the
    add pipeline, each holding one slot ref on the DriveInfo. The
    ephemeral blockdev-create continuation reuses the latter two so
    its post-cont replies go through drive_info_add_fail instead of
    the generic on_qmp_complete (which would silently log under
    setup_done).
  - on_scsi_controller_complete: handles the SCSI controller setup
    (releases the reserved port on failure, propagates the boot-time
    fatal error policy).
  - qmp_build_blockdev_add_inline(): single blockdev-add JSON that
    creates the file+format pair as one node, used by the hotplug
    path (the boot-time helpers stay separate so they can stack with
    the ephemeral path's base/overlay format nodes).

EphemeralDriveCtx is trimmed down to a DriveInfo ref plus the two
ephemeral-local scratch node names (overlay-file, base-fmt). The
copies of disk_driver/serial/pcie_port/flags/qmp_node_name/
qmp_device_id go away — the continuation reads them straight off the
ref'd drive. qmp_setup_ephemeral_drive now sets drive->bridge /
drive->id / drive->counter up front (matching the hotplug path) and
folds the feature-dependent DISCARD_NO_UNREF into drive->flags so
qmp_build_blockdev_add_format picks it up.

vmspawn_qmp_bridge_free() unrefs the qmp client first — its pending
callbacks may still reach for the bridge's hotplug port table when
they drop their last DriveInfo ref — then tears down the hashmaps
and the port owner strings.

The boot-time qmp_setup_regular_drive() collapses to a thin wrapper
that asserts "caller hasn't pre-set drive->id", takes ownership and
calls vmspawn_qmp_add_block_device(); the dispatcher in
vmspawn_qmp_setup_drives() now hands ownership over with TAKE_PTR.
The previous qmp_setup_drive() dispatcher disappears (its body is
inlined into the loop). vmspawn_qmp_init() initialises
scsi_controller_port_idx to -1.

The cosmetic (*d) → DriveInfo *drive = *d; locals in
drives_need_scsi_controller (vmspawn-qmp.c) and assign_pcie_ports
(vmspawn.c) ride along — they live in code touched by this commit
and would otherwise produce churn.

vmspawn_qmp_remove_block_device() — the symmetric remove API — is
added in the next commit so this one stays focused on the add path.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2 weeks agovmspawn-qmp: keep the event loop running on post-setup QMP failures
Christian Brauner [Tue, 21 Apr 2026 22:29:37 +0000 (00:29 +0200)] 
vmspawn-qmp: keep the event loop running on post-setup QMP failures

on_qmp_complete tears the event loop down on any QMP error, which is
the right behaviour while we're still building the VM (a missing
device means we'd boot a half-configured guest). Once the boot-time
setup is finished and the guest is running, killing the event loop on
a QMP error means a single failed runtime command (e.g. a hotplug
device_add that the guest rejects) takes the whole VM down.

Consult bridge->setup_done — already flipped at the end of boot
setup — and skip the event-loop exit once it's set; logging is
sufficient post-setup. The bridge is fetched from the qmp client
userdata, the same pointer the rest of the file uses.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2 weeks agovmspawn-qmp: pipeline remove-fd after each blockdev-add
Christian Brauner [Tue, 21 Apr 2026 22:28:51 +0000 (00:28 +0200)] 
vmspawn-qmp: pipeline remove-fd after each blockdev-add

QEMU keeps a monitor-side fd alive until either an explicit remove-fd
arrives or the fdset's last duplicate is closed. Today vmspawn issues
add-fd but never the matching remove-fd, so each fdset stays around for
the lifetime of the VM even after the consuming blockdev is torn down.
Pipelining a remove-fd directly after the blockdev-add that consumed
the fd hands ownership entirely to the blockdev: the fdset
auto-disposes when raw_close runs at blockdev-del time. This is the
shape needed by hotplug, where blockdev-del must clean up everything
without further coordination.

Mechanically:
- qmp_fdset_add() takes a callback/userdata pair (so callers control
  failure handling) and an optional out-param for the numeric fdset id.
  All boot-time callers keep using on_qmp_complete with a label.
- A new qmp_fdset_remove() helper sends remove-fd with caller-supplied
  callback/userdata.
- qmp_setup_ephemeral_drive captures both fdset ids and fires remove-fd
  immediately after each base/overlay file blockdev-add.
- qmp_setup_regular_drive does the same for its single file blockdev-add.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2 weeks agovmspawn-qmp: derive QMP node and device ids from a bridge counter
Christian Brauner [Tue, 21 Apr 2026 22:26:52 +0000 (00:26 +0200)] 
vmspawn-qmp: derive QMP node and device ids from a bridge counter

Replace the caller-supplied DriveInfo.node_name with two QMP-internal
strings generated at setup time from a monotonic per-bridge counter:

  qmp_node_name   = "vmspawn-<N>-storage"  (blockdev node-name)
  qmp_device_id   = "vmspawn-<N>-disk"     (qdev id)

This is the naming scheme the upcoming runtime-hotplug add path needs:
unique across the lifetime of the VM, decoupled from any user-visible id,
and stable across the four QMP commands that make up an add (add-fd,
blockdev-add, remove-fd, device_add). The boot-time setups don't care
about uniqueness, but switching them now means the hotplug path can share
qmp_build_device_add() and EphemeralDriveCtx without a parallel naming
scheme.

vmspawn.c stops assigning node_name in prepare_primary_drive (which used
the literal "vmspawn") and prepare_extra_drives (which counted
"vmspawn_extra_%zu"); both are replaced by the bridge counter at the
point the drive is actually pushed into QEMU. Ephemeral helper-node
names follow the same vmspawn-<N>-{base-file,base-fmt,overlay-file}
convention; the blockdev-create job-id becomes
vmspawn-<N>-overlay-create.

EphemeralDriveCtx grows a qmp_device_id field (the qdev id is
independent of the format node-name now) and renames node_name →
qmp_node_name to match. No external behaviour change other than the new
internal names.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2 weeks agovmspawn-qmp: convert DriveInfo to a refcounted object
Christian Brauner [Tue, 21 Apr 2026 22:23:02 +0000 (00:23 +0200)] 
vmspawn-qmp: convert DriveInfo to a refcounted object

In preparation for runtime block-device hotplug, where in-flight QMP
callbacks need to keep a slot reference on the DriveInfo while the bridge
also holds it in its block-device registry. Today each DriveInfo has
exactly one owner; switch the API from drive_info_free() /
drive_info_freep to drive_info_ref() / drive_info_unref() /
drive_info_unrefp so future code can take additional refs without the
caller losing track of ownership.

drive_info_new() initialises n_ref to 1 (one ref for the caller). The
existing drive_infos_done() and the prepare_*_drive() callers in
vmspawn.c are switched to the unref form. No behaviour change: each
DriveInfo still has exactly one ref at every point in this commit.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2 weeks agovmspawn-qmp: pass bridge to on_cont_complete via invoke userdata
Christian Brauner [Tue, 21 Apr 2026 22:21:43 +0000 (00:21 +0200)] 
vmspawn-qmp: pass bridge to on_cont_complete via invoke userdata

The callback already has the bridge available — but it was reaching for
it via qmp_client_get_userdata() instead of through its own userdata
parameter. Pass the bridge directly from vmspawn_qmp_start() so the
callback can read its argument the way the rest of the file does. No
behaviour change.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2 weeks agovmspawn-varlink: treat empty event subscription filter as catch-all
Christian Brauner [Tue, 21 Apr 2026 22:21:00 +0000 (00:21 +0200)] 
vmspawn-varlink: treat empty event subscription filter as catch-all

A client supplying "filter": [] previously matched no events at all,
because filter is checked with strv_contains() — an unintuitive corner
case. Treat an empty filter strv identically to a NULL filter (deliver
all events) by freeing the empty strv before it lands in the
subscription map. Brings the API closer to least-surprise.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2 weeks agovmspawn-varlink: extract notify_event_subscribers from on_qmp_event
Christian Brauner [Tue, 21 Apr 2026 22:20:24 +0000 (00:20 +0200)] 
vmspawn-varlink: extract notify_event_subscribers from on_qmp_event

Pure refactor: factor the subscriber-notification body out of on_qmp_event
into a static helper. on_qmp_event keeps the JOB_STATUS_CHANGE
short-circuit and otherwise delegates to the new helper. No behaviour
change.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2 weeks agovmspawn-varlink: simplify on_qmp_describe_complete result extraction
Christian Brauner [Tue, 21 Apr 2026 22:19:48 +0000 (00:19 +0200)] 
vmspawn-varlink: simplify on_qmp_describe_complete result extraction

Lift the running/status extraction out of the inline ternaries inside
SD_JSON_BUILD_PAIR_*() into named local variables with explicit defaults.
Pure readability change.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2 weeks agovmspawn-varlink: use error < 0 in async QMP completion callbacks
Christian Brauner [Tue, 21 Apr 2026 22:19:20 +0000 (00:19 +0200)] 
vmspawn-varlink: use error < 0 in async QMP completion callbacks

The QMP client always passes either 0 or a negative errno; the != 0 check
flagged values that cannot occur. Switch to the < 0 idiom used elsewhere
in the tree, and reorder on_qmp_simple_complete so the error path is the
first branch (the more conventional shape for callbacks). Equivalent in
behaviour.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2 weeks agovmspawn: move VMSPAWN_PCIE_HOTPLUG_SPARES to vmspawn-qmp.h
Christian Brauner [Tue, 21 Apr 2026 22:18:27 +0000 (00:18 +0200)] 
vmspawn: move VMSPAWN_PCIE_HOTPLUG_SPARES to vmspawn-qmp.h

Pure code motion, in preparation for the bridge-side hotplug machinery
that needs the same constant to size its hotplug_port_owner[] array. The
unsigned-suffix on the literal is dropped: the only consumer that compares
against unsigned (vmspawn.c's pcie-port assert) is happy with a plain
integer literal.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2 weeks agoqmp-client: widen next_fdset_id to uint64_t
Christian Brauner [Tue, 21 Apr 2026 22:17:21 +0000 (00:17 +0200)] 
qmp-client: widen next_fdset_id to uint64_t

The fdset id is a monotonic counter; an unsigned int is more than wide
enough today, but uint64_t matches the type of other QMP-internal counters
(e.g. job ids) and avoids any worry about wraparound on long-running
hosts. Update the storage in struct QmpClient, the qmp_client_next_fdset_id()
return type, and the corresponding caller in qmp_fdset_add(), switching the
sprintf format from %u to PRIu64.

No behavioural change.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2 weeks agovmspawn: use qemu_device_driver_to_string() in resolve_disk_driver
Christian Brauner [Mon, 20 Apr 2026 09:07:38 +0000 (11:07 +0200)] 
vmspawn: use qemu_device_driver_to_string() in resolve_disk_driver

Drop the inline DiskType → QEMU device driver switch and call the shared
helper instead. serial_max and the CD-ROM read-only flag stay inline
since they are vmspawn-local.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>