mirror of
https://github.com/Dasharo/systemd.git
synced 2026-03-06 15:02:31 -08:00
Merge pull request #7186 from poettering/track-deps
rework unit dependency data structure to track why deps get created
This commit is contained in:
@@ -74,3 +74,6 @@ BuildPackages=
|
||||
|
||||
Packages=
|
||||
libidn2
|
||||
|
||||
BuildDirectory=mkosi.builddir
|
||||
Cache=mkosi.cache
|
||||
|
||||
42
TODO
42
TODO
@@ -24,6 +24,48 @@ Janitorial Clean-ups:
|
||||
|
||||
Features:
|
||||
|
||||
* let's log the "tainted" string at boot
|
||||
|
||||
* Add NetworkNamespacePath= to specify a path to a network namespace
|
||||
|
||||
* Add StandardInputData= and StandardInputText= for putting together data to
|
||||
pass to a service through stdin
|
||||
|
||||
* Add StandardInputPath=, StandardOutputPath=, StandardErrorPath= to connect a
|
||||
service to a specific file. Be smart, and if the specified path refers to an
|
||||
AF_UNIX socket, connect() to it.
|
||||
|
||||
* maybe use SOURCE_DATE_EPOCH (i.e. the env var the reproducible builds folks
|
||||
introduced) as the RTC epoch, instead of the mtime of NEWS.
|
||||
|
||||
* Introduce GCMode= as unit file property or so, for tweaking the GC
|
||||
logic. Specifically, there should be a way to tell systemd to collect
|
||||
individual units even on failure. Then, make systemd-run --wait use this, so
|
||||
that failed transient units in that case don't stick around.
|
||||
|
||||
* add a way to lock down cgroup migration: a boolean, which when set for a unit
|
||||
makes sure the processes in it can never migrate out of it
|
||||
|
||||
* complain if a unit starts up and there are already processes in its cgroup
|
||||
|
||||
* blog about fd store and restartable services
|
||||
|
||||
* document Environment=SYSTEMD_LOG_LEVEL=debug drop-in in debugging document
|
||||
|
||||
* add a way to remove fds from the fdstore by name, and make logind use it
|
||||
|
||||
* in the long run: permit a system with /etc/machine-id linked to /dev/null, to
|
||||
make it lose its identity, i.e. be anonymous. For this we'd have to patch
|
||||
through the whole tree to make all code deal with the case where no machine
|
||||
ID is available.
|
||||
|
||||
* optionally, collect cgroup resource data, and store it in per-unit RRD files,
|
||||
suitable for processing with rrdtool. Add bus API to access this data, and
|
||||
possibly implement a CPULoad property based on it.
|
||||
|
||||
* In journalctl add a way how "-o verbose" and suchlike can be tweaked to show
|
||||
only a specific set of properties
|
||||
|
||||
* export UID ranges nspawns's --private-user and DynamicUser= uses in
|
||||
the systemd.pc pkg-config file, the same way we already expose the system
|
||||
user boundary there
|
||||
|
||||
@@ -73,6 +73,9 @@
|
||||
special mode of escaping is applied instead, which assumes the
|
||||
string is already escaped but will escape everything that
|
||||
appears obviously non-escaped.</para>
|
||||
|
||||
<para>For details on the escaping and unescaping algorithms see the relevant section in
|
||||
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
@@ -107,11 +110,12 @@
|
||||
<term><option>--path</option></term>
|
||||
<term><option>-p</option></term>
|
||||
|
||||
<listitem><para>When escaping or unescaping a string, assume
|
||||
it refers to a file system path. This eliminates leading,
|
||||
trailing or duplicate <literal>/</literal> characters
|
||||
and rejects <literal>.</literal> and <literal>..</literal>
|
||||
path components.</para></listitem>
|
||||
<listitem><para>When escaping or unescaping a string, assume it refers to a file system path. This eliminates
|
||||
leading, trailing or duplicate <literal>/</literal> characters and rejects <literal>.</literal> and
|
||||
<literal>..</literal> path components. This is particularly useful for generating strings suitable for
|
||||
unescaping with the <literal>%f</literal> specifier in unit files, see
|
||||
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@@ -172,6 +176,7 @@ systemd-nspawn@My\x20Container\x201.service systemd-nspawn@containerb.service sy
|
||||
<title>See Also</title>
|
||||
<para>
|
||||
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
@@ -112,35 +112,36 @@
|
||||
<refsect1>
|
||||
<title>The udev Database</title>
|
||||
|
||||
<para>The settings of device units may either be configured via
|
||||
unit files, or directly from the udev database (which is
|
||||
recommended). The following udev device properties are understood
|
||||
by systemd:</para>
|
||||
<para>Unit settings of device units may either be configured via unit files, or directly from the udev
|
||||
database. The following udev device properties are understood by the service manager:</para>
|
||||
|
||||
<variablelist class='udev-directives'>
|
||||
<varlistentry>
|
||||
<term><varname>SYSTEMD_WANTS=</varname></term>
|
||||
<term><varname>SYSTEMD_USER_WANTS=</varname></term>
|
||||
<listitem><para>Adds dependencies of type
|
||||
<varname>Wants</varname> from the device unit to all listed
|
||||
units. The first form is used by the system systemd instance,
|
||||
the second by user systemd instances. Those settings may be
|
||||
used to activate arbitrary units when a specific device
|
||||
becomes available.</para>
|
||||
<listitem><para>Adds dependencies of type <varname>Wants=</varname> from the device unit to the specified
|
||||
units. <varname>SYSTEMD_WANTS=</varname> is read by the system service manager,
|
||||
<varname>SYSTEMD_USER_WANTS=</varname> by user service manager instances. These properties may be used to
|
||||
activate arbitrary units when a specific device becomes available.</para>
|
||||
|
||||
<para>Note that this and the other tags are not taken into
|
||||
account unless the device is tagged with the
|
||||
<literal>systemd</literal> string in the udev database,
|
||||
because otherwise the device is not exposed as a systemd unit
|
||||
(see above).</para>
|
||||
<para>Note that this and the other udev device properties are not taken into account unless the device is
|
||||
tagged with the <literal>systemd</literal> tag in the udev database, because otherwise the device is not
|
||||
exposed as a systemd unit (see above).</para>
|
||||
|
||||
<para>Note that systemd will only act on
|
||||
<varname>Wants</varname> dependencies when a device first
|
||||
becomes active. It will not act on them if they are added to
|
||||
devices that are already active. Use
|
||||
<varname>SYSTEMD_READY=</varname> (see below) to influence on
|
||||
which udev event to trigger the dependencies.
|
||||
</para></listitem>
|
||||
<para>Note that systemd will only act on <varname>Wants=</varname> dependencies when a device first becomes
|
||||
active. It will not act on them if they are added to devices that are already active. Use
|
||||
<varname>SYSTEMD_READY=</varname> (see below) to configure when a udev device shall be considered active, and
|
||||
thus when to trigger the dependencies.</para>
|
||||
|
||||
<!-- Note that we don't document here that we actually apply unit_name_mangle() to all specified names, since
|
||||
that's kinda ugly, and people should instead specify correctly escaped names -->
|
||||
|
||||
<para>The specified property value should be a space-separated list of valid unit names. If a unit template
|
||||
name is specified (that is, a unit name containing an <literal>@</literal> character indicating a unit name to
|
||||
use for multiple instantiation, but with an empty instance name following the <literal>@</literal>), it will be
|
||||
automatically instantiated by the device's <literal>sysfs</literal> path (that is: the path is escaped and
|
||||
inserted as instance name into the template unit name). This is useful in order to instantiate a specific
|
||||
template unit once for each device that appears and matches specific properties.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@@ -152,20 +153,14 @@
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>SYSTEMD_READY=</varname></term>
|
||||
<listitem><para>If set to 0, systemd will consider this device
|
||||
unplugged even if it shows up in the udev tree. If this
|
||||
property is unset or set to 1, the device will be considered
|
||||
plugged if it is visible in the udev tree. This property has
|
||||
no influence on the behavior when a device disappears from the
|
||||
udev tree.</para>
|
||||
<listitem><para>If set to 0, systemd will consider this device unplugged even if it shows up in the udev
|
||||
tree. If this property is unset or set to 1, the device will be considered plugged if it is visible in the udev
|
||||
tree.</para>
|
||||
|
||||
<para>This option is useful to support devices that initially
|
||||
show up in an uninitialized state in the tree, and for which a
|
||||
<literal>changed</literal> event is generated the moment they
|
||||
are fully set up. Note that <varname>SYSTEMD_WANTS=</varname>
|
||||
(see above) is not acted on as long as
|
||||
<varname>SYSTEMD_READY=0</varname> is set for a
|
||||
device.</para></listitem>
|
||||
<para>This option is useful for devices that initially show up in an uninitialized state in the tree, and for
|
||||
which a <literal>changed</literal> event is generated the moment they are fully set up. Note that
|
||||
<varname>SYSTEMD_WANTS=</varname> (see above) is not acted on as long as <varname>SYSTEMD_READY=0</varname> is
|
||||
set for a device.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
||||
@@ -213,22 +213,6 @@
|
||||
socket-based activation which make dependencies implicit,
|
||||
resulting in a both simpler and more flexible system.</para>
|
||||
|
||||
<para>Some unit names reflect paths existing in the file system
|
||||
namespace. Example: a device unit
|
||||
<filename>dev-sda.device</filename> refers to a device with the
|
||||
device node <filename noindex='true'>/dev/sda</filename> in the
|
||||
file system namespace. If this applies, a special way to escape
|
||||
the path name is used, so that the result is usable as part of a
|
||||
filename. Basically, given a path, "/" is replaced by "-", and all
|
||||
other characters which are not ASCII alphanumerics are replaced by
|
||||
C-style "\x2d" escapes (except that "_" is never replaced and "."
|
||||
is only replaced when it would be the first character in the
|
||||
escaped path). The root directory "/" is encoded as single dash,
|
||||
while otherwise the initial and ending "/" are removed from all
|
||||
paths during transformation. This escaping is reversible. Properly
|
||||
escaped paths can be generated using the
|
||||
<citerefentry><refentrytitle>systemd-escape</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
command.</para>
|
||||
|
||||
<para>Optionally, units may be instantiated from a
|
||||
template file at runtime. This allows creation of
|
||||
@@ -265,6 +249,32 @@
|
||||
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>String Escaping for Inclusion in Unit Names</title>
|
||||
|
||||
<para>Sometimes it is useful to convert arbitrary strings into unit names. To facilitate this, a method of string
|
||||
escaping is used, in order to map strings containing arbitrary byte values (except NUL) into valid unit names and
|
||||
their restricted character set. A common special case are unit names that reflect paths to objects in the file
|
||||
system hierarchy. Example: a device unit <filename>dev-sda.device</filename> refers to a device with the device
|
||||
node <filename noindex='true'>/dev/sda</filename> in the file system.</para>
|
||||
|
||||
<para>The escaping algorithm operates as follows: given a string, any <literal>/</literal> character is replaced by
|
||||
<literal>-</literal>, and all other characters which are not ASCII alphanumerics or <literal>_</literal> are
|
||||
replaced by C-style <literal>\x2d</literal> escapes. In addition, <literal>.</literal> is replaced with such a
|
||||
C-style escape when it would appear as the first character in the escaped string.</para>
|
||||
|
||||
<para>When the input qualifies as absolute file system path, this algorithm is extended slightly: the path to the
|
||||
root directory <literal>/</literal> is encoded as single dash <literal>-</literal>. In addition, any leading,
|
||||
trailing or duplicate <literal>/</literal> characters are removed from the string before transformation. Example:
|
||||
<filename>/foo//bar/baz/</filename> becomes <literal>foo-bar-baz</literal>.</para>
|
||||
|
||||
<para>This escaping is fully reversible, as long as it is known whether the escaped string was a path (the
|
||||
unescaping results are different for paths and non-path strings). The
|
||||
<citerefentry><refentrytitle>systemd-escape</refentrytitle><manvolnum>1</manvolnum></citerefentry> command may be
|
||||
used to apply and reverse escaping on arbitrary strings. Use <command>systemd-escape --path</command> to escape
|
||||
path strings, and <command>systemd-escape</command> without <option>--path</option> otherwise.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Implicit Dependencies</title>
|
||||
|
||||
@@ -1241,7 +1251,7 @@
|
||||
<row>
|
||||
<entry><literal>%N</literal></entry>
|
||||
<entry>Unescaped full unit name</entry>
|
||||
<entry>Same as <literal>%n</literal>, but with escaping undone</entry>
|
||||
<entry>Same as <literal>%n</literal>, but with escaping undone. This undoes the escaping used when generating unit names from arbitrary strings (see above). </entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>%p</literal></entry>
|
||||
@@ -1266,7 +1276,7 @@
|
||||
<row>
|
||||
<entry><literal>%f</literal></entry>
|
||||
<entry>Unescaped filename</entry>
|
||||
<entry>This is either the unescaped instance name (if applicable) with <filename>/</filename> prepended (if applicable), or the unescaped prefix name prepended with <filename>/</filename>.</entry>
|
||||
<entry>This is either the unescaped instance name (if applicable) with <filename>/</filename> prepended (if applicable), or the unescaped prefix name prepended with <filename>/</filename>. This implements unescaping according to the rules for escaping absolute file system paths discussed above.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>%t</literal></entry>
|
||||
|
||||
@@ -26,7 +26,9 @@
|
||||
|
||||
export LC_CTYPE=en_US.UTF-8
|
||||
|
||||
[ -f "$BUILDDIR"/build.ninja ] || meson "$BUILDDIR"
|
||||
sysvinit_path=`realpath /etc/init.d`
|
||||
|
||||
[ -f "$BUILDDIR"/build.ninja ] || meson "$BUILDDIR" -D "sysvinit-path=$sysvinit_path"
|
||||
ninja -C "$BUILDDIR" all
|
||||
[ "$WITH_TESTS" = 0 ] || ninja -C "$BUILDDIR" test || ( RET="$?" ; cat "$BUILDDIR"/meson-logs/testlog.txt ; exit "$RET" )
|
||||
ninja -C "$BUILDDIR" install
|
||||
|
||||
@@ -216,6 +216,7 @@ static int detect_vm_dmi(void) {
|
||||
}
|
||||
|
||||
static int detect_vm_xen(void) {
|
||||
|
||||
/* Check for Dom0 will be executed later in detect_vm_xen_dom0
|
||||
Thats why we dont check the content of /proc/xen/capabilities here. */
|
||||
if (access("/proc/xen/capabilities", F_OK) < 0) {
|
||||
@@ -224,8 +225,7 @@ static int detect_vm_xen(void) {
|
||||
}
|
||||
|
||||
log_debug("Virtualization XEN found (/proc/xen/capabilities exists)");
|
||||
return VIRTUALIZATION_XEN;
|
||||
|
||||
return VIRTUALIZATION_XEN;
|
||||
}
|
||||
|
||||
static bool detect_vm_xen_dom0(void) {
|
||||
|
||||
@@ -130,7 +130,20 @@ static void automount_done(Unit *u) {
|
||||
a->expire_event_source = sd_event_source_unref(a->expire_event_source);
|
||||
}
|
||||
|
||||
static int automount_add_mount_links(Automount *a) {
|
||||
static int automount_add_trigger_dependencies(Automount *a) {
|
||||
Unit *x;
|
||||
int r;
|
||||
|
||||
assert(a);
|
||||
|
||||
r = unit_load_related_unit(UNIT(a), ".mount", &x);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return unit_add_two_dependencies(UNIT(a), UNIT_BEFORE, UNIT_TRIGGERS, x, true, UNIT_DEPENDENCY_IMPLICIT);
|
||||
}
|
||||
|
||||
static int automount_add_mount_dependencies(Automount *a) {
|
||||
_cleanup_free_ char *parent = NULL;
|
||||
|
||||
assert(a);
|
||||
@@ -139,7 +152,7 @@ static int automount_add_mount_links(Automount *a) {
|
||||
if (!parent)
|
||||
return -ENOMEM;
|
||||
|
||||
return unit_require_mounts_for(UNIT(a), parent);
|
||||
return unit_require_mounts_for(UNIT(a), parent, UNIT_DEPENDENCY_IMPLICIT);
|
||||
}
|
||||
|
||||
static int automount_add_default_dependencies(Automount *a) {
|
||||
@@ -153,7 +166,7 @@ static int automount_add_default_dependencies(Automount *a) {
|
||||
if (!MANAGER_IS_SYSTEM(UNIT(a)->manager))
|
||||
return 0;
|
||||
|
||||
r = unit_add_two_dependencies_by_name(UNIT(a), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
|
||||
r = unit_add_two_dependencies_by_name(UNIT(a), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true, UNIT_DEPENDENCY_DEFAULT);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -215,21 +228,15 @@ static int automount_load(Unit *u) {
|
||||
return r;
|
||||
|
||||
if (u->load_state == UNIT_LOADED) {
|
||||
Unit *x;
|
||||
|
||||
r = automount_set_where(a);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = unit_load_related_unit(u, ".mount", &x);
|
||||
r = automount_add_trigger_dependencies(a);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, x, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = automount_add_mount_links(a);
|
||||
r = automount_add_mount_dependencies(a);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
@@ -1095,10 +1095,11 @@ CGroupMask unit_get_members_mask(Unit *u) {
|
||||
u->cgroup_members_mask = 0;
|
||||
|
||||
if (u->type == UNIT_SLICE) {
|
||||
void *v;
|
||||
Unit *member;
|
||||
Iterator i;
|
||||
|
||||
SET_FOREACH(member, u->dependencies[UNIT_BEFORE], i) {
|
||||
HASHMAP_FOREACH_KEY(v, member, u->dependencies[UNIT_BEFORE], i) {
|
||||
|
||||
if (member == u)
|
||||
continue;
|
||||
@@ -1575,8 +1576,9 @@ static void unit_add_siblings_to_cgroup_realize_queue(Unit *u) {
|
||||
while ((slice = UNIT_DEREF(u->slice))) {
|
||||
Iterator i;
|
||||
Unit *m;
|
||||
void *v;
|
||||
|
||||
SET_FOREACH(m, slice->dependencies[UNIT_BEFORE], i) {
|
||||
HASHMAP_FOREACH_KEY(v, m, u->dependencies[UNIT_BEFORE], i) {
|
||||
if (m == u)
|
||||
continue;
|
||||
|
||||
@@ -2426,8 +2428,9 @@ void unit_invalidate_cgroup_bpf(Unit *u) {
|
||||
if (u->type == UNIT_SLICE) {
|
||||
Unit *member;
|
||||
Iterator i;
|
||||
void *v;
|
||||
|
||||
SET_FOREACH(member, u->dependencies[UNIT_BEFORE], i) {
|
||||
HASHMAP_FOREACH_KEY(v, member, u->dependencies[UNIT_BEFORE], i) {
|
||||
if (member == u)
|
||||
continue;
|
||||
|
||||
|
||||
@@ -139,8 +139,10 @@ static int property_get_tainted(
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
char buf[sizeof("split-usr:cgroups-missing:local-hwclock:")] = "", *e = buf;
|
||||
char buf[sizeof("split-usr:cgroups-missing:local-hwclock:var-run-bad:")] = "", *e = buf;
|
||||
_cleanup_free_ char *destination = NULL;
|
||||
Manager *m = userdata;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
assert(reply);
|
||||
@@ -155,6 +157,10 @@ static int property_get_tainted(
|
||||
if (clock_is_localtime(NULL) > 0)
|
||||
e = stpcpy(e, "local-hwclock:");
|
||||
|
||||
r = readlink_malloc("/var/run", &destination);
|
||||
if (r < 0 || !PATH_IN_SET(destination, "../run", "/run"))
|
||||
e = stpcpy(e, "var-run-bad:");
|
||||
|
||||
/* remove the last ':' */
|
||||
if (e != buf)
|
||||
e[-1] = 0;
|
||||
|
||||
@@ -36,7 +36,7 @@ static int property_get_what(
|
||||
sd_bus_error *error) {
|
||||
|
||||
Mount *m = userdata;
|
||||
const char *d;
|
||||
const char *d = NULL;
|
||||
|
||||
assert(bus);
|
||||
assert(reply);
|
||||
@@ -46,8 +46,6 @@ static int property_get_what(
|
||||
d = m->parameters_proc_self_mountinfo.what;
|
||||
else if (m->from_fragment && m->parameters_fragment.what)
|
||||
d = m->parameters_fragment.what;
|
||||
else
|
||||
d = "";
|
||||
|
||||
return sd_bus_message_append(reply, "s", d);
|
||||
}
|
||||
@@ -62,7 +60,7 @@ static int property_get_options(
|
||||
sd_bus_error *error) {
|
||||
|
||||
Mount *m = userdata;
|
||||
const char *d;
|
||||
const char *d = NULL;
|
||||
|
||||
assert(bus);
|
||||
assert(reply);
|
||||
@@ -72,8 +70,6 @@ static int property_get_options(
|
||||
d = m->parameters_proc_self_mountinfo.options;
|
||||
else if (m->from_fragment && m->parameters_fragment.options)
|
||||
d = m->parameters_fragment.options;
|
||||
else
|
||||
d = "";
|
||||
|
||||
return sd_bus_message_append(reply, "s", d);
|
||||
}
|
||||
@@ -87,13 +83,19 @@ static int property_get_type(
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
const char *fstype = NULL;
|
||||
Mount *m = userdata;
|
||||
|
||||
assert(bus);
|
||||
assert(reply);
|
||||
assert(m);
|
||||
|
||||
return sd_bus_message_append(reply, "s", mount_get_fstype(m));
|
||||
if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.fstype)
|
||||
fstype = m->parameters_proc_self_mountinfo.fstype;
|
||||
else if (m->from_fragment && m->parameters_fragment.fstype)
|
||||
fstype = m->parameters_fragment.fstype;
|
||||
|
||||
return sd_bus_message_append(reply, "s", fstype);
|
||||
}
|
||||
|
||||
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, mount_result, MountResult);
|
||||
|
||||
@@ -100,9 +100,10 @@ static int property_get_dependencies(
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
Set *s = *(Set**) userdata;
|
||||
Hashmap *h = *(Hashmap**) userdata;
|
||||
Iterator j;
|
||||
Unit *u;
|
||||
void *v;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
@@ -112,7 +113,7 @@ static int property_get_dependencies(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
SET_FOREACH(u, s, j) {
|
||||
HASHMAP_FOREACH_KEY(v, u, h, j) {
|
||||
r = sd_bus_message_append(reply, "s", u->id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -1395,7 +1396,7 @@ static int bus_unit_set_transient_property(
|
||||
if (mode != UNIT_CHECK) {
|
||||
_cleanup_free_ char *label = NULL;
|
||||
|
||||
r = unit_add_dependency_by_name(u, d, other, NULL, true);
|
||||
r = unit_add_dependency_by_name(u, d, other, NULL, true, UNIT_DEPENDENCY_FILE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
@@ -256,60 +256,89 @@ static int device_update_description(Unit *u, struct udev_device *dev, const cha
|
||||
}
|
||||
|
||||
static int device_add_udev_wants(Unit *u, struct udev_device *dev) {
|
||||
const char *wants, *property, *p;
|
||||
const char *wants, *property;
|
||||
int r;
|
||||
|
||||
assert(u);
|
||||
assert(dev);
|
||||
|
||||
property = MANAGER_IS_USER(u->manager) ? "SYSTEMD_USER_WANTS" : "SYSTEMD_WANTS";
|
||||
|
||||
wants = udev_device_get_property_value(dev, property);
|
||||
for (p = wants;;) {
|
||||
if (!wants)
|
||||
return 0;
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *word = NULL, *k = NULL;
|
||||
|
||||
r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
|
||||
r = extract_first_word(&wants, &word, NULL, EXTRACT_QUOTES);
|
||||
if (r == 0)
|
||||
return 0;
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
if (r < 0)
|
||||
return log_unit_error_errno(u, r, "Failed to add parse %s: %m", property);
|
||||
return log_unit_error_errno(u, r, "Failed to parse property %s with value %s: %m", property, wants);
|
||||
|
||||
r = unit_name_mangle(word, UNIT_NAME_NOGLOB, &k);
|
||||
if (r < 0)
|
||||
return log_unit_error_errno(u, r, "Failed to mangle unit name \"%s\": %m", word);
|
||||
if (unit_name_is_valid(word, UNIT_NAME_TEMPLATE) && DEVICE(u)->sysfs) {
|
||||
_cleanup_free_ char *escaped = NULL;
|
||||
|
||||
r = unit_add_dependency_by_name(u, UNIT_WANTS, k, NULL, true);
|
||||
/* If the unit name is specified as template, then automatically fill in the sysfs path of the
|
||||
* device as instance name, properly escaped. */
|
||||
|
||||
r = unit_name_path_escape(DEVICE(u)->sysfs, &escaped);
|
||||
if (r < 0)
|
||||
return log_unit_error_errno(u, r, "Failed to escape %s: %m", DEVICE(u)->sysfs);
|
||||
|
||||
r = unit_name_replace_instance(word, escaped, &k);
|
||||
if (r < 0)
|
||||
return log_unit_error_errno(u, r, "Failed to build %s instance of template %s: %m", escaped, word);
|
||||
} else {
|
||||
/* If this is not a template, then let's mangle it so, that it becomes a valid unit name. */
|
||||
|
||||
r = unit_name_mangle(word, UNIT_NAME_NOGLOB, &k);
|
||||
if (r < 0)
|
||||
return log_unit_error_errno(u, r, "Failed to mangle unit name \"%s\": %m", word);
|
||||
}
|
||||
|
||||
r = unit_add_dependency_by_name(u, UNIT_WANTS, k, NULL, true, UNIT_DEPENDENCY_UDEV);
|
||||
if (r < 0)
|
||||
return log_unit_error_errno(u, r, "Failed to add wants dependency: %m");
|
||||
return log_unit_error_errno(u, r, "Failed to add Wants= dependency: %m");
|
||||
}
|
||||
}
|
||||
|
||||
static bool device_is_bound_by_mounts(Unit *d, struct udev_device *dev) {
|
||||
static bool device_is_bound_by_mounts(Device *d, struct udev_device *dev) {
|
||||
const char *bound_by;
|
||||
int r = false;
|
||||
int r;
|
||||
|
||||
assert(d);
|
||||
assert(dev);
|
||||
|
||||
bound_by = udev_device_get_property_value(dev, "SYSTEMD_MOUNT_DEVICE_BOUND");
|
||||
if (bound_by)
|
||||
r = parse_boolean(bound_by) > 0;
|
||||
if (bound_by) {
|
||||
r = parse_boolean(bound_by);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to parse SYSTEMD_MOUNT_DEVICE_BOUND='%s' udev property of %s, ignoring: %m", bound_by, strna(d->sysfs));
|
||||
|
||||
DEVICE(d)->bind_mounts = r;
|
||||
return r;
|
||||
d->bind_mounts = r > 0;
|
||||
} else
|
||||
d->bind_mounts = false;
|
||||
|
||||
return d->bind_mounts;
|
||||
}
|
||||
|
||||
static int device_upgrade_mount_deps(Unit *u) {
|
||||
Unit *other;
|
||||
Iterator i;
|
||||
void *v;
|
||||
int r;
|
||||
|
||||
SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY], i) {
|
||||
/* Let's upgrade Requires= to BindsTo= on us. (Used when SYSTEMD_MOUNT_DEVICE_BOUND is set) */
|
||||
|
||||
HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_REQUIRED_BY], i) {
|
||||
if (other->type != UNIT_MOUNT)
|
||||
continue;
|
||||
|
||||
r = unit_add_dependency(other, UNIT_BINDS_TO, u, true);
|
||||
r = unit_add_dependency(other, UNIT_BINDS_TO, u, true, UNIT_DEPENDENCY_UDEV);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@@ -337,23 +366,26 @@ static int device_setup_unit(Manager *m, struct udev_device *dev, const char *pa
|
||||
return log_error_errno(r, "Failed to generate unit name from device path: %m");
|
||||
|
||||
u = manager_get_unit(m, e);
|
||||
if (u) {
|
||||
/* The device unit can still be present even if the device was unplugged: a mount unit can reference it hence
|
||||
* preventing the GC to have garbaged it. That's desired since the device unit may have a dependency on the
|
||||
* mount unit which was added during the loading of the later. */
|
||||
if (dev && DEVICE(u)->state == DEVICE_PLUGGED) {
|
||||
|
||||
/* The device unit can still be present even if the device was
|
||||
* unplugged: a mount unit can reference it hence preventing
|
||||
* the GC to have garbaged it. That's desired since the device
|
||||
* unit may have a dependency on the mount unit which was
|
||||
* added during the loading of the later. */
|
||||
if (dev && u && DEVICE(u)->state == DEVICE_PLUGGED) {
|
||||
/* This unit is in plugged state: we're sure it's
|
||||
* attached to a device. */
|
||||
if (!path_equal(DEVICE(u)->sysfs, sysfs)) {
|
||||
log_unit_debug(u, "Dev %s appeared twice with different sysfs paths %s and %s",
|
||||
e, DEVICE(u)->sysfs, sysfs);
|
||||
return -EEXIST;
|
||||
/* This unit is in plugged state: we're sure it's attached to a device. */
|
||||
if (!path_equal(DEVICE(u)->sysfs, sysfs)) {
|
||||
log_unit_debug(u, "Dev %s appeared twice with different sysfs paths %s and %s",
|
||||
e, DEVICE(u)->sysfs, sysfs);
|
||||
return -EEXIST;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!u) {
|
||||
delete = false;
|
||||
|
||||
/* Let's remove all dependencies generated due to udev properties. We'll readd whatever is configured
|
||||
* now below. */
|
||||
unit_remove_dependencies(u, UNIT_DEPENDENCY_UDEV);
|
||||
} else {
|
||||
delete = true;
|
||||
|
||||
r = unit_new_for_name(m, sizeof(Device), e, &u);
|
||||
@@ -361,8 +393,7 @@ static int device_setup_unit(Manager *m, struct udev_device *dev, const char *pa
|
||||
goto fail;
|
||||
|
||||
unit_add_to_load_queue(u);
|
||||
} else
|
||||
delete = false;
|
||||
}
|
||||
|
||||
/* If this was created via some dependency and has not
|
||||
* actually been seen yet ->sysfs will not be
|
||||
@@ -380,16 +411,13 @@ static int device_setup_unit(Manager *m, struct udev_device *dev, const char *pa
|
||||
(void) device_add_udev_wants(u, dev);
|
||||
}
|
||||
|
||||
/* So the user wants the mount units to be bound to the device but a
|
||||
* mount unit might has been seen by systemd before the device appears
|
||||
* on its radar. In this case the device unit is partially initialized
|
||||
* and includes the deps on the mount unit but at that time the "bind
|
||||
* mounts" flag wasn't not present. Fix this up now. */
|
||||
if (dev && device_is_bound_by_mounts(u, dev))
|
||||
/* So the user wants the mount units to be bound to the device but a mount unit might has been seen by systemd
|
||||
* before the device appears on its radar. In this case the device unit is partially initialized and includes
|
||||
* the deps on the mount unit but at that time the "bind mounts" flag wasn't not present. Fix this up now. */
|
||||
if (dev && device_is_bound_by_mounts(DEVICE(u), dev))
|
||||
device_upgrade_mount_deps(u);
|
||||
|
||||
/* Note that this won't dispatch the load queue, the caller
|
||||
* has to do that if needed and appropriate */
|
||||
/* Note that this won't dispatch the load queue, the caller has to do that if needed and appropriate */
|
||||
|
||||
unit_add_to_dbus_queue(u);
|
||||
return 0;
|
||||
|
||||
@@ -437,6 +437,7 @@ int job_type_merge_and_collapse(JobType *a, JobType b, Unit *u) {
|
||||
static bool job_is_runnable(Job *j) {
|
||||
Iterator i;
|
||||
Unit *other;
|
||||
void *v;
|
||||
|
||||
assert(j);
|
||||
assert(j->installed);
|
||||
@@ -459,13 +460,12 @@ static bool job_is_runnable(Job *j) {
|
||||
return true;
|
||||
|
||||
if (IN_SET(j->type, JOB_START, JOB_VERIFY_ACTIVE, JOB_RELOAD)) {
|
||||
|
||||
/* Immediate result is that the job is or might be
|
||||
* started. In this case let's wait for the
|
||||
* dependencies, regardless whether they are
|
||||
* starting or stopping something. */
|
||||
|
||||
SET_FOREACH(other, j->unit->dependencies[UNIT_AFTER], i)
|
||||
HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER], i)
|
||||
if (other->job)
|
||||
return false;
|
||||
}
|
||||
@@ -473,7 +473,7 @@ static bool job_is_runnable(Job *j) {
|
||||
/* Also, if something else is being stopped and we should
|
||||
* change state after it, then let's wait. */
|
||||
|
||||
SET_FOREACH(other, j->unit->dependencies[UNIT_BEFORE], i)
|
||||
HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE], i)
|
||||
if (other->job &&
|
||||
IN_SET(other->job->type, JOB_STOP, JOB_RESTART))
|
||||
return false;
|
||||
@@ -832,10 +832,11 @@ static void job_emit_status_message(Unit *u, JobType t, JobResult result) {
|
||||
static void job_fail_dependencies(Unit *u, UnitDependency d) {
|
||||
Unit *other;
|
||||
Iterator i;
|
||||
void *v;
|
||||
|
||||
assert(u);
|
||||
|
||||
SET_FOREACH(other, u->dependencies[d], i) {
|
||||
HASHMAP_FOREACH_KEY(v, other, u->dependencies[d], i) {
|
||||
Job *j = other->job;
|
||||
|
||||
if (!j)
|
||||
@@ -852,6 +853,7 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool alr
|
||||
Unit *other;
|
||||
JobType t;
|
||||
Iterator i;
|
||||
void *v;
|
||||
|
||||
assert(j);
|
||||
assert(j->installed);
|
||||
@@ -919,12 +921,12 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool alr
|
||||
|
||||
finish:
|
||||
/* Try to start the next jobs that can be started */
|
||||
SET_FOREACH(other, u->dependencies[UNIT_AFTER], i)
|
||||
HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_AFTER], i)
|
||||
if (other->job) {
|
||||
job_add_to_run_queue(other->job);
|
||||
job_add_to_gc_queue(other->job);
|
||||
}
|
||||
SET_FOREACH(other, u->dependencies[UNIT_BEFORE], i)
|
||||
HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_BEFORE], i)
|
||||
if (other->job) {
|
||||
job_add_to_run_queue(other->job);
|
||||
job_add_to_gc_queue(other->job);
|
||||
@@ -1273,6 +1275,7 @@ int job_get_timeout(Job *j, usec_t *timeout) {
|
||||
bool job_check_gc(Job *j) {
|
||||
Unit *other;
|
||||
Iterator i;
|
||||
void *v;
|
||||
|
||||
assert(j);
|
||||
|
||||
@@ -1301,7 +1304,7 @@ bool job_check_gc(Job *j) {
|
||||
|
||||
/* If a job is ordered after ours, and is to be started, then it needs to wait for us, regardless if we stop or
|
||||
* start, hence let's not GC in that case. */
|
||||
SET_FOREACH(other, j->unit->dependencies[UNIT_BEFORE], i) {
|
||||
HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE], i) {
|
||||
if (!other->job)
|
||||
continue;
|
||||
|
||||
@@ -1314,7 +1317,7 @@ bool job_check_gc(Job *j) {
|
||||
|
||||
/* If we are going down, but something else is ordered After= us, then it needs to wait for us */
|
||||
if (IN_SET(j->type, JOB_STOP, JOB_RESTART))
|
||||
SET_FOREACH(other, j->unit->dependencies[UNIT_AFTER], i) {
|
||||
HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER], i) {
|
||||
if (!other->job)
|
||||
continue;
|
||||
|
||||
@@ -1392,6 +1395,7 @@ int job_get_before(Job *j, Job*** ret) {
|
||||
size_t n = 0, n_allocated = 0;
|
||||
Unit *other = NULL;
|
||||
Iterator i;
|
||||
void *v;
|
||||
|
||||
/* Returns a list of all pending jobs that need to finish before this job may be started. */
|
||||
|
||||
@@ -1405,7 +1409,7 @@ int job_get_before(Job *j, Job*** ret) {
|
||||
|
||||
if (IN_SET(j->type, JOB_START, JOB_VERIFY_ACTIVE, JOB_RELOAD)) {
|
||||
|
||||
SET_FOREACH(other, j->unit->dependencies[UNIT_AFTER], i) {
|
||||
HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER], i) {
|
||||
if (!other->job)
|
||||
continue;
|
||||
|
||||
@@ -1415,7 +1419,7 @@ int job_get_before(Job *j, Job*** ret) {
|
||||
}
|
||||
}
|
||||
|
||||
SET_FOREACH(other, j->unit->dependencies[UNIT_BEFORE], i) {
|
||||
HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE], i) {
|
||||
if (!other->job)
|
||||
continue;
|
||||
|
||||
@@ -1439,6 +1443,7 @@ int job_get_after(Job *j, Job*** ret) {
|
||||
_cleanup_free_ Job** list = NULL;
|
||||
size_t n = 0, n_allocated = 0;
|
||||
Unit *other = NULL;
|
||||
void *v;
|
||||
Iterator i;
|
||||
|
||||
assert(j);
|
||||
@@ -1446,7 +1451,7 @@ int job_get_after(Job *j, Job*** ret) {
|
||||
|
||||
/* Returns a list of all pending jobs that are waiting for this job to finish. */
|
||||
|
||||
SET_FOREACH(other, j->unit->dependencies[UNIT_BEFORE], i) {
|
||||
HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE], i) {
|
||||
if (!other->job)
|
||||
continue;
|
||||
|
||||
@@ -1463,7 +1468,7 @@ int job_get_after(Job *j, Job*** ret) {
|
||||
|
||||
if (IN_SET(j->type, JOB_STOP, JOB_RESTART)) {
|
||||
|
||||
SET_FOREACH(other, j->unit->dependencies[UNIT_AFTER], i) {
|
||||
HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER], i) {
|
||||
if (!other->job)
|
||||
continue;
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ static int process_deps(Unit *u, UnitDependency dependency, const char *dir_suff
|
||||
log_unit_warning(u, "%s dependency dropin %s target %s has different name",
|
||||
unit_dependency_to_string(dependency), *p, target);
|
||||
|
||||
r = unit_add_dependency_by_name(u, dependency, entry, *p, true);
|
||||
r = unit_add_dependency_by_name(u, dependency, entry, *p, true, UNIT_DEPENDENCY_FILE);
|
||||
if (r < 0)
|
||||
log_unit_error_errno(u, r, "cannot add %s dependency on %s, ignoring: %m",
|
||||
unit_dependency_to_string(dependency), entry);
|
||||
|
||||
@@ -142,7 +142,7 @@ int config_parse_unit_deps(
|
||||
continue;
|
||||
}
|
||||
|
||||
r = unit_add_dependency_by_name(u, d, k, NULL, true);
|
||||
r = unit_add_dependency_by_name(u, d, k, NULL, true, UNIT_DEPENDENCY_FILE);
|
||||
if (r < 0)
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add dependency on %s, ignoring: %m", k);
|
||||
}
|
||||
@@ -1538,7 +1538,7 @@ int config_parse_trigger_unit(
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
if (!set_isempty(u->dependencies[UNIT_TRIGGERS])) {
|
||||
if (!hashmap_isempty(u->dependencies[UNIT_TRIGGERS])) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Multiple units to trigger specified, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
@@ -1560,7 +1560,7 @@ int config_parse_trigger_unit(
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = unit_add_two_dependencies_by_name(u, UNIT_BEFORE, UNIT_TRIGGERS, p, NULL, true);
|
||||
r = unit_add_two_dependencies_by_name(u, UNIT_BEFORE, UNIT_TRIGGERS, p, NULL, true, UNIT_DEPENDENCY_FILE);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add trigger on %s, ignoring: %m", p);
|
||||
return 0;
|
||||
@@ -1760,11 +1760,11 @@ int config_parse_service_sockets(
|
||||
continue;
|
||||
}
|
||||
|
||||
r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_WANTS, UNIT_AFTER, k, NULL, true);
|
||||
r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_WANTS, UNIT_AFTER, k, NULL, true, UNIT_DEPENDENCY_FILE);
|
||||
if (r < 0)
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add dependency on %s, ignoring: %m", k);
|
||||
|
||||
r = unit_add_dependency_by_name(UNIT(s), UNIT_TRIGGERED_BY, k, NULL, true);
|
||||
r = unit_add_dependency_by_name(UNIT(s), UNIT_TRIGGERED_BY, k, NULL, true, UNIT_DEPENDENCY_FILE);
|
||||
if (r < 0)
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add dependency on %s, ignoring: %m", k);
|
||||
}
|
||||
@@ -2569,7 +2569,7 @@ int config_parse_unit_requires_mounts_for(
|
||||
continue;
|
||||
}
|
||||
|
||||
r = unit_require_mounts_for(u, resolved);
|
||||
r = unit_require_mounts_for(u, resolved, UNIT_DEPENDENCY_FILE);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add required mount \"%s\", ignoring: %m", resolved);
|
||||
continue;
|
||||
|
||||
@@ -967,21 +967,23 @@ enum {
|
||||
};
|
||||
|
||||
static void unit_gc_mark_good(Unit *u, unsigned gc_marker) {
|
||||
Iterator i;
|
||||
Unit *other;
|
||||
Iterator i;
|
||||
void *v;
|
||||
|
||||
u->gc_marker = gc_marker + GC_OFFSET_GOOD;
|
||||
|
||||
/* Recursively mark referenced units as GOOD as well */
|
||||
SET_FOREACH(other, u->dependencies[UNIT_REFERENCES], i)
|
||||
HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_REFERENCES], i)
|
||||
if (other->gc_marker == gc_marker + GC_OFFSET_UNSURE)
|
||||
unit_gc_mark_good(other, gc_marker);
|
||||
}
|
||||
|
||||
static void unit_gc_sweep(Unit *u, unsigned gc_marker) {
|
||||
Iterator i;
|
||||
Unit *other;
|
||||
bool is_bad;
|
||||
Iterator i;
|
||||
void *v;
|
||||
|
||||
assert(u);
|
||||
|
||||
@@ -999,7 +1001,7 @@ static void unit_gc_sweep(Unit *u, unsigned gc_marker) {
|
||||
|
||||
is_bad = true;
|
||||
|
||||
SET_FOREACH(other, u->dependencies[UNIT_REFERENCED_BY], i) {
|
||||
HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_REFERENCED_BY], i) {
|
||||
unit_gc_sweep(other, gc_marker);
|
||||
|
||||
if (other->gc_marker == gc_marker + GC_OFFSET_GOOD)
|
||||
|
||||
100
src/core/mount.c
100
src/core/mount.c
@@ -156,21 +156,6 @@ static bool needs_quota(const MountParameters *p) {
|
||||
"usrquota\0" "grpquota\0" "quota\0" "usrjquota\0" "grpjquota\0");
|
||||
}
|
||||
|
||||
const char *mount_get_fstype(const Mount *m) {
|
||||
const char *type = NULL;
|
||||
|
||||
assert(m);
|
||||
|
||||
if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.fstype)
|
||||
type = m->parameters_proc_self_mountinfo.fstype;
|
||||
else if (m->from_fragment && m->parameters_fragment.fstype)
|
||||
type = m->parameters_fragment.fstype;
|
||||
else
|
||||
type = "";
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
static void mount_init(Unit *u) {
|
||||
Mount *m = MOUNT(u);
|
||||
|
||||
@@ -280,9 +265,7 @@ _pure_ static MountParameters* get_mount_parameters(Mount *m) {
|
||||
return get_mount_parameters_fragment(m);
|
||||
}
|
||||
|
||||
static int mount_add_mount_links(Mount *m) {
|
||||
_cleanup_free_ char *parent = NULL;
|
||||
const char *fstype;
|
||||
static int mount_add_mount_dependencies(Mount *m) {
|
||||
MountParameters *pm;
|
||||
Unit *other;
|
||||
Iterator i;
|
||||
@@ -292,33 +275,32 @@ static int mount_add_mount_links(Mount *m) {
|
||||
assert(m);
|
||||
|
||||
if (!path_equal(m->where, "/")) {
|
||||
/* Adds in links to other mount points that might lie further
|
||||
* up in the hierarchy */
|
||||
_cleanup_free_ char *parent = NULL;
|
||||
|
||||
/* Adds in links to other mount points that might lie further up in the hierarchy */
|
||||
|
||||
parent = dirname_malloc(m->where);
|
||||
if (!parent)
|
||||
return -ENOMEM;
|
||||
|
||||
r = unit_require_mounts_for(UNIT(m), parent);
|
||||
r = unit_require_mounts_for(UNIT(m), parent, UNIT_DEPENDENCY_IMPLICIT);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Adds in links to other mount points that might be needed
|
||||
* for the source path (if this is a bind mount or a loop mount) to be
|
||||
* available. */
|
||||
/* Adds in dependencies to other mount points that might be needed for the source path (if this is a bind mount
|
||||
* or a loop mount) to be available. */
|
||||
pm = get_mount_parameters_fragment(m);
|
||||
if (pm && pm->what &&
|
||||
path_is_absolute(pm->what) &&
|
||||
(mount_is_bind(pm) || mount_is_loop(pm) || !mount_is_network(pm))) {
|
||||
|
||||
r = unit_require_mounts_for(UNIT(m), pm->what);
|
||||
r = unit_require_mounts_for(UNIT(m), pm->what, UNIT_DEPENDENCY_FILE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Adds in links to other units that use this path or paths
|
||||
* further down in the hierarchy */
|
||||
/* Adds in dependencies to other units that use this path or paths further down in the hierarchy */
|
||||
s = manager_get_units_requiring_mounts_for(UNIT(m)->manager, m->where);
|
||||
SET_FOREACH(other, s, i) {
|
||||
|
||||
@@ -328,32 +310,25 @@ static int mount_add_mount_links(Mount *m) {
|
||||
if (other == UNIT(m))
|
||||
continue;
|
||||
|
||||
r = unit_add_dependency(other, UNIT_AFTER, UNIT(m), true);
|
||||
r = unit_add_dependency(other, UNIT_AFTER, UNIT(m), true, UNIT_DEPENDENCY_PATH);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (UNIT(m)->fragment_path) {
|
||||
/* If we have fragment configuration, then make this dependency required */
|
||||
r = unit_add_dependency(other, UNIT_REQUIRES, UNIT(m), true);
|
||||
r = unit_add_dependency(other, UNIT_REQUIRES, UNIT(m), true, UNIT_DEPENDENCY_PATH);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
/* If this is a tmpfs mount then we have to unmount it before we try to deactivate swaps */
|
||||
fstype = mount_get_fstype(m);
|
||||
if (streq(fstype, "tmpfs")) {
|
||||
r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, SPECIAL_SWAP_TARGET, NULL, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mount_add_device_links(Mount *m) {
|
||||
MountParameters *p;
|
||||
static int mount_add_device_dependencies(Mount *m) {
|
||||
bool device_wants_mount = false;
|
||||
UnitDependencyMask mask;
|
||||
MountParameters *p;
|
||||
UnitDependency dep;
|
||||
int r;
|
||||
|
||||
@@ -391,16 +366,19 @@ static int mount_add_device_links(Mount *m) {
|
||||
* automatically stopped when the device disappears suddenly. */
|
||||
dep = mount_is_bound_to_device(m) ? UNIT_BINDS_TO : UNIT_REQUIRES;
|
||||
|
||||
r = unit_add_node_link(UNIT(m), p->what, device_wants_mount, dep);
|
||||
mask = m->from_fragment ? UNIT_DEPENDENCY_FILE : UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT;
|
||||
|
||||
r = unit_add_node_dependency(UNIT(m), p->what, device_wants_mount, dep, mask);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mount_add_quota_links(Mount *m) {
|
||||
int r;
|
||||
static int mount_add_quota_dependencies(Mount *m) {
|
||||
UnitDependencyMask mask;
|
||||
MountParameters *p;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
@@ -414,11 +392,13 @@ static int mount_add_quota_links(Mount *m) {
|
||||
if (!needs_quota(p))
|
||||
return 0;
|
||||
|
||||
r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTACHECK_SERVICE, NULL, true);
|
||||
mask = m->from_fragment ? UNIT_DEPENDENCY_FILE : UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT;
|
||||
|
||||
r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTACHECK_SERVICE, NULL, true, mask);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTAON_SERVICE, NULL, true);
|
||||
r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTAON_SERVICE, NULL, true, mask);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -457,9 +437,10 @@ static bool mount_is_extrinsic(Mount *m) {
|
||||
}
|
||||
|
||||
static int mount_add_default_dependencies(Mount *m) {
|
||||
UnitDependencyMask mask;
|
||||
int r;
|
||||
MountParameters *p;
|
||||
const char *after;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
@@ -476,6 +457,8 @@ static int mount_add_default_dependencies(Mount *m) {
|
||||
if (!p)
|
||||
return 0;
|
||||
|
||||
mask = m->from_fragment ? UNIT_DEPENDENCY_FILE : UNIT_DEPENDENCY_MOUNTINFO_DEFAULT;
|
||||
|
||||
if (mount_is_network(p)) {
|
||||
/* We order ourselves after network.target. This is
|
||||
* primarily useful at shutdown: services that take
|
||||
@@ -483,7 +466,7 @@ static int mount_add_default_dependencies(Mount *m) {
|
||||
* network.target, so that they are shut down only
|
||||
* after this mount unit is stopped. */
|
||||
|
||||
r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, SPECIAL_NETWORK_TARGET, NULL, true);
|
||||
r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, SPECIAL_NETWORK_TARGET, NULL, true, mask);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -494,7 +477,7 @@ static int mount_add_default_dependencies(Mount *m) {
|
||||
* whose purpose it is to delay this until the network
|
||||
* is "up". */
|
||||
|
||||
r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_WANTS, UNIT_AFTER, SPECIAL_NETWORK_ONLINE_TARGET, NULL, true);
|
||||
r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_WANTS, UNIT_AFTER, SPECIAL_NETWORK_ONLINE_TARGET, NULL, true, mask);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -502,14 +485,21 @@ static int mount_add_default_dependencies(Mount *m) {
|
||||
} else
|
||||
after = SPECIAL_LOCAL_FS_PRE_TARGET;
|
||||
|
||||
r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, NULL, true);
|
||||
r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, NULL, true, mask);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
|
||||
r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true, mask);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* If this is a tmpfs mount then we have to unmount it before we try to deactivate swaps */
|
||||
if (streq_ptr(p->fstype, "tmpfs")) {
|
||||
r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, SPECIAL_SWAP_TARGET, NULL, true, mask);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -577,15 +567,15 @@ static int mount_add_extras(Mount *m) {
|
||||
return r;
|
||||
}
|
||||
|
||||
r = mount_add_device_links(m);
|
||||
r = mount_add_device_dependencies(m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = mount_add_mount_links(m);
|
||||
r = mount_add_mount_dependencies(m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = mount_add_quota_links(m);
|
||||
r = mount_add_quota_dependencies(m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -1453,11 +1443,11 @@ static int mount_setup_new_unit(
|
||||
int r;
|
||||
|
||||
target = mount_is_network(p) ? SPECIAL_REMOTE_FS_TARGET : SPECIAL_LOCAL_FS_TARGET;
|
||||
r = unit_add_dependency_by_name(u, UNIT_BEFORE, target, NULL, true);
|
||||
r = unit_add_dependency_by_name(u, UNIT_BEFORE, target, NULL, true, UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = unit_add_dependency_by_name(u, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
|
||||
r = unit_add_dependency_by_name(u, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true, UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@@ -1515,7 +1505,7 @@ static int mount_setup_existing_unit(
|
||||
* in the dependency "Set*" objects who created a
|
||||
* dependency), we can only add deps, never lose them,
|
||||
* until the next full daemon-reload. */
|
||||
unit_add_dependency_by_name(u, UNIT_BEFORE, SPECIAL_REMOTE_FS_TARGET, NULL, true);
|
||||
unit_add_dependency_by_name(u, UNIT_BEFORE, SPECIAL_REMOTE_FS_TARGET, NULL, true, UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT);
|
||||
load_extras = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -110,5 +110,3 @@ MountExecCommand mount_exec_command_from_string(const char *s) _pure_;
|
||||
|
||||
const char* mount_result_to_string(MountResult i) _const_;
|
||||
MountResult mount_result_from_string(const char *s) _pure_;
|
||||
|
||||
const char *mount_get_fstype(const Mount *m);
|
||||
|
||||
@@ -277,14 +277,14 @@ static void path_done(Unit *u) {
|
||||
path_free_specs(p);
|
||||
}
|
||||
|
||||
static int path_add_mount_links(Path *p) {
|
||||
static int path_add_mount_dependencies(Path *p) {
|
||||
PathSpec *s;
|
||||
int r;
|
||||
|
||||
assert(p);
|
||||
|
||||
LIST_FOREACH(spec, s, p->specs) {
|
||||
r = unit_require_mounts_for(UNIT(p), s->path);
|
||||
r = unit_require_mounts_for(UNIT(p), s->path, UNIT_DEPENDENCY_FILE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@@ -314,17 +314,33 @@ static int path_add_default_dependencies(Path *p) {
|
||||
if (!UNIT(p)->default_dependencies)
|
||||
return 0;
|
||||
|
||||
r = unit_add_dependency_by_name(UNIT(p), UNIT_BEFORE, SPECIAL_PATHS_TARGET, NULL, true);
|
||||
r = unit_add_dependency_by_name(UNIT(p), UNIT_BEFORE, SPECIAL_PATHS_TARGET, NULL, true, UNIT_DEPENDENCY_DEFAULT);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (MANAGER_IS_SYSTEM(UNIT(p)->manager)) {
|
||||
r = unit_add_two_dependencies_by_name(UNIT(p), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true);
|
||||
r = unit_add_two_dependencies_by_name(UNIT(p), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true, UNIT_DEPENDENCY_DEFAULT);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return unit_add_two_dependencies_by_name(UNIT(p), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
|
||||
return unit_add_two_dependencies_by_name(UNIT(p), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true, UNIT_DEPENDENCY_DEFAULT);
|
||||
}
|
||||
|
||||
static int path_add_trigger_dependencies(Path *p) {
|
||||
Unit *x;
|
||||
int r;
|
||||
|
||||
assert(p);
|
||||
|
||||
if (!hashmap_isempty(UNIT(p)->dependencies[UNIT_TRIGGERS]))
|
||||
return 0;
|
||||
|
||||
r = unit_load_related_unit(UNIT(p), ".service", &x);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return unit_add_two_dependencies(UNIT(p), UNIT_BEFORE, UNIT_TRIGGERS, x, true, UNIT_DEPENDENCY_IMPLICIT);
|
||||
}
|
||||
|
||||
static int path_load(Unit *u) {
|
||||
@@ -340,19 +356,11 @@ static int path_load(Unit *u) {
|
||||
|
||||
if (u->load_state == UNIT_LOADED) {
|
||||
|
||||
if (set_isempty(u->dependencies[UNIT_TRIGGERS])) {
|
||||
Unit *x;
|
||||
r = path_add_trigger_dependencies(p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = unit_load_related_unit(u, ".service", &x);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, x, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = path_add_mount_links(p);
|
||||
r = path_add_mount_dependencies(p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user