1
0
mirror of https://github.com/systemd/systemd synced 2026-03-24 07:44:52 +01:00

Compare commits

..

12 Commits

Author SHA1 Message Date
Luca Boccassi
cac38a9803
Merge pull request #20123 from keszybz/extended-job-status
Nested job status for systemd+user service managers
2021-07-21 11:39:10 +01:00
Matthijs van Duin
654eaa4030
sd-bus: fix missing initializer in SD_BUS_VTABLE_END (#20253)
When two fields were added to the vtable.x.start struct, no initializers
for these were added to SD_BUS_VTABLE_END which also (ab)used that
struct (albeit sneakily by using non-designated initialization).

While C tolerates this, C++ prohibits these missing initializers, and
both g++ and clang++ will complain when using -Wextra.

This patch gives SD_BUS_VTABLE_END its own case in the union and
clarifies its initialization.

I tested the behaviour of g++ 10.2 and clang 11 in various cases. Both will warn
(-Wmissing-field-initializers, implied by -Wextra) if you provide initializers for some
but not all fields of a struct. Declaring x.end as empty struct or using an empty initializer
{} to initialize the union or one of its members is valid C++ but not C, although both gcc
and clang accept it without warning (even at -Wall -Wextra -std=c90/c++11) unless you
use -pedantic (which requires -std=c99/c++2a to support designated initializers).

Interestingly, .x = { .start = { 0, 0, NULL } } is the only initializer I found for the union
(among candidates for SD_BUS_VTABLE_END) where gcc doesn't zero-fill it entirely
when allocated on stack, it looked like it did in all other cases (I only examined this on
32-bit arm). clang always seems to initialize all bytes of the union.

[zjs: test case:
$ cat vtable-test.cc                                                          
#include "sd-bus.h"

const sd_bus_vtable vtable[] = {
   SD_BUS_VTABLE_END
};

$ g++ -I src/systemd/ -Wall -Wmissing-field-initializers -c vtable-test.cc
vtable-test.cc:5:1: warning: missing initializer for member ‘sd_bus_vtable::<unnamed union>::<unnamed struct>::features’ [-Wmissing-field-initializers]
    5 | };
      | ^
vtable-test.cc:5:1: warning: missing initializer for member ‘sd_bus_vtable::<unnamed union>::<unnamed struct>::vtable_format_reference’ [-Wmissing-field-initializers]

$ clang++ -I src/systemd/ -Wmissing-field-initializers -c vtable-test.cc 
vtable-test.cc:4:4: warning: missing field 'features' initializer [-Wmissing-field-initializers]
   SD_BUS_VTABLE_END
   ^
src/systemd/sd-bus-vtable.h:188:28: note: expanded from macro 'SD_BUS_VTABLE_END'
                .x = { { 0 } },                                         \
                           ^
1 warning generated.

Both warnings are gone with the patch.]
2021-07-21 11:10:36 +02:00
Zbigniew Jędrzejewski-Szmek
3cfd5ddd59
Merge pull request #20087 from xen0n/loongarch64-gpt
gpt: support LoongArch 64-bit
2021-07-21 10:50:08 +02:00
WANG Xuerui
f15f2ab42e
gpt: reformat for restoring vertical alignment 2021-07-20 17:32:59 +08:00
WANG Xuerui
4e76715489
gpt: support LoongArch 64-bit 2021-07-20 17:32:59 +08:00
Zbigniew Jędrzejewski-Szmek
3889fc6fc3 manager: print status text of the service when waiting for a job
This does two semi-independent but interleaved things: firstly, the manager now
prints the status text (if available) of a service when we have a job running
for that service and it is slow. Because it's hard to fit enough info on the
line, we only do this if the output mode uses unit names. The format of the
line "… job is running for …" is changed to be shorter. This way we can
somewhat reasonably fit two status messages on one line.

Secondly, the manager now sends more information using sd_notify. This mostly
matters for in case of the user manager. In particular, we notify when starting
one of the special units. Without this, when the system manager would display a
line about waiting for the user manager, it would show status like "Ready.",
which is confusing. Now it'll either show something like "Started special unit
shutdown.target", or the line about waiting for a user job.

Also, the timeouts for the user manager are lowered: the user manager usually
(always?) has status disabled, so we would wait for 25 seconds before showing
job progress. Normally we don't expect to have any jobs that take more than a
second. So let's start the progress output fairly quickly, like we would if
status showing was enabled. This obviously makes the output in the system
manager about the user manager more useful. The timeouts are "desynchronized"
by a fraction so if there are multiple jobs running, we'll cycle through
showing all combinations.

Example output:

         Stopping user@1000.service...
[  OK  ] Stopped dracut-shutdown.service.
[  OK  ] Stopped systemd-logind.service.
[  OK  ] Stopped systemd-logind.service - User Login Management.
[*     ] Job user@1000.service/stop running (2s / 2min): (1 of 2) User job slowstop.service/stop running (1s / 1min 30s)...
[***   ] Job user@1000.service/stop running (3s / 2min): (2 of 2) User job slowstop2.service/stop running (2s / 1min 30s)...
[   ***] Job user@1000.service/stop running (4s / 2min): (1 of 2) User job slowstop.service/stop running (4s / 1min 30s)...
[     *] Job user@1000.service/stop running (5s / 2min): (1 of 2) User job slowstop.service/stop running (5s / 1min 30s)...
[   ***] Job user@1000.service/stop running (6s / 2min): (2 of 2) User job slowstop2.service/stop running (6s / 1min 30s)...
[***   ] Job user@1000.service/stop running (8s / 2min): (1 of 2) User job slowstop.service/stop running (7s / 1min 30s)...
[***   ] Job user@1000.service/stop running (10s / 2min): (2 of 2) User job slowstop2.service/stop running (9s / 1min 30s)...
[  *** ] Job user@1000.service/stop running (11s / 2min): (1 of 2) User job slowstop.service/stop running (10s / 1min 30s)...
[     *] Job user@1000.service/stop running (12s / 2min): (2 of 2) User job slowstop2.service/stop running (12s / 1min 30s)...
[   ***] Job user@1000.service/stop running (13s / 2min): (1 of 2) User job slowstop.service/stop running (13s / 1min 30s)...
[***   ] Job user@1000.service/stop running (15s / 2min): (2 of 2) User job slowstop2.service/stop running (14s / 1min 30s)...
[*     ] Job user@1000.service/stop running (15s / 2min): (2 of 2) User job slowstop2.service/stop running (14s / 1min 30s)...
[***   ] Job user@1000.service/stop running (16s / 2min): User job slowstop.service/stop running (16s / 1min 30s)...
[   ***] Job user@1000.service/stop running (18s / 2min): User job slowstop.service/stop running (17s / 1min 30s)...
[     *] Job user@1000.service/stop running (19s / 2min): User job slowstop.service/stop running (18s / 1min 30s)...
[   ***] Job user@1000.service/stop running (20s / 2min): User job slowstop.service/stop running (19s / 1min 30s)...
[*     ] Job user@1000.service/stop running (22s / 2min): User job slowstop.service/stop running (22s / 1min 30s)...
[**    ] Job user@1000.service/stop running (30s / 2min): User job slowstop.service/stop running (29s / 1min 30s)...
[   ***] Job user@1000.service/stop running (32s / 2min): User job slowstop.service/stop running (31s / 1min 30s)...
[     *] Job user@1000.service/stop running (33s / 2min): User job slowstop.service/stop running (32s / 1min 30s)...
[   ***] Job user@1000.service/stop running (34s / 2min): User job slowstop.service/stop running (33s / 1min 30s)...
[**    ] Job user@1000.service/stop running (37s / 2min): User job slowstop.service/stop running (36s / 1min 30s)...
[  *** ] Job user@1000.service/stop running (41s / 2min): User job slowstop.service/stop running (41s / 1min 30s)...
[  OK  ] Stopped user@1000.service - User Manager for UID 1000.
         Stopping user-runtime-dir@1000.service - User Runtime Directory /run/user/1000...
[  OK  ] Unmounted run-user-1000.mount - /run/user/1000.
[  OK  ] Stopped user-runtime-dir@1000.service - User Runtime Directory /run/user/1000.

If the output width is lower than approximately 100 columns, the output stops
being very useful. No idea what to do about that.
2021-07-19 11:42:55 +02:00
Zbigniew Jędrzejewski-Szmek
6d93265955 manager: rework sending of STATUS=
We would send READY=1,STATUS="Startup finished in …" once after finishing
boot. This changes the message to just "Ready.". The time used to reach
readiness is not part of the ongoing status — it's just a bit of debug
information that it useful in some scenarious, but completely uninteresting
most of the time. Also, when we start sending status about other things in
subsequent patches, we can't really go back to showing "Startup finished in …"
later on. So let's just show "Ready." whenever we're in the steady state.

In manager_check_finished(), more steps are skipped if MANAGER_IS_FINISHED().
Those steps are idempotent, but no need to waste cycles trying to do them
more than once.

We'll now also check whether to send the status message whenever the job queue
runs empty. If we already sent the exact same message already, we'll not send
again.
2021-07-19 11:36:25 +02:00
Zbigniew Jędrzejewski-Szmek
5f96809628 manager: always log when starting a "special unit"
This is the initiatation of the machine shutdown/reboot/etc, so it's
useful to log about this. We log about the steps that we take, but
so far we didn't really log why we started the sequence (except at
debug level).

The function is renamed, because we also use it for dbus.service,
not just targets.
2021-07-19 11:33:52 +02:00
Zbigniew Jędrzejewski-Szmek
5e1669ff26 core: add helper to retrieve service.status_text 2021-07-19 11:33:52 +02:00
Zbigniew Jędrzejewski-Szmek
48d83e3368 core: align string tables 2021-07-19 11:33:52 +02:00
Zbigniew Jędrzejewski-Szmek
305757d808 core: modernize asprintf error handling
The man page says asprintf() pointer is "undefined" on error, but the
only meaningful interpretation is that it's either NULL or points to
something that should be freed with free().
2021-07-19 11:33:44 +02:00
Zbigniew Jędrzejewski-Szmek
a01ba4b2b8 core: split out manager-serialize.[ch]
The file is super long, so let's split this out one subject to a new file.
2021-07-19 11:27:11 +02:00
22 changed files with 947 additions and 809 deletions

View File

@ -46,6 +46,7 @@ Interface](https://systemd.io/BOOT_LOADER_INTERFACE).
| `69dad710-2ce4-4e3c-b16c-21a1d49abed3` | _Root Partition (32-bit ARM)_ | ditto | ditto | | `69dad710-2ce4-4e3c-b16c-21a1d49abed3` | _Root Partition (32-bit ARM)_ | ditto | ditto |
| `b921b045-1df0-41c3-af44-4c6f280d3fae` | _Root Partition (64-bit ARM/AArch64)_ | ditto | ditto | | `b921b045-1df0-41c3-af44-4c6f280d3fae` | _Root Partition (64-bit ARM/AArch64)_ | ditto | ditto |
| `993d8d3d-f80e-4225-855a-9daf8ed7ea97` | _Root Partition (Itanium/IA-64)_ | ditto | ditto | | `993d8d3d-f80e-4225-855a-9daf8ed7ea97` | _Root Partition (Itanium/IA-64)_ | ditto | ditto |
| `77055800-792c-4f94-b39a-98c91b762bb6` | _Root Partition (LoongArch 64-bit)_ | ditto | ditto |
| `60d5a7fe-8e7d-435c-b714-3dd8162144e1` | _Root Partition (RISC-V 32-bit)_ | ditto | ditto | | `60d5a7fe-8e7d-435c-b714-3dd8162144e1` | _Root Partition (RISC-V 32-bit)_ | ditto | ditto |
| `72ec70a6-cf74-40e6-bd49-4bda08e8f224` | _Root Partition (RISC-V 64-bit)_ | ditto | ditto | | `72ec70a6-cf74-40e6-bd49-4bda08e8f224` | _Root Partition (RISC-V 64-bit)_ | ditto | ditto |
| `d13c5d3b-b5d1-422a-b29f-9454fdc89d76` | _Root Verity Partition (x86)_ | A dm-verity superblock followed by hash data | On systems with matching architecture, contains dm-verity integrity hash data for the matching root partition. If this feature is used the partition UUID of the root partition should be the first 128bit of the root hash of the dm-verity hash data, and the partition UUID of this dm-verity partition should be the final 128bit of it, so that the root partition and its verity partition can be discovered easily, simply by specifying the root hash. | | `d13c5d3b-b5d1-422a-b29f-9454fdc89d76` | _Root Verity Partition (x86)_ | A dm-verity superblock followed by hash data | On systems with matching architecture, contains dm-verity integrity hash data for the matching root partition. If this feature is used the partition UUID of the root partition should be the first 128bit of the root hash of the dm-verity hash data, and the partition UUID of this dm-verity partition should be the final 128bit of it, so that the root partition and its verity partition can be discovered easily, simply by specifying the root hash. |
@ -53,6 +54,7 @@ Interface](https://systemd.io/BOOT_LOADER_INTERFACE).
| `7386cdf2-203c-47a9-a498-f2ecce45a2d6` | _Root Verity Partition (32-bit ARM)_ | ditto | ditto | | `7386cdf2-203c-47a9-a498-f2ecce45a2d6` | _Root Verity Partition (32-bit ARM)_ | ditto | ditto |
| `df3300ce-d69f-4c92-978c-9bfb0f38d820` | _Root Verity Partition (64-bit ARM/AArch64)_ | ditto | ditto | | `df3300ce-d69f-4c92-978c-9bfb0f38d820` | _Root Verity Partition (64-bit ARM/AArch64)_ | ditto | ditto |
| `86ed10d5-b607-45bb-8957-d350f23d0571` | _Root Verity Partition (Itanium/IA-64)_ | ditto | ditto | | `86ed10d5-b607-45bb-8957-d350f23d0571` | _Root Verity Partition (Itanium/IA-64)_ | ditto | ditto |
| `f3393b22-e9af-4613-a948-9d3bfbd0c535` | _Root Verity Partition (LoongArch 64-bit)_ | ditto | ditto |
| `ae0253be-1167-4007-ac68-43926c14c5de` | _Root Verity Partition (RISC-V 32-bit)_ | ditto | ditto | | `ae0253be-1167-4007-ac68-43926c14c5de` | _Root Verity Partition (RISC-V 32-bit)_ | ditto | ditto |
| `b6ed5582-440b-4209-b8da-5ff7c419ea3d` | _Root Verity Partition (RISC-V 64-bit)_ | ditto | ditto | | `b6ed5582-440b-4209-b8da-5ff7c419ea3d` | _Root Verity Partition (RISC-V 64-bit)_ | ditto | ditto |
| `75250d76-8cc6-458e-bd66-bd47cc81a812` | _`/usr/` Partition (x86)_ | Any native, optionally in LUKS | Similar semantics to root partition, but just the `/usr/` partition. | | `75250d76-8cc6-458e-bd66-bd47cc81a812` | _`/usr/` Partition (x86)_ | Any native, optionally in LUKS | Similar semantics to root partition, but just the `/usr/` partition. |
@ -60,6 +62,7 @@ Interface](https://systemd.io/BOOT_LOADER_INTERFACE).
| `7d0359a3-02b3-4f0a-865c-654403e70625` | _`/usr/` Partition (32-bit ARM)_ | ditto | ditto | | `7d0359a3-02b3-4f0a-865c-654403e70625` | _`/usr/` Partition (32-bit ARM)_ | ditto | ditto |
| `b0e01050-ee5f-4390-949a-9101b17104e9` | _`/usr/` Partition (64-bit ARM/AArch64)_ | ditto | ditto | | `b0e01050-ee5f-4390-949a-9101b17104e9` | _`/usr/` Partition (64-bit ARM/AArch64)_ | ditto | ditto |
| `4301d2a6-4e3b-4b2a-bb94-9e0b2c4225ea` | _`/usr/` Partition (Itanium/IA-64)_ | ditto | ditto | | `4301d2a6-4e3b-4b2a-bb94-9e0b2c4225ea` | _`/usr/` Partition (Itanium/IA-64)_ | ditto | ditto |
| `e611c702-575c-4cbe-9a46-434fa0bf7e3f` | _`/usr/` Partition (LoongArch 64-bit)_ | ditto | ditto |
| `b933fb22-5c3f-4f91-af90-e2bb0fa50702` | _`/usr/` Partition (RISC-V 32-bit)_ | ditto | ditto | | `b933fb22-5c3f-4f91-af90-e2bb0fa50702` | _`/usr/` Partition (RISC-V 32-bit)_ | ditto | ditto |
| `beaec34b-8442-439b-a40b-984381ed097d` | _`/usr/` Partition (RISC-V 64-bit)_ | ditto | ditto | | `beaec34b-8442-439b-a40b-984381ed097d` | _`/usr/` Partition (RISC-V 64-bit)_ | ditto | ditto |
| `8f461b0d-14ee-4e81-9aa9-049b6fb97abd` | _`/usr/` Verity Partition (x86)_ | A dm-verity superblock followed by hash data | Similar semantics to root Verity partition, but just for the `/usr/` partition. | | `8f461b0d-14ee-4e81-9aa9-049b6fb97abd` | _`/usr/` Verity Partition (x86)_ | A dm-verity superblock followed by hash data | Similar semantics to root Verity partition, but just for the `/usr/` partition. |
@ -67,6 +70,7 @@ Interface](https://systemd.io/BOOT_LOADER_INTERFACE).
| `c215d751-7bcd-4649-be90-6627490a4c05` | _`/usr/` Verity Partition (32-bit ARM)_ | ditto | ditto | | `c215d751-7bcd-4649-be90-6627490a4c05` | _`/usr/` Verity Partition (32-bit ARM)_ | ditto | ditto |
| `6e11a4e7-fbca-4ded-b9e9-e1a512bb664e` | _`/usr/` Verity Partition (64-bit ARM/AArch64)_ | ditto | ditto | | `6e11a4e7-fbca-4ded-b9e9-e1a512bb664e` | _`/usr/` Verity Partition (64-bit ARM/AArch64)_ | ditto | ditto |
| `6a491e03-3be7-4545-8e38-83320e0ea880` | _`/usr/` Verity Partition (Itanium/IA-64)_ | ditto | ditto | | `6a491e03-3be7-4545-8e38-83320e0ea880` | _`/usr/` Verity Partition (Itanium/IA-64)_ | ditto | ditto |
| `f46b2c26-59ae-48f0-9106-c50ed47f673d` | _`/usr/` Verity Partition (LoongArch 64-bit)_ | ditto | ditto |
| `cb1ee4e3-8cd0-4136-a0a4-aa61a32e8730` | _`/usr/` Verity Partition (RISC-V 32-bit)_ | ditto | ditto | | `cb1ee4e3-8cd0-4136-a0a4-aa61a32e8730` | _`/usr/` Verity Partition (RISC-V 32-bit)_ | ditto | ditto |
| `8f1056be-9b05-47c4-81d6-be53128e5b54` | _`/usr/` Verity Partition (RISC-V 64-bit)_ | ditto | ditto | | `8f1056be-9b05-47c4-81d6-be53128e5b54` | _`/usr/` Verity Partition (RISC-V 64-bit)_ | ditto | ditto |
| `933ac7e1-2eb4-4f13-b844-0e14e2aef915` | _Home Partition_ | Any native, optionally in LUKS | The first partition with this type UUID on the disk containing the root partition is automatically mounted to `/home/`. If the partition is encrypted with LUKS, the device mapper file will be named `/dev/mapper/home`. | | `933ac7e1-2eb4-4f13-b844-0e14e2aef915` | _Home Partition_ | Any native, optionally in LUKS | The first partition with this type UUID on the disk containing the root partition is automatically mounted to `/home/`. If the partition is encrypted with LUKS, the device mapper file will be named `/dev/mapper/home`. |
@ -221,13 +225,13 @@ We are not. `/etc/fstab` always overrides automatic discovery and is indeed
mentioned in the specifications. We are simply trying to make the boot and mentioned in the specifications. We are simply trying to make the boot and
installation processes of Linux a bit more robust and self-descriptive. installation processes of Linux a bit more robust and self-descriptive.
### Why did you only define the root partition for x86, x86-64, ARM, ARM64, ia64, riscv32, riscv64? ### Why did you only define the root partition for these listed architectures?
The automatic discovery of the root partition is defined to operate on the disk The automatic discovery of the root partition is defined to operate on the disk
containing the current EFI System Partition (ESP). Since EFI only exists on containing the current EFI System Partition (ESP). Since EFI only exists on
x86, x86-64, ia64, ARM and RISC-V so far, we only defined root partition UUIDs for x86, x86-64, ia64, ARM, LoongArch and RISC-V so far, we only defined root
these architectures. Should EFI become more common on other architectures, we partition UUIDs for these architectures. Should EFI become more common on
can define additional UUIDs for them. other architectures, we can define additional UUIDs for them.
### Why define distinct root partition UUIDs for the various architectures? ### Why define distinct root partition UUIDs for the various architectures?

View File

@ -200,6 +200,16 @@
<entry>Verity data for the ia64 root file system partition</entry> <entry>Verity data for the ia64 root file system partition</entry>
</row> </row>
<row>
<entry><constant>root-loongarch64</constant></entry>
<entry>Root file system partition for the LoongArch 64-bit architecture</entry>
</row>
<row>
<entry><constant>root-loongarch64-verity</constant></entry>
<entry>Verity data for the LoongArch 64-bit root file system partition</entry>
</row>
<row> <row>
<entry><constant>root-riscv32</constant></entry> <entry><constant>root-riscv32</constant></entry>
<entry>Root file system partition for the RISC-V 32-bit architecture</entry> <entry>Root file system partition for the RISC-V 32-bit architecture</entry>
@ -290,6 +300,16 @@
<entry>Verity data for the ia64 <filename>/usr/</filename> file system partition</entry> <entry>Verity data for the ia64 <filename>/usr/</filename> file system partition</entry>
</row> </row>
<row>
<entry><constant>usr-loongarch64</constant></entry>
<entry><filename>/usr/</filename> file system partition for the LoongArch 64-bit architecture</entry>
</row>
<row>
<entry><constant>usr-loongarch64-verity</constant></entry>
<entry>Verity data for the LoongArch 64-bit <filename>/usr/</filename> file system partition</entry>
</row>
<row> <row>
<entry><constant>usr-riscv32</constant></entry> <entry><constant>usr-riscv32</constant></entry>
<entry><filename>/usr/</filename> file system partition for the RISC-V 32-bit architecture</entry> <entry><filename>/usr/</filename> file system partition for the RISC-V 32-bit architecture</entry>

View File

@ -109,6 +109,12 @@
<entry><filename>/</filename></entry> <entry><filename>/</filename></entry>
<entry>On Itanium systems, the first Itanium root partition on the disk the EFI ESP is located on is mounted to the root directory <filename>/</filename>.</entry> <entry>On Itanium systems, the first Itanium root partition on the disk the EFI ESP is located on is mounted to the root directory <filename>/</filename>.</entry>
</row> </row>
<row>
<entry>77055800-792c-4f94-b39a-98c91b762bb6</entry>
<entry><filename>Root Partition (LoongArch 64)</filename></entry>
<entry><filename>/</filename></entry>
<entry>On LoongArch 64-bit systems, the first LoongArch 64-bit root partition on the disk the EFI ESP is located on is mounted to the root directory <filename>/</filename>.</entry>
</row>
<row> <row>
<entry>60d5a7fe-8e7d-435c-b714-3dd8162144e1</entry> <entry>60d5a7fe-8e7d-435c-b714-3dd8162144e1</entry>
<entry><filename>Root Partition (RISCV-V 32)</filename></entry> <entry><filename>Root Partition (RISCV-V 32)</filename></entry>

View File

@ -1065,11 +1065,11 @@ static bool automount_supported(void) {
} }
static const char* const automount_result_table[_AUTOMOUNT_RESULT_MAX] = { static const char* const automount_result_table[_AUTOMOUNT_RESULT_MAX] = {
[AUTOMOUNT_SUCCESS] = "success", [AUTOMOUNT_SUCCESS] = "success",
[AUTOMOUNT_FAILURE_RESOURCES] = "resources", [AUTOMOUNT_FAILURE_RESOURCES] = "resources",
[AUTOMOUNT_FAILURE_START_LIMIT_HIT] = "start-limit-hit", [AUTOMOUNT_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
[AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT] = "mount-start-limit-hit", [AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT] = "mount-start-limit-hit",
[AUTOMOUNT_FAILURE_UNMOUNTED] = "unmounted", [AUTOMOUNT_FAILURE_UNMOUNTED] = "unmounted",
}; };
DEFINE_STRING_TABLE_LOOKUP(automount_result, AutomountResult); DEFINE_STRING_TABLE_LOOKUP(automount_result, AutomountResult);

View File

@ -1511,44 +1511,44 @@ static const char* const job_state_table[_JOB_STATE_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(job_state, JobState); DEFINE_STRING_TABLE_LOOKUP(job_state, JobState);
static const char* const job_type_table[_JOB_TYPE_MAX] = { static const char* const job_type_table[_JOB_TYPE_MAX] = {
[JOB_START] = "start", [JOB_START] = "start",
[JOB_VERIFY_ACTIVE] = "verify-active", [JOB_VERIFY_ACTIVE] = "verify-active",
[JOB_STOP] = "stop", [JOB_STOP] = "stop",
[JOB_RELOAD] = "reload", [JOB_RELOAD] = "reload",
[JOB_RELOAD_OR_START] = "reload-or-start", [JOB_RELOAD_OR_START] = "reload-or-start",
[JOB_RESTART] = "restart", [JOB_RESTART] = "restart",
[JOB_TRY_RESTART] = "try-restart", [JOB_TRY_RESTART] = "try-restart",
[JOB_TRY_RELOAD] = "try-reload", [JOB_TRY_RELOAD] = "try-reload",
[JOB_NOP] = "nop", [JOB_NOP] = "nop",
}; };
DEFINE_STRING_TABLE_LOOKUP(job_type, JobType); DEFINE_STRING_TABLE_LOOKUP(job_type, JobType);
static const char* const job_mode_table[_JOB_MODE_MAX] = { static const char* const job_mode_table[_JOB_MODE_MAX] = {
[JOB_FAIL] = "fail", [JOB_FAIL] = "fail",
[JOB_REPLACE] = "replace", [JOB_REPLACE] = "replace",
[JOB_REPLACE_IRREVERSIBLY] = "replace-irreversibly", [JOB_REPLACE_IRREVERSIBLY] = "replace-irreversibly",
[JOB_ISOLATE] = "isolate", [JOB_ISOLATE] = "isolate",
[JOB_FLUSH] = "flush", [JOB_FLUSH] = "flush",
[JOB_IGNORE_DEPENDENCIES] = "ignore-dependencies", [JOB_IGNORE_DEPENDENCIES] = "ignore-dependencies",
[JOB_IGNORE_REQUIREMENTS] = "ignore-requirements", [JOB_IGNORE_REQUIREMENTS] = "ignore-requirements",
[JOB_TRIGGERING] = "triggering", [JOB_TRIGGERING] = "triggering",
}; };
DEFINE_STRING_TABLE_LOOKUP(job_mode, JobMode); DEFINE_STRING_TABLE_LOOKUP(job_mode, JobMode);
static const char* const job_result_table[_JOB_RESULT_MAX] = { static const char* const job_result_table[_JOB_RESULT_MAX] = {
[JOB_DONE] = "done", [JOB_DONE] = "done",
[JOB_CANCELED] = "canceled", [JOB_CANCELED] = "canceled",
[JOB_TIMEOUT] = "timeout", [JOB_TIMEOUT] = "timeout",
[JOB_FAILED] = "failed", [JOB_FAILED] = "failed",
[JOB_DEPENDENCY] = "dependency", [JOB_DEPENDENCY] = "dependency",
[JOB_SKIPPED] = "skipped", [JOB_SKIPPED] = "skipped",
[JOB_INVALID] = "invalid", [JOB_INVALID] = "invalid",
[JOB_ASSERT] = "assert", [JOB_ASSERT] = "assert",
[JOB_UNSUPPORTED] = "unsupported", [JOB_UNSUPPORTED] = "unsupported",
[JOB_COLLECTED] = "collected", [JOB_COLLECTED] = "collected",
[JOB_ONCE] = "once", [JOB_ONCE] = "once",
}; };
DEFINE_STRING_TABLE_LOOKUP(job_result, JobResult); DEFINE_STRING_TABLE_LOOKUP(job_result, JobResult);

View File

@ -55,6 +55,7 @@
#include "machine-id-setup.h" #include "machine-id-setup.h"
#include "manager.h" #include "manager.h"
#include "manager-dump.h" #include "manager-dump.h"
#include "manager-serialize.h"
#include "mkdir.h" #include "mkdir.h"
#include "mount-setup.h" #include "mount-setup.h"
#include "os-util.h" #include "os-util.h"

View File

@ -0,0 +1,536 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "clean-ipc.h"
#include "dbus.h"
#include "fd-util.h"
#include "fileio.h"
#include "format-util.h"
#include "macro.h"
#include "manager-serialize.h"
#include "manager.h"
#include "parse-util.h"
#include "serialize.h"
#include "syslog-util.h"
#include "unit-serialize.h"
#include "user-util.h"
int manager_open_serialization(Manager *m, FILE **ret_f) {
_cleanup_close_ int fd = -1;
FILE *f;
assert(ret_f);
fd = open_serialization_fd("systemd-state");
if (fd < 0)
return fd;
f = take_fdopen(&fd, "w+");
if (!f)
return -errno;
*ret_f = f;
return 0;
}
static bool manager_timestamp_shall_serialize(ManagerTimestamp t) {
if (!in_initrd())
return true;
/* The following timestamps only apply to the host system, hence only serialize them there */
return !IN_SET(t,
MANAGER_TIMESTAMP_USERSPACE, MANAGER_TIMESTAMP_FINISH,
MANAGER_TIMESTAMP_SECURITY_START, MANAGER_TIMESTAMP_SECURITY_FINISH,
MANAGER_TIMESTAMP_GENERATORS_START, MANAGER_TIMESTAMP_GENERATORS_FINISH,
MANAGER_TIMESTAMP_UNITS_LOAD_START, MANAGER_TIMESTAMP_UNITS_LOAD_FINISH);
}
static void manager_serialize_uid_refs_internal(
FILE *f,
Hashmap *uid_refs,
const char *field_name) {
void *p, *k;
assert(f);
assert(field_name);
/* Serialize the UID reference table. Or actually, just the IPC destruction flag of it, as
* the actual counter of it is better rebuild after a reload/reexec. */
HASHMAP_FOREACH_KEY(p, k, uid_refs) {
uint32_t c;
uid_t uid;
uid = PTR_TO_UID(k);
c = PTR_TO_UINT32(p);
if (!(c & DESTROY_IPC_FLAG))
continue;
(void) serialize_item_format(f, field_name, UID_FMT, uid);
}
}
static void manager_serialize_uid_refs(Manager *m, FILE *f) {
manager_serialize_uid_refs_internal(f, m->uid_refs, "destroy-ipc-uid");
}
static void manager_serialize_gid_refs(Manager *m, FILE *f) {
manager_serialize_uid_refs_internal(f, m->gid_refs, "destroy-ipc-gid");
}
int manager_serialize(
Manager *m,
FILE *f,
FDSet *fds,
bool switching_root) {
const char *t;
Unit *u;
int r;
assert(m);
assert(f);
assert(fds);
_cleanup_(manager_reloading_stopp) _unused_ Manager *reloading = manager_reloading_start(m);
(void) serialize_item_format(f, "current-job-id", "%" PRIu32, m->current_job_id);
(void) serialize_item_format(f, "n-installed-jobs", "%u", m->n_installed_jobs);
(void) serialize_item_format(f, "n-failed-jobs", "%u", m->n_failed_jobs);
(void) serialize_bool(f, "taint-usr", m->taint_usr);
(void) serialize_bool(f, "ready-sent", m->ready_sent);
(void) serialize_bool(f, "taint-logged", m->taint_logged);
(void) serialize_bool(f, "service-watchdogs", m->service_watchdogs);
/* After switching root, udevd has not been started yet. So, enumeration results should not be emitted. */
(void) serialize_bool(f, "honor-device-enumeration", !switching_root);
if (m->show_status_overridden != _SHOW_STATUS_INVALID)
(void) serialize_item(f, "show-status-overridden",
show_status_to_string(m->show_status_overridden));
if (m->log_level_overridden)
(void) serialize_item_format(f, "log-level-override", "%i", log_get_max_level());
if (m->log_target_overridden)
(void) serialize_item(f, "log-target-override", log_target_to_string(log_get_target()));
(void) serialize_usec(f, "runtime-watchdog-overridden", m->watchdog_overridden[WATCHDOG_RUNTIME]);
(void) serialize_usec(f, "reboot-watchdog-overridden", m->watchdog_overridden[WATCHDOG_REBOOT]);
(void) serialize_usec(f, "kexec-watchdog-overridden", m->watchdog_overridden[WATCHDOG_KEXEC]);
for (ManagerTimestamp q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) {
_cleanup_free_ char *joined = NULL;
if (!manager_timestamp_shall_serialize(q))
continue;
joined = strjoin(manager_timestamp_to_string(q), "-timestamp");
if (!joined)
return log_oom();
(void) serialize_dual_timestamp(f, joined, m->timestamps + q);
}
if (!switching_root)
(void) serialize_strv(f, "env", m->client_environment);
if (m->notify_fd >= 0) {
r = serialize_fd(f, fds, "notify-fd", m->notify_fd);
if (r < 0)
return r;
(void) serialize_item(f, "notify-socket", m->notify_socket);
}
if (m->cgroups_agent_fd >= 0) {
r = serialize_fd(f, fds, "cgroups-agent-fd", m->cgroups_agent_fd);
if (r < 0)
return r;
}
if (m->user_lookup_fds[0] >= 0) {
int copy0, copy1;
copy0 = fdset_put_dup(fds, m->user_lookup_fds[0]);
if (copy0 < 0)
return log_error_errno(copy0, "Failed to add user lookup fd to serialization: %m");
copy1 = fdset_put_dup(fds, m->user_lookup_fds[1]);
if (copy1 < 0)
return log_error_errno(copy1, "Failed to add user lookup fd to serialization: %m");
(void) serialize_item_format(f, "user-lookup", "%i %i", copy0, copy1);
}
bus_track_serialize(m->subscribed, f, "subscribed");
r = dynamic_user_serialize(m, f, fds);
if (r < 0)
return r;
manager_serialize_uid_refs(m, f);
manager_serialize_gid_refs(m, f);
r = exec_runtime_serialize(m, f, fds);
if (r < 0)
return r;
(void) fputc('\n', f);
HASHMAP_FOREACH_KEY(u, t, m->units) {
if (u->id != t)
continue;
r = unit_serialize(u, f, fds, switching_root);
if (r < 0)
return r;
}
r = fflush_and_check(f);
if (r < 0)
return log_error_errno(r, "Failed to flush serialization: %m");
r = bus_fdset_add_all(m, fds);
if (r < 0)
return log_error_errno(r, "Failed to add bus sockets to serialization: %m");
return 0;
}
static int manager_deserialize_one_unit(Manager *m, const char *name, FILE *f, FDSet *fds) {
Unit *u;
int r;
r = manager_load_unit(m, name, NULL, NULL, &u);
if (r < 0) {
if (r == -ENOMEM)
return r;
return log_notice_errno(r, "Failed to load unit \"%s\", skipping deserialization: %m", name);
}
r = unit_deserialize(u, f, fds);
if (r < 0) {
if (r == -ENOMEM)
return r;
return log_notice_errno(r, "Failed to deserialize unit \"%s\", skipping: %m", name);
}
return 0;
}
static int manager_deserialize_units(Manager *m, FILE *f, FDSet *fds) {
const char *unit_name;
int r;
for (;;) {
_cleanup_free_ char *line = NULL;
/* Start marker */
r = read_line(f, LONG_LINE_MAX, &line);
if (r < 0)
return log_error_errno(r, "Failed to read serialization line: %m");
if (r == 0)
break;
unit_name = strstrip(line);
r = manager_deserialize_one_unit(m, unit_name, f, fds);
if (r == -ENOMEM)
return r;
if (r < 0) {
r = unit_deserialize_skip(f);
if (r < 0)
return r;
}
}
return 0;
}
static void manager_deserialize_uid_refs_one_internal(
Hashmap** uid_refs,
const char *value) {
uid_t uid;
uint32_t c;
int r;
assert(uid_refs);
assert(value);
r = parse_uid(value, &uid);
if (r < 0 || uid == 0) {
log_debug("Unable to parse UID/GID reference serialization: " UID_FMT, uid);
return;
}
if (hashmap_ensure_allocated(uid_refs, &trivial_hash_ops) < 0) {
log_oom();
return;
}
c = PTR_TO_UINT32(hashmap_get(*uid_refs, UID_TO_PTR(uid)));
if (c & DESTROY_IPC_FLAG)
return;
c |= DESTROY_IPC_FLAG;
r = hashmap_replace(*uid_refs, UID_TO_PTR(uid), UINT32_TO_PTR(c));
if (r < 0) {
log_debug_errno(r, "Failed to add UID/GID reference entry: %m");
return;
}
}
static void manager_deserialize_uid_refs_one(Manager *m, const char *value) {
manager_deserialize_uid_refs_one_internal(&m->uid_refs, value);
}
static void manager_deserialize_gid_refs_one(Manager *m, const char *value) {
manager_deserialize_uid_refs_one_internal(&m->gid_refs, value);
}
int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
int r = 0;
assert(m);
assert(f);
if (DEBUG_LOGGING) {
if (fdset_isempty(fds))
log_debug("No file descriptors passed");
else {
int fd;
FDSET_FOREACH(fd, fds) {
_cleanup_free_ char *fn = NULL;
r = fd_get_path(fd, &fn);
if (r < 0)
log_debug_errno(r, "Received serialized fd %i → %m", fd);
else
log_debug("Received serialized fd %i → %s", fd, strna(fn));
}
}
}
log_debug("Deserializing state...");
/* If we are not in reload mode yet, enter it now. Not that this is recursive, a caller might already have
* increased it to non-zero, which is why we just increase it by one here and down again at the end of this
* call. */
_cleanup_(manager_reloading_stopp) _unused_ Manager *reloading = manager_reloading_start(m);
for (;;) {
_cleanup_free_ char *line = NULL;
const char *val, *l;
r = read_line(f, LONG_LINE_MAX, &line);
if (r < 0)
return log_error_errno(r, "Failed to read serialization line: %m");
if (r == 0)
break;
l = strstrip(line);
if (isempty(l)) /* end marker */
break;
if ((val = startswith(l, "current-job-id="))) {
uint32_t id;
if (safe_atou32(val, &id) < 0)
log_notice("Failed to parse current job id value '%s', ignoring.", val);
else
m->current_job_id = MAX(m->current_job_id, id);
} else if ((val = startswith(l, "n-installed-jobs="))) {
uint32_t n;
if (safe_atou32(val, &n) < 0)
log_notice("Failed to parse installed jobs counter '%s', ignoring.", val);
else
m->n_installed_jobs += n;
} else if ((val = startswith(l, "n-failed-jobs="))) {
uint32_t n;
if (safe_atou32(val, &n) < 0)
log_notice("Failed to parse failed jobs counter '%s', ignoring.", val);
else
m->n_failed_jobs += n;
} else if ((val = startswith(l, "taint-usr="))) {
int b;
b = parse_boolean(val);
if (b < 0)
log_notice("Failed to parse taint /usr flag '%s', ignoring.", val);
else
m->taint_usr = m->taint_usr || b;
} else if ((val = startswith(l, "ready-sent="))) {
int b;
b = parse_boolean(val);
if (b < 0)
log_notice("Failed to parse ready-sent flag '%s', ignoring.", val);
else
m->ready_sent = m->ready_sent || b;
} else if ((val = startswith(l, "taint-logged="))) {
int b;
b = parse_boolean(val);
if (b < 0)
log_notice("Failed to parse taint-logged flag '%s', ignoring.", val);
else
m->taint_logged = m->taint_logged || b;
} else if ((val = startswith(l, "service-watchdogs="))) {
int b;
b = parse_boolean(val);
if (b < 0)
log_notice("Failed to parse service-watchdogs flag '%s', ignoring.", val);
else
m->service_watchdogs = b;
} else if ((val = startswith(l, "honor-device-enumeration="))) {
int b;
b = parse_boolean(val);
if (b < 0)
log_notice("Failed to parse honor-device-enumeration flag '%s', ignoring.", val);
else
m->honor_device_enumeration = b;
} else if ((val = startswith(l, "show-status-overridden="))) {
ShowStatus s;
s = show_status_from_string(val);
if (s < 0)
log_notice("Failed to parse show-status-overridden flag '%s', ignoring.", val);
else
manager_override_show_status(m, s, "deserialize");
} else if ((val = startswith(l, "log-level-override="))) {
int level;
level = log_level_from_string(val);
if (level < 0)
log_notice("Failed to parse log-level-override value '%s', ignoring.", val);
else
manager_override_log_level(m, level);
} else if ((val = startswith(l, "log-target-override="))) {
LogTarget target;
target = log_target_from_string(val);
if (target < 0)
log_notice("Failed to parse log-target-override value '%s', ignoring.", val);
else
manager_override_log_target(m, target);
} else if ((val = startswith(l, "runtime-watchdog-overridden="))) {
usec_t t;
if (deserialize_usec(val, &t) < 0)
log_notice("Failed to parse runtime-watchdog-overridden value '%s', ignoring.", val);
else
manager_override_watchdog(m, WATCHDOG_RUNTIME, t);
} else if ((val = startswith(l, "reboot-watchdog-overridden="))) {
usec_t t;
if (deserialize_usec(val, &t) < 0)
log_notice("Failed to parse reboot-watchdog-overridden value '%s', ignoring.", val);
else
manager_override_watchdog(m, WATCHDOG_REBOOT, t);
} else if ((val = startswith(l, "kexec-watchdog-overridden="))) {
usec_t t;
if (deserialize_usec(val, &t) < 0)
log_notice("Failed to parse kexec-watchdog-overridden value '%s', ignoring.", val);
else
manager_override_watchdog(m, WATCHDOG_KEXEC, t);
} else if (startswith(l, "env=")) {
r = deserialize_environment(l + 4, &m->client_environment);
if (r < 0)
log_notice_errno(r, "Failed to parse environment entry: \"%s\", ignoring: %m", l);
} else if ((val = startswith(l, "notify-fd="))) {
int fd;
if (safe_atoi(val, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
log_notice("Failed to parse notify fd, ignoring: \"%s\"", val);
else {
m->notify_event_source = sd_event_source_disable_unref(m->notify_event_source);
safe_close(m->notify_fd);
m->notify_fd = fdset_remove(fds, fd);
}
} else if ((val = startswith(l, "notify-socket="))) {
r = free_and_strdup(&m->notify_socket, val);
if (r < 0)
return r;
} else if ((val = startswith(l, "cgroups-agent-fd="))) {
int fd;
if (safe_atoi(val, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
log_notice("Failed to parse cgroups agent fd, ignoring.: %s", val);
else {
m->cgroups_agent_event_source = sd_event_source_disable_unref(m->cgroups_agent_event_source);
safe_close(m->cgroups_agent_fd);
m->cgroups_agent_fd = fdset_remove(fds, fd);
}
} else if ((val = startswith(l, "user-lookup="))) {
int fd0, fd1;
if (sscanf(val, "%i %i", &fd0, &fd1) != 2 || fd0 < 0 || fd1 < 0 || fd0 == fd1 || !fdset_contains(fds, fd0) || !fdset_contains(fds, fd1))
log_notice("Failed to parse user lookup fd, ignoring: %s", val);
else {
m->user_lookup_event_source = sd_event_source_disable_unref(m->user_lookup_event_source);
safe_close_pair(m->user_lookup_fds);
m->user_lookup_fds[0] = fdset_remove(fds, fd0);
m->user_lookup_fds[1] = fdset_remove(fds, fd1);
}
} else if ((val = startswith(l, "dynamic-user=")))
dynamic_user_deserialize_one(m, val, fds);
else if ((val = startswith(l, "destroy-ipc-uid=")))
manager_deserialize_uid_refs_one(m, val);
else if ((val = startswith(l, "destroy-ipc-gid=")))
manager_deserialize_gid_refs_one(m, val);
else if ((val = startswith(l, "exec-runtime=")))
(void) exec_runtime_deserialize_one(m, val, fds);
else if ((val = startswith(l, "subscribed="))) {
if (strv_extend(&m->deserialized_subscribed, val) < 0)
return -ENOMEM;
} else {
ManagerTimestamp q;
for (q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) {
val = startswith(l, manager_timestamp_to_string(q));
if (!val)
continue;
val = startswith(val, "-timestamp=");
if (val)
break;
}
if (q < _MANAGER_TIMESTAMP_MAX) /* found it */
(void) deserialize_dual_timestamp(val, m->timestamps + q);
else if (!startswith(l, "kdbus-fd=")) /* ignore kdbus */
log_notice("Unknown serialization item '%s', ignoring.", l);
}
}
return manager_deserialize_units(m, f, fds);
}

View File

@ -0,0 +1,13 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <stdbool.h>
#include "manager.h"
#include "fdset.h"
#define DESTROY_IPC_FLAG (UINT32_C(1) << 31)
int manager_open_serialization(Manager *m, FILE **ret_f);
int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root);
int manager_deserialize(Manager *m, FILE *f, FDSet *fds);

View File

@ -56,6 +56,7 @@
#include "macro.h" #include "macro.h"
#include "manager.h" #include "manager.h"
#include "manager-dump.h" #include "manager-dump.h"
#include "manager-serialize.h"
#include "memory-util.h" #include "memory-util.h"
#include "mkdir.h" #include "mkdir.h"
#include "parse-util.h" #include "parse-util.h"
@ -66,7 +67,6 @@
#include "rlimit-util.h" #include "rlimit-util.h"
#include "rm-rf.h" #include "rm-rf.h"
#include "selinux-util.h" #include "selinux-util.h"
#include "serialize.h"
#include "signal-util.h" #include "signal-util.h"
#include "socket-util.h" #include "socket-util.h"
#include "special.h" #include "special.h"
@ -82,7 +82,6 @@
#include "transaction.h" #include "transaction.h"
#include "umask-util.h" #include "umask-util.h"
#include "unit-name.h" #include "unit-name.h"
#include "unit-serialize.h"
#include "user-util.h" #include "user-util.h"
#include "virt.h" #include "virt.h"
#include "watchdog.h" #include "watchdog.h"
@ -118,9 +117,19 @@ static int manager_run_generators(Manager *m);
static void manager_vacuum(Manager *m); static void manager_vacuum(Manager *m);
static usec_t manager_watch_jobs_next_time(Manager *m) { static usec_t manager_watch_jobs_next_time(Manager *m) {
return usec_add(now(CLOCK_MONOTONIC), usec_t timeout;
show_status_on(m->show_status) ? JOBS_IN_PROGRESS_WAIT_USEC :
JOBS_IN_PROGRESS_QUIET_WAIT_USEC); if (MANAGER_IS_USER(m))
/* Let the user manager without a timeout show status quickly, so the system manager can make
* use of it, if it wants to. */
timeout = JOBS_IN_PROGRESS_WAIT_USEC * 2 / 3;
else if (show_status_on(m->show_status))
/* When status is on, just use the usual timeout. */
timeout = JOBS_IN_PROGRESS_WAIT_USEC;
else
timeout = JOBS_IN_PROGRESS_QUIET_WAIT_USEC;
return usec_add(now(CLOCK_MONOTONIC), timeout);
} }
static void manager_watch_jobs_in_progress(Manager *m) { static void manager_watch_jobs_in_progress(Manager *m) {
@ -200,7 +209,6 @@ static void manager_flip_auto_status(Manager *m, bool enable, const char *reason
} }
static void manager_print_jobs_in_progress(Manager *m) { static void manager_print_jobs_in_progress(Manager *m) {
_cleanup_free_ char *job_of_n = NULL;
Job *j; Job *j;
unsigned counter = 0, print_nr; unsigned counter = 0, print_nr;
char cylon[6 + CYLON_BUFFER_EXTRA + 1]; char cylon[6 + CYLON_BUFFER_EXTRA + 1];
@ -230,26 +238,51 @@ static void manager_print_jobs_in_progress(Manager *m) {
m->jobs_in_progress_iteration++; m->jobs_in_progress_iteration++;
char job_of_n[STRLEN("( of ) ") + DECIMAL_STR_MAX(unsigned)*2] = "";
if (m->n_running_jobs > 1) if (m->n_running_jobs > 1)
if (asprintf(&job_of_n, "(%u of %u) ", counter, m->n_running_jobs) < 0) xsprintf(job_of_n, "(%u of %u) ", counter, m->n_running_jobs);
job_of_n = NULL;
bool have_timeout = job_get_timeout(j, &x) > 0; bool have_timeout = job_get_timeout(j, &x) > 0;
/* We want to use enough information for the user to identify previous lines talking about the same /* We want to use enough information for the user to identify previous lines talking about the same
* unit, but keep the message as short as possible. So if 'Starting foo.service' or 'Starting * unit, but keep the message as short as possible. So if 'Starting foo.service' or 'Starting
* foo.service (Description)' were used, 'foo.service' is enough here. On the other hand, if we used * foo.service - Description' were used, 'foo.service' is enough here. On the other hand, if we used
* 'Starting Description' before, then we shall also use 'Description' here. So we pass NULL as the * 'Starting Description' before, then we shall also use 'Description' here. So we pass NULL as the
* second argument to unit_status_string(). */ * second argument to unit_status_string(). */
const char *ident = unit_status_string(j->unit, NULL); const char *ident = unit_status_string(j->unit, NULL);
manager_status_printf(m, STATUS_TYPE_EPHEMERAL, cylon, const char *time = FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - j->begin_usec, 1*USEC_PER_SEC);
"%sA %s job is running for %s (%s / %s)", const char *limit = have_timeout ? FORMAT_TIMESPAN(x - j->begin_usec, 1*USEC_PER_SEC) : "no limit";
strempty(job_of_n),
job_type_to_string(j->type), if (m->status_unit_format == STATUS_UNIT_FORMAT_DESCRIPTION)
ident, /* When using 'Description', we effectively don't have enough space to show the nested status
FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - j->begin_usec, 1*USEC_PER_SEC), * without ellipsization, so let's not even try. */
have_timeout ? FORMAT_TIMESPAN(x - j->begin_usec, 1*USEC_PER_SEC) : "no limit"); manager_status_printf(m, STATUS_TYPE_EPHEMERAL, cylon,
"%sA %s job is running for %s (%s / %s)",
job_of_n,
job_type_to_string(j->type),
ident,
time, limit);
else {
const char *status_text = unit_status_text(j->unit);
manager_status_printf(m, STATUS_TYPE_EPHEMERAL, cylon,
"%sJob %s/%s running (%s / %s)%s%s",
job_of_n,
ident,
job_type_to_string(j->type),
time, limit,
status_text ? ": " : "",
strempty(status_text));
}
sd_notifyf(false,
"STATUS=%sUser job %s/%s running (%s / %s)...",
job_of_n,
ident,
job_type_to_string(j->type),
time, limit);
m->status_ready = false;
} }
static int have_ask_password(void) { static int have_ask_password(void) {
@ -621,9 +654,7 @@ static char** sanitize_environment(char **l) {
NULL); NULL);
/* Let's order the environment alphabetically, just to make it pretty */ /* Let's order the environment alphabetically, just to make it pretty */
strv_sort(l); return strv_sort(l);
return l;
} }
int manager_default_environment(Manager *m) { int manager_default_environment(Manager *m) {
@ -1686,11 +1717,11 @@ static void manager_ready(Manager *m) {
m->honor_device_enumeration = true; m->honor_device_enumeration = true;
} }
static Manager* manager_reloading_start(Manager *m) { Manager* manager_reloading_start(Manager *m) {
m->n_reloading++; m->n_reloading++;
return m; return m;
} }
static void manager_reloading_stopp(Manager **m) { void manager_reloading_stopp(Manager **m) {
if (*m) { if (*m) {
assert((*m)->n_reloading > 0); assert((*m)->n_reloading > 0);
(*m)->n_reloading--; (*m)->n_reloading--;
@ -2616,15 +2647,19 @@ turn_off:
return 0; return 0;
} }
static void manager_start_target(Manager *m, const char *name, JobMode mode) { static void manager_start_special(Manager *m, const char *name, JobMode mode) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; Job *job;
int r;
log_debug("Activating special unit %s", name); if (manager_add_job_by_name_and_warn(m, JOB_START, name, mode, NULL, &job) < 0)
return;
r = manager_add_job_by_name(m, JOB_START, name, mode, NULL, &error, NULL); const char *s = unit_status_string(job->unit, NULL);
if (r < 0)
log_error("Failed to enqueue %s job: %s", name, bus_error_message(&error, r)); log_info("Activating special unit %s...", s);
sd_notifyf(false,
"STATUS=Activating special unit %s...", s);
m->status_ready = false;
} }
static void manager_handle_ctrl_alt_del(Manager *m) { static void manager_handle_ctrl_alt_del(Manager *m) {
@ -2633,7 +2668,7 @@ static void manager_handle_ctrl_alt_del(Manager *m) {
* unless it was disabled in system.conf */ * unless it was disabled in system.conf */
if (ratelimit_below(&m->ctrl_alt_del_ratelimit) || m->cad_burst_action == EMERGENCY_ACTION_NONE) if (ratelimit_below(&m->ctrl_alt_del_ratelimit) || m->cad_burst_action == EMERGENCY_ACTION_NONE)
manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE_IRREVERSIBLY); manager_start_special(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE_IRREVERSIBLY);
else else
emergency_action(m, m->cad_burst_action, EMERGENCY_ACTION_WARN, NULL, -1, emergency_action(m, m->cad_burst_action, EMERGENCY_ACTION_WARN, NULL, -1,
"Ctrl-Alt-Del was pressed more than 7 times within 2s"); "Ctrl-Alt-Del was pressed more than 7 times within 2s");
@ -2697,21 +2732,20 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t
if (MANAGER_IS_SYSTEM(m)) if (MANAGER_IS_SYSTEM(m))
manager_handle_ctrl_alt_del(m); manager_handle_ctrl_alt_del(m);
else else
manager_start_target(m, SPECIAL_EXIT_TARGET, manager_start_special(m, SPECIAL_EXIT_TARGET, JOB_REPLACE_IRREVERSIBLY);
JOB_REPLACE_IRREVERSIBLY);
break; break;
case SIGWINCH: case SIGWINCH:
/* This is a nop on non-init */ /* This is a nop on non-init */
if (MANAGER_IS_SYSTEM(m)) if (MANAGER_IS_SYSTEM(m))
manager_start_target(m, SPECIAL_KBREQUEST_TARGET, JOB_REPLACE); manager_start_special(m, SPECIAL_KBREQUEST_TARGET, JOB_REPLACE);
break; break;
case SIGPWR: case SIGPWR:
/* This is a nop on non-init */ /* This is a nop on non-init */
if (MANAGER_IS_SYSTEM(m)) if (MANAGER_IS_SYSTEM(m))
manager_start_target(m, SPECIAL_SIGPWR_TARGET, JOB_REPLACE); manager_start_special(m, SPECIAL_SIGPWR_TARGET, JOB_REPLACE);
break; break;
@ -2723,10 +2757,8 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t
if (MANAGER_IS_SYSTEM(m)) if (MANAGER_IS_SYSTEM(m))
(void) bus_init_system(m); (void) bus_init_system(m);
} else { } else
log_info("Starting D-Bus service..."); manager_start_special(m, SPECIAL_DBUS_SERVICE, JOB_REPLACE);
manager_start_target(m, SPECIAL_DBUS_SERVICE, JOB_REPLACE);
}
break; break;
@ -2777,8 +2809,7 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t
if ((int) sfsi.ssi_signo >= SIGRTMIN+0 && if ((int) sfsi.ssi_signo >= SIGRTMIN+0 &&
(int) sfsi.ssi_signo < SIGRTMIN+(int) ELEMENTSOF(target_table)) { (int) sfsi.ssi_signo < SIGRTMIN+(int) ELEMENTSOF(target_table)) {
int idx = (int) sfsi.ssi_signo - SIGRTMIN; int idx = (int) sfsi.ssi_signo - SIGRTMIN;
manager_start_target(m, target_table[idx].target, manager_start_special(m, target_table[idx].target, target_table[idx].mode);
target_table[idx].mode);
break; break;
} }
@ -3143,10 +3174,8 @@ void manager_send_unit_plymouth(Manager *m, Unit *u) {
return; return;
} }
if (asprintf(&message, "U\002%c%s%n", (int) (strlen(u->id) + 1), u->id, &n) < 0) { if (asprintf(&message, "U\002%c%s%n", (int) (strlen(u->id) + 1), u->id, &n) < 0)
log_oom(); return (void) log_oom();
return;
}
errno = 0; errno = 0;
if (write(fd, message, n + 1) != n + 1) if (write(fd, message, n + 1) != n + 1)
@ -3154,242 +3183,6 @@ void manager_send_unit_plymouth(Manager *m, Unit *u) {
log_error_errno(errno, "Failed to write Plymouth message: %m"); log_error_errno(errno, "Failed to write Plymouth message: %m");
} }
int manager_open_serialization(Manager *m, FILE **_f) {
_cleanup_close_ int fd = -1;
FILE *f;
assert(_f);
fd = open_serialization_fd("systemd-state");
if (fd < 0)
return fd;
f = take_fdopen(&fd, "w+");
if (!f)
return -errno;
*_f = f;
return 0;
}
static bool manager_timestamp_shall_serialize(ManagerTimestamp t) {
if (!in_initrd())
return true;
/* The following timestamps only apply to the host system, hence only serialize them there */
return !IN_SET(t,
MANAGER_TIMESTAMP_USERSPACE, MANAGER_TIMESTAMP_FINISH,
MANAGER_TIMESTAMP_SECURITY_START, MANAGER_TIMESTAMP_SECURITY_FINISH,
MANAGER_TIMESTAMP_GENERATORS_START, MANAGER_TIMESTAMP_GENERATORS_FINISH,
MANAGER_TIMESTAMP_UNITS_LOAD_START, MANAGER_TIMESTAMP_UNITS_LOAD_FINISH);
}
#define DESTROY_IPC_FLAG (UINT32_C(1) << 31)
static void manager_serialize_uid_refs_internal(
FILE *f,
Hashmap *uid_refs,
const char *field_name) {
void *p, *k;
assert(f);
assert(field_name);
/* Serialize the UID reference table. Or actually, just the IPC destruction flag of it, as
* the actual counter of it is better rebuild after a reload/reexec. */
HASHMAP_FOREACH_KEY(p, k, uid_refs) {
uint32_t c;
uid_t uid;
uid = PTR_TO_UID(k);
c = PTR_TO_UINT32(p);
if (!(c & DESTROY_IPC_FLAG))
continue;
(void) serialize_item_format(f, field_name, UID_FMT, uid);
}
}
static void manager_serialize_uid_refs(Manager *m, FILE *f) {
manager_serialize_uid_refs_internal(f, m->uid_refs, "destroy-ipc-uid");
}
static void manager_serialize_gid_refs(Manager *m, FILE *f) {
manager_serialize_uid_refs_internal(f, m->gid_refs, "destroy-ipc-gid");
}
int manager_serialize(
Manager *m,
FILE *f,
FDSet *fds,
bool switching_root) {
const char *t;
Unit *u;
int r;
assert(m);
assert(f);
assert(fds);
_cleanup_(manager_reloading_stopp) _unused_ Manager *reloading = manager_reloading_start(m);
(void) serialize_item_format(f, "current-job-id", "%" PRIu32, m->current_job_id);
(void) serialize_item_format(f, "n-installed-jobs", "%u", m->n_installed_jobs);
(void) serialize_item_format(f, "n-failed-jobs", "%u", m->n_failed_jobs);
(void) serialize_bool(f, "taint-usr", m->taint_usr);
(void) serialize_bool(f, "ready-sent", m->ready_sent);
(void) serialize_bool(f, "taint-logged", m->taint_logged);
(void) serialize_bool(f, "service-watchdogs", m->service_watchdogs);
/* After switching root, udevd has not been started yet. So, enumeration results should not be emitted. */
(void) serialize_bool(f, "honor-device-enumeration", !switching_root);
if (m->show_status_overridden != _SHOW_STATUS_INVALID)
(void) serialize_item(f, "show-status-overridden",
show_status_to_string(m->show_status_overridden));
if (m->log_level_overridden)
(void) serialize_item_format(f, "log-level-override", "%i", log_get_max_level());
if (m->log_target_overridden)
(void) serialize_item(f, "log-target-override", log_target_to_string(log_get_target()));
(void) serialize_usec(f, "runtime-watchdog-overridden", m->watchdog_overridden[WATCHDOG_RUNTIME]);
(void) serialize_usec(f, "reboot-watchdog-overridden", m->watchdog_overridden[WATCHDOG_REBOOT]);
(void) serialize_usec(f, "kexec-watchdog-overridden", m->watchdog_overridden[WATCHDOG_KEXEC]);
for (ManagerTimestamp q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) {
_cleanup_free_ char *joined = NULL;
if (!manager_timestamp_shall_serialize(q))
continue;
joined = strjoin(manager_timestamp_to_string(q), "-timestamp");
if (!joined)
return log_oom();
(void) serialize_dual_timestamp(f, joined, m->timestamps + q);
}
if (!switching_root)
(void) serialize_strv(f, "env", m->client_environment);
if (m->notify_fd >= 0) {
r = serialize_fd(f, fds, "notify-fd", m->notify_fd);
if (r < 0)
return r;
(void) serialize_item(f, "notify-socket", m->notify_socket);
}
if (m->cgroups_agent_fd >= 0) {
r = serialize_fd(f, fds, "cgroups-agent-fd", m->cgroups_agent_fd);
if (r < 0)
return r;
}
if (m->user_lookup_fds[0] >= 0) {
int copy0, copy1;
copy0 = fdset_put_dup(fds, m->user_lookup_fds[0]);
if (copy0 < 0)
return log_error_errno(copy0, "Failed to add user lookup fd to serialization: %m");
copy1 = fdset_put_dup(fds, m->user_lookup_fds[1]);
if (copy1 < 0)
return log_error_errno(copy1, "Failed to add user lookup fd to serialization: %m");
(void) serialize_item_format(f, "user-lookup", "%i %i", copy0, copy1);
}
bus_track_serialize(m->subscribed, f, "subscribed");
r = dynamic_user_serialize(m, f, fds);
if (r < 0)
return r;
manager_serialize_uid_refs(m, f);
manager_serialize_gid_refs(m, f);
r = exec_runtime_serialize(m, f, fds);
if (r < 0)
return r;
(void) fputc('\n', f);
HASHMAP_FOREACH_KEY(u, t, m->units) {
if (u->id != t)
continue;
r = unit_serialize(u, f, fds, switching_root);
if (r < 0)
return r;
}
r = fflush_and_check(f);
if (r < 0)
return log_error_errno(r, "Failed to flush serialization: %m");
r = bus_fdset_add_all(m, fds);
if (r < 0)
return log_error_errno(r, "Failed to add bus sockets to serialization: %m");
return 0;
}
static int manager_deserialize_one_unit(Manager *m, const char *name, FILE *f, FDSet *fds) {
Unit *u;
int r;
r = manager_load_unit(m, name, NULL, NULL, &u);
if (r < 0) {
if (r == -ENOMEM)
return r;
return log_notice_errno(r, "Failed to load unit \"%s\", skipping deserialization: %m", name);
}
r = unit_deserialize(u, f, fds);
if (r < 0) {
if (r == -ENOMEM)
return r;
return log_notice_errno(r, "Failed to deserialize unit \"%s\", skipping: %m", name);
}
return 0;
}
static int manager_deserialize_units(Manager *m, FILE *f, FDSet *fds) {
const char *unit_name;
int r;
for (;;) {
_cleanup_free_ char *line = NULL;
/* Start marker */
r = read_line(f, LONG_LINE_MAX, &line);
if (r < 0)
return log_error_errno(r, "Failed to read serialization line: %m");
if (r == 0)
break;
unit_name = strstrip(line);
r = manager_deserialize_one_unit(m, unit_name, f, fds);
if (r == -ENOMEM)
return r;
if (r < 0) {
r = unit_deserialize_skip(f);
if (r < 0)
return r;
}
}
return 0;
}
usec_t manager_get_watchdog(Manager *m, WatchdogType t) { usec_t manager_get_watchdog(Manager *m, WatchdogType t) {
assert(m); assert(m);
@ -3474,294 +3267,6 @@ void manager_retry_runtime_watchdog(Manager *m) {
m->runtime_watchdog_running = true; m->runtime_watchdog_running = true;
} }
static void manager_deserialize_uid_refs_one_internal(
Hashmap** uid_refs,
const char *value) {
uid_t uid;
uint32_t c;
int r;
assert(uid_refs);
assert(value);
r = parse_uid(value, &uid);
if (r < 0 || uid == 0) {
log_debug("Unable to parse UID/GID reference serialization: " UID_FMT, uid);
return;
}
if (hashmap_ensure_allocated(uid_refs, &trivial_hash_ops) < 0) {
log_oom();
return;
}
c = PTR_TO_UINT32(hashmap_get(*uid_refs, UID_TO_PTR(uid)));
if (c & DESTROY_IPC_FLAG)
return;
c |= DESTROY_IPC_FLAG;
r = hashmap_replace(*uid_refs, UID_TO_PTR(uid), UINT32_TO_PTR(c));
if (r < 0) {
log_debug_errno(r, "Failed to add UID/GID reference entry: %m");
return;
}
}
static void manager_deserialize_uid_refs_one(Manager *m, const char *value) {
manager_deserialize_uid_refs_one_internal(&m->uid_refs, value);
}
static void manager_deserialize_gid_refs_one(Manager *m, const char *value) {
manager_deserialize_uid_refs_one_internal(&m->gid_refs, value);
}
int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
int r = 0;
assert(m);
assert(f);
if (DEBUG_LOGGING) {
if (fdset_isempty(fds))
log_debug("No file descriptors passed");
else {
int fd;
FDSET_FOREACH(fd, fds) {
_cleanup_free_ char *fn = NULL;
r = fd_get_path(fd, &fn);
if (r < 0)
log_debug_errno(r, "Received serialized fd %i → %m", fd);
else
log_debug("Received serialized fd %i → %s", fd, strna(fn));
}
}
}
log_debug("Deserializing state...");
/* If we are not in reload mode yet, enter it now. Not that this is recursive, a caller might already have
* increased it to non-zero, which is why we just increase it by one here and down again at the end of this
* call. */
_cleanup_(manager_reloading_stopp) _unused_ Manager *reloading = manager_reloading_start(m);
for (;;) {
_cleanup_free_ char *line = NULL;
const char *val, *l;
r = read_line(f, LONG_LINE_MAX, &line);
if (r < 0)
return log_error_errno(r, "Failed to read serialization line: %m");
if (r == 0)
break;
l = strstrip(line);
if (isempty(l)) /* end marker */
break;
if ((val = startswith(l, "current-job-id="))) {
uint32_t id;
if (safe_atou32(val, &id) < 0)
log_notice("Failed to parse current job id value '%s', ignoring.", val);
else
m->current_job_id = MAX(m->current_job_id, id);
} else if ((val = startswith(l, "n-installed-jobs="))) {
uint32_t n;
if (safe_atou32(val, &n) < 0)
log_notice("Failed to parse installed jobs counter '%s', ignoring.", val);
else
m->n_installed_jobs += n;
} else if ((val = startswith(l, "n-failed-jobs="))) {
uint32_t n;
if (safe_atou32(val, &n) < 0)
log_notice("Failed to parse failed jobs counter '%s', ignoring.", val);
else
m->n_failed_jobs += n;
} else if ((val = startswith(l, "taint-usr="))) {
int b;
b = parse_boolean(val);
if (b < 0)
log_notice("Failed to parse taint /usr flag '%s', ignoring.", val);
else
m->taint_usr = m->taint_usr || b;
} else if ((val = startswith(l, "ready-sent="))) {
int b;
b = parse_boolean(val);
if (b < 0)
log_notice("Failed to parse ready-sent flag '%s', ignoring.", val);
else
m->ready_sent = m->ready_sent || b;
} else if ((val = startswith(l, "taint-logged="))) {
int b;
b = parse_boolean(val);
if (b < 0)
log_notice("Failed to parse taint-logged flag '%s', ignoring.", val);
else
m->taint_logged = m->taint_logged || b;
} else if ((val = startswith(l, "service-watchdogs="))) {
int b;
b = parse_boolean(val);
if (b < 0)
log_notice("Failed to parse service-watchdogs flag '%s', ignoring.", val);
else
m->service_watchdogs = b;
} else if ((val = startswith(l, "honor-device-enumeration="))) {
int b;
b = parse_boolean(val);
if (b < 0)
log_notice("Failed to parse honor-device-enumeration flag '%s', ignoring.", val);
else
m->honor_device_enumeration = b;
} else if ((val = startswith(l, "show-status-overridden="))) {
ShowStatus s;
s = show_status_from_string(val);
if (s < 0)
log_notice("Failed to parse show-status-overridden flag '%s', ignoring.", val);
else
manager_override_show_status(m, s, "deserialize");
} else if ((val = startswith(l, "log-level-override="))) {
int level;
level = log_level_from_string(val);
if (level < 0)
log_notice("Failed to parse log-level-override value '%s', ignoring.", val);
else
manager_override_log_level(m, level);
} else if ((val = startswith(l, "log-target-override="))) {
LogTarget target;
target = log_target_from_string(val);
if (target < 0)
log_notice("Failed to parse log-target-override value '%s', ignoring.", val);
else
manager_override_log_target(m, target);
} else if ((val = startswith(l, "runtime-watchdog-overridden="))) {
usec_t t;
if (deserialize_usec(val, &t) < 0)
log_notice("Failed to parse runtime-watchdog-overridden value '%s', ignoring.", val);
else
manager_override_watchdog(m, WATCHDOG_RUNTIME, t);
} else if ((val = startswith(l, "reboot-watchdog-overridden="))) {
usec_t t;
if (deserialize_usec(val, &t) < 0)
log_notice("Failed to parse reboot-watchdog-overridden value '%s', ignoring.", val);
else
manager_override_watchdog(m, WATCHDOG_REBOOT, t);
} else if ((val = startswith(l, "kexec-watchdog-overridden="))) {
usec_t t;
if (deserialize_usec(val, &t) < 0)
log_notice("Failed to parse kexec-watchdog-overridden value '%s', ignoring.", val);
else
manager_override_watchdog(m, WATCHDOG_KEXEC, t);
} else if (startswith(l, "env=")) {
r = deserialize_environment(l + 4, &m->client_environment);
if (r < 0)
log_notice_errno(r, "Failed to parse environment entry: \"%s\", ignoring: %m", l);
} else if ((val = startswith(l, "notify-fd="))) {
int fd;
if (safe_atoi(val, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
log_notice("Failed to parse notify fd, ignoring: \"%s\"", val);
else {
m->notify_event_source = sd_event_source_disable_unref(m->notify_event_source);
safe_close(m->notify_fd);
m->notify_fd = fdset_remove(fds, fd);
}
} else if ((val = startswith(l, "notify-socket="))) {
r = free_and_strdup(&m->notify_socket, val);
if (r < 0)
return r;
} else if ((val = startswith(l, "cgroups-agent-fd="))) {
int fd;
if (safe_atoi(val, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
log_notice("Failed to parse cgroups agent fd, ignoring.: %s", val);
else {
m->cgroups_agent_event_source = sd_event_source_disable_unref(m->cgroups_agent_event_source);
safe_close(m->cgroups_agent_fd);
m->cgroups_agent_fd = fdset_remove(fds, fd);
}
} else if ((val = startswith(l, "user-lookup="))) {
int fd0, fd1;
if (sscanf(val, "%i %i", &fd0, &fd1) != 2 || fd0 < 0 || fd1 < 0 || fd0 == fd1 || !fdset_contains(fds, fd0) || !fdset_contains(fds, fd1))
log_notice("Failed to parse user lookup fd, ignoring: %s", val);
else {
m->user_lookup_event_source = sd_event_source_disable_unref(m->user_lookup_event_source);
safe_close_pair(m->user_lookup_fds);
m->user_lookup_fds[0] = fdset_remove(fds, fd0);
m->user_lookup_fds[1] = fdset_remove(fds, fd1);
}
} else if ((val = startswith(l, "dynamic-user=")))
dynamic_user_deserialize_one(m, val, fds);
else if ((val = startswith(l, "destroy-ipc-uid=")))
manager_deserialize_uid_refs_one(m, val);
else if ((val = startswith(l, "destroy-ipc-gid=")))
manager_deserialize_gid_refs_one(m, val);
else if ((val = startswith(l, "exec-runtime=")))
(void) exec_runtime_deserialize_one(m, val, fds);
else if ((val = startswith(l, "subscribed="))) {
if (strv_extend(&m->deserialized_subscribed, val) < 0)
return -ENOMEM;
} else {
ManagerTimestamp q;
for (q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) {
val = startswith(l, manager_timestamp_to_string(q));
if (!val)
continue;
val = startswith(val, "-timestamp=");
if (val)
break;
}
if (q < _MANAGER_TIMESTAMP_MAX) /* found it */
(void) deserialize_dual_timestamp(val, m->timestamps + q);
else if (!startswith(l, "kdbus-fd=")) /* ignore kdbus */
log_notice("Unknown serialization item '%s', ignoring.", l);
}
}
return manager_deserialize_units(m, f, fds);
}
int manager_reload(Manager *m) { int manager_reload(Manager *m) {
_cleanup_(manager_reloading_stopp) Manager *reloading = NULL; _cleanup_(manager_reloading_stopp) Manager *reloading = NULL;
_cleanup_fdset_free_ FDSet *fds = NULL; _cleanup_fdset_free_ FDSet *fds = NULL;
@ -3974,28 +3479,32 @@ static void manager_notify_finished(Manager *m) {
bus_manager_send_finished(m, firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec); bus_manager_send_finished(m, firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec);
sd_notifyf(false,
m->ready_sent ? "STATUS=Startup finished in %s."
: "READY=1\n"
"STATUS=Startup finished in %s.",
FORMAT_TIMESPAN(total_usec, USEC_PER_MSEC));
m->ready_sent = true;
log_taint_string(m); log_taint_string(m);
} }
static void manager_send_ready(Manager *m) { static void user_manager_send_ready(Manager *m) {
assert(m); assert(m);
/* We send READY=1 on reaching basic.target only when running in --user mode. */ /* We send READY=1 on reaching basic.target only when running in --user mode. */
if (!MANAGER_IS_USER(m) || m->ready_sent) if (!MANAGER_IS_USER(m) || m->ready_sent)
return; return;
m->ready_sent = true;
sd_notifyf(false, sd_notifyf(false,
"READY=1\n" "READY=1\n"
"STATUS=Reached " SPECIAL_BASIC_TARGET "."); "STATUS=Reached " SPECIAL_BASIC_TARGET ".");
m->ready_sent = true;
m->status_ready = false;
}
static void manager_send_ready(Manager *m) {
if (m->ready_sent && m->status_ready)
/* Skip the notification if nothing changed. */
return;
sd_notifyf(false,
"%sSTATUS=Ready.",
m->ready_sent ? "READY=1\n" : "");
m->ready_sent = m->status_ready = true;
} }
static void manager_check_basic_target(Manager *m) { static void manager_check_basic_target(Manager *m) {
@ -4012,7 +3521,7 @@ static void manager_check_basic_target(Manager *m) {
return; return;
/* For user managers, send out READY=1 as soon as we reach basic.target */ /* For user managers, send out READY=1 as soon as we reach basic.target */
manager_send_ready(m); user_manager_send_ready(m);
/* Log the taint string as soon as we reach basic.target */ /* Log the taint string as soon as we reach basic.target */
log_taint_string(m); log_taint_string(m);
@ -4043,6 +3552,11 @@ void manager_check_finished(Manager *m) {
if (hashmap_buckets(m->jobs) > hashmap_size(m->units) / 10) if (hashmap_buckets(m->jobs) > hashmap_size(m->units) / 10)
m->jobs = hashmap_free(m->jobs); m->jobs = hashmap_free(m->jobs);
manager_send_ready(m);
if (MANAGER_IS_FINISHED(m))
return;
manager_flip_auto_status(m, false, "boot finished"); manager_flip_auto_status(m, false, "boot finished");
/* Notify Type=idle units that we are done now */ /* Notify Type=idle units that we are done now */
@ -4057,9 +3571,6 @@ void manager_check_finished(Manager *m) {
/* This is no longer the first boot */ /* This is no longer the first boot */
manager_set_first_boot(m, false); manager_set_first_boot(m, false);
if (MANAGER_IS_FINISHED(m))
return;
dual_timestamp_get(m->timestamps + MANAGER_TIMESTAMP_FINISH); dual_timestamp_get(m->timestamps + MANAGER_TIMESTAMP_FINISH);
manager_notify_finished(m); manager_notify_finished(m);
@ -4929,33 +4440,33 @@ ManagerTimestamp manager_timestamp_initrd_mangle(ManagerTimestamp s) {
static const char *const manager_state_table[_MANAGER_STATE_MAX] = { static const char *const manager_state_table[_MANAGER_STATE_MAX] = {
[MANAGER_INITIALIZING] = "initializing", [MANAGER_INITIALIZING] = "initializing",
[MANAGER_STARTING] = "starting", [MANAGER_STARTING] = "starting",
[MANAGER_RUNNING] = "running", [MANAGER_RUNNING] = "running",
[MANAGER_DEGRADED] = "degraded", [MANAGER_DEGRADED] = "degraded",
[MANAGER_MAINTENANCE] = "maintenance", [MANAGER_MAINTENANCE] = "maintenance",
[MANAGER_STOPPING] = "stopping", [MANAGER_STOPPING] = "stopping",
}; };
DEFINE_STRING_TABLE_LOOKUP(manager_state, ManagerState); DEFINE_STRING_TABLE_LOOKUP(manager_state, ManagerState);
static const char *const manager_timestamp_table[_MANAGER_TIMESTAMP_MAX] = { static const char *const manager_timestamp_table[_MANAGER_TIMESTAMP_MAX] = {
[MANAGER_TIMESTAMP_FIRMWARE] = "firmware", [MANAGER_TIMESTAMP_FIRMWARE] = "firmware",
[MANAGER_TIMESTAMP_LOADER] = "loader", [MANAGER_TIMESTAMP_LOADER] = "loader",
[MANAGER_TIMESTAMP_KERNEL] = "kernel", [MANAGER_TIMESTAMP_KERNEL] = "kernel",
[MANAGER_TIMESTAMP_INITRD] = "initrd", [MANAGER_TIMESTAMP_INITRD] = "initrd",
[MANAGER_TIMESTAMP_USERSPACE] = "userspace", [MANAGER_TIMESTAMP_USERSPACE] = "userspace",
[MANAGER_TIMESTAMP_FINISH] = "finish", [MANAGER_TIMESTAMP_FINISH] = "finish",
[MANAGER_TIMESTAMP_SECURITY_START] = "security-start", [MANAGER_TIMESTAMP_SECURITY_START] = "security-start",
[MANAGER_TIMESTAMP_SECURITY_FINISH] = "security-finish", [MANAGER_TIMESTAMP_SECURITY_FINISH] = "security-finish",
[MANAGER_TIMESTAMP_GENERATORS_START] = "generators-start", [MANAGER_TIMESTAMP_GENERATORS_START] = "generators-start",
[MANAGER_TIMESTAMP_GENERATORS_FINISH] = "generators-finish", [MANAGER_TIMESTAMP_GENERATORS_FINISH] = "generators-finish",
[MANAGER_TIMESTAMP_UNITS_LOAD_START] = "units-load-start", [MANAGER_TIMESTAMP_UNITS_LOAD_START] = "units-load-start",
[MANAGER_TIMESTAMP_UNITS_LOAD_FINISH] = "units-load-finish", [MANAGER_TIMESTAMP_UNITS_LOAD_FINISH] = "units-load-finish",
[MANAGER_TIMESTAMP_INITRD_SECURITY_START] = "initrd-security-start", [MANAGER_TIMESTAMP_INITRD_SECURITY_START] = "initrd-security-start",
[MANAGER_TIMESTAMP_INITRD_SECURITY_FINISH] = "initrd-security-finish", [MANAGER_TIMESTAMP_INITRD_SECURITY_FINISH] = "initrd-security-finish",
[MANAGER_TIMESTAMP_INITRD_GENERATORS_START] = "initrd-generators-start", [MANAGER_TIMESTAMP_INITRD_GENERATORS_START] = "initrd-generators-start",
[MANAGER_TIMESTAMP_INITRD_GENERATORS_FINISH] = "initrd-generators-finish", [MANAGER_TIMESTAMP_INITRD_GENERATORS_FINISH] = "initrd-generators-finish",
[MANAGER_TIMESTAMP_INITRD_UNITS_LOAD_START] = "initrd-units-load-start", [MANAGER_TIMESTAMP_INITRD_UNITS_LOAD_START] = "initrd-units-load-start",
[MANAGER_TIMESTAMP_INITRD_UNITS_LOAD_FINISH] = "initrd-units-load-finish", [MANAGER_TIMESTAMP_INITRD_UNITS_LOAD_FINISH] = "initrd-units-load-finish",
}; };
@ -4963,8 +4474,8 @@ DEFINE_STRING_TABLE_LOOKUP(manager_timestamp, ManagerTimestamp);
static const char* const oom_policy_table[_OOM_POLICY_MAX] = { static const char* const oom_policy_table[_OOM_POLICY_MAX] = {
[OOM_CONTINUE] = "continue", [OOM_CONTINUE] = "continue",
[OOM_STOP] = "stop", [OOM_STOP] = "stop",
[OOM_KILL] = "kill", [OOM_KILL] = "kill",
}; };
DEFINE_STRING_TABLE_LOOKUP(oom_policy, OOMPolicy); DEFINE_STRING_TABLE_LOOKUP(oom_policy, OOMPolicy);

View File

@ -329,6 +329,9 @@ struct Manager {
/* Have we already sent out the READY=1 notification? */ /* Have we already sent out the READY=1 notification? */
bool ready_sent; bool ready_sent;
/* Was the last status sent "STATUS=Ready."? */
bool status_ready;
/* Have we already printed the taint line if necessary? */ /* Have we already printed the taint line if necessary? */
bool taint_logged; bool taint_logged;
@ -500,12 +503,9 @@ int manager_set_default_rlimits(Manager *m, struct rlimit **default_rlimit);
int manager_loop(Manager *m); int manager_loop(Manager *m);
int manager_open_serialization(Manager *m, FILE **_f);
int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root);
int manager_deserialize(Manager *m, FILE *f, FDSet *fds);
int manager_reload(Manager *m); int manager_reload(Manager *m);
Manager* manager_reloading_start(Manager *m);
void manager_reloading_stopp(Manager **m);
void manager_reset_failed(Manager *m); void manager_reset_failed(Manager *m);

View File

@ -87,6 +87,8 @@ libcore_sources = '''
locale-setup.h locale-setup.h
manager-dump.c manager-dump.c
manager-dump.h manager-dump.h
manager-serialize.c
manager-serialize.h
manager.c manager.c
manager.h manager.h
mount.c mount.c

View File

@ -2139,7 +2139,7 @@ static int mount_can_clean(Unit *u, ExecCleanMask *ret) {
} }
static const char* const mount_exec_command_table[_MOUNT_EXEC_COMMAND_MAX] = { static const char* const mount_exec_command_table[_MOUNT_EXEC_COMMAND_MAX] = {
[MOUNT_EXEC_MOUNT] = "ExecMount", [MOUNT_EXEC_MOUNT] = "ExecMount",
[MOUNT_EXEC_UNMOUNT] = "ExecUnmount", [MOUNT_EXEC_UNMOUNT] = "ExecUnmount",
[MOUNT_EXEC_REMOUNT] = "ExecRemount", [MOUNT_EXEC_REMOUNT] = "ExecRemount",
}; };
@ -2147,14 +2147,14 @@ static const char* const mount_exec_command_table[_MOUNT_EXEC_COMMAND_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(mount_exec_command, MountExecCommand); DEFINE_STRING_TABLE_LOOKUP(mount_exec_command, MountExecCommand);
static const char* const mount_result_table[_MOUNT_RESULT_MAX] = { static const char* const mount_result_table[_MOUNT_RESULT_MAX] = {
[MOUNT_SUCCESS] = "success", [MOUNT_SUCCESS] = "success",
[MOUNT_FAILURE_RESOURCES] = "resources", [MOUNT_FAILURE_RESOURCES] = "resources",
[MOUNT_FAILURE_TIMEOUT] = "timeout", [MOUNT_FAILURE_TIMEOUT] = "timeout",
[MOUNT_FAILURE_EXIT_CODE] = "exit-code", [MOUNT_FAILURE_EXIT_CODE] = "exit-code",
[MOUNT_FAILURE_SIGNAL] = "signal", [MOUNT_FAILURE_SIGNAL] = "signal",
[MOUNT_FAILURE_CORE_DUMP] = "core-dump", [MOUNT_FAILURE_CORE_DUMP] = "core-dump",
[MOUNT_FAILURE_START_LIMIT_HIT] = "start-limit-hit", [MOUNT_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
[MOUNT_FAILURE_PROTOCOL] = "protocol", [MOUNT_FAILURE_PROTOCOL] = "protocol",
}; };
DEFINE_STRING_TABLE_LOOKUP(mount_result, MountResult); DEFINE_STRING_TABLE_LOOKUP(mount_result, MountResult);

View File

@ -813,19 +813,19 @@ static void path_reset_failed(Unit *u) {
} }
static const char* const path_type_table[_PATH_TYPE_MAX] = { static const char* const path_type_table[_PATH_TYPE_MAX] = {
[PATH_EXISTS] = "PathExists", [PATH_EXISTS] = "PathExists",
[PATH_EXISTS_GLOB] = "PathExistsGlob", [PATH_EXISTS_GLOB] = "PathExistsGlob",
[PATH_DIRECTORY_NOT_EMPTY] = "DirectoryNotEmpty", [PATH_DIRECTORY_NOT_EMPTY] = "DirectoryNotEmpty",
[PATH_CHANGED] = "PathChanged", [PATH_CHANGED] = "PathChanged",
[PATH_MODIFIED] = "PathModified", [PATH_MODIFIED] = "PathModified",
}; };
DEFINE_STRING_TABLE_LOOKUP(path_type, PathType); DEFINE_STRING_TABLE_LOOKUP(path_type, PathType);
static const char* const path_result_table[_PATH_RESULT_MAX] = { static const char* const path_result_table[_PATH_RESULT_MAX] = {
[PATH_SUCCESS] = "success", [PATH_SUCCESS] = "success",
[PATH_FAILURE_RESOURCES] = "resources", [PATH_FAILURE_RESOURCES] = "resources",
[PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit", [PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
[PATH_FAILURE_UNIT_START_LIMIT_HIT] = "unit-start-limit-hit", [PATH_FAILURE_UNIT_START_LIMIT_HIT] = "unit-start-limit-hit",
}; };

View File

@ -632,9 +632,9 @@ static void scope_enumerate_perpetual(Manager *m) {
} }
static const char* const scope_result_table[_SCOPE_RESULT_MAX] = { static const char* const scope_result_table[_SCOPE_RESULT_MAX] = {
[SCOPE_SUCCESS] = "success", [SCOPE_SUCCESS] = "success",
[SCOPE_FAILURE_RESOURCES] = "resources", [SCOPE_FAILURE_RESOURCES] = "resources",
[SCOPE_FAILURE_TIMEOUT] = "timeout", [SCOPE_FAILURE_TIMEOUT] = "timeout",
}; };
DEFINE_STRING_TABLE_LOOKUP(scope_result, ScopeResult); DEFINE_STRING_TABLE_LOOKUP(scope_result, ScopeResult);

View File

@ -4379,6 +4379,14 @@ static int service_exit_status(Unit *u) {
return s->main_exec_status.status; return s->main_exec_status.status;
} }
static const char* service_status_text(Unit *u) {
Service *s = SERVICE(u);
assert(s);
return s->status_text;
}
static int service_clean(Unit *u, ExecCleanMask mask) { static int service_clean(Unit *u, ExecCleanMask mask) {
_cleanup_strv_free_ char **l = NULL; _cleanup_strv_free_ char **l = NULL;
Service *s = SERVICE(u); Service *s = SERVICE(u);
@ -4440,82 +4448,82 @@ static const char *service_finished_job(Unit *u, JobType t, JobResult result) {
} }
static const char* const service_restart_table[_SERVICE_RESTART_MAX] = { static const char* const service_restart_table[_SERVICE_RESTART_MAX] = {
[SERVICE_RESTART_NO] = "no", [SERVICE_RESTART_NO] = "no",
[SERVICE_RESTART_ON_SUCCESS] = "on-success", [SERVICE_RESTART_ON_SUCCESS] = "on-success",
[SERVICE_RESTART_ON_FAILURE] = "on-failure", [SERVICE_RESTART_ON_FAILURE] = "on-failure",
[SERVICE_RESTART_ON_ABNORMAL] = "on-abnormal", [SERVICE_RESTART_ON_ABNORMAL] = "on-abnormal",
[SERVICE_RESTART_ON_WATCHDOG] = "on-watchdog", [SERVICE_RESTART_ON_WATCHDOG] = "on-watchdog",
[SERVICE_RESTART_ON_ABORT] = "on-abort", [SERVICE_RESTART_ON_ABORT] = "on-abort",
[SERVICE_RESTART_ALWAYS] = "always", [SERVICE_RESTART_ALWAYS] = "always",
}; };
DEFINE_STRING_TABLE_LOOKUP(service_restart, ServiceRestart); DEFINE_STRING_TABLE_LOOKUP(service_restart, ServiceRestart);
static const char* const service_type_table[_SERVICE_TYPE_MAX] = { static const char* const service_type_table[_SERVICE_TYPE_MAX] = {
[SERVICE_SIMPLE] = "simple", [SERVICE_SIMPLE] = "simple",
[SERVICE_FORKING] = "forking", [SERVICE_FORKING] = "forking",
[SERVICE_ONESHOT] = "oneshot", [SERVICE_ONESHOT] = "oneshot",
[SERVICE_DBUS] = "dbus", [SERVICE_DBUS] = "dbus",
[SERVICE_NOTIFY] = "notify", [SERVICE_NOTIFY] = "notify",
[SERVICE_IDLE] = "idle", [SERVICE_IDLE] = "idle",
[SERVICE_EXEC] = "exec", [SERVICE_EXEC] = "exec",
}; };
DEFINE_STRING_TABLE_LOOKUP(service_type, ServiceType); DEFINE_STRING_TABLE_LOOKUP(service_type, ServiceType);
static const char* const service_exec_command_table[_SERVICE_EXEC_COMMAND_MAX] = { static const char* const service_exec_command_table[_SERVICE_EXEC_COMMAND_MAX] = {
[SERVICE_EXEC_CONDITION] = "ExecCondition", [SERVICE_EXEC_CONDITION] = "ExecCondition",
[SERVICE_EXEC_START_PRE] = "ExecStartPre", [SERVICE_EXEC_START_PRE] = "ExecStartPre",
[SERVICE_EXEC_START] = "ExecStart", [SERVICE_EXEC_START] = "ExecStart",
[SERVICE_EXEC_START_POST] = "ExecStartPost", [SERVICE_EXEC_START_POST] = "ExecStartPost",
[SERVICE_EXEC_RELOAD] = "ExecReload", [SERVICE_EXEC_RELOAD] = "ExecReload",
[SERVICE_EXEC_STOP] = "ExecStop", [SERVICE_EXEC_STOP] = "ExecStop",
[SERVICE_EXEC_STOP_POST] = "ExecStopPost", [SERVICE_EXEC_STOP_POST] = "ExecStopPost",
}; };
DEFINE_STRING_TABLE_LOOKUP(service_exec_command, ServiceExecCommand); DEFINE_STRING_TABLE_LOOKUP(service_exec_command, ServiceExecCommand);
static const char* const service_exec_ex_command_table[_SERVICE_EXEC_COMMAND_MAX] = { static const char* const service_exec_ex_command_table[_SERVICE_EXEC_COMMAND_MAX] = {
[SERVICE_EXEC_CONDITION] = "ExecConditionEx", [SERVICE_EXEC_CONDITION] = "ExecConditionEx",
[SERVICE_EXEC_START_PRE] = "ExecStartPreEx", [SERVICE_EXEC_START_PRE] = "ExecStartPreEx",
[SERVICE_EXEC_START] = "ExecStartEx", [SERVICE_EXEC_START] = "ExecStartEx",
[SERVICE_EXEC_START_POST] = "ExecStartPostEx", [SERVICE_EXEC_START_POST] = "ExecStartPostEx",
[SERVICE_EXEC_RELOAD] = "ExecReloadEx", [SERVICE_EXEC_RELOAD] = "ExecReloadEx",
[SERVICE_EXEC_STOP] = "ExecStopEx", [SERVICE_EXEC_STOP] = "ExecStopEx",
[SERVICE_EXEC_STOP_POST] = "ExecStopPostEx", [SERVICE_EXEC_STOP_POST] = "ExecStopPostEx",
}; };
DEFINE_STRING_TABLE_LOOKUP(service_exec_ex_command, ServiceExecCommand); DEFINE_STRING_TABLE_LOOKUP(service_exec_ex_command, ServiceExecCommand);
static const char* const notify_state_table[_NOTIFY_STATE_MAX] = { static const char* const notify_state_table[_NOTIFY_STATE_MAX] = {
[NOTIFY_UNKNOWN] = "unknown", [NOTIFY_UNKNOWN] = "unknown",
[NOTIFY_READY] = "ready", [NOTIFY_READY] = "ready",
[NOTIFY_RELOADING] = "reloading", [NOTIFY_RELOADING] = "reloading",
[NOTIFY_STOPPING] = "stopping", [NOTIFY_STOPPING] = "stopping",
}; };
DEFINE_STRING_TABLE_LOOKUP(notify_state, NotifyState); DEFINE_STRING_TABLE_LOOKUP(notify_state, NotifyState);
static const char* const service_result_table[_SERVICE_RESULT_MAX] = { static const char* const service_result_table[_SERVICE_RESULT_MAX] = {
[SERVICE_SUCCESS] = "success", [SERVICE_SUCCESS] = "success",
[SERVICE_FAILURE_RESOURCES] = "resources", [SERVICE_FAILURE_RESOURCES] = "resources",
[SERVICE_FAILURE_PROTOCOL] = "protocol", [SERVICE_FAILURE_PROTOCOL] = "protocol",
[SERVICE_FAILURE_TIMEOUT] = "timeout", [SERVICE_FAILURE_TIMEOUT] = "timeout",
[SERVICE_FAILURE_EXIT_CODE] = "exit-code", [SERVICE_FAILURE_EXIT_CODE] = "exit-code",
[SERVICE_FAILURE_SIGNAL] = "signal", [SERVICE_FAILURE_SIGNAL] = "signal",
[SERVICE_FAILURE_CORE_DUMP] = "core-dump", [SERVICE_FAILURE_CORE_DUMP] = "core-dump",
[SERVICE_FAILURE_WATCHDOG] = "watchdog", [SERVICE_FAILURE_WATCHDOG] = "watchdog",
[SERVICE_FAILURE_START_LIMIT_HIT] = "start-limit-hit", [SERVICE_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
[SERVICE_FAILURE_OOM_KILL] = "oom-kill", [SERVICE_FAILURE_OOM_KILL] = "oom-kill",
[SERVICE_SKIP_CONDITION] = "exec-condition", [SERVICE_SKIP_CONDITION] = "exec-condition",
}; };
DEFINE_STRING_TABLE_LOOKUP(service_result, ServiceResult); DEFINE_STRING_TABLE_LOOKUP(service_result, ServiceResult);
static const char* const service_timeout_failure_mode_table[_SERVICE_TIMEOUT_FAILURE_MODE_MAX] = { static const char* const service_timeout_failure_mode_table[_SERVICE_TIMEOUT_FAILURE_MODE_MAX] = {
[SERVICE_TIMEOUT_TERMINATE] = "terminate", [SERVICE_TIMEOUT_TERMINATE] = "terminate",
[SERVICE_TIMEOUT_ABORT] = "abort", [SERVICE_TIMEOUT_ABORT] = "abort",
[SERVICE_TIMEOUT_KILL] = "kill", [SERVICE_TIMEOUT_KILL] = "kill",
}; };
DEFINE_STRING_TABLE_LOOKUP(service_timeout_failure_mode, ServiceTimeoutFailureMode); DEFINE_STRING_TABLE_LOOKUP(service_timeout_failure_mode, ServiceTimeoutFailureMode);
@ -4590,6 +4598,7 @@ const UnitVTable service_vtable = {
.get_timeout = service_get_timeout, .get_timeout = service_get_timeout,
.needs_console = service_needs_console, .needs_console = service_needs_console,
.exit_status = service_exit_status, .exit_status = service_exit_status,
.status_text = service_status_text,
.status_message_formats = { .status_message_formats = {
.finished_start_job = { .finished_start_job = {

View File

@ -3425,24 +3425,24 @@ static int socket_can_clean(Unit *u, ExecCleanMask *ret) {
} }
static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = { static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = {
[SOCKET_EXEC_START_PRE] = "ExecStartPre", [SOCKET_EXEC_START_PRE] = "ExecStartPre",
[SOCKET_EXEC_START_CHOWN] = "ExecStartChown", [SOCKET_EXEC_START_CHOWN] = "ExecStartChown",
[SOCKET_EXEC_START_POST] = "ExecStartPost", [SOCKET_EXEC_START_POST] = "ExecStartPost",
[SOCKET_EXEC_STOP_PRE] = "ExecStopPre", [SOCKET_EXEC_STOP_PRE] = "ExecStopPre",
[SOCKET_EXEC_STOP_POST] = "ExecStopPost" [SOCKET_EXEC_STOP_POST] = "ExecStopPost"
}; };
DEFINE_STRING_TABLE_LOOKUP(socket_exec_command, SocketExecCommand); DEFINE_STRING_TABLE_LOOKUP(socket_exec_command, SocketExecCommand);
static const char* const socket_result_table[_SOCKET_RESULT_MAX] = { static const char* const socket_result_table[_SOCKET_RESULT_MAX] = {
[SOCKET_SUCCESS] = "success", [SOCKET_SUCCESS] = "success",
[SOCKET_FAILURE_RESOURCES] = "resources", [SOCKET_FAILURE_RESOURCES] = "resources",
[SOCKET_FAILURE_TIMEOUT] = "timeout", [SOCKET_FAILURE_TIMEOUT] = "timeout",
[SOCKET_FAILURE_EXIT_CODE] = "exit-code", [SOCKET_FAILURE_EXIT_CODE] = "exit-code",
[SOCKET_FAILURE_SIGNAL] = "signal", [SOCKET_FAILURE_SIGNAL] = "signal",
[SOCKET_FAILURE_CORE_DUMP] = "core-dump", [SOCKET_FAILURE_CORE_DUMP] = "core-dump",
[SOCKET_FAILURE_START_LIMIT_HIT] = "start-limit-hit", [SOCKET_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
[SOCKET_FAILURE_TRIGGER_LIMIT_HIT] = "trigger-limit-hit", [SOCKET_FAILURE_TRIGGER_LIMIT_HIT] = "trigger-limit-hit",
[SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit" [SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit"
}; };
@ -3450,8 +3450,8 @@ DEFINE_STRING_TABLE_LOOKUP(socket_result, SocketResult);
static const char* const socket_timestamping_table[_SOCKET_TIMESTAMPING_MAX] = { static const char* const socket_timestamping_table[_SOCKET_TIMESTAMPING_MAX] = {
[SOCKET_TIMESTAMPING_OFF] = "off", [SOCKET_TIMESTAMPING_OFF] = "off",
[SOCKET_TIMESTAMPING_US] = "us", [SOCKET_TIMESTAMPING_US] = "us",
[SOCKET_TIMESTAMPING_NS] = "ns", [SOCKET_TIMESTAMPING_NS] = "ns",
}; };
DEFINE_STRING_TABLE_LOOKUP(socket_timestamping, SocketTimestamping); DEFINE_STRING_TABLE_LOOKUP(socket_timestamping, SocketTimestamping);

View File

@ -1589,19 +1589,19 @@ static int swap_can_clean(Unit *u, ExecCleanMask *ret) {
} }
static const char* const swap_exec_command_table[_SWAP_EXEC_COMMAND_MAX] = { static const char* const swap_exec_command_table[_SWAP_EXEC_COMMAND_MAX] = {
[SWAP_EXEC_ACTIVATE] = "ExecActivate", [SWAP_EXEC_ACTIVATE] = "ExecActivate",
[SWAP_EXEC_DEACTIVATE] = "ExecDeactivate", [SWAP_EXEC_DEACTIVATE] = "ExecDeactivate",
}; };
DEFINE_STRING_TABLE_LOOKUP(swap_exec_command, SwapExecCommand); DEFINE_STRING_TABLE_LOOKUP(swap_exec_command, SwapExecCommand);
static const char* const swap_result_table[_SWAP_RESULT_MAX] = { static const char* const swap_result_table[_SWAP_RESULT_MAX] = {
[SWAP_SUCCESS] = "success", [SWAP_SUCCESS] = "success",
[SWAP_FAILURE_RESOURCES] = "resources", [SWAP_FAILURE_RESOURCES] = "resources",
[SWAP_FAILURE_TIMEOUT] = "timeout", [SWAP_FAILURE_TIMEOUT] = "timeout",
[SWAP_FAILURE_EXIT_CODE] = "exit-code", [SWAP_FAILURE_EXIT_CODE] = "exit-code",
[SWAP_FAILURE_SIGNAL] = "signal", [SWAP_FAILURE_SIGNAL] = "signal",
[SWAP_FAILURE_CORE_DUMP] = "core-dump", [SWAP_FAILURE_CORE_DUMP] = "core-dump",
[SWAP_FAILURE_START_LIMIT_HIT] = "start-limit-hit", [SWAP_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
}; };

View File

@ -891,19 +891,19 @@ static int timer_can_clean(Unit *u, ExecCleanMask *ret) {
} }
static const char* const timer_base_table[_TIMER_BASE_MAX] = { static const char* const timer_base_table[_TIMER_BASE_MAX] = {
[TIMER_ACTIVE] = "OnActiveSec", [TIMER_ACTIVE] = "OnActiveSec",
[TIMER_BOOT] = "OnBootSec", [TIMER_BOOT] = "OnBootSec",
[TIMER_STARTUP] = "OnStartupSec", [TIMER_STARTUP] = "OnStartupSec",
[TIMER_UNIT_ACTIVE] = "OnUnitActiveSec", [TIMER_UNIT_ACTIVE] = "OnUnitActiveSec",
[TIMER_UNIT_INACTIVE] = "OnUnitInactiveSec", [TIMER_UNIT_INACTIVE] = "OnUnitInactiveSec",
[TIMER_CALENDAR] = "OnCalendar" [TIMER_CALENDAR] = "OnCalendar"
}; };
DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase); DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase);
static const char* const timer_result_table[_TIMER_RESULT_MAX] = { static const char* const timer_result_table[_TIMER_RESULT_MAX] = {
[TIMER_SUCCESS] = "success", [TIMER_SUCCESS] = "success",
[TIMER_FAILURE_RESOURCES] = "resources", [TIMER_FAILURE_RESOURCES] = "resources",
[TIMER_FAILURE_START_LIMIT_HIT] = "start-limit-hit", [TIMER_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
}; };

View File

@ -631,6 +631,9 @@ typedef struct UnitVTable {
* exit code of the "main" process of the service or similar. */ * exit code of the "main" process of the service or similar. */
int (*exit_status)(Unit *u); int (*exit_status)(Unit *u);
/* Return a copy of the status string pointer. */
const char* (*status_text)(Unit *u);
/* Like the enumerate() callback further down, but only enumerates the perpetual units, i.e. all units that /* Like the enumerate() callback further down, but only enumerates the perpetual units, i.e. all units that
* unconditionally exist and are always active. The main reason to keep both enumeration functions separate is * unconditionally exist and are always active. The main reason to keep both enumeration functions separate is
* philosophical: the state of perpetual units should be put in place by coldplug(), while the state of those * philosophical: the state of perpetual units should be put in place by coldplug(), while the state of those
@ -744,6 +747,12 @@ static inline bool unit_is_extrinsic(Unit *u) {
(UNIT_VTABLE(u)->is_extrinsic && UNIT_VTABLE(u)->is_extrinsic(u)); (UNIT_VTABLE(u)->is_extrinsic && UNIT_VTABLE(u)->is_extrinsic(u));
} }
static inline const char* unit_status_text(Unit *u) {
if (u && UNIT_VTABLE(u)->status_text)
return UNIT_VTABLE(u)->status_text(u);
return NULL;
}
void unit_add_to_load_queue(Unit *u); void unit_add_to_load_queue(Unit *u);
void unit_add_to_dbus_queue(Unit *u); void unit_add_to_dbus_queue(Unit *u);
void unit_add_to_cleanup_queue(Unit *u); void unit_add_to_cleanup_queue(Unit *u);

View File

@ -5,59 +5,63 @@
#include "utf8.h" #include "utf8.h"
const GptPartitionType gpt_partition_type_table[] = { const GptPartitionType gpt_partition_type_table[] = {
{ GPT_ROOT_X86, "root-x86" }, { GPT_ROOT_X86, "root-x86" },
{ GPT_ROOT_X86_VERITY, "root-x86-verity" }, { GPT_ROOT_X86_VERITY, "root-x86-verity" },
{ GPT_ROOT_X86_64, "root-x86-64" }, { GPT_ROOT_X86_64, "root-x86-64" },
{ GPT_ROOT_X86_64_VERITY, "root-x86-64-verity" }, { GPT_ROOT_X86_64_VERITY, "root-x86-64-verity" },
{ GPT_ROOT_ARM, "root-arm" }, { GPT_ROOT_ARM, "root-arm" },
{ GPT_ROOT_ARM_VERITY, "root-arm-verity" }, { GPT_ROOT_ARM_VERITY, "root-arm-verity" },
{ GPT_ROOT_ARM_64, "root-arm64" }, { GPT_ROOT_ARM_64, "root-arm64" },
{ GPT_ROOT_ARM_64_VERITY, "root-arm64-verity" }, { GPT_ROOT_ARM_64_VERITY, "root-arm64-verity" },
{ GPT_ROOT_IA64, "root-ia64" }, { GPT_ROOT_IA64, "root-ia64" },
{ GPT_ROOT_IA64_VERITY, "root-ia64-verity" }, { GPT_ROOT_IA64_VERITY, "root-ia64-verity" },
{ GPT_ROOT_RISCV32, "root-riscv32" }, { GPT_ROOT_LOONGARCH64, "root-loongarch64" },
{ GPT_ROOT_RISCV32_VERITY, "root-riscv32-verity" }, { GPT_ROOT_LOONGARCH64_VERITY, "root-loongarch64-verity" },
{ GPT_ROOT_RISCV64, "root-riscv64" }, { GPT_ROOT_RISCV32, "root-riscv32" },
{ GPT_ROOT_RISCV64_VERITY, "root-riscv64-verity" }, { GPT_ROOT_RISCV32_VERITY, "root-riscv32-verity" },
{ GPT_ROOT_RISCV64, "root-riscv64" },
{ GPT_ROOT_RISCV64_VERITY, "root-riscv64-verity" },
#ifdef GPT_ROOT_NATIVE #ifdef GPT_ROOT_NATIVE
{ GPT_ROOT_NATIVE, "root" }, { GPT_ROOT_NATIVE, "root" },
{ GPT_ROOT_NATIVE_VERITY, "root-verity" }, { GPT_ROOT_NATIVE_VERITY, "root-verity" },
#endif #endif
#ifdef GPT_ROOT_SECONDARY #ifdef GPT_ROOT_SECONDARY
{ GPT_ROOT_SECONDARY, "root-secondary" }, { GPT_ROOT_SECONDARY, "root-secondary" },
{ GPT_ROOT_SECONDARY_VERITY, "root-secondary-verity" }, { GPT_ROOT_SECONDARY_VERITY, "root-secondary-verity" },
#endif #endif
{ GPT_USR_X86, "usr-x86" }, { GPT_USR_X86, "usr-x86" },
{ GPT_USR_X86_VERITY, "usr-x86-verity" }, { GPT_USR_X86_VERITY, "usr-x86-verity" },
{ GPT_USR_X86_64, "usr-x86-64" }, { GPT_USR_X86_64, "usr-x86-64" },
{ GPT_USR_X86_64_VERITY, "usr-x86-64-verity" }, { GPT_USR_X86_64_VERITY, "usr-x86-64-verity" },
{ GPT_USR_ARM, "usr-arm" }, { GPT_USR_ARM, "usr-arm" },
{ GPT_USR_ARM_VERITY, "usr-arm-verity" }, { GPT_USR_ARM_VERITY, "usr-arm-verity" },
{ GPT_USR_ARM_64, "usr-arm64" }, { GPT_USR_ARM_64, "usr-arm64" },
{ GPT_USR_ARM_64_VERITY, "usr-arm64-verity" }, { GPT_USR_ARM_64_VERITY, "usr-arm64-verity" },
{ GPT_USR_IA64, "usr-ia64" }, { GPT_USR_IA64, "usr-ia64" },
{ GPT_USR_IA64_VERITY, "usr-ia64-verity" }, { GPT_USR_IA64_VERITY, "usr-ia64-verity" },
{ GPT_USR_RISCV32, "usr-riscv32" }, { GPT_USR_LOONGARCH64, "usr-loongarch64" },
{ GPT_USR_RISCV32_VERITY, "usr-riscv32-verity" }, { GPT_USR_LOONGARCH64_VERITY, "usr-loongarch64-verity" },
{ GPT_USR_RISCV64, "usr-riscv64" }, { GPT_USR_RISCV32, "usr-riscv32" },
{ GPT_USR_RISCV64_VERITY, "usr-riscv64-verity" }, { GPT_USR_RISCV32_VERITY, "usr-riscv32-verity" },
{ GPT_USR_RISCV64, "usr-riscv64" },
{ GPT_USR_RISCV64_VERITY, "usr-riscv64-verity" },
#ifdef GPT_USR_NATIVE #ifdef GPT_USR_NATIVE
{ GPT_USR_NATIVE, "usr" }, { GPT_USR_NATIVE, "usr" },
{ GPT_USR_NATIVE_VERITY, "usr-verity" }, { GPT_USR_NATIVE_VERITY, "usr-verity" },
#endif #endif
#ifdef GPT_USR_SECONDARY #ifdef GPT_USR_SECONDARY
{ GPT_USR_SECONDARY, "usr-secondary" }, { GPT_USR_SECONDARY, "usr-secondary" },
{ GPT_USR_SECONDARY_VERITY, "usr-secondary-verity" }, { GPT_USR_SECONDARY_VERITY, "usr-secondary-verity" },
#endif #endif
{ GPT_ESP, "esp" }, { GPT_ESP, "esp" },
{ GPT_XBOOTLDR, "xbootldr" }, { GPT_XBOOTLDR, "xbootldr" },
{ GPT_SWAP, "swap" }, { GPT_SWAP, "swap" },
{ GPT_HOME, "home" }, { GPT_HOME, "home" },
{ GPT_SRV, "srv" }, { GPT_SRV, "srv" },
{ GPT_VAR, "var" }, { GPT_VAR, "var" },
{ GPT_TMP, "tmp" }, { GPT_TMP, "tmp" },
{ GPT_USER_HOME, "user-home" }, { GPT_USER_HOME, "user-home" },
{ GPT_LINUX_GENERIC, "linux-generic" }, { GPT_LINUX_GENERIC, "linux-generic" },
{} {}
}; };
@ -114,6 +118,7 @@ bool gpt_partition_type_is_root(sd_id128_t id) {
GPT_ROOT_ARM, GPT_ROOT_ARM,
GPT_ROOT_ARM_64, GPT_ROOT_ARM_64,
GPT_ROOT_IA64, GPT_ROOT_IA64,
GPT_ROOT_LOONGARCH64,
GPT_ROOT_RISCV32, GPT_ROOT_RISCV32,
GPT_ROOT_RISCV64); GPT_ROOT_RISCV64);
} }
@ -125,6 +130,7 @@ bool gpt_partition_type_is_root_verity(sd_id128_t id) {
GPT_ROOT_ARM_VERITY, GPT_ROOT_ARM_VERITY,
GPT_ROOT_ARM_64_VERITY, GPT_ROOT_ARM_64_VERITY,
GPT_ROOT_IA64_VERITY, GPT_ROOT_IA64_VERITY,
GPT_ROOT_LOONGARCH64_VERITY,
GPT_ROOT_RISCV32_VERITY, GPT_ROOT_RISCV32_VERITY,
GPT_ROOT_RISCV64_VERITY); GPT_ROOT_RISCV64_VERITY);
} }
@ -136,6 +142,7 @@ bool gpt_partition_type_is_usr(sd_id128_t id) {
GPT_USR_ARM, GPT_USR_ARM,
GPT_USR_ARM_64, GPT_USR_ARM_64,
GPT_USR_IA64, GPT_USR_IA64,
GPT_USR_LOONGARCH64,
GPT_USR_RISCV32, GPT_USR_RISCV32,
GPT_USR_RISCV64); GPT_USR_RISCV64);
} }
@ -147,6 +154,7 @@ bool gpt_partition_type_is_usr_verity(sd_id128_t id) {
GPT_USR_ARM_VERITY, GPT_USR_ARM_VERITY,
GPT_USR_ARM_64_VERITY, GPT_USR_ARM_64_VERITY,
GPT_USR_IA64_VERITY, GPT_USR_IA64_VERITY,
GPT_USR_LOONGARCH64_VERITY,
GPT_USR_RISCV32_VERITY, GPT_USR_RISCV32_VERITY,
GPT_USR_RISCV64_VERITY); GPT_USR_RISCV64_VERITY);
} }

View File

@ -7,49 +7,54 @@
#include "id128-util.h" #include "id128-util.h"
/* We only support root disk discovery for x86, x86-64, Itanium and ARM for now, since EFI for anything else /* We only support root disk discovery for x86, x86-64, Itanium, ARM and LoongArch for now,
* doesn't really exist, and we only care for root partitions on the same disk as the EFI ESP. */ * since EFI for anything else doesn't really exist, and we only care for root partitions
* on the same disk as the EFI ESP. */
#define GPT_ROOT_X86 SD_ID128_MAKE(44,47,95,40,f2,97,41,b2,9a,f7,d1,31,d5,f0,45,8a) #define GPT_ROOT_X86 SD_ID128_MAKE(44,47,95,40,f2,97,41,b2,9a,f7,d1,31,d5,f0,45,8a)
#define GPT_ROOT_X86_64 SD_ID128_MAKE(4f,68,bc,e3,e8,cd,4d,b1,96,e7,fb,ca,f9,84,b7,09) #define GPT_ROOT_X86_64 SD_ID128_MAKE(4f,68,bc,e3,e8,cd,4d,b1,96,e7,fb,ca,f9,84,b7,09)
#define GPT_ROOT_ARM SD_ID128_MAKE(69,da,d7,10,2c,e4,4e,3c,b1,6c,21,a1,d4,9a,be,d3) #define GPT_ROOT_ARM SD_ID128_MAKE(69,da,d7,10,2c,e4,4e,3c,b1,6c,21,a1,d4,9a,be,d3)
#define GPT_ROOT_ARM_64 SD_ID128_MAKE(b9,21,b0,45,1d,f0,41,c3,af,44,4c,6f,28,0d,3f,ae) #define GPT_ROOT_ARM_64 SD_ID128_MAKE(b9,21,b0,45,1d,f0,41,c3,af,44,4c,6f,28,0d,3f,ae)
#define GPT_ROOT_IA64 SD_ID128_MAKE(99,3d,8d,3d,f8,0e,42,25,85,5a,9d,af,8e,d7,ea,97) #define GPT_ROOT_IA64 SD_ID128_MAKE(99,3d,8d,3d,f8,0e,42,25,85,5a,9d,af,8e,d7,ea,97)
#define GPT_ROOT_RISCV32 SD_ID128_MAKE(60,d5,a7,fe,8e,7d,43,5c,b7,14,3d,d8,16,21,44,e1) #define GPT_ROOT_LOONGARCH64 SD_ID128_MAKE(77,05,58,00,79,2c,4f,94,b3,9a,99,c9,1b,76,2b,b6)
#define GPT_ROOT_RISCV64 SD_ID128_MAKE(72,ec,70,a6,cf,74,40,e6,bd,49,4b,da,08,e8,f2,24) #define GPT_ROOT_RISCV32 SD_ID128_MAKE(60,d5,a7,fe,8e,7d,43,5c,b7,14,3d,d8,16,21,44,e1)
#define GPT_USR_X86 SD_ID128_MAKE(75,25,0d,76,8c,c6,45,8e,bd,66,bd,47,cc,81,a8,12) #define GPT_ROOT_RISCV64 SD_ID128_MAKE(72,ec,70,a6,cf,74,40,e6,bd,49,4b,da,08,e8,f2,24)
#define GPT_USR_X86_64 SD_ID128_MAKE(84,84,68,0c,95,21,48,c6,9c,11,b0,72,06,56,f6,9e) #define GPT_USR_X86 SD_ID128_MAKE(75,25,0d,76,8c,c6,45,8e,bd,66,bd,47,cc,81,a8,12)
#define GPT_USR_ARM SD_ID128_MAKE(7d,03,59,a3,02,b3,4f,0a,86,5c,65,44,03,e7,06,25) #define GPT_USR_X86_64 SD_ID128_MAKE(84,84,68,0c,95,21,48,c6,9c,11,b0,72,06,56,f6,9e)
#define GPT_USR_ARM_64 SD_ID128_MAKE(b0,e0,10,50,ee,5f,43,90,94,9a,91,01,b1,71,04,e9) #define GPT_USR_ARM SD_ID128_MAKE(7d,03,59,a3,02,b3,4f,0a,86,5c,65,44,03,e7,06,25)
#define GPT_USR_IA64 SD_ID128_MAKE(43,01,d2,a6,4e,3b,4b,2a,bb,94,9e,0b,2c,42,25,ea) #define GPT_USR_ARM_64 SD_ID128_MAKE(b0,e0,10,50,ee,5f,43,90,94,9a,91,01,b1,71,04,e9)
#define GPT_USR_RISCV32 SD_ID128_MAKE(b9,33,fb,22,5c,3f,4f,91,af,90,e2,bb,0f,a5,07,02) #define GPT_USR_IA64 SD_ID128_MAKE(43,01,d2,a6,4e,3b,4b,2a,bb,94,9e,0b,2c,42,25,ea)
#define GPT_USR_RISCV64 SD_ID128_MAKE(be,ae,c3,4b,84,42,43,9b,a4,0b,98,43,81,ed,09,7d) #define GPT_USR_LOONGARCH64 SD_ID128_MAKE(e6,11,c7,02,57,5c,4c,be,9a,46,43,4f,a0,bf,7e,3f)
#define GPT_ESP SD_ID128_MAKE(c1,2a,73,28,f8,1f,11,d2,ba,4b,00,a0,c9,3e,c9,3b) #define GPT_USR_RISCV32 SD_ID128_MAKE(b9,33,fb,22,5c,3f,4f,91,af,90,e2,bb,0f,a5,07,02)
#define GPT_XBOOTLDR SD_ID128_MAKE(bc,13,c2,ff,59,e6,42,62,a3,52,b2,75,fd,6f,71,72) #define GPT_USR_RISCV64 SD_ID128_MAKE(be,ae,c3,4b,84,42,43,9b,a4,0b,98,43,81,ed,09,7d)
#define GPT_SWAP SD_ID128_MAKE(06,57,fd,6d,a4,ab,43,c4,84,e5,09,33,c8,4b,4f,4f) #define GPT_ESP SD_ID128_MAKE(c1,2a,73,28,f8,1f,11,d2,ba,4b,00,a0,c9,3e,c9,3b)
#define GPT_HOME SD_ID128_MAKE(93,3a,c7,e1,2e,b4,4f,13,b8,44,0e,14,e2,ae,f9,15) #define GPT_XBOOTLDR SD_ID128_MAKE(bc,13,c2,ff,59,e6,42,62,a3,52,b2,75,fd,6f,71,72)
#define GPT_SRV SD_ID128_MAKE(3b,8f,84,25,20,e0,4f,3b,90,7f,1a,25,a7,6f,98,e8) #define GPT_SWAP SD_ID128_MAKE(06,57,fd,6d,a4,ab,43,c4,84,e5,09,33,c8,4b,4f,4f)
#define GPT_VAR SD_ID128_MAKE(4d,21,b0,16,b5,34,45,c2,a9,fb,5c,16,e0,91,fd,2d) #define GPT_HOME SD_ID128_MAKE(93,3a,c7,e1,2e,b4,4f,13,b8,44,0e,14,e2,ae,f9,15)
#define GPT_TMP SD_ID128_MAKE(7e,c6,f5,57,3b,c5,4a,ca,b2,93,16,ef,5d,f6,39,d1) #define GPT_SRV SD_ID128_MAKE(3b,8f,84,25,20,e0,4f,3b,90,7f,1a,25,a7,6f,98,e8)
#define GPT_USER_HOME SD_ID128_MAKE(77,3f,91,ef,66,d4,49,b5,bd,83,d6,83,bf,40,ad,16) #define GPT_VAR SD_ID128_MAKE(4d,21,b0,16,b5,34,45,c2,a9,fb,5c,16,e0,91,fd,2d)
#define GPT_LINUX_GENERIC SD_ID128_MAKE(0f,c6,3d,af,84,83,47,72,8e,79,3d,69,d8,47,7d,e4) #define GPT_TMP SD_ID128_MAKE(7e,c6,f5,57,3b,c5,4a,ca,b2,93,16,ef,5d,f6,39,d1)
#define GPT_USER_HOME SD_ID128_MAKE(77,3f,91,ef,66,d4,49,b5,bd,83,d6,83,bf,40,ad,16)
#define GPT_LINUX_GENERIC SD_ID128_MAKE(0f,c6,3d,af,84,83,47,72,8e,79,3d,69,d8,47,7d,e4)
/* Verity partitions for the root partitions above (we only define them for the root and /usr partitions, /* Verity partitions for the root partitions above (we only define them for the root and /usr partitions,
* because only they are commonly read-only and hence suitable for verity). */ * because only they are commonly read-only and hence suitable for verity). */
#define GPT_ROOT_X86_VERITY SD_ID128_MAKE(d1,3c,5d,3b,b5,d1,42,2a,b2,9f,94,54,fd,c8,9d,76) #define GPT_ROOT_X86_VERITY SD_ID128_MAKE(d1,3c,5d,3b,b5,d1,42,2a,b2,9f,94,54,fd,c8,9d,76)
#define GPT_ROOT_X86_64_VERITY SD_ID128_MAKE(2c,73,57,ed,eb,d2,46,d9,ae,c1,23,d4,37,ec,2b,f5) #define GPT_ROOT_X86_64_VERITY SD_ID128_MAKE(2c,73,57,ed,eb,d2,46,d9,ae,c1,23,d4,37,ec,2b,f5)
#define GPT_ROOT_ARM_VERITY SD_ID128_MAKE(73,86,cd,f2,20,3c,47,a9,a4,98,f2,ec,ce,45,a2,d6) #define GPT_ROOT_ARM_VERITY SD_ID128_MAKE(73,86,cd,f2,20,3c,47,a9,a4,98,f2,ec,ce,45,a2,d6)
#define GPT_ROOT_ARM_64_VERITY SD_ID128_MAKE(df,33,00,ce,d6,9f,4c,92,97,8c,9b,fb,0f,38,d8,20) #define GPT_ROOT_ARM_64_VERITY SD_ID128_MAKE(df,33,00,ce,d6,9f,4c,92,97,8c,9b,fb,0f,38,d8,20)
#define GPT_ROOT_IA64_VERITY SD_ID128_MAKE(86,ed,10,d5,b6,07,45,bb,89,57,d3,50,f2,3d,05,71) #define GPT_ROOT_IA64_VERITY SD_ID128_MAKE(86,ed,10,d5,b6,07,45,bb,89,57,d3,50,f2,3d,05,71)
#define GPT_ROOT_RISCV32_VERITY SD_ID128_MAKE(ae,02,53,be,11,67,40,07,ac,68,43,92,6c,14,c5,de) #define GPT_ROOT_LOONGARCH64_VERITY SD_ID128_MAKE(f3,39,3b,22,e9,af,46,13,a9,48,9d,3b,fb,d0,c5,35)
#define GPT_ROOT_RISCV64_VERITY SD_ID128_MAKE(b6,ed,55,82,44,0b,42,09,b8,da,5f,f7,c4,19,ea,3d) #define GPT_ROOT_RISCV32_VERITY SD_ID128_MAKE(ae,02,53,be,11,67,40,07,ac,68,43,92,6c,14,c5,de)
#define GPT_USR_X86_VERITY SD_ID128_MAKE(8f,46,1b,0d,14,ee,4e,81,9a,a9,04,9b,6f,b9,7a,bd) #define GPT_ROOT_RISCV64_VERITY SD_ID128_MAKE(b6,ed,55,82,44,0b,42,09,b8,da,5f,f7,c4,19,ea,3d)
#define GPT_USR_X86_64_VERITY SD_ID128_MAKE(77,ff,5f,63,e7,b6,46,33,ac,f4,15,65,b8,64,c0,e6) #define GPT_USR_X86_VERITY SD_ID128_MAKE(8f,46,1b,0d,14,ee,4e,81,9a,a9,04,9b,6f,b9,7a,bd)
#define GPT_USR_ARM_VERITY SD_ID128_MAKE(c2,15,d7,51,7b,cd,46,49,be,90,66,27,49,0a,4c,05) #define GPT_USR_X86_64_VERITY SD_ID128_MAKE(77,ff,5f,63,e7,b6,46,33,ac,f4,15,65,b8,64,c0,e6)
#define GPT_USR_ARM_64_VERITY SD_ID128_MAKE(6e,11,a4,e7,fb,ca,4d,ed,b9,e9,e1,a5,12,bb,66,4e) #define GPT_USR_ARM_VERITY SD_ID128_MAKE(c2,15,d7,51,7b,cd,46,49,be,90,66,27,49,0a,4c,05)
#define GPT_USR_IA64_VERITY SD_ID128_MAKE(6a,49,1e,03,3b,e7,45,45,8e,38,83,32,0e,0e,a8,80) #define GPT_USR_ARM_64_VERITY SD_ID128_MAKE(6e,11,a4,e7,fb,ca,4d,ed,b9,e9,e1,a5,12,bb,66,4e)
#define GPT_USR_RISCV32_VERITY SD_ID128_MAKE(cb,1e,e4,e3,8c,d0,41,36,a0,a4,aa,61,a3,2e,87,30) #define GPT_USR_IA64_VERITY SD_ID128_MAKE(6a,49,1e,03,3b,e7,45,45,8e,38,83,32,0e,0e,a8,80)
#define GPT_USR_RISCV64_VERITY SD_ID128_MAKE(8f,10,56,be,9b,05,47,c4,81,d6,be,53,12,8e,5b,54) #define GPT_USR_LOONGARCH64_VERITY SD_ID128_MAKE(f4,6b,2c,26,59,ae,48,f0,91,06,c5,0e,d4,7f,67,3d)
#define GPT_USR_RISCV32_VERITY SD_ID128_MAKE(cb,1e,e4,e3,8c,d0,41,36,a0,a4,aa,61,a3,2e,87,30)
#define GPT_USR_RISCV64_VERITY SD_ID128_MAKE(8f,10,56,be,9b,05,47,c4,81,d6,be,53,12,8e,5b,54)
#if defined(__x86_64__) #if defined(__x86_64__)
# define GPT_ROOT_NATIVE GPT_ROOT_X86_64 # define GPT_ROOT_NATIVE GPT_ROOT_X86_64
@ -90,6 +95,13 @@
# define GPT_USR_NATIVE_VERITY GPT_USR_ARM_VERITY # define GPT_USR_NATIVE_VERITY GPT_USR_ARM_VERITY
#endif #endif
#if defined(__loongarch64)
# define GPT_ROOT_NATIVE GPT_ROOT_LOONGARCH64
# define GPT_ROOT_NATIVE_VERITY GPT_ROOT_LOONGARCH64_VERITY
# define GPT_USR_NATIVE GPT_USR_LOONGARCH64
# define GPT_USR_NATIVE_VERITY GPT_USR_LOONGARCH64_VERITY
#endif
#if defined(__riscv) #if defined(__riscv)
#if (__riscv_xlen == 32) #if (__riscv_xlen == 32)
# define GPT_ROOT_NATIVE GPT_ROOT_RISCV32 # define GPT_ROOT_NATIVE GPT_ROOT_RISCV32

View File

@ -75,6 +75,9 @@ struct sd_bus_vtable {
uint64_t features; uint64_t features;
const unsigned *vtable_format_reference; const unsigned *vtable_format_reference;
} start; } start;
struct {
size_t reserved;
} end;
struct { struct {
const char *member; const char *member;
const char *signature; const char *signature;
@ -185,7 +188,11 @@ struct sd_bus_vtable {
{ \ { \
.type = _SD_BUS_VTABLE_END, \ .type = _SD_BUS_VTABLE_END, \
.flags = 0, \ .flags = 0, \
.x = { { 0 } }, \ .x = { \
.end = { \
.reserved = 0, \
}, \
}, \
} }
#define _SD_ECHO(X) X #define _SD_ECHO(X) X