Compare commits
14 Commits
383b0d6997
...
c5ace602f2
Author | SHA1 | Date |
---|---|---|
leafcompost | c5ace602f2 | |
Antonio Alvarez Feijoo | fb4c82b643 | |
Daan De Meyer | 4d9ccdc9ae | |
Antonio Alvarez Feijoo | bf39626d61 | |
Marius Hoch | ff831e7c50 | |
Daan De Meyer | 81af8f998e | |
chenjiayi | 4fc8a63f9e | |
Jason Yundt | dfb3155419 | |
Daan De Meyer | fc5037e7d7 | |
Yu Watanabe | 13f6ec7ce7 | |
Yu Watanabe | 6e1816ef16 | |
maia x. | 77aa738875 | |
maia x. | f659808442 | |
maia x. | a9dbf27342 |
|
@ -760,8 +760,9 @@ sensor:modalias:i2c:bmc150_accel:dmi:*:svnLENOVO:*:pvrLenovoYoga300-11IBR:*
|
|||
sensor:modalias:acpi:ACCL0001*:dmi:*:svnLENOVO:pn60072:pvr851*:*
|
||||
ACCEL_MOUNT_MATRIX=0, 1, 0; -1, 0, 0; 0, 0, 1
|
||||
|
||||
# IdeaPad Duet 3 10IGL5 (82AT)
|
||||
# IdeaPad Duet 3 10IGL5 (82AT) and 10IGL5-LTE (82HK)
|
||||
sensor:modalias:acpi:SMO8B30*:dmi:*:svnLENOVO*:pn82AT:*
|
||||
sensor:modalias:acpi:SMO8B30*:dmi:*:svnLENOVO*:pn82HK:*
|
||||
ACCEL_MOUNT_MATRIX=0, 1, 0; -1, 0, 0; 0, 0, 1
|
||||
|
||||
#########################################
|
||||
|
|
|
@ -593,8 +593,6 @@ node /org/freedesktop/systemd1 {
|
|||
|
||||
<!--method GetJobBefore is not documented!-->
|
||||
|
||||
<!--method SetShowStatus is not documented!-->
|
||||
|
||||
<!--method ListUnitsFiltered is not documented!-->
|
||||
|
||||
<!--method ListUnitsByPatterns is not documented!-->
|
||||
|
@ -673,8 +671,6 @@ node /org/freedesktop/systemd1 {
|
|||
|
||||
<!--property ConfirmSpawn is not documented!-->
|
||||
|
||||
<!--property ShowStatus is not documented!-->
|
||||
|
||||
<!--property DefaultStandardOutput is not documented!-->
|
||||
|
||||
<!--property DefaultStandardError is not documented!-->
|
||||
|
@ -1362,6 +1358,24 @@ node /org/freedesktop/systemd1 {
|
|||
|
||||
<para><function>ResetFailedUnit()</function> resets the "failed" state of a specific unit.</para>
|
||||
|
||||
<para><function>SetShowStatus()</function> configures the display of status messages during bootup and
|
||||
shutdown. The <varname>mode</varname> parameter can be set to any value that's valid for the
|
||||
<varname>systemd.show_status</varname> kernel parameter. For more information about
|
||||
<varname>systemd.show_status</varname>, see
|
||||
<citerefentry project="man-pages"><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
|
||||
The <varname>mode</varname> parameter can also be set to an empty string. When <varname>mode</varname>
|
||||
is set to an empty string, <function>SetShowStatus()</function> will reset
|
||||
<varname>ShowStatus</varname> back to its original value. You can use
|
||||
<function>SetShowStatus()</function> create a service that does something like this:
|
||||
<orderedlist>
|
||||
<listitem><para>Send a D-Bus message that will turn off status messages.</para></listitem>
|
||||
<listitem><para>Block until a reply to that message is received.</para></listitem>
|
||||
<listitem><para>Print multiples lines without being interrupted by status messages.</para></listitem>
|
||||
<listitem><para>Send a D-Bus message that will reset <varname>ShowStatus</varname> back to its
|
||||
original value.</para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
|
||||
<para><function>ResetFailed()</function> resets the "failed" state of all units.</para>
|
||||
|
||||
<para><function>ListUnits()</function> returns an array of all currently loaded units. Note that
|
||||
|
@ -1788,6 +1802,12 @@ node /org/freedesktop/systemd1 {
|
|||
<para><varname>Environment</varname> encodes the environment block passed to all executed services. It
|
||||
may be altered with bus calls such as <function>SetEnvironment()</function> (see above).</para>
|
||||
|
||||
<para><varname>ShowStatus</varname> encodes systemd's current policy for displaying status messages
|
||||
during bootup and shutdown. Its value can be any valid value for the
|
||||
<varname>systemd.show_status</varname> kernel parameter (see
|
||||
<citerefentry project="man-pages"><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>).
|
||||
It may be altered using <function>SetShowStatus()</function> (see above).</para>
|
||||
|
||||
<para><varname>UnitPath</varname> encodes the currently active unit file search path. It is an array of
|
||||
file system paths encoded as strings.</para>
|
||||
|
||||
|
|
|
@ -483,18 +483,18 @@
|
|||
<term><varname>ExcludeFiles=</varname></term>
|
||||
<term><varname>ExcludeFilesTarget=</varname></term>
|
||||
|
||||
<listitem><para>Takes an absolute file system path referring to a source file or directory on the
|
||||
host. This setting may be used to exclude files or directories from the host from being copied into
|
||||
the file system when <varname>CopyFiles=</varname> is used. This option may be used multiple times to
|
||||
exclude multiple files or directories from host from being copied into the newly formatted file
|
||||
system.</para>
|
||||
<listitem><para>Takes one or more absolute paths, separated by whitespace, each referring to a
|
||||
source file or directory on the host. This setting may be used to exclude files or directories from
|
||||
the host from being copied into the file system when <varname>CopyFiles=</varname> is used. This
|
||||
option may be used multiple times to exclude multiple files or directories from host from being
|
||||
copied into the newly formatted file system.</para>
|
||||
|
||||
<para>If the path is a directory and ends with <literal>/</literal>, only the directory's
|
||||
contents are excluded but not the directory itself. If the path is a directory and does not end with
|
||||
<literal>/</literal>, both the directory and its contents are excluded.</para>
|
||||
|
||||
<para><varname>ExcludeFilesTarget=</varname> is like <varname>ExcludeFiles=</varname> except that
|
||||
instead of excluding the path on the host from being copied into the partition, we exclude any files
|
||||
instead of excluding the path on the host from being copied into the partition, it exclude any files
|
||||
and directories from being copied into the given path in the partition.</para>
|
||||
|
||||
<para>When
|
||||
|
@ -922,9 +922,9 @@
|
|||
target for some other supplement definition. A target cannot have more than one supplement partition
|
||||
associated with it.</para>
|
||||
|
||||
<para>For example, distributions can use this to implement <variable>$BOOT</variable> as defined in
|
||||
<para>For example, distributions can use this to implement <varname>$BOOT</varname> as defined in
|
||||
the <ulink url="https://uapi-group.org/specifications/specs/boot_loader_specification/">Boot Loader
|
||||
Specification</ulink>. Distributions may prefer to use the ESP as <variable>$BOOT</variable> whenever
|
||||
Specification</ulink>. Distributions may prefer to use the ESP as <varname>$BOOT</varname> whenever
|
||||
possible, but to adhere to the spec XBOOTLDR must sometimes be used instead. So, they should create
|
||||
two definitions: the first defining an ESP big enough to hold just the bootloader, and a second for
|
||||
the XBOOTLDR that's sufficiently large to hold kernels and configured as a supplement for the ESP.
|
||||
|
|
|
@ -562,6 +562,13 @@
|
|||
To disable the safety check that the extension-release file name matches the image file name, the
|
||||
<varname>x-systemd.relax-extension-release-check</varname> mount option may be appended.</para>
|
||||
|
||||
<para>This option can be used together with a <option>notify-reload</option> service type and
|
||||
<citerefentry><refentrytitle>systemd.v</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
||||
to manage configuration updates. When such a service carrying confext images is reloaded, the confext
|
||||
itself will also be reloaded to pick up any changes. This only applies to confext extensions. See
|
||||
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
also for details.</para>
|
||||
|
||||
<para>When <varname>DevicePolicy=</varname> is set to <literal>closed</literal> or
|
||||
<literal>strict</literal>, or set to <literal>auto</literal> and <varname>DeviceAllow=</varname> is
|
||||
set, then this setting adds <filename>/dev/loop-control</filename> with <constant>rw</constant> mode,
|
||||
|
@ -606,6 +613,14 @@
|
|||
or the host. See:
|
||||
<citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
|
||||
|
||||
<para>This option can be used together with a <option>notify-reload</option> service type and
|
||||
<citerefentry><refentrytitle>systemd.v</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
||||
to manage configuration updates. When such a system service carrying confext directories is reloaded,
|
||||
the confext itself will also be reloaded to pick up any changes. This only applies to confext
|
||||
extensions. See
|
||||
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
also for details.</para>
|
||||
|
||||
<para>Note that usage from user units requires overlayfs support in unprivileged user namespaces,
|
||||
which was first introduced in kernel v5.11.</para>
|
||||
|
||||
|
@ -3001,7 +3016,12 @@ SystemCallErrorNumber=EPERM</programlisting>
|
|||
|
||||
<para><option>tty</option> connects standard output to a tty (as configured via <varname>TTYPath=</varname>,
|
||||
see below). If the TTY is used for output only, the executed process will not become the controlling process of
|
||||
the terminal, and will not fail or wait for other processes to release the terminal.</para>
|
||||
the terminal, and will not fail or wait for other processes to release the terminal. Note: if a unit
|
||||
tries to print multiple lines to a TTY during bootup or shutdown, then there's a chance that those
|
||||
lines will be broken up by status messages. <function>SetShowStatus()</function> can be used to
|
||||
prevent this problem. See
|
||||
<citerefentry project="man-pages"><refentrytitle>org.freedesktop.systemd1</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
for details.</para>
|
||||
|
||||
<para><option>journal</option> connects standard output with the journal, which is accessible via
|
||||
<citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>. Note
|
||||
|
|
|
@ -568,7 +568,11 @@
|
|||
<listitem><para>Enables display of status messages on the
|
||||
console, as controlled via
|
||||
<varname>systemd.show_status=1</varname> on the kernel command
|
||||
line.</para></listitem>
|
||||
line.</para>
|
||||
<para>You may want to use <function>SetShowStatus()</function> instead of
|
||||
<constant>SIGRTMIN+20</constant> in order to prevent race conditions. See
|
||||
<citerefentry project="man-pages"><refentrytitle>org.freedesktop.systemd1</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
@ -579,7 +583,11 @@
|
|||
controlled via
|
||||
<varname>systemd.show_status=0</varname>
|
||||
on the kernel command
|
||||
line.</para></listitem>
|
||||
line.</para>
|
||||
<para>You may want to use <function>SetShowStatus()</function> instead of
|
||||
<constant>SIGRTMIN+21</constant> in order to prevent race conditions. See
|
||||
<citerefentry project="man-pages"><refentrytitle>org.freedesktop.systemd1</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
|
|
@ -1875,6 +1875,40 @@ char** exec_context_get_restrict_filesystems(const ExecContext *c) {
|
|||
return l ? TAKE_PTR(l) : strv_new(NULL);
|
||||
}
|
||||
|
||||
static int extension_name_is_vpicked(const char *path) {
|
||||
_cleanup_free_ char *dir = NULL;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
|
||||
r = path_extract_filename(path, &dir);
|
||||
if (r == -EADDRNOTAVAIL)
|
||||
return 0;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return !!endswith(dir, ".v");
|
||||
}
|
||||
|
||||
int exec_context_has_vpicked_extensions(const ExecContext *context) {
|
||||
int r;
|
||||
|
||||
assert(context);
|
||||
|
||||
FOREACH_ARRAY(mi, context->extension_images, context->n_extension_images) {
|
||||
r = extension_name_is_vpicked(mi->source);
|
||||
if (r != 0)
|
||||
return r;
|
||||
}
|
||||
STRV_FOREACH(ed, context->extension_directories) {
|
||||
r = extension_name_is_vpicked(*ed);
|
||||
if (r != 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void exec_status_start(ExecStatus *s, pid_t pid, const dual_timestamp *ts) {
|
||||
assert(s);
|
||||
|
||||
|
|
|
@ -547,6 +547,8 @@ char** exec_context_get_syscall_log(const ExecContext *c);
|
|||
char** exec_context_get_address_families(const ExecContext *c);
|
||||
char** exec_context_get_restrict_filesystems(const ExecContext *c);
|
||||
|
||||
int exec_context_has_vpicked_extensions(const ExecContext *context);
|
||||
|
||||
void exec_status_start(ExecStatus *s, pid_t pid, const dual_timestamp *ts);
|
||||
void exec_status_exit(ExecStatus *s, const ExecContext *context, pid_t pid, int code, int status);
|
||||
void exec_status_handoff(ExecStatus *s, const struct ucred *ucred, const dual_timestamp *ts);
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
#include "nulstr-util.h"
|
||||
#include "os-util.h"
|
||||
#include "path-util.h"
|
||||
#include "pidref.h"
|
||||
#include "process-util.h"
|
||||
#include "selinux-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "sort-util.h"
|
||||
|
@ -3181,6 +3183,118 @@ bool ns_type_supported(NamespaceType type) {
|
|||
return access(ns_proc, F_OK) == 0;
|
||||
}
|
||||
|
||||
int refresh_extensions_in_namespace(
|
||||
const PidRef *target,
|
||||
const char *hierarchy_env,
|
||||
const NamespaceParameters *p) {
|
||||
|
||||
const char *overlay_prefix = "/run/systemd/mount-rootfs";
|
||||
_cleanup_(mount_list_done) MountList ml = {};
|
||||
_cleanup_free_ char *extension_dir = NULL;
|
||||
_cleanup_strv_free_ char **hierarchies = NULL;
|
||||
MountInNamespaceFlags min_flags = 0;
|
||||
int r;
|
||||
|
||||
assert(pidref_is_set(target));
|
||||
assert(hierarchy_env);
|
||||
assert(p);
|
||||
|
||||
log_debug("Refreshing extensions in-namespace for hierarchy '%s'", hierarchy_env);
|
||||
|
||||
extension_dir = path_join(p->private_namespace_dir, "unit-extensions");
|
||||
if (!extension_dir)
|
||||
return -ENOMEM;
|
||||
|
||||
min_flags |= MOUNT_IN_NAMESPACE_MAKE_FILE_OR_DIRECTORY;
|
||||
|
||||
r = parse_env_extension_hierarchies(&hierarchies, hierarchy_env);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = append_extensions(
|
||||
&ml,
|
||||
overlay_prefix,
|
||||
p->private_namespace_dir,
|
||||
hierarchies,
|
||||
p->extension_images,
|
||||
p->n_extension_images,
|
||||
p->extension_directories);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (ml.n_mounts == 0)
|
||||
return 0;
|
||||
|
||||
r = safe_fork("(sd-ns-refresh-exts)",
|
||||
FORK_DEATHSIG_SIGTERM | FORK_WAIT | FORK_NEW_MOUNTNS | FORK_MOUNTNS_SLAVE,
|
||||
NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) {
|
||||
(void) mkdir_p_label(overlay_prefix, 0555);
|
||||
|
||||
/* This is effectively two rounds, since all the extensions come
|
||||
* before overlays (setup_namespace() similarly relies on this
|
||||
* property).
|
||||
*
|
||||
* (1) First, set up all the extension mounts in the child, which
|
||||
* are not visible from the process. (2) Then, set up overlays
|
||||
* for the sysext/confext hierarchies again using the new
|
||||
* extension mounts as layers, and move them into the namespace. */
|
||||
FOREACH_ARRAY(m, ml.mounts, ml.n_mounts) {
|
||||
if (m->mode == MOUNT_EXTENSION_DIRECTORY || m->mode == MOUNT_EXTENSION_IMAGE) {
|
||||
r = apply_one_mount(p->root_directory, m, p);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to apply extension mount: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
} else if (m->mode == MOUNT_OVERLAY) {
|
||||
_cleanup_free_ char *path_relative = NULL, *path_in_namespace = NULL;
|
||||
|
||||
r = mount_overlay(m);
|
||||
if (r < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
if (r == 0) /* Tried to mount overlay, but skipped. */
|
||||
continue;
|
||||
|
||||
/* bind_mount_in_namespace takes a src on the outside
|
||||
* and a dest evaluated within the namespace. First,
|
||||
* figure out where we want the overlay on top of within
|
||||
* the namespace.
|
||||
*/
|
||||
r = path_make_relative(overlay_prefix, mount_entry_path(m), &path_relative);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to make path relative: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
r = asprintf(&path_in_namespace, "%s/%s", empty_to_root(p->root_directory), path_relative);
|
||||
if (r < 0) {
|
||||
log_oom_debug();
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
r = bind_mount_in_namespace(
|
||||
target,
|
||||
p->propagate_dir,
|
||||
p->incoming_dir,
|
||||
/* src= */ mount_entry_path(m),
|
||||
/* dest= */ path_in_namespace,
|
||||
min_flags);
|
||||
if (r < 0) {
|
||||
log_debug_errno(
|
||||
r,
|
||||
"Failed to move overlay within %s->%s: %m",
|
||||
mount_entry_path(m),
|
||||
path_in_namespace);
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *const protect_home_table[_PROTECT_HOME_MAX] = {
|
||||
[PROTECT_HOME_NO] = "no",
|
||||
[PROTECT_HOME_YES] = "yes",
|
||||
|
|
|
@ -16,6 +16,7 @@ typedef struct MountImage MountImage;
|
|||
#include "fs-util.h"
|
||||
#include "macro.h"
|
||||
#include "namespace-util.h"
|
||||
#include "pidref.h"
|
||||
#include "runtime-scope.h"
|
||||
#include "string-util.h"
|
||||
|
||||
|
@ -224,3 +225,8 @@ const char* namespace_type_to_string(NamespaceType t) _const_;
|
|||
NamespaceType namespace_type_from_string(const char *s) _pure_;
|
||||
|
||||
bool ns_type_supported(NamespaceType type);
|
||||
|
||||
int refresh_extensions_in_namespace(
|
||||
const PidRef *target,
|
||||
const char *hierarchy_env,
|
||||
const NamespaceParameters *p);
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "devnum-util.h"
|
||||
#include "env-util.h"
|
||||
#include "escape.h"
|
||||
#include "execute.h"
|
||||
#include "exec-credential.h"
|
||||
#include "exit-status.h"
|
||||
#include "fd-util.h"
|
||||
|
@ -33,11 +34,13 @@
|
|||
#include "manager.h"
|
||||
#include "missing_audit.h"
|
||||
#include "mount-util.h"
|
||||
#include "namespace.h"
|
||||
#include "open-file.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
#include "random-util.h"
|
||||
#include "runtime-scope.h"
|
||||
#include "selinux-util.h"
|
||||
#include "serialize.h"
|
||||
#include "service.h"
|
||||
|
@ -2787,6 +2790,63 @@ static void service_run_next_main(Service *s) {
|
|||
(void) service_set_main_pidref(s, TAKE_PIDREF(pidref), &s->main_command->exec_status.start_timestamp);
|
||||
}
|
||||
|
||||
static bool service_should_reload_extensions(Unit *u) {
|
||||
Service *s = ASSERT_PTR(SERVICE(u));
|
||||
int r;
|
||||
|
||||
/* Only support this for notify-reload service types. */
|
||||
if (s->type != SERVICE_NOTIFY_RELOAD)
|
||||
return false;
|
||||
|
||||
/* TODO: Add support for user services, which can use
|
||||
* ExtensionDirectories= + notify-reload. For now, skip for user
|
||||
* services. */
|
||||
if (u->manager->runtime_scope != RUNTIME_SCOPE_SYSTEM) {
|
||||
log_unit_debug(UNIT(s), "Not reloading extensions for user services.");
|
||||
return false;
|
||||
}
|
||||
|
||||
r = exec_context_has_vpicked_extensions(&s->exec_context);
|
||||
if (r < 0) {
|
||||
log_unit_warning_errno(u, r, "Failed to determine if service should reload extensions, assuming false: %m");
|
||||
return false;
|
||||
}
|
||||
return r > 0;
|
||||
}
|
||||
|
||||
static int service_reload_extensions(Unit *u) {
|
||||
/* TODO: do this asynchronously */
|
||||
Service *s = ASSERT_PTR(SERVICE(u));
|
||||
_cleanup_free_ char *propagate_dir = NULL;
|
||||
|
||||
if (!service_should_reload_extensions(u)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
propagate_dir = path_join("/run/systemd/propagate/", u->id);
|
||||
if (!propagate_dir)
|
||||
return -ENOMEM;
|
||||
|
||||
NamespaceParameters p = {
|
||||
.private_namespace_dir = "/run/systemd",
|
||||
.incoming_dir = "/run/systemd/incoming",
|
||||
.propagate_dir = propagate_dir,
|
||||
.runtime_scope = RUNTIME_SCOPE_SYSTEM,
|
||||
.root_directory = s->exec_context.root_directory,
|
||||
.extension_images = s->exec_context.extension_images,
|
||||
.n_extension_images = s->exec_context.n_extension_images,
|
||||
.extension_directories = s->exec_context.extension_directories,
|
||||
.extension_image_policy = s->exec_context.extension_image_policy
|
||||
};
|
||||
|
||||
/* Only reload confext, and not sysext, because it doesn't make sense
|
||||
for program code to be swapped at reload. */
|
||||
return refresh_extensions_in_namespace(
|
||||
unit_main_pid(u),
|
||||
"SYSTEMD_CONFEXT_HIERARCHIES",
|
||||
&p);
|
||||
}
|
||||
|
||||
static int service_start(Unit *u) {
|
||||
Service *s = ASSERT_PTR(SERVICE(u));
|
||||
int r;
|
||||
|
@ -2941,9 +3001,19 @@ static int service_stop(Unit *u) {
|
|||
|
||||
static int service_reload(Unit *u) {
|
||||
Service *s = ASSERT_PTR(SERVICE(u));
|
||||
int r;
|
||||
|
||||
assert(IN_SET(s->state, SERVICE_RUNNING, SERVICE_EXITED));
|
||||
|
||||
/* If we have confexts extensions, try to reload vpick'd confext
|
||||
* extensions, which is particularly beneficial for notify-reload
|
||||
* services that could potentially pick up a new version of its
|
||||
* configuration.
|
||||
*/
|
||||
r = service_reload_extensions(u);
|
||||
if (r < 0)
|
||||
log_unit_error_errno(u, r, "Failed to reload confexts, ignoring: %m");
|
||||
|
||||
service_enter_reload(s);
|
||||
return 1;
|
||||
}
|
||||
|
@ -4169,7 +4239,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
|||
* detect when the cgroup becomes empty. Note that the control process is always
|
||||
* our child so it's pointless to watch all other processes. */
|
||||
if (!control_pid_good(s))
|
||||
if (!s->main_pid_known || s->main_pid_alien)
|
||||
if (!s->main_pid_known || s->main_pid_alien || unit_cgroup_delegate(u))
|
||||
(void) unit_enqueue_rewatch_pids(u);
|
||||
}
|
||||
|
||||
|
|
|
@ -404,15 +404,16 @@ static int context_set_path_strv(Context *c, char* const* strv, const char *sour
|
|||
|
||||
static int context_set_plugins(Context *c, const char *s, const char *source) {
|
||||
_cleanup_strv_free_ char **v = NULL;
|
||||
int r;
|
||||
|
||||
assert(c);
|
||||
|
||||
if (c->plugins || !s)
|
||||
return 0;
|
||||
|
||||
v = strv_split(s, NULL);
|
||||
if (!v)
|
||||
return log_oom();
|
||||
r = strv_split_full(&v, s, NULL, EXTRACT_UNQUOTE);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse plugin paths from %s: %m", source);
|
||||
|
||||
return context_set_path_strv(c, v, source, "plugins", &c->plugins);
|
||||
}
|
||||
|
|
|
@ -46,7 +46,13 @@ echo 'DTBDTBDTBDTB' >"$D/sources/subdir/whatever.dtb"
|
|||
|
||||
export KERNEL_INSTALL_CONF_ROOT="$D/sources"
|
||||
# We "install" multiple plugins, but control which ones will be active via install.conf.
|
||||
export KERNEL_INSTALL_PLUGINS="${ukify_install} ${loaderentry_install} ${uki_copy_install}"
|
||||
KERNEL_INSTALL_PLUGINS="'${loaderentry_install}' '${uki_copy_install}'"
|
||||
if [[ -n "$ukify_install" ]]; then
|
||||
# shellcheck disable=SC2089
|
||||
KERNEL_INSTALL_PLUGINS="'${ukify_install}' $KERNEL_INSTALL_PLUGINS"
|
||||
fi
|
||||
# shellcheck disable=SC2090
|
||||
export KERNEL_INSTALL_PLUGINS
|
||||
export BOOT_ROOT="$D/boot"
|
||||
export BOOT_MNT="$D/boot"
|
||||
export MACHINE_ID='3e0484f3634a418b8e6a39e8828b03e3'
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
#include "sd-daemon.h"
|
||||
|
||||
#include "bpf-dlopen.h"
|
||||
#if HAVE_VMLINUX_H
|
||||
#include "bpf-link.h"
|
||||
#endif
|
||||
#include "build-path.h"
|
||||
#include "common-signal.h"
|
||||
#include "env-util.h"
|
||||
|
|
|
@ -304,19 +304,6 @@ static SubvolumeFlags subvolume_flags_from_string(const char *s) {
|
|||
return flags;
|
||||
}
|
||||
|
||||
static char* subvolume_flags_to_string(SubvolumeFlags flags) {
|
||||
const char *l[CONST_LOG2U(_SUBVOLUME_FLAGS_MASK + 1) + 1]; /* one string per known flag at most */
|
||||
size_t m = 0;
|
||||
|
||||
if (FLAGS_SET(flags, SUBVOLUME_RO))
|
||||
l[m++] = "ro";
|
||||
|
||||
assert(m < ELEMENTSOF(l));
|
||||
l[m] = NULL;
|
||||
|
||||
return strv_join((char**) l, ",");
|
||||
}
|
||||
|
||||
typedef struct Subvolume {
|
||||
char *path;
|
||||
SubvolumeFlags flags;
|
||||
|
@ -1742,8 +1729,9 @@ static int config_parse_exclude_files(
|
|||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
_cleanup_free_ char *resolved = NULL;
|
||||
|
||||
char ***exclude_files = ASSERT_PTR(data);
|
||||
const char *p = ASSERT_PTR(rvalue);
|
||||
int r;
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
|
@ -1751,10 +1739,23 @@ static int config_parse_exclude_files(
|
|||
return 0;
|
||||
}
|
||||
|
||||
r = specifier_printf(rvalue, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, NULL, &resolved);
|
||||
for (;;) {
|
||||
_cleanup_free_ char *word = NULL, *resolved = NULL;
|
||||
|
||||
r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", p);
|
||||
return 0;
|
||||
}
|
||||
if (r == 0)
|
||||
return 0;
|
||||
|
||||
r = specifier_printf(word, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, NULL, &resolved);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to expand specifiers in ExcludeFiles= path, ignoring: %s", rvalue);
|
||||
"Failed to expand specifiers in %s path, ignoring: %s", lvalue, word);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1764,6 +1765,7 @@ static int config_parse_exclude_files(
|
|||
|
||||
if (strv_consume(exclude_files, TAKE_PTR(resolved)) < 0)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2423,6 +2425,14 @@ static int partition_read_definition(Partition *p, const char *path, const char
|
|||
"SizeMinBytes=/SizeMaxBytes= cannot be used with Verity=%s.",
|
||||
verity_mode_to_string(p->verity));
|
||||
|
||||
if (!ordered_hashmap_isempty(p->subvolumes) && arg_offline > 0)
|
||||
return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"Subvolumes= cannot be used with --offline=yes.");
|
||||
|
||||
if (p->default_subvolume && arg_offline > 0)
|
||||
return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"DefaultSubvolume= cannot be used with --offline=yes.");
|
||||
|
||||
if (p->default_subvolume && !ordered_hashmap_contains(p->subvolumes, p->default_subvolume))
|
||||
return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
|
||||
"DefaultSubvolume= must be one of the paths in Subvolumes=.");
|
||||
|
@ -4271,7 +4281,7 @@ static int prepare_temporary_file(Context *context, PartitionTarget *t, uint64_t
|
|||
|
||||
static bool loop_device_error_is_fatal(const Partition *p, int r) {
|
||||
assert(p);
|
||||
return arg_offline == 0 || (r != -ENOENT && !ERRNO_IS_PRIVILEGE(r));
|
||||
return arg_offline == 0 || (r != -ENOENT && !ERRNO_IS_PRIVILEGE(r)) || !ordered_hashmap_isempty(p->subvolumes) || p->default_subvolume;
|
||||
}
|
||||
|
||||
static int partition_target_prepare(
|
||||
|
@ -5778,38 +5788,6 @@ static int partition_populate_filesystem(Context *context, Partition *p, const c
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int append_btrfs_subvols(char ***l, OrderedHashmap *subvolumes, const char *default_subvolume) {
|
||||
Subvolume *subvolume;
|
||||
int r;
|
||||
|
||||
assert(l);
|
||||
|
||||
ORDERED_HASHMAP_FOREACH(subvolume, subvolumes) {
|
||||
_cleanup_free_ char *s = NULL, *f = NULL;
|
||||
|
||||
s = strdup(subvolume->path);
|
||||
if (!s)
|
||||
return log_oom();
|
||||
|
||||
f = subvolume_flags_to_string(subvolume->flags);
|
||||
if (!f)
|
||||
return log_oom();
|
||||
|
||||
if (streq_ptr(subvolume->path, default_subvolume) &&
|
||||
!strextend_with_separator(&f, ",", "default"))
|
||||
return log_oom();
|
||||
|
||||
if (!isempty(f) && !strextend_with_separator(&s, ":", f))
|
||||
return log_oom();
|
||||
|
||||
r = strv_extend_many(l, "--subvol", s);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int finalize_extra_mkfs_options(const Partition *p, const char *root, char ***ret) {
|
||||
_cleanup_strv_free_ char **sv = NULL;
|
||||
int r;
|
||||
|
@ -5823,18 +5801,6 @@ static int finalize_extra_mkfs_options(const Partition *p, const char *root, cha
|
|||
"Failed to determine mkfs command line options for '%s': %m",
|
||||
p->format);
|
||||
|
||||
if (partition_needs_populate(p) && root && streq(p->format, "btrfs")) {
|
||||
r = append_btrfs_subvols(&sv, p->subvolumes, p->default_subvolume);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (p->suppressing) {
|
||||
r = append_btrfs_subvols(&sv, p->suppressing->subvolumes, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(sv);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -197,7 +197,7 @@ _unused_ static void test_compress_stream(const char *compression,
|
|||
ASSERT_OK(compress(src, dst, -1, &uncompressed_size));
|
||||
|
||||
if (cat) {
|
||||
assert_se(asprintf(&cmd, "%s %s | diff %s -", cat, pattern, srcfile) > 0);
|
||||
assert_se(asprintf(&cmd, "%s %s | diff '%s' -", cat, pattern, srcfile) > 0);
|
||||
assert_se(system(cmd) == 0);
|
||||
}
|
||||
|
||||
|
@ -212,7 +212,7 @@ _unused_ static void test_compress_stream(const char *compression,
|
|||
r = decompress(dst, dst2, st.st_size);
|
||||
assert_se(r == 0);
|
||||
|
||||
assert_se(asprintf(&cmd2, "diff %s %s", srcfile, pattern2) > 0);
|
||||
assert_se(asprintf(&cmd2, "diff '%s' %s", srcfile, pattern2) > 0);
|
||||
assert_se(system(cmd2) == 0);
|
||||
|
||||
log_debug("/* test faulty decompression */");
|
||||
|
|
|
@ -52,7 +52,8 @@ static void test_event_spawn_self(const char *self, const char *arg, bool with_p
|
|||
|
||||
log_debug("/* %s(%s, %s) */", __func__, arg, yes_no(with_pidfd));
|
||||
|
||||
assert_se(cmd = strjoin(self, " ", arg));
|
||||
/* 'self' may contain spaces, hence needs to be quoted. */
|
||||
assert_se(cmd = strjoin("'", self, "' ", arg));
|
||||
|
||||
test_event_spawn_core(with_pidfd, cmd, result_buf, BUF_SIZE);
|
||||
|
||||
|
|
|
@ -4,32 +4,32 @@ set -e
|
|||
|
||||
ANALYZE="${1:-systemd-analyze}"
|
||||
|
||||
$ANALYZE compare-versions 1 lt 2
|
||||
$ANALYZE compare-versions 1 '<' 2
|
||||
$ANALYZE compare-versions 1 le 2
|
||||
$ANALYZE compare-versions 1 '<=' 2
|
||||
$ANALYZE compare-versions 1 ne 2
|
||||
$ANALYZE compare-versions 1 '!=' 2
|
||||
( ! $ANALYZE compare-versions 1 ge 2 )
|
||||
( ! $ANALYZE compare-versions 1 '>=' 2 )
|
||||
( ! $ANALYZE compare-versions 1 eq 2 )
|
||||
( ! $ANALYZE compare-versions 1 '==' 2 )
|
||||
( ! $ANALYZE compare-versions 1 gt 2 )
|
||||
( ! $ANALYZE compare-versions 1 '>' 2 )
|
||||
"$ANALYZE" compare-versions 1 lt 2
|
||||
"$ANALYZE" compare-versions 1 '<' 2
|
||||
"$ANALYZE" compare-versions 1 le 2
|
||||
"$ANALYZE" compare-versions 1 '<=' 2
|
||||
"$ANALYZE" compare-versions 1 ne 2
|
||||
"$ANALYZE" compare-versions 1 '!=' 2
|
||||
( ! "$ANALYZE" compare-versions 1 ge 2 )
|
||||
( ! "$ANALYZE" compare-versions 1 '>=' 2 )
|
||||
( ! "$ANALYZE" compare-versions 1 eq 2 )
|
||||
( ! "$ANALYZE" compare-versions 1 '==' 2 )
|
||||
( ! "$ANALYZE" compare-versions 1 gt 2 )
|
||||
( ! "$ANALYZE" compare-versions 1 '>' 2 )
|
||||
|
||||
test "$($ANALYZE compare-versions 1 2)" = '1 < 2'
|
||||
test "$($ANALYZE compare-versions 2 2)" = '2 == 2'
|
||||
test "$($ANALYZE compare-versions 2 1)" = '2 > 1'
|
||||
test "$($ANALYZE compare-versions '' '')" = "'' == ''"
|
||||
test "$("$ANALYZE" compare-versions 1 2)" = '1 < 2'
|
||||
test "$("$ANALYZE" compare-versions 2 2)" = '2 == 2'
|
||||
test "$("$ANALYZE" compare-versions 2 1)" = '2 > 1'
|
||||
test "$("$ANALYZE" compare-versions '' '')" = "'' == ''"
|
||||
|
||||
set +e
|
||||
|
||||
$ANALYZE compare-versions 1 2; ret1=$?
|
||||
$ANALYZE compare-versions 2 2; ret2=$?
|
||||
$ANALYZE compare-versions 2 1; ret3=$?
|
||||
"$ANALYZE" compare-versions 1 2; ret1=$?
|
||||
"$ANALYZE" compare-versions 2 2; ret2=$?
|
||||
"$ANALYZE" compare-versions 2 1; ret3=$?
|
||||
|
||||
set -e
|
||||
|
||||
test $ret1 == 12
|
||||
test $ret2 == 0
|
||||
test $ret3 == 11
|
||||
test "$ret1" == 12
|
||||
test "$ret2" == 0
|
||||
test "$ret3" == 11
|
||||
|
|
|
@ -44,9 +44,9 @@ test_one() (
|
|||
fi
|
||||
|
||||
if [[ "${input##*/}" =~ \.fstab\.input ]]; then
|
||||
SYSTEMD_LOG_LEVEL=debug SYSTEMD_IN_INITRD="$initrd" SYSTEMD_SYSFS_CHECK=no SYSTEMD_PROC_CMDLINE="fstab=yes root=fstab" SYSTEMD_FSTAB="$input" SYSTEMD_SYSROOT_FSTAB="/dev/null" $generator "$out" "$out" "$out"
|
||||
SYSTEMD_LOG_LEVEL=debug SYSTEMD_IN_INITRD="$initrd" SYSTEMD_SYSFS_CHECK=no SYSTEMD_PROC_CMDLINE="fstab=yes root=fstab" SYSTEMD_FSTAB="$input" SYSTEMD_SYSROOT_FSTAB="/dev/null" "$generator" "$out" "$out" "$out"
|
||||
else
|
||||
SYSTEMD_LOG_LEVEL=debug SYSTEMD_IN_INITRD="$initrd" SYSTEMD_SYSFS_CHECK=no SYSTEMD_PROC_CMDLINE="fstab=no $(cat "$input")" $generator "$out" "$out" "$out"
|
||||
SYSTEMD_LOG_LEVEL=debug SYSTEMD_IN_INITRD="$initrd" SYSTEMD_SYSFS_CHECK=no SYSTEMD_PROC_CMDLINE="fstab=no $(cat "$input")" "$generator" "$out" "$out" "$out"
|
||||
fi
|
||||
|
||||
# The option x-systemd.growfs creates symlink to system's systemd-growfs@.service in .mount.wants directory.
|
||||
|
|
|
@ -53,7 +53,7 @@ for f in $(find "$SOURCE"/test-*.input | sort -V); do
|
|||
echo "*** Running $f"
|
||||
prepare_testdir "${f%.input}"
|
||||
cp "$f" "$TESTDIR/usr/lib/sysusers.d/test.conf"
|
||||
$SYSUSERS --root="$TESTDIR"
|
||||
"$SYSUSERS" --root="$TESTDIR"
|
||||
|
||||
compare "${f%.*}" ""
|
||||
done
|
||||
|
@ -62,7 +62,7 @@ for f in $(find "$SOURCE"/test-*.input | sort -V); do
|
|||
echo "*** Running $f on stdin"
|
||||
prepare_testdir "${f%.input}"
|
||||
touch "$TESTDIR/etc/sysusers.d/test.conf"
|
||||
$SYSUSERS --root="$TESTDIR" - <"$f"
|
||||
"$SYSUSERS" --root="$TESTDIR" - <"$f"
|
||||
|
||||
compare "${f%.*}" "on stdin"
|
||||
done
|
||||
|
@ -72,9 +72,9 @@ for f in $(find "$SOURCE"/test-*.input | sort -V); do
|
|||
prepare_testdir "${f%.input}"
|
||||
touch "$TESTDIR/etc/sysusers.d/test.conf"
|
||||
# this overrides test.conf which is masked on disk
|
||||
$SYSUSERS --root="$TESTDIR" --replace=/etc/sysusers.d/test.conf - <"$f"
|
||||
"$SYSUSERS" --root="$TESTDIR" --replace=/etc/sysusers.d/test.conf - <"$f"
|
||||
# this should be ignored
|
||||
$SYSUSERS --root="$TESTDIR" --replace=/usr/lib/sysusers.d/test.conf - <"$SOURCE/test-1.input"
|
||||
"$SYSUSERS" --root="$TESTDIR" --replace=/usr/lib/sysusers.d/test.conf - <"$SOURCE/test-1.input"
|
||||
|
||||
compare "${f%.*}" "on stdin with --replace"
|
||||
done
|
||||
|
@ -84,7 +84,7 @@ echo "*** Testing --inline"
|
|||
prepare_testdir "$SOURCE/inline"
|
||||
# copy a random file to make sure it is ignored
|
||||
cp "$f" "$TESTDIR/etc/sysusers.d/confuse.conf"
|
||||
$SYSUSERS --root="$TESTDIR" --inline \
|
||||
"$SYSUSERS" --root="$TESTDIR" --inline \
|
||||
"u u1 222 - - /bin/zsh" \
|
||||
"g g1 111"
|
||||
|
||||
|
@ -95,7 +95,7 @@ echo "*** Testing --inline with --replace"
|
|||
prepare_testdir "$SOURCE/inline"
|
||||
# copy a random file to make sure it is ignored
|
||||
cp "$f" "$TESTDIR/etc/sysusers.d/confuse.conf"
|
||||
$SYSUSERS --root="$TESTDIR" \
|
||||
"$SYSUSERS" --root="$TESTDIR" \
|
||||
--inline \
|
||||
--replace=/etc/sysusers.d/confuse.conf \
|
||||
"u u1 222 - - /bin/zsh" \
|
||||
|
@ -105,7 +105,7 @@ compare "$SOURCE/inline" "(--inline --replace=…)"
|
|||
|
||||
echo "*** Testing --inline with no /etc"
|
||||
rm -rf "${TESTDIR:?}/etc"
|
||||
$SYSUSERS --root="$TESTDIR" --inline \
|
||||
"$SYSUSERS" --root="$TESTDIR" --inline \
|
||||
"u u1 222 - - /bin/zsh" \
|
||||
"g g1 111"
|
||||
|
||||
|
@ -136,7 +136,7 @@ for f in $(find "$SOURCE"/test-*.input | sort -V); do
|
|||
echo "*** Running $f (with login.defs)"
|
||||
prepare_testdir "${f%.input}"
|
||||
cp "$f" "$TESTDIR/usr/lib/sysusers.d/test.conf"
|
||||
$SYSUSERS --root="$TESTDIR"
|
||||
"$SYSUSERS" --root="$TESTDIR"
|
||||
|
||||
# shellcheck disable=SC2050
|
||||
[ @ENABLE_COMPAT_MUTABLE_UID_BOUNDARIES@ = 1 ] && bound=555 || bound=$system_guid_max
|
||||
|
@ -152,7 +152,7 @@ for f in $(find "$SOURCE"/test-*.input | sort -V); do
|
|||
echo "*** Running $f (with login.defs symlinked)"
|
||||
prepare_testdir "${f%.input}"
|
||||
cp "$f" "$TESTDIR/usr/lib/sysusers.d/test.conf"
|
||||
$SYSUSERS --root="$TESTDIR"
|
||||
"$SYSUSERS" --root="$TESTDIR"
|
||||
|
||||
# shellcheck disable=SC2050
|
||||
[ @ENABLE_COMPAT_MUTABLE_UID_BOUNDARIES@ = 1 ] && bound=555 || bound=$system_guid_max
|
||||
|
@ -166,7 +166,7 @@ for f in $(find "$SOURCE"/unhappy-*.input | sort -V); do
|
|||
echo "*** Running test $f"
|
||||
prepare_testdir "${f%.input}"
|
||||
cp "$f" "$TESTDIR/usr/lib/sysusers.d/test.conf"
|
||||
SYSTEMD_LOG_LEVEL=info $SYSUSERS --root="$TESTDIR" 2>&1 | tail -n1 | sed -r 's/^[^:]+:[^:]+://' >"$TESTDIR/err"
|
||||
SYSTEMD_LOG_LEVEL=info "$SYSUSERS" --root="$TESTDIR" 2>&1 | tail -n1 | sed -r 's/^[^:]+:[^:]+://' >"$TESTDIR/err"
|
||||
if ! diff -u "$TESTDIR/err" "${f%.*}.expected-err"; then
|
||||
echo >&2 "**** Unexpected error output for $f"
|
||||
cat >&2 "$TESTDIR/err"
|
||||
|
|
|
@ -516,6 +516,68 @@ rm -rf "$VDIR" "$EMPTY_VDIR"
|
|||
systemd-dissect --umount "$IMAGE_DIR/app0"
|
||||
systemd-dissect --umount "$IMAGE_DIR/app1"
|
||||
|
||||
# Check reloading refreshes vpick extensions
|
||||
VBASE="vtest$RANDOM"
|
||||
VDIR="/tmp/${VBASE}.v"
|
||||
mkdir "$VDIR"
|
||||
cat >/run/systemd/system/testservice-50g.service <<EOF
|
||||
[Service]
|
||||
Type=notify-reload
|
||||
EnvironmentFile=-/usr/lib/systemd/systemd-asan-env
|
||||
ExtensionDirectories=${VDIR}
|
||||
ExecStart=bash -c ' \\
|
||||
trap "{ \\
|
||||
systemd-notify --reloading; \\
|
||||
ls /etc | grep marker; \\
|
||||
systemd-notify --ready; \\
|
||||
}" SIGHUP; \\
|
||||
systemd-notify --ready; \\
|
||||
while true; do sleep 1; done; \\
|
||||
'
|
||||
EOF
|
||||
mkdir -p "$VDIR/${VBASE}_1/etc/extension-release.d/"
|
||||
echo "ID=_any" >"$VDIR/${VBASE}_1/etc/extension-release.d/extension-release.${VBASE}_1"
|
||||
touch "$VDIR/${VBASE}_1/etc/${VBASE}_1.marker"
|
||||
systemctl start testservice-50g.service
|
||||
systemctl is-active testservice-50g.service
|
||||
# First reload; at reload time, the marker file in /etc should be picked up.
|
||||
systemctl try-reload-or-restart testservice-50g.service
|
||||
journalctl -b -u testservice-50g | grep -q -F "${VBASE}_1.marker"
|
||||
# Make a version 2 and reload again; this time we should see the v2 marker
|
||||
mkdir -p "$VDIR/${VBASE}_2/etc/extension-release.d/"
|
||||
echo "ID=_any" >"$VDIR/${VBASE}_2/etc/extension-release.d/extension-release.${VBASE}_2"
|
||||
touch "$VDIR/${VBASE}_2/etc/${VBASE}_2.marker"
|
||||
systemctl try-reload-or-restart testservice-50g.service
|
||||
journalctl --sync
|
||||
journalctl -b -u testservice-50g | grep -q -F "${VBASE}_2.marker"
|
||||
# Do it for a couple more times (to make sure we're tearing down old overlays)
|
||||
for _ in {1..5}; do systemctl reload testservice-50g.service; done
|
||||
systemctl stop testservice-50g.service
|
||||
|
||||
# Repeat the same vpick notify-reload test with ExtensionImages= (keeping the
|
||||
# same VBASE and reusing VDIR files for convenience, but using .raw extensions
|
||||
# this time)
|
||||
VDIR2="/tmp/${VBASE}.raw.v"
|
||||
mkdir "$VDIR2"
|
||||
cp /run/systemd/system/testservice-50g.service /run/systemd/system/testservice-50h.service
|
||||
sed -i "s%ExtensionDirectories=.*%ExtensionImages=$VDIR2%g" \
|
||||
/run/systemd/system/testservice-50h.service
|
||||
mksquashfs "$VDIR/${VBASE}_1" "$VDIR2/${VBASE}_1.raw"
|
||||
systemctl start testservice-50h.service
|
||||
systemctl is-active testservice-50h.service
|
||||
# First reload should pick up the v1 marker
|
||||
systemctl try-reload-or-restart testservice-50h.service
|
||||
journalctl --sync
|
||||
journalctl -b -u testservice-50h | grep -q -F "${VBASE}_1.marker"
|
||||
# Second reload should pick up the v2 marker
|
||||
mksquashfs "$VDIR/${VBASE}_2" "$VDIR2/${VBASE}_2.raw"
|
||||
systemctl try-reload-or-restart testservice-50h.service
|
||||
journalctl --sync
|
||||
journalctl -b -u testservice-50h | grep -q -F "${VBASE}_2.marker"
|
||||
systemctl stop testservice-50h.service
|
||||
|
||||
rm -rf "$VDIR" "$VDIR2"
|
||||
|
||||
# Test that an extension consisting of an empty directory under /etc/extensions/ takes precedence
|
||||
mkdir -p /var/lib/extensions/
|
||||
ln -s /tmp/app-nodistro.raw /var/lib/extensions/app-nodistro.raw
|
||||
|
|
Loading…
Reference in New Issue