mirror of
https://github.com/systemd/systemd
synced 2026-03-17 18:44:46 +01:00
Compare commits
14 Commits
51df483846
...
5f94ac5435
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5f94ac5435 | ||
|
|
2ecce1f1a8 | ||
|
|
d0fd114929 | ||
|
|
92ca7e052d | ||
|
|
f973aea740 | ||
|
|
e82c6e8b62 | ||
|
|
6aeb8c89ba | ||
|
|
4d94c74fae | ||
|
|
68695ce4d6 | ||
|
|
9951c8df1e | ||
|
|
ad172d19d5 | ||
|
|
c8ad151a58 | ||
|
|
e41db484c3 | ||
|
|
75a50eb0dd |
366
NEWS
366
NEWS
@ -1,5 +1,371 @@
|
|||||||
systemd System and Service Manager
|
systemd System and Service Manager
|
||||||
|
|
||||||
|
CHANGES WITH 249 in spe:
|
||||||
|
|
||||||
|
* When operating on disk images via the --image= switch of various
|
||||||
|
tools (such as systemd-nspawn or systemd-dissect), and multiple
|
||||||
|
suitable root or /usr/ partitions exist in the image, then a simple
|
||||||
|
strverscmp() inspired comparison is done on the GPT partition label,
|
||||||
|
and the newest partition picked. This permits a simple and generic
|
||||||
|
whole-file-system A/B update logic where new operating system
|
||||||
|
versions are dropped into partitions whose label is then updated with
|
||||||
|
a matching version identifier.
|
||||||
|
|
||||||
|
* systemd-sysusers now supports querying the passwords to set for the
|
||||||
|
users it creates via the "credentials" logic introduced in v247: the
|
||||||
|
passwd.hashed-password.<user> and passwd.plaintext-password.<user>
|
||||||
|
credentials are consulted for the password to use (either in UNIX
|
||||||
|
hashed form, or literally). By default these credentials are inherited
|
||||||
|
down from PID1 (which in turn imports it from a container manager if
|
||||||
|
there is one). This permits easy configuration of user passwords
|
||||||
|
during first boot. Example:
|
||||||
|
|
||||||
|
# systemd-nspawn -i foo.raw --volatile=yes --set-credential=passwd.plaintext-password.root:foo
|
||||||
|
|
||||||
|
Note that systemd-sysusers operates in purely additive mode: it
|
||||||
|
executes no operation if the declared users already exist, and hence
|
||||||
|
doesn't set any passwords as effect of the command line above if the
|
||||||
|
specified root user exists already in the image. (Note that
|
||||||
|
--volatile=yes ensures it doesn't, though.)
|
||||||
|
|
||||||
|
* systemd-firstboot now also supports querying various system
|
||||||
|
parameters via the credential subsystems. Thus, as above this may be
|
||||||
|
used to initialize important system parameters on first boot of
|
||||||
|
previously unprovisioned images (i.e. images with a mostly empty
|
||||||
|
/etc/).
|
||||||
|
|
||||||
|
* The systemd-ask-password now also supports reading passwords from the
|
||||||
|
credentials subsystem, via the new --credential= switch.
|
||||||
|
|
||||||
|
* Services gained a new ExitType= setting which can configure how to
|
||||||
|
determine when a service exited: the default is "main" which defines
|
||||||
|
the runtime by the service's main process lifetime (this matches the
|
||||||
|
only behaviour implemented in v248 and before), but with "cgroup" the
|
||||||
|
runtime is defined by the existence of any process in the service's
|
||||||
|
cgroup.
|
||||||
|
|
||||||
|
* The systemd-machine-id-setup tool now supports a --image= switch for
|
||||||
|
provisioning a machine ID file into an OS disk image, similar to how
|
||||||
|
--root= operates on an OS file tree. This matches the existing switch
|
||||||
|
of the same name to the systemd-tmpfiles, systemd-firstboot or
|
||||||
|
systemd-sysusers tools.
|
||||||
|
|
||||||
|
* Similar, systemd-repart gained support for a --image= switch, too. In
|
||||||
|
combination with the existing --size= makes the tool particularly
|
||||||
|
useful for easily growing disk images in a single command invocation,
|
||||||
|
following the declarative rules included in the image itself.
|
||||||
|
|
||||||
|
* systemd-repart's partition configuration files gained support for a
|
||||||
|
new switch MakeDirectories= which may be used to create arbitrary
|
||||||
|
directories inside file systems that are created, before registering
|
||||||
|
them in the partition table. This is useful in particular if root
|
||||||
|
partitions are created that way to create mount point directories for
|
||||||
|
other partitions included in the image. For example, a disk image
|
||||||
|
that is created to contain a /home/ and a /var/ partition in addition
|
||||||
|
to a root partition may MakeDirectories= to create /home/ and /var/
|
||||||
|
as empty directories in the root file system on creation so that the
|
||||||
|
resulting image can mounted immediately, even in read-only mode.
|
||||||
|
|
||||||
|
* systemd-repart's CopyBlocks= setting gained support for a special
|
||||||
|
value "auto". If used a suitable, matching partition on the booted OS
|
||||||
|
is found as source to copy blocks from. This is useful for
|
||||||
|
implementing replicating installers, that are booted from one medium
|
||||||
|
and then stream their own root partition on the target medium.
|
||||||
|
|
||||||
|
* systemd-repart's partition configuration files gained support for a
|
||||||
|
Flags= and a ReadOnly= setting, allowing control of the GPT partition
|
||||||
|
flags for the created partitions: this is useful for marking newly
|
||||||
|
created partitions as read-only from the start.
|
||||||
|
|
||||||
|
* The /etc/os-release file has been extended with two new (optional)
|
||||||
|
variables IMAGE_VERSION= and IMAGE_ID=, for carrying identification
|
||||||
|
and versioning information for OS images that are updated
|
||||||
|
consistently, comprehensively and atomically as one image. The two
|
||||||
|
new specifiers %M, %A now resolve to these two fields in the various
|
||||||
|
configuration options that resolve specifiers.
|
||||||
|
|
||||||
|
* portablectl gained a new switch --extension= for enabling portable
|
||||||
|
service images with extensions that follow the extension image
|
||||||
|
concept introduced with v248.
|
||||||
|
|
||||||
|
* systemd-coredump will now extract ELF build-id information from
|
||||||
|
processes dumping core and include it in the coredump
|
||||||
|
report. Moreover, if will look for ELF .note.package sections that
|
||||||
|
may carry distribution packaging meta-information about the crashing
|
||||||
|
process. This is useful to directly embed the RPM or Debian (or any
|
||||||
|
other) package name and version in the ELF files where they originate
|
||||||
|
from, making it easy to match up coredump reports with the software
|
||||||
|
versions they were found it. This is particular useful on
|
||||||
|
environments with ELF files form multiple vendors, different
|
||||||
|
distributions and versions, as it is common today, in particular in a
|
||||||
|
containerized and sand-boxed world. For further information, see:
|
||||||
|
|
||||||
|
https://systemd.io/COREDUMP_PACKAGE_METADATA
|
||||||
|
|
||||||
|
* A new udev hwdb has been added for Firewire audio devices
|
||||||
|
|
||||||
|
* sd-bus' sd_bus_is_ready() and sd_bus_is_open() calls now accept a
|
||||||
|
NULL bus object, for which they will return false. Or in other words,
|
||||||
|
an unallocated bus connection is neither ready nor open.
|
||||||
|
|
||||||
|
* The native Journal protocol has been documented. Clients may talk
|
||||||
|
this as alternative to the classic BSD syslog protocol for locally
|
||||||
|
delivering log records to the Journal. The protocol has been stable
|
||||||
|
since a long time and in fact been implemented already in a variety
|
||||||
|
of alternative client libraries. This documentation makes the support
|
||||||
|
for that official:
|
||||||
|
|
||||||
|
https://systemd.io/JOURNAL_NATIVE_PROTOCOL
|
||||||
|
|
||||||
|
* A new BPFProgram= setting has been added to service files. It may be
|
||||||
|
set to a path to a loaded kernel BPF program, i.e. a path to a bpffs
|
||||||
|
file, or a bind mount or symlink to one. This may be used to upload
|
||||||
|
and manage BPF programs externally and then hook arbitrary systemd
|
||||||
|
services into them.
|
||||||
|
|
||||||
|
* The "home.arpa" domain that has been officially declared as the
|
||||||
|
choice for domain for local home networks per RFC 8375 has been added
|
||||||
|
to the default NTA list of resolved, since DNSSEC is generally not
|
||||||
|
available on private domains.
|
||||||
|
|
||||||
|
* The CPUAffinity= setting of unit files now resolves "%" specifiers.
|
||||||
|
|
||||||
|
* A new ManageForeignRoutingPolicyRules= setting has been added to
|
||||||
|
.network files which may be used to exclude foreign-created routing
|
||||||
|
policy rules from systemd-networkd management.
|
||||||
|
|
||||||
|
* systemd-network-wait-online gained two new switches -4 and -6 that
|
||||||
|
may be used to tweak whether to wait for only IPv4 or only IPv6
|
||||||
|
connectivity.
|
||||||
|
|
||||||
|
* .network files gained a new RequiredFamilyForOnline= setting to
|
||||||
|
fine-tune whether to require an IPv4 or IPv6 address in order to
|
||||||
|
consider an interface "online".
|
||||||
|
|
||||||
|
* The RestrictAddressFamilies= setting in service files now supports a
|
||||||
|
new special value "none". If specified sockets of all address
|
||||||
|
families will be made unavailable to services configured that way.
|
||||||
|
|
||||||
|
* The DHCP server logic configured in .network files gained a new
|
||||||
|
setting RelayTarget= that turns the server into a DHCP server
|
||||||
|
relay. The RelayAgentCircuitId= and RelayAgentRemoteId= settings may
|
||||||
|
be used to further tweak the DHCP relay behaviour.
|
||||||
|
|
||||||
|
* The DHCP server logic also gained a new setting ServerAddress= in
|
||||||
|
.network files for explicitly specifying the server IP address to
|
||||||
|
use. If not used, the address is determined automatically, as before.
|
||||||
|
|
||||||
|
* The sd-device API acquired a new API function
|
||||||
|
sd_device_get_usec_initialized() that returns the monotonic timestamp
|
||||||
|
when a udev device appeared in the database first.
|
||||||
|
|
||||||
|
* systemd-fstab-generator and systemd-repart have been updated to
|
||||||
|
support booting from disks that carry only a /usr/ partition but no
|
||||||
|
root partition yet, but where systemd-repart can add them in on first
|
||||||
|
boot. This is useful for implementing systems that ship with a single
|
||||||
|
/usr/ file system and whose root file system shall be set up on a
|
||||||
|
LUKS encrypted volume whose key is generated locally (and possibly
|
||||||
|
enrolled in TPM), and which is set up and formatted during first
|
||||||
|
boot.
|
||||||
|
|
||||||
|
* The [Address] section of .network files now accepts a new
|
||||||
|
RouteMetric= setting that configures the routing metric to use for
|
||||||
|
the prefix route created as effect of the address
|
||||||
|
configuration. Similar, the [DHCPv6PrefixDelegation] and [IPv6Prefix]
|
||||||
|
sections gained matching settings for their prefix routes. (The
|
||||||
|
option of the same name of the [DHCPv6] section is moved to
|
||||||
|
[IPv6AcceptRA], since it conceptually belongs there; the old option
|
||||||
|
is still understood for compatibility.)
|
||||||
|
|
||||||
|
* The DHCPv6 IAID and DUID are now explicitly configurable in .network
|
||||||
|
files.
|
||||||
|
|
||||||
|
* A new udev property ID_NET_DHCP_BROADCAST on network interface
|
||||||
|
devices is not honoured by systemd-networkd, that controls whether to
|
||||||
|
issue DHCP offers via broadcasting. This is used to ensure that s390
|
||||||
|
layer 3 network interfaces work out-of-the-box with systemd-networkd.
|
||||||
|
|
||||||
|
* nss-myhostname and systemd-resolved will now synthesize address
|
||||||
|
records for a new special hostname "_outbound". The name will always
|
||||||
|
resolve to the local IP addresses most likely used for outbound
|
||||||
|
connections towards the default route. On multi-homed hosts this is
|
||||||
|
useful to have a stable handle referring to "the" local IP address
|
||||||
|
that matters most, to the point where this is defined.
|
||||||
|
|
||||||
|
* The Discoverable Partition Specification has been updated with a new
|
||||||
|
GPT partition flag defined its partition types: a "growfs"
|
||||||
|
flag. Whenever partitions with this flag set are automatically
|
||||||
|
mounted (i.e. via systemd-gpt-auto-generator or the --image= switch
|
||||||
|
of systemd-nspawn or other tools; and as opposed to explicit mounting
|
||||||
|
via /etc/fstab), the file system within the partition is
|
||||||
|
automatically grown to the full size of the partition should it be
|
||||||
|
smaller. If the file system size already matches the partition size
|
||||||
|
this flag has no effect. Previously, this functionality has been
|
||||||
|
available via the explicit x-systemd.growfs mount option, and this
|
||||||
|
new flag extends this to automatically discovered mounts. A new
|
||||||
|
GrowFileSystem= setting has been added to systemd-repart drop-in
|
||||||
|
files that allows configuring this partition flag. This new flag
|
||||||
|
defaults to on for partitions automatically created by
|
||||||
|
systemd-repart, except if they are marked read-only. See the
|
||||||
|
specification for further details:
|
||||||
|
|
||||||
|
https://systemd.io/DISCOVERABLE_PARTITIONS
|
||||||
|
|
||||||
|
* .network files gained a new setting RoutToNTP= in the [DHCPv4]
|
||||||
|
section. If enabled (which is the default), and an NTP server address
|
||||||
|
is acquired through a DHCP lease on this interface an explicit route
|
||||||
|
to this address is created on this interface to ensure that NTP
|
||||||
|
traffic to the NTP server acquired on an interface is also routed
|
||||||
|
trough that interface. The pre-existing RoutesToDNS= setting that
|
||||||
|
implements the same for DNS servers is now enabled by default.
|
||||||
|
|
||||||
|
* A pair of service settings SocketBindAllow= + SocketBindDeny= have
|
||||||
|
been added that may be used to restrict the network interfaces
|
||||||
|
sockets created by the service may be bound to. This is implemented
|
||||||
|
via BPF.
|
||||||
|
|
||||||
|
* A new ConditionFirmware= condition type has been added to unit
|
||||||
|
files. It may be used to detect certain firmware features. At the
|
||||||
|
moment it may check whether running on an UEFI system, a device.tree
|
||||||
|
system or if the system is compatible with some specified device-tree
|
||||||
|
feature.
|
||||||
|
|
||||||
|
* hostnamed gained a new Describe() D-Bus method that returns a JSON
|
||||||
|
serialization of the host data it exposes. This is exposed via
|
||||||
|
"hostnamectl --json=" to acquire a host identity description in
|
||||||
|
JSON. It's our intention to add a similar concept to most services
|
||||||
|
and objects systemd manages, in order to simplify integration with
|
||||||
|
program code the consumes JSON.
|
||||||
|
|
||||||
|
* Similar, networkd gained a Describe() method on its Manager and Link
|
||||||
|
bus objects. This is exposed via "networkctl --json=".
|
||||||
|
|
||||||
|
* hostnamectl's various set-xyz verbs (e.g. "hostnamectl set-hostname")
|
||||||
|
have been renamed to just xyz (e.g. "hostnamectl hostname") and may
|
||||||
|
now be used to print the indicated data in terse form, instead of
|
||||||
|
only setting it. The old names continue to be supported for
|
||||||
|
compatibility.
|
||||||
|
|
||||||
|
* systemd-detect-virt and ConditionVirtualization= are now able to
|
||||||
|
correctly identify Amazon EC2 environments.
|
||||||
|
|
||||||
|
* The LogLevelMax= setting of unit files now applies not only to log
|
||||||
|
messages generated *by* the service, but also to log messages
|
||||||
|
generated *about* the service by PID 1. To suppress logs concerning a
|
||||||
|
specific service comprehensively, set this option to a high log
|
||||||
|
level.
|
||||||
|
|
||||||
|
* bootctl gained support for a new --make-machine-id-directory= switch
|
||||||
|
that allows precise control on whether to create the top-level
|
||||||
|
per-machine directory in the boot partition that typically contain
|
||||||
|
Type #1 boot loader entries.
|
||||||
|
|
||||||
|
* During build SBAT data to include in the systemd-boot EFI PE binaries
|
||||||
|
may be specified now.
|
||||||
|
|
||||||
|
* /etc/crypttab learnt a new option "headless". If specified any
|
||||||
|
requests to query the user interactively for passwords or PINs will
|
||||||
|
be skipped. This is useful on systems that are headless, i.e. where
|
||||||
|
an interactive user is generally not present.
|
||||||
|
|
||||||
|
* FIDO2 support in systemd-cryptenroll/systemd-cryptsetup and
|
||||||
|
systemd-homed has been updated to allow explicit configuration of the
|
||||||
|
"user presence" and "user verification" checks, as well as whether a
|
||||||
|
PIN is required for authentication, via the new switches
|
||||||
|
--fido2-with-user-presence=, --fido2-with-user-verification=,
|
||||||
|
--fido2-with-client-pin= to systemd-cryptenroll and homectl. Which
|
||||||
|
features are available, and may be enabled or disabled depends on the
|
||||||
|
used FIDO2 token.
|
||||||
|
|
||||||
|
* systemd-nspawn's --private-user= switch now accepts the special value
|
||||||
|
"identity" which configures a user namespacing environment with an
|
||||||
|
identity mapping of 65535 UIDs. This means the container UID 0 is
|
||||||
|
mapped to the host UID 0, and the UID 1 to host UID 1. On first look
|
||||||
|
this doesn't appear to be useful, however it does reduce the attack
|
||||||
|
surface a bit, since the resulting container will possess process
|
||||||
|
capabilities only within its namespace and not on the host.
|
||||||
|
|
||||||
|
* systemd-nspawn's --private-user-chown switch has been replaced by a
|
||||||
|
more generic --private-user-ownership= switch that accepts one of
|
||||||
|
three values: "chown" is equivalent to the old --private-user-chown,
|
||||||
|
and "off" is equivalent to the absence of the old switch. The value
|
||||||
|
"map" uses the new UID mapping mounts of Linux 5.12 to map ownership
|
||||||
|
of files and directories of the underlying image to the chosen UID
|
||||||
|
range for the container. "auto" is equivalent to "map" if UID mapping
|
||||||
|
mount are supported, otherwise it is equivalent to "chown". The short
|
||||||
|
-U switch systemd-nspawn now implies --private-user-ownership=auto
|
||||||
|
instead of the old --private-user-chown. Effectively this means: if
|
||||||
|
the backing file system supports UID mapping mounts the feature is
|
||||||
|
now used by default if -U is used. Generally, it's a good idea to use
|
||||||
|
UID mapping mounts instead of recursive chown()ing, since it allows
|
||||||
|
running containers off immutable images (since no modifications of
|
||||||
|
the images need to take place), and share images between multiple
|
||||||
|
instances. Moreover, the recursive chown()ing operation is slow and
|
||||||
|
can be avoided. Conceptually it's also a good thing if transient UID
|
||||||
|
range uses do not leak into persistent file ownership anymore. TLDR:
|
||||||
|
finally, the last major drawback of user namespacing has been
|
||||||
|
removed, and -U should always be used (unless you use btrfs, where
|
||||||
|
UID mapped mounts do not exist; or your container actually needs
|
||||||
|
privileges on the host).
|
||||||
|
|
||||||
|
* nss-systemd now synthesizes user and group shadow records in addition
|
||||||
|
to the main user and group records. Thus, hashed passwords managed by
|
||||||
|
systemd-homed are now accessible via the shadow database.
|
||||||
|
|
||||||
|
* The userdb logic (and thus nss-systemd, and so on) now read
|
||||||
|
additional user/group definitions in JSON format from the drop-in
|
||||||
|
directories /etc/userdb/, /run/userdb/, /run/host/userdb/ and
|
||||||
|
/usr/lib/userdb/. This is a simple and powerful mechanism for making
|
||||||
|
additional users available to the system, with full integration into
|
||||||
|
NSS including the shadow databases. Since the full JSON user/group
|
||||||
|
record format is supported this may also be used to define users with
|
||||||
|
resource management settings and other runtime settings that
|
||||||
|
pam_systemd and systemd-logind enforce at login.
|
||||||
|
|
||||||
|
* The userdbctl tool gained two new switches --with-dropin= and
|
||||||
|
--with-varlink= which can be used to fine-tune the sources used for
|
||||||
|
user database lookups.
|
||||||
|
|
||||||
|
* systemd-nspawn gained a new switch --bind-user= for binding a host
|
||||||
|
user account into the container. This does three things: the user's
|
||||||
|
home directory is bind mounted from the host into the container,
|
||||||
|
below the /run/userdb/home/ hierarchy. A free UID is picked in the
|
||||||
|
container, and a user namespacing UID mapping to the host user's UID
|
||||||
|
installed. And finally, a minimal JSON user and group record (along
|
||||||
|
with its hashed password) is dropped into /run/host/userdb/. These
|
||||||
|
records are picked up automatically by the userdb drop-in logic
|
||||||
|
describe above, and allow the user to login with the same password as
|
||||||
|
on the host. Effectively this means: if host and container run new
|
||||||
|
enough systemd versions making a host user available to the container
|
||||||
|
is trivially simple.
|
||||||
|
|
||||||
|
* systemd-journal-gatewayd now supports the switches --user, --system,
|
||||||
|
--merge, --file= that are equivalent to the same switches of
|
||||||
|
journalctl, and permit exposing only the specified subset of the
|
||||||
|
Journal records.
|
||||||
|
|
||||||
|
* networkctl will now show an over-all "online" state in the per-link
|
||||||
|
information.
|
||||||
|
|
||||||
|
* In .network files a new OutgoingInterface= setting has been added to
|
||||||
|
specify the output interface in bridge FDB setups.
|
||||||
|
|
||||||
|
* In ,network files the Multipath group ID may now be configured for
|
||||||
|
[NextHop] entries, via the new Group= setting.
|
||||||
|
|
||||||
|
* The OnFailure= dependency between units is now augmented with a
|
||||||
|
implicit reverse dependency OnFailureOf= (this new dependency cannot
|
||||||
|
be configured directly it's only created as effect of an OnFailure=
|
||||||
|
dependency in the reverse order — it's visible in "systemctl show"
|
||||||
|
however). Similar, Slice= now has an reverse dependency SliceOf=,
|
||||||
|
that is also not configurable directly, but useful to determine all
|
||||||
|
units that are members of a slice.
|
||||||
|
|
||||||
|
* A pair of new dependency types between units PropagatesStopTo= +
|
||||||
|
StopPropagatedFrom= has been added, that allows propagation of unit
|
||||||
|
stop events between two units. It operates similar to the existing
|
||||||
|
PropagatesReloadTo= + ReloadPropagatedFrom= dependencies.
|
||||||
|
|
||||||
CHANGES WITH 248:
|
CHANGES WITH 248:
|
||||||
|
|
||||||
* A concept of system extension images is introduced. Such images may
|
* A concept of system extension images is introduced. Such images may
|
||||||
|
|||||||
@ -26,6 +26,8 @@ Information about build requirements is provided in the [README file](README).
|
|||||||
|
|
||||||
Consult our [NEWS file](NEWS) for information about what's new in the most recent systemd versions.
|
Consult our [NEWS file](NEWS) for information about what's new in the most recent systemd versions.
|
||||||
|
|
||||||
|
Please see the [Code Map](docs/ARCHITECTURE.md) for information about this repository's layout and content.
|
||||||
|
|
||||||
Please see the [Hacking guide](docs/HACKING.md) for information on how to hack on systemd and test your modifications.
|
Please see the [Hacking guide](docs/HACKING.md) for information on how to hack on systemd and test your modifications.
|
||||||
|
|
||||||
Please see our [Contribution Guidelines](docs/CONTRIBUTING.md) for more information about filing GitHub Issues and posting GitHub Pull Requests.
|
Please see our [Contribution Guidelines](docs/CONTRIBUTING.md) for more information about filing GitHub Issues and posting GitHub Pull Requests.
|
||||||
|
|||||||
121
docs/ARCHITECTURE.md
Normal file
121
docs/ARCHITECTURE.md
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
---
|
||||||
|
title: systemd repository architecture
|
||||||
|
category: Contributing
|
||||||
|
layout: default
|
||||||
|
---
|
||||||
|
|
||||||
|
# Code Map
|
||||||
|
|
||||||
|
This section will attempt to provide a high-level overview of the various
|
||||||
|
components of the systemd repository.
|
||||||
|
|
||||||
|
# Source Code
|
||||||
|
|
||||||
|
Directories in `src/` provide the implementation of all daemons, libraries and
|
||||||
|
command-line tools shipped by the project. There are many, and more are
|
||||||
|
constantly added, so we will not enumerate them all here - the directory
|
||||||
|
names are self-explanatory.
|
||||||
|
|
||||||
|
## Shared Code
|
||||||
|
|
||||||
|
You might wonder what kind of common code belongs in `src/shared/` and what
|
||||||
|
belongs in `src/basic/`. The split is like this: anything that is used to
|
||||||
|
implement the public shared object we provide (sd-bus, sd-login, sd-id128,
|
||||||
|
nss-systemd, nss-mymachines, nss-resolve, nss-myhostname, pam_systemd), must
|
||||||
|
be located in `src/basic` (those objects are not allowed to link to
|
||||||
|
libsystemd-shared.so). Conversely, anything which is shared between multiple
|
||||||
|
components and does not need to be in `src/basic/`, should be in
|
||||||
|
`src/shared/`.
|
||||||
|
|
||||||
|
To summarize:
|
||||||
|
|
||||||
|
`src/basic/`
|
||||||
|
- may be used by all code in the tree
|
||||||
|
- may not use any code outside of `src/basic/`
|
||||||
|
|
||||||
|
`src/libsystemd/`
|
||||||
|
- may be used by all code in the tree, except for code in `src/basic/`
|
||||||
|
- may not use any code outside of `src/basic/`, `src/libsystemd/`
|
||||||
|
|
||||||
|
`src/shared/`
|
||||||
|
- may be used by all code in the tree, except for code in `src/basic/`,
|
||||||
|
`src/libsystemd/`, `src/nss-*`, `src/login/pam_systemd.*`, and files under
|
||||||
|
`src/journal/` that end up in `libjournal-client.a` convenience library.
|
||||||
|
- may not use any code outside of `src/basic/`, `src/libsystemd/`, `src/shared/`
|
||||||
|
|
||||||
|
## PID 1
|
||||||
|
|
||||||
|
Code located in `src/core/` implements the main logic of the systemd system (and user)
|
||||||
|
service manager.
|
||||||
|
|
||||||
|
BPF helpers written in C and used by PID 1 can be found under `src/core/bpf/`.
|
||||||
|
|
||||||
|
## UDEV
|
||||||
|
|
||||||
|
Sources for the udev daemon and command-line tool (single binary) can be found under
|
||||||
|
`src/udev/`.
|
||||||
|
|
||||||
|
## Unit Tests
|
||||||
|
|
||||||
|
Source files found under `src/test/` implement unit-level testing, mostly for
|
||||||
|
modules found in `src/basic/` and `src/shared/`, but not exclusively. Each test
|
||||||
|
file is compiled in a standalone binary that can be run to exercise the
|
||||||
|
corresponding module. While most of the tests can be ran by any user, some
|
||||||
|
require privileges, and will attempt to clearly log about what they need
|
||||||
|
(mostly in the form of effective capabilities). These tests are self-contained,
|
||||||
|
and generally safe to run on a host without side effects.
|
||||||
|
|
||||||
|
Ideally, every module in `src/basic/` and `src/shared/` should have a corresponding
|
||||||
|
unit test under `src/test/`, which exercises every helper function.
|
||||||
|
|
||||||
|
# Integration Tests
|
||||||
|
|
||||||
|
Sources in `test/` implement system-level testing for executables, libraries and
|
||||||
|
daemons that are shipped by the project. They require privileges to run, and
|
||||||
|
are not safe to execute directly on a host. By default they will build an image
|
||||||
|
and run the test under it via `QEMU` or `systemd-nspawn`.
|
||||||
|
|
||||||
|
Most of those tests should be able to run via `systemd-nspawn`, which is orders of
|
||||||
|
magnitude faster than `QEMU`, but some tests require privileged operations like
|
||||||
|
using `dm-crypt` or `loopdev`. They are clearly marked if that is the case.
|
||||||
|
|
||||||
|
See `test/README.testsuite` for more specific details.
|
||||||
|
|
||||||
|
# HWDB
|
||||||
|
|
||||||
|
Rules built in the static `HWDB` database shipped by the project can be found
|
||||||
|
under `hwdb.d/`. Some of these files are updated automatically, some are filled
|
||||||
|
by contributors.
|
||||||
|
|
||||||
|
# Documentation
|
||||||
|
|
||||||
|
## systemd.io
|
||||||
|
|
||||||
|
Markdown files found under `docs/` are automatically published on the
|
||||||
|
[systemd.io](https://systemd.io) website using Github Pages. A minimal unit test
|
||||||
|
to ensure the formatting doesn't have errors is included in the
|
||||||
|
`meson test -C build/ github-pages` run as part of the CI.
|
||||||
|
|
||||||
|
## MAN pages
|
||||||
|
|
||||||
|
Manpages for binaries and libraries, and the DBUS interfaces, can be found under
|
||||||
|
`man/` and should ideally be kept in sync with changes to the corresponding
|
||||||
|
binaries and libraries.
|
||||||
|
|
||||||
|
## Translations
|
||||||
|
|
||||||
|
Translations files for binaries and daemons, provided by volunteers, can be found
|
||||||
|
under `po/` in the usual format. They are kept up to date by contributors and by
|
||||||
|
automated tools.
|
||||||
|
|
||||||
|
# System Configuration files and presets
|
||||||
|
|
||||||
|
Presets (or templates from which they are generated) for various daemons and tools
|
||||||
|
can be found under various directories such as `factory/`, `modprobe.d/`, `network/`,
|
||||||
|
`presets/`, `rules.d/`, `shell-completion/`, `sysctl.d/`, `sysusers.d/`, `tmpfiles.d/`.
|
||||||
|
|
||||||
|
# Utilities for Developers
|
||||||
|
|
||||||
|
`tools/`, `coccinelle/`, `.github/`, `.semaphore/`, `.lgtm/`, `.mkosi/` host various
|
||||||
|
utilities and scripts that are used by maintainers and developers. They are not
|
||||||
|
shipped or installed.
|
||||||
@ -135,31 +135,6 @@ layout: default
|
|||||||
global in global variables, for example data parsed from command lines, see
|
global in global variables, for example data parsed from command lines, see
|
||||||
below.
|
below.
|
||||||
|
|
||||||
- You might wonder what kind of common code belongs in `src/shared/` and what
|
|
||||||
belongs in `src/basic/`. The split is like this: anything that is used to
|
|
||||||
implement the public shared object we provide (sd-bus, sd-login, sd-id128,
|
|
||||||
nss-systemd, nss-mymachines, nss-resolve, nss-myhostname, pam_systemd), must
|
|
||||||
be located in `src/basic` (those objects are not allowed to link to
|
|
||||||
libsystemd-shared.so). Conversely, anything which is shared between multiple
|
|
||||||
components and does not need to be in `src/basic/`, should be in
|
|
||||||
`src/shared/`.
|
|
||||||
|
|
||||||
To summarize:
|
|
||||||
|
|
||||||
`src/basic/`
|
|
||||||
- may be used by all code in the tree
|
|
||||||
- may not use any code outside of `src/basic/`
|
|
||||||
|
|
||||||
`src/libsystemd/`
|
|
||||||
- may be used by all code in the tree, except for code in `src/basic/`
|
|
||||||
- may not use any code outside of `src/basic/`, `src/libsystemd/`
|
|
||||||
|
|
||||||
`src/shared/`
|
|
||||||
- may be used by all code in the tree, except for code in `src/basic/`,
|
|
||||||
`src/libsystemd/`, `src/nss-*`, `src/login/pam_systemd.*`, and files under
|
|
||||||
`src/journal/` that end up in `libjournal-client.a` convenience library.
|
|
||||||
- may not use any code outside of `src/basic/`, `src/libsystemd/`, `src/shared/`
|
|
||||||
|
|
||||||
- Our focus is on the GNU libc (glibc), not any other libcs. If other libcs are
|
- Our focus is on the GNU libc (glibc), not any other libcs. If other libcs are
|
||||||
incompatible with glibc it's on them. However, if there are equivalent POSIX
|
incompatible with glibc it's on them. However, if there are equivalent POSIX
|
||||||
and Linux/GNU-specific APIs, we generally prefer the POSIX APIs. If there
|
and Linux/GNU-specific APIs, we generally prefer the POSIX APIs. If there
|
||||||
|
|||||||
@ -1405,7 +1405,7 @@
|
|||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>ConditionPathExists=</varname></term>
|
<term><varname>ConditionPathExists=</varname></term>
|
||||||
|
|
||||||
<listitem><para>Check for the exists of a file. If the specified absolute path name does not exist,
|
<listitem><para>Check for the existence of a file. If the specified absolute path name does not exist,
|
||||||
the condition will fail. If the absolute path name passed to
|
the condition will fail. If the absolute path name passed to
|
||||||
<varname>ConditionPathExists=</varname> is prefixed with an exclamation mark
|
<varname>ConditionPathExists=</varname> is prefixed with an exclamation mark
|
||||||
(<literal>!</literal>), the test is negated, and the unit is only started if the path does not
|
(<literal>!</literal>), the test is negated, and the unit is only started if the path does not
|
||||||
|
|||||||
@ -3,6 +3,8 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
|
|
||||||
|
#include "sd-messages.h"
|
||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
#include "bus-error.h"
|
#include "bus-error.h"
|
||||||
#include "dbus-device.h"
|
#include "dbus-device.h"
|
||||||
@ -12,6 +14,7 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
|
#include "ratelimit.h"
|
||||||
#include "serialize.h"
|
#include "serialize.h"
|
||||||
#include "stat-util.h"
|
#include "stat-util.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
@ -122,8 +125,8 @@ static int device_load(Unit *u) {
|
|||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (!u->description) {
|
if (!u->description) {
|
||||||
/* Generate a description based on the path, to be used until the
|
/* Generate a description based on the path, to be used until the device is initialized
|
||||||
device is initialized properly */
|
properly */
|
||||||
r = unit_name_to_path(u->id, &u->description);
|
r = unit_name_to_path(u->id, &u->description);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_unit_debug_errno(u, r, "Failed to unescape name: %m");
|
log_unit_debug_errno(u, r, "Failed to unescape name: %m");
|
||||||
@ -490,15 +493,37 @@ static int device_setup_unit(Manager *m, sd_device *dev, const char *path, bool
|
|||||||
|
|
||||||
if (dev) {
|
if (dev) {
|
||||||
r = sd_device_get_syspath(dev, &sysfs);
|
r = sd_device_get_syspath(dev, &sysfs);
|
||||||
if (r < 0) {
|
if (r < 0)
|
||||||
log_device_debug_errno(dev, r, "Couldn't get syspath from device, ignoring: %m");
|
return log_device_debug_errno(dev, r, "Couldn't get syspath from device, ignoring: %m");
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r = unit_name_from_path(path, ".device", &e);
|
r = unit_name_from_path(path, ".device", &e);
|
||||||
if (r < 0)
|
if (r < 0) {
|
||||||
return log_device_error_errno(dev, r, "Failed to generate unit name from device path: %m");
|
/* Let's complain about overly long device names only at most once every 5s or so. This is
|
||||||
|
* something we should mention, since relevant devices are not manageable by systemd, but not
|
||||||
|
* flood the log about. */
|
||||||
|
static RateLimit rate_limit = {
|
||||||
|
.interval = 5 * USEC_PER_SEC,
|
||||||
|
.burst = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* If we cannot convert a device name to a unit name then let's ignore the device. So far,
|
||||||
|
* devices with such long names weren't really the kind you want to manage with systemd
|
||||||
|
* anyway, hence this shouldn't be a problem. */
|
||||||
|
|
||||||
|
if (r == -ENAMETOOLONG)
|
||||||
|
return log_struct_errno(
|
||||||
|
ratelimit_below(&rate_limit) ? LOG_WARNING : LOG_DEBUG, r,
|
||||||
|
"MESSAGE_ID=" SD_MESSAGE_DEVICE_PATH_NOT_SUITABLE_STR,
|
||||||
|
"DEVICE=%s", path,
|
||||||
|
LOG_MESSAGE("Device path '%s' too long to fit into unit name, ignoring device.", path));
|
||||||
|
|
||||||
|
return log_struct_errno(
|
||||||
|
ratelimit_below(&rate_limit) ? LOG_WARNING : LOG_DEBUG, r,
|
||||||
|
"MESSAGE_ID=" SD_MESSAGE_DEVICE_PATH_NOT_SUITABLE_STR,
|
||||||
|
"DEVICE=%s", path,
|
||||||
|
LOG_MESSAGE("Failed to generate valid unit name from device path '%s', ignoring device: %m", path));
|
||||||
|
}
|
||||||
|
|
||||||
u = manager_get_unit(m, e);
|
u = manager_get_unit(m, e);
|
||||||
if (u) {
|
if (u) {
|
||||||
@ -551,9 +576,10 @@ static int device_setup_unit(Manager *m, sd_device *dev, const char *path, bool
|
|||||||
|
|
||||||
(void) device_update_description(u, dev, path);
|
(void) device_update_description(u, dev, path);
|
||||||
|
|
||||||
/* So the user wants the mount units to be bound to the device but a mount unit might has been seen by systemd
|
/* So the user wants the mount units to be bound to the device but a mount unit might has been seen
|
||||||
* before the device appears on its radar. In this case the device unit is partially initialized and includes
|
* by systemd before the device appears on its radar. In this case the device unit is partially
|
||||||
* the deps on the mount unit but at that time the "bind mounts" flag wasn't not present. Fix this up now. */
|
* initialized and includes the deps on the mount unit but at that time the "bind mounts" flag wasn't
|
||||||
|
* present. Fix this up now. */
|
||||||
if (dev && device_is_bound_by_mounts(DEVICE(u), dev))
|
if (dev && device_is_bound_by_mounts(DEVICE(u), dev))
|
||||||
device_upgrade_mount_deps(u);
|
device_upgrade_mount_deps(u);
|
||||||
|
|
||||||
@ -566,7 +592,7 @@ fail:
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int device_process_new(Manager *m, sd_device *dev) {
|
static void device_process_new(Manager *m, sd_device *dev) {
|
||||||
const char *sysfs, *dn, *alias;
|
const char *sysfs, *dn, *alias;
|
||||||
dev_t devnum;
|
dev_t devnum;
|
||||||
int r;
|
int r;
|
||||||
@ -574,12 +600,13 @@ static int device_process_new(Manager *m, sd_device *dev) {
|
|||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
if (sd_device_get_syspath(dev, &sysfs) < 0)
|
if (sd_device_get_syspath(dev, &sysfs) < 0)
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
/* Add the main unit named after the sysfs path */
|
/* Add the main unit named after the sysfs path. If this one fails, don't bother with the rest, as
|
||||||
r = device_setup_unit(m, dev, sysfs, true);
|
* this one shall be the main device unit the others just follow. (Compare with how
|
||||||
if (r < 0)
|
* device_following() is implemented, see below, which looks for the sysfs device.) */
|
||||||
return r;
|
if (device_setup_unit(m, dev, sysfs, true) < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
/* Add an additional unit for the device node */
|
/* Add an additional unit for the device node */
|
||||||
if (sd_device_get_devname(dev, &dn) >= 0)
|
if (sd_device_get_devname(dev, &dn) >= 0)
|
||||||
@ -595,13 +622,11 @@ static int device_process_new(Manager *m, sd_device *dev) {
|
|||||||
if (PATH_STARTSWITH_SET(p, "/dev/block/", "/dev/char/"))
|
if (PATH_STARTSWITH_SET(p, "/dev/block/", "/dev/char/"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Verify that the symlink in the FS actually belongs
|
/* Verify that the symlink in the FS actually belongs to this device. This is useful
|
||||||
* to this device. This is useful to deal with
|
* to deal with conflicting devices, e.g. when two disks want the same
|
||||||
* conflicting devices, e.g. when two disks want the
|
* /dev/disk/by-label/xxx link because they have the same label. We want to make sure
|
||||||
* same /dev/disk/by-label/xxx link because they have
|
* that the same device that won the symlink wins in systemd, so we check the device
|
||||||
* the same label. We want to make sure that the same
|
* node major/minor */
|
||||||
* device that won the symlink wins in systemd, so we
|
|
||||||
* check the device node major/minor */
|
|
||||||
if (stat(p, &st) >= 0 &&
|
if (stat(p, &st) >= 0 &&
|
||||||
((!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) ||
|
((!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) ||
|
||||||
st.st_rdev != devnum))
|
st.st_rdev != devnum))
|
||||||
@ -613,7 +638,7 @@ static int device_process_new(Manager *m, sd_device *dev) {
|
|||||||
|
|
||||||
/* Add additional units for all explicitly configured aliases */
|
/* Add additional units for all explicitly configured aliases */
|
||||||
if (sd_device_get_property_value(dev, "SYSTEMD_ALIAS", &alias) < 0)
|
if (sd_device_get_property_value(dev, "SYSTEMD_ALIAS", &alias) < 0)
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
_cleanup_free_ char *word = NULL;
|
_cleanup_free_ char *word = NULL;
|
||||||
@ -622,9 +647,9 @@ static int device_process_new(Manager *m, sd_device *dev) {
|
|||||||
if (r == 0)
|
if (r == 0)
|
||||||
break;
|
break;
|
||||||
if (r == -ENOMEM)
|
if (r == -ENOMEM)
|
||||||
return log_oom();
|
return (void) log_oom();
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_device_warning_errno(dev, r, "Failed to parse SYSTEMD_ALIAS property: %m");
|
return (void) log_device_warning_errno(dev, r, "Failed to parse SYSTEMD_ALIAS property, ignoring: %m");
|
||||||
|
|
||||||
if (!path_is_absolute(word))
|
if (!path_is_absolute(word))
|
||||||
log_device_warning(dev, "SYSTEMD_ALIAS is not an absolute path, ignoring: %s", word);
|
log_device_warning(dev, "SYSTEMD_ALIAS is not an absolute path, ignoring: %s", word);
|
||||||
@ -633,8 +658,6 @@ static int device_process_new(Manager *m, sd_device *dev) {
|
|||||||
else
|
else
|
||||||
(void) device_setup_unit(m, dev, word, false);
|
(void) device_setup_unit(m, dev, word, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void device_found_changed(Device *d, DeviceFound previous, DeviceFound now) {
|
static void device_found_changed(Device *d, DeviceFound previous, DeviceFound now) {
|
||||||
@ -698,7 +721,7 @@ static void device_update_found_by_sysfs(Manager *m, const char *sysfs, DeviceFo
|
|||||||
device_update_found_one(d, found, mask);
|
device_update_found_one(d, found, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int device_update_found_by_name(Manager *m, const char *path, DeviceFound found, DeviceFound mask) {
|
static void device_update_found_by_name(Manager *m, const char *path, DeviceFound found, DeviceFound mask) {
|
||||||
_cleanup_free_ char *e = NULL;
|
_cleanup_free_ char *e = NULL;
|
||||||
Unit *u;
|
Unit *u;
|
||||||
int r;
|
int r;
|
||||||
@ -707,18 +730,17 @@ static int device_update_found_by_name(Manager *m, const char *path, DeviceFound
|
|||||||
assert(path);
|
assert(path);
|
||||||
|
|
||||||
if (mask == 0)
|
if (mask == 0)
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
r = unit_name_from_path(path, ".device", &e);
|
r = unit_name_from_path(path, ".device", &e);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to generate unit name from device path: %m");
|
return (void) log_debug_errno(r, "Failed to generate unit name from device path, ignoring: %m");
|
||||||
|
|
||||||
u = manager_get_unit(m, e);
|
u = manager_get_unit(m, e);
|
||||||
if (!u)
|
if (!u)
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
device_update_found_one(DEVICE(u), found, mask);
|
device_update_found_one(DEVICE(u), found, mask);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool device_is_ready(sd_device *dev) {
|
static bool device_is_ready(sd_device *dev) {
|
||||||
@ -859,7 +881,7 @@ static void device_enumerate(Manager *m) {
|
|||||||
if (!device_is_ready(dev))
|
if (!device_is_ready(dev))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
(void) device_process_new(m, dev);
|
device_process_new(m, dev);
|
||||||
|
|
||||||
if (sd_device_get_syspath(dev, &sysfs) < 0)
|
if (sd_device_get_syspath(dev, &sysfs) < 0)
|
||||||
continue;
|
continue;
|
||||||
@ -891,27 +913,24 @@ static void device_propagate_reload_by_sysfs(Manager *m, const char *sysfs) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int device_remove_old(Manager *m, sd_device *dev) {
|
static void device_remove_old_on_move(Manager *m, sd_device *dev) {
|
||||||
_cleanup_free_ char *syspath_old = NULL, *e = NULL;
|
_cleanup_free_ char *syspath_old = NULL, *e = NULL;
|
||||||
const char *devpath_old;
|
const char *devpath_old;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = sd_device_get_property_value(dev, "DEVPATH_OLD", &devpath_old);
|
r = sd_device_get_property_value(dev, "DEVPATH_OLD", &devpath_old);
|
||||||
if (r < 0) {
|
if (r < 0)
|
||||||
log_device_debug_errno(dev, r, "Failed to get DEVPATH_OLD= property on 'move' uevent, ignoring: %m");
|
return (void) log_device_debug_errno(dev, r, "Failed to get DEVPATH_OLD= property on 'move' uevent, ignoring: %m");
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
syspath_old = path_join("/sys", devpath_old);
|
syspath_old = path_join("/sys", devpath_old);
|
||||||
if (!syspath_old)
|
if (!syspath_old)
|
||||||
return log_oom();
|
return (void) log_oom();
|
||||||
|
|
||||||
r = unit_name_from_path(syspath_old, ".device", &e);
|
r = unit_name_from_path(syspath_old, ".device", &e);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_device_error_errno(dev, r, "Failed to generate unit name from old device path: %m");
|
return (void) log_device_debug_errno(dev, r, "Failed to generate unit name from old device path, ignoring: %m");
|
||||||
|
|
||||||
device_update_found_by_sysfs(m, syspath_old, 0, DEVICE_FOUND_UDEV|DEVICE_FOUND_MOUNT|DEVICE_FOUND_SWAP);
|
device_update_found_by_sysfs(m, syspath_old, 0, DEVICE_FOUND_UDEV|DEVICE_FOUND_MOUNT|DEVICE_FOUND_SWAP);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void *userdata) {
|
static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void *userdata) {
|
||||||
@ -939,7 +958,7 @@ static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void *
|
|||||||
device_propagate_reload_by_sysfs(m, sysfs);
|
device_propagate_reload_by_sysfs(m, sysfs);
|
||||||
|
|
||||||
if (action == SD_DEVICE_MOVE)
|
if (action == SD_DEVICE_MOVE)
|
||||||
(void) device_remove_old(m, dev);
|
device_remove_old_on_move(m, dev);
|
||||||
|
|
||||||
/* A change event can signal that a device is becoming ready, in particular if the device is using
|
/* A change event can signal that a device is becoming ready, in particular if the device is using
|
||||||
* the SYSTEMD_READY logic in udev so we need to reach the else block of the following if, even for
|
* the SYSTEMD_READY logic in udev so we need to reach the else block of the following if, even for
|
||||||
@ -955,7 +974,7 @@ static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void *
|
|||||||
|
|
||||||
} else if (device_is_ready(dev)) {
|
} else if (device_is_ready(dev)) {
|
||||||
|
|
||||||
(void) device_process_new(m, dev);
|
device_process_new(m, dev);
|
||||||
|
|
||||||
r = swap_process_device_new(m, dev);
|
r = swap_process_device_new(m, dev);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -965,7 +984,6 @@ static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void *
|
|||||||
|
|
||||||
/* The device is found now, set the udev found bit */
|
/* The device is found now, set the udev found bit */
|
||||||
device_update_found_by_sysfs(m, sysfs, DEVICE_FOUND_UDEV, DEVICE_FOUND_UDEV);
|
device_update_found_by_sysfs(m, sysfs, DEVICE_FOUND_UDEV, DEVICE_FOUND_UDEV);
|
||||||
|
|
||||||
} else
|
} else
|
||||||
/* The device is nominally around, but not ready for us. Hence unset the udev bit, but leave
|
/* The device is nominally around, but not ready for us. Hence unset the udev bit, but leave
|
||||||
* the rest around. */
|
* the rest around. */
|
||||||
@ -1028,8 +1046,6 @@ static int validate_node(Manager *m, const char *node, sd_device **ret) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void device_found_node(Manager *m, const char *node, DeviceFound found, DeviceFound mask) {
|
void device_found_node(Manager *m, const char *node, DeviceFound found, DeviceFound mask) {
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
assert(node);
|
assert(node);
|
||||||
|
|
||||||
@ -1054,8 +1070,7 @@ void device_found_node(Manager *m, const char *node, DeviceFound found, DeviceFo
|
|||||||
* under the name referenced in /proc/swaps or /proc/self/mountinfo. But first, let's validate if
|
* under the name referenced in /proc/swaps or /proc/self/mountinfo. But first, let's validate if
|
||||||
* everything is alright with the device node. */
|
* everything is alright with the device node. */
|
||||||
|
|
||||||
r = validate_node(m, node, &dev);
|
if (validate_node(m, node, &dev) <= 0)
|
||||||
if (r <= 0)
|
|
||||||
return; /* Don't create a device unit for this if the device node is borked. */
|
return; /* Don't create a device unit for this if the device node is borked. */
|
||||||
|
|
||||||
(void) device_setup_unit(m, dev, node, false);
|
(void) device_setup_unit(m, dev, node, false);
|
||||||
|
|||||||
@ -492,7 +492,7 @@ fail:
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int swap_process_new(Manager *m, const char *device, int prio, bool set_flags) {
|
static void swap_process_new(Manager *m, const char *device, int prio, bool set_flags) {
|
||||||
_cleanup_(sd_device_unrefp) sd_device *d = NULL;
|
_cleanup_(sd_device_unrefp) sd_device *d = NULL;
|
||||||
const char *dn, *devlink;
|
const char *dn, *devlink;
|
||||||
struct stat st, st_link;
|
struct stat st, st_link;
|
||||||
@ -500,25 +500,22 @@ static int swap_process_new(Manager *m, const char *device, int prio, bool set_f
|
|||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
r = swap_setup_unit(m, device, device, prio, set_flags);
|
if (swap_setup_unit(m, device, device, prio, set_flags) < 0)
|
||||||
if (r < 0)
|
return;
|
||||||
return r;
|
|
||||||
|
|
||||||
/* If this is a block device, then let's add duplicates for
|
/* If this is a block device, then let's add duplicates for
|
||||||
* all other names of this block device */
|
* all other names of this block device */
|
||||||
if (stat(device, &st) < 0 || !S_ISBLK(st.st_mode))
|
if (stat(device, &st) < 0 || !S_ISBLK(st.st_mode))
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
r = sd_device_new_from_stat_rdev(&d, &st);
|
r = sd_device_new_from_stat_rdev(&d, &st);
|
||||||
if (r < 0) {
|
if (r < 0)
|
||||||
log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
|
return (void) log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
|
||||||
"Failed to allocate device for swap %s: %m", device);
|
"Failed to allocate device for swap %s: %m", device);
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add the main device node */
|
/* Add the main device node */
|
||||||
if (sd_device_get_devname(d, &dn) >= 0 && !streq(dn, device))
|
if (sd_device_get_devname(d, &dn) >= 0 && !streq(dn, device))
|
||||||
swap_setup_unit(m, dn, device, prio, set_flags);
|
(void) swap_setup_unit(m, dn, device, prio, set_flags);
|
||||||
|
|
||||||
/* Add additional units for all symlinks */
|
/* Add additional units for all symlinks */
|
||||||
FOREACH_DEVICE_DEVLINK(d, devlink) {
|
FOREACH_DEVICE_DEVLINK(d, devlink) {
|
||||||
@ -535,10 +532,8 @@ static int swap_process_new(Manager *m, const char *device, int prio, bool set_f
|
|||||||
st_link.st_rdev != st.st_rdev))
|
st_link.st_rdev != st.st_rdev))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
swap_setup_unit(m, devlink, device, prio, set_flags);
|
(void) swap_setup_unit(m, devlink, device, prio, set_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void swap_set_state(Swap *s, SwapState state) {
|
static void swap_set_state(Swap *s, SwapState state) {
|
||||||
@ -1431,13 +1426,14 @@ int swap_process_device_new(Manager *m, sd_device *dev) {
|
|||||||
assert(m);
|
assert(m);
|
||||||
assert(dev);
|
assert(dev);
|
||||||
|
|
||||||
r = sd_device_get_devname(dev, &dn);
|
if (sd_device_get_devname(dev, &dn) < 0)
|
||||||
if (r < 0)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
r = unit_name_from_path(dn, ".swap", &e);
|
r = unit_name_from_path(dn, ".swap", &e);
|
||||||
if (r < 0)
|
if (r < 0) {
|
||||||
return r;
|
log_debug_errno(r, "Cannot convert device name '%s' to unit name, ignoring: %m", dn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
u = manager_get_unit(m, e);
|
u = manager_get_unit(m, e);
|
||||||
if (u)
|
if (u)
|
||||||
|
|||||||
@ -170,6 +170,10 @@ _SD_BEGIN_DECLARATIONS;
|
|||||||
SD_ID128_MAKE(1b,3b,b9,40,37,f0,4b,bf,81,02,8e,13,5a,12,d2,93)
|
SD_ID128_MAKE(1b,3b,b9,40,37,f0,4b,bf,81,02,8e,13,5a,12,d2,93)
|
||||||
#define SD_MESSAGE_MOUNT_POINT_PATH_NOT_SUITABLE_STR \
|
#define SD_MESSAGE_MOUNT_POINT_PATH_NOT_SUITABLE_STR \
|
||||||
SD_ID128_MAKE_STR(1b,3b,b9,40,37,f0,4b,bf,81,02,8e,13,5a,12,d2,93)
|
SD_ID128_MAKE_STR(1b,3b,b9,40,37,f0,4b,bf,81,02,8e,13,5a,12,d2,93)
|
||||||
|
#define SD_MESSAGE_DEVICE_PATH_NOT_SUITABLE \
|
||||||
|
SD_ID128_MAKE(01,01,90,13,8f,49,4e,29,a0,ef,66,69,74,95,31,aa)
|
||||||
|
#define SD_MESSAGE_DEVICE_PATH_NOT_SUITABLE_STR \
|
||||||
|
SD_ID128_MAKE_STR(01,01,90,13,8f,49,4e,29,a0,ef,66,69,74,95,31,aa)
|
||||||
|
|
||||||
#define SD_MESSAGE_NOBODY_USER_UNSUITABLE SD_ID128_MAKE(b4,80,32,5f,9c,39,4a,7b,80,2c,23,1e,51,a2,75,2c)
|
#define SD_MESSAGE_NOBODY_USER_UNSUITABLE SD_ID128_MAKE(b4,80,32,5f,9c,39,4a,7b,80,2c,23,1e,51,a2,75,2c)
|
||||||
#define SD_MESSAGE_NOBODY_USER_UNSUITABLE_STR \
|
#define SD_MESSAGE_NOBODY_USER_UNSUITABLE_STR \
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user