mirror of
https://github.com/systemd/systemd.git
synced 2025-03-24 14:50:17 +03:00
core/mount: rework GracefulOptions= as x-systemd.graceful-option= (#36356)
Prompted by #36337
This commit is contained in:
commit
4053af87bb
@ -7048,10 +7048,10 @@ node /org/freedesktop/systemd1/unit/home_2emount {
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly b ReadWriteOnly = ...;
|
||||
readonly s Result = '...';
|
||||
readonly s ReloadResult = '...';
|
||||
readonly s CleanResult = '...';
|
||||
readonly u UID = ...;
|
||||
readonly u GID = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly as GracefulOptions = ['...', ...];
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
|
||||
readonly a(sasbttttuii) ExecMount = [...];
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
|
||||
@ -7652,12 +7652,14 @@ node /org/freedesktop/systemd1/unit/home_2emount {
|
||||
|
||||
<!--property ReadWriteOnly is not documented!-->
|
||||
|
||||
<!--property ReloadResult is not documented!-->
|
||||
|
||||
<!--property CleanResult is not documented!-->
|
||||
|
||||
<!--property UID is not documented!-->
|
||||
|
||||
<!--property GID is not documented!-->
|
||||
|
||||
<!--property GracefulOptions is not documented!-->
|
||||
|
||||
<!--property ExecUnmount is not documented!-->
|
||||
|
||||
<!--property ExecRemount is not documented!-->
|
||||
@ -8200,12 +8202,14 @@ node /org/freedesktop/systemd1/unit/home_2emount {
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="Result"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="ReloadResult"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="CleanResult"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="UID"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="GID"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="GracefulOptions"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="ExecMount"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="ExecUnmount"/>
|
||||
@ -12462,8 +12466,9 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \
|
||||
<varname>ProtectControlGroupsEx</varname>, and
|
||||
<varname>PrivatePIDs</varname> were added in version 257.</para>
|
||||
<para><varname>ProtectHostnameEx</varname>,
|
||||
<function>RemoveSubgroup()</function>, and
|
||||
<varname>GracefulOptions</varname> were added in version 258.</para>
|
||||
<function>RemoveSubgroup()</function>,
|
||||
<varname>ReloadResult</varname>, and
|
||||
<varname>CleanResult</varname> were added in version 258.</para>
|
||||
</refsect2>
|
||||
<refsect2>
|
||||
<title>Swap Unit Objects</title>
|
||||
|
@ -284,6 +284,19 @@
|
||||
<xi:include href="version-info.xml" xpointer="v220"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>x-systemd.graceful-option=</option></term>
|
||||
|
||||
<listitem><para>Additional mount option that shall be appended if supported by the kernel.
|
||||
This may be used to configure mount options that are optional and only enabled on kernels that
|
||||
support them. Note that this is supported only for native kernel mount options (i.e. explicitly not
|
||||
for mount options implemented in userspace, such as those processed by
|
||||
<command>/usr/bin/mount</command> itself, by FUSE or by mount helpers such as
|
||||
<command>mount.nfs</command>). This option may be specified more than once.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>x-systemd.device-bound=</option></term>
|
||||
|
||||
@ -650,22 +663,6 @@
|
||||
<citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>GracefulOptions=</varname></term>
|
||||
|
||||
<listitem><para>Additional mount options that shall be appended to <varname>Options=</varname> if
|
||||
supported by the kernel. This may be used to configure mount options that are optional and only
|
||||
enabled on kernels that support them. Note that this is supported only for native kernel mount
|
||||
options (i.e. explicitly not for mount options implemented in userspace, such as those processed by
|
||||
<command>/usr/bin/mount</command> itself, by FUSE or by mount helpers such as
|
||||
<command>mount.nfs</command>).</para>
|
||||
|
||||
<para>May be specified multiple times. If specified multiple times, all listed, supported mount
|
||||
options are combined. If an empty string is assigned, the list is reset.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<xi:include href="systemd.service.xml" xpointer="shared-unit-options" />
|
||||
|
@ -797,14 +797,10 @@ int mount_option_supported(const char *fstype, const char *key, const char *valu
|
||||
assert(key);
|
||||
|
||||
fd = fsopen(fstype, FSOPEN_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
if (ERRNO_IS_NOT_SUPPORTED(errno))
|
||||
return -EAGAIN; /* new mount API not available → don't know */
|
||||
|
||||
if (fd < 0)
|
||||
return log_debug_errno(errno, "Failed to open superblock context for '%s': %m", fstype);
|
||||
}
|
||||
|
||||
/* Various file systems have not been converted to the new mount API yet. For such file systems
|
||||
/* Various file systems support fs context only in recent kernels (e.g. btrfs). For older kernels
|
||||
* fsconfig() with FSCONFIG_SET_STRING/FSCONFIG_SET_FLAG never fail. Which sucks, because we want to
|
||||
* use it for testing support, after all. Let's hence do a check if the file system got converted yet
|
||||
* first. */
|
||||
@ -813,9 +809,9 @@ int mount_option_supported(const char *fstype, const char *key, const char *valu
|
||||
* the new mount API yet. If it returns EINVAL the mount option doesn't exist, but the fstype
|
||||
* is converted. */
|
||||
if (errno == EOPNOTSUPP)
|
||||
return -EAGAIN; /* FSCONFIG_SET_FD not supported on the fs, hence not converted to new mount API → don't know */
|
||||
return -EAGAIN; /* fs not converted to new mount API → don't know */
|
||||
if (errno != EINVAL)
|
||||
return log_debug_errno(errno, "Failed to check if file system has been converted to new mount API: %m");
|
||||
return log_debug_errno(errno, "Failed to check if file system '%s' has been converted to new mount API: %m", fstype);
|
||||
|
||||
/* So FSCONFIG_SET_FD worked, but the option didn't exist (we got EINVAL), this means the fs
|
||||
* is converted. Let's now ask the actual question we wonder about. */
|
||||
|
@ -73,9 +73,11 @@ const sd_bus_vtable bus_mount_vtable[] = {
|
||||
SD_BUS_PROPERTY("ForceUnmount", "b", bus_property_get_bool, offsetof(Mount, force_unmount), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("ReadWriteOnly", "b", bus_property_get_bool, offsetof(Mount, read_write_only), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Mount, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("ReloadResult", "s", property_get_result, offsetof(Mount, reload_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("CleanResult", "s", property_get_result, offsetof(Mount, clean_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("UID", "u", bus_property_get_uid, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("GID", "u", bus_property_get_gid, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("GracefulOptions", "as", NULL, offsetof(Mount, graceful_options), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
|
||||
BUS_EXEC_COMMAND_VTABLE("ExecMount", offsetof(Mount, exec_command[MOUNT_EXEC_MOUNT]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
|
||||
BUS_EXEC_COMMAND_VTABLE("ExecUnmount", offsetof(Mount, exec_command[MOUNT_EXEC_UNMOUNT]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
|
||||
BUS_EXEC_COMMAND_VTABLE("ExecRemount", offsetof(Mount, exec_command[MOUNT_EXEC_REMOUNT]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
|
||||
@ -151,30 +153,6 @@ static int bus_mount_set_transient_property(
|
||||
if (streq(name, "ReadWriteOnly"))
|
||||
return bus_set_transient_bool(u, name, &m->read_write_only, message, flags, error);
|
||||
|
||||
if (streq(name, "GracefulOptions")) {
|
||||
_cleanup_strv_free_ char **add = NULL;
|
||||
r = sd_bus_message_read_strv(message, &add);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
|
||||
if (strv_isempty(add)) {
|
||||
m->graceful_options = strv_free(m->graceful_options);
|
||||
unit_write_settingf(u, flags, name, "GracefulOptions=");
|
||||
} else {
|
||||
r = strv_extend_strv(&m->graceful_options, add, /* filter_duplicates= */ false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
STRV_FOREACH(a, add)
|
||||
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "GracefulOptions=%s", *a);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -393,10 +393,10 @@ const sd_bus_vtable bus_service_vtable[] = {
|
||||
SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
|
||||
SD_BUS_METHOD_WITH_ARGS("MountImage",
|
||||
SD_BUS_ARGS("s", source, "s", destination, "b", read_only, "b", mkdir, "a(ss)", options),
|
||||
SD_BUS_NO_RESULT,
|
||||
bus_service_method_mount_image,
|
||||
SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_ARGS("s", source, "s", destination, "b", read_only, "b", mkdir, "a(ss)", options),
|
||||
SD_BUS_NO_RESULT,
|
||||
bus_service_method_mount_image,
|
||||
SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
|
||||
SD_BUS_METHOD_WITH_ARGS("DumpFileDescriptorStore",
|
||||
SD_BUS_NO_ARGS,
|
||||
|
@ -549,7 +549,6 @@ Mount.SloppyOptions, config_parse_bool,
|
||||
Mount.LazyUnmount, config_parse_bool, 0, offsetof(Mount, lazy_unmount)
|
||||
Mount.ForceUnmount, config_parse_bool, 0, offsetof(Mount, force_unmount)
|
||||
Mount.ReadWriteOnly, config_parse_bool, 0, offsetof(Mount, read_write_only)
|
||||
Mount.GracefulOptions, config_parse_mount_graceful_options, 0, offsetof(Mount, graceful_options)
|
||||
{{ EXEC_CONTEXT_CONFIG_ITEMS('Mount') }}
|
||||
{{ CGROUP_CONTEXT_CONFIG_ITEMS('Mount') }}
|
||||
{{ KILL_CONTEXT_CONFIG_ITEMS('Mount') }}
|
||||
|
@ -6131,51 +6131,6 @@ int config_parse_mount_node(
|
||||
return config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, path, data, userdata);
|
||||
}
|
||||
|
||||
int config_parse_mount_graceful_options(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
const Unit *u = ASSERT_PTR(userdata);
|
||||
char ***sv = ASSERT_PTR(data);
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
*sv = strv_free(*sv);
|
||||
return 1;
|
||||
}
|
||||
|
||||
_cleanup_free_ char *resolved = NULL;
|
||||
r = unit_full_printf(u, rvalue, &resolved);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
_cleanup_strv_free_ char **strv = NULL;
|
||||
|
||||
r = strv_split_full(&strv, resolved, ",", EXTRACT_RETAIN_ESCAPE|EXTRACT_UNESCAPE_SEPARATORS);
|
||||
if (r < 0)
|
||||
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
|
||||
|
||||
r = strv_extend_strv_consume(sv, TAKE_PTR(strv), /* filter_duplicates = */ false);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int merge_by_names(Unit *u, Set *names, const char *id) {
|
||||
char *k;
|
||||
int r;
|
||||
|
@ -165,7 +165,6 @@ CONFIG_PARSER_PROTOTYPE(config_parse_open_file);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_memory_pressure_watch);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_cgroup_nft_set);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_mount_node);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_mount_graceful_options);
|
||||
|
||||
/* gperf prototypes */
|
||||
const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
|
||||
|
139
src/core/mount.c
139
src/core/mount.c
@ -45,9 +45,9 @@ static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = {
|
||||
[MOUNT_MOUNTING_DONE] = UNIT_ACTIVATING,
|
||||
[MOUNT_MOUNTED] = UNIT_ACTIVE,
|
||||
[MOUNT_REMOUNTING] = UNIT_RELOADING,
|
||||
[MOUNT_UNMOUNTING] = UNIT_DEACTIVATING,
|
||||
[MOUNT_REMOUNTING_SIGTERM] = UNIT_RELOADING,
|
||||
[MOUNT_REMOUNTING_SIGKILL] = UNIT_RELOADING,
|
||||
[MOUNT_UNMOUNTING] = UNIT_DEACTIVATING,
|
||||
[MOUNT_UNMOUNTING_SIGTERM] = UNIT_DEACTIVATING,
|
||||
[MOUNT_UNMOUNTING_SIGKILL] = UNIT_DEACTIVATING,
|
||||
[MOUNT_FAILED] = UNIT_FAILED,
|
||||
@ -231,8 +231,6 @@ static void mount_done(Unit *u) {
|
||||
mount_unwatch_control_pid(m);
|
||||
|
||||
m->timer_event_source = sd_event_source_disable_unref(m->timer_event_source);
|
||||
|
||||
m->graceful_options = strv_free(m->graceful_options);
|
||||
}
|
||||
|
||||
static int update_parameters_proc_self_mountinfo(
|
||||
@ -1056,6 +1054,8 @@ static void mount_enter_unmounting(Mount *m) {
|
||||
MOUNT_UNMOUNTING_SIGKILL))
|
||||
m->n_retry_umount = 0;
|
||||
|
||||
mount_unwatch_control_pid(m);
|
||||
|
||||
m->control_command_id = MOUNT_EXEC_UNMOUNT;
|
||||
m->control_command = m->exec_command + MOUNT_EXEC_UNMOUNT;
|
||||
|
||||
@ -1065,8 +1065,6 @@ static void mount_enter_unmounting(Mount *m) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
mount_unwatch_control_pid(m);
|
||||
|
||||
r = mount_spawn(m, m->control_command, mount_exec_flags(MOUNT_UNMOUNTING), &m->control_pid);
|
||||
if (r < 0) {
|
||||
log_unit_warning_errno(UNIT(m), r, "Failed to spawn 'umount' task: %m");
|
||||
@ -1074,29 +1072,31 @@ static void mount_enter_unmounting(Mount *m) {
|
||||
}
|
||||
|
||||
mount_set_state(m, MOUNT_UNMOUNTING);
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
mount_enter_dead_or_mounted(m, MOUNT_FAILURE_RESOURCES, /* flush_result = */ false);
|
||||
}
|
||||
|
||||
static int mount_append_graceful_options(Mount *m, const MountParameters *p, char **opts) {
|
||||
static int mount_apply_graceful_options(Mount *m, const MountParameters *p, char **opts) {
|
||||
_cleanup_strv_free_ char **graceful = NULL;
|
||||
_cleanup_free_ char *filtered = NULL;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(p);
|
||||
assert(opts);
|
||||
|
||||
if (strv_isempty(m->graceful_options))
|
||||
return 0;
|
||||
r = fstab_filter_options(*opts, "x-systemd.graceful-option\0", NULL, NULL, &graceful, &filtered);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
if (!p->fstype) {
|
||||
log_unit_warning(UNIT(m), "GracefulOptions= used but file system type not known, suppressing all graceful options.");
|
||||
log_unit_warning(UNIT(m), "x-systemd.graceful-option= used but file system type not known, suppressing all graceful options.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
STRV_FOREACH(o, m->graceful_options) {
|
||||
STRV_FOREACH(o, graceful) {
|
||||
_cleanup_free_ char *k = NULL, *v = NULL;
|
||||
|
||||
r = split_pair(*o, "=", &k, &v);
|
||||
@ -1104,22 +1104,29 @@ static int mount_append_graceful_options(Mount *m, const MountParameters *p, cha
|
||||
return r;
|
||||
|
||||
r = mount_option_supported(p->fstype, k ?: *o, v);
|
||||
if (r == -EAGAIN) {
|
||||
log_unit_warning_errno(UNIT(m), r,
|
||||
"x-systemd.graceful-option= used but not supported by file system %s, suppressing all.",
|
||||
p->fstype);
|
||||
break;
|
||||
}
|
||||
if (r < 0)
|
||||
log_unit_warning_errno(UNIT(m), r, "GracefulOptions=%s specified, but cannot determine availability, suppressing.", *o);
|
||||
log_unit_warning_errno(UNIT(m), r,
|
||||
"x-systemd.graceful-option=%s specified, but cannot determine availability, suppressing: %m", *o);
|
||||
else if (r == 0)
|
||||
log_unit_info(UNIT(m), "GracefulOptions=%s specified, but option is not available, suppressing.", *o);
|
||||
log_unit_info(UNIT(m), "x-systemd.graceful-option=%s specified, but option is not available, suppressing.", *o);
|
||||
else {
|
||||
log_unit_debug(UNIT(m), "GracefulOptions=%s specified and supported, appending to mount option string.", *o);
|
||||
log_unit_debug(UNIT(m), "x-systemd.graceful-option=%s specified and supported, appending to mount option string.", *o);
|
||||
|
||||
if (!strextend_with_separator(opts, ",", *o))
|
||||
if (!strextend_with_separator(&filtered, ",", *o))
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return free_and_replace(*opts, filtered);
|
||||
}
|
||||
|
||||
static int mount_set_mount_command(Mount *m, ExecCommand *c, const MountParameters *p) {
|
||||
static int mount_set_mount_command(Mount *m, ExecCommand *c, const MountParameters *p, bool remount) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
@ -1149,14 +1156,23 @@ static int mount_set_mount_command(Mount *m, ExecCommand *c, const MountParamete
|
||||
}
|
||||
|
||||
_cleanup_free_ char *opts = NULL;
|
||||
r = fstab_filter_options(p->options, "nofail\0" "noauto\0" "auto\0", NULL, NULL, NULL, &opts);
|
||||
r = fstab_filter_options(p->options, "nofail\0" "fail\0" "noauto\0" "auto\0", NULL, NULL, NULL, &opts);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = mount_append_graceful_options(m, p, &opts);
|
||||
r = mount_apply_graceful_options(m, p, &opts);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (remount) {
|
||||
if (isempty(opts)) {
|
||||
opts = strdup("remount");
|
||||
if (!opts)
|
||||
return -ENOMEM;
|
||||
} else if (!strprepend(&opts, "remount,"))
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (!isempty(opts)) {
|
||||
r = exec_command_append(c, "-o", opts, NULL);
|
||||
if (r < 0)
|
||||
@ -1178,7 +1194,12 @@ static void mount_enter_mounting(Mount *m) {
|
||||
goto fail;
|
||||
|
||||
p = get_mount_parameters_fragment(m);
|
||||
if (p && mount_is_bind(p)) {
|
||||
if (!p) {
|
||||
r = log_unit_warning_errno(UNIT(m), SYNTHETIC_ERRNO(ENOENT), "No mount parameters to operate on.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (mount_is_bind(p)) {
|
||||
r = is_dir(p->what, /* follow = */ true);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
log_unit_info_errno(UNIT(m), r, "Failed to determine type of bind mount source '%s', ignoring: %m", p->what);
|
||||
@ -1194,7 +1215,7 @@ static void mount_enter_mounting(Mount *m) {
|
||||
log_unit_warning_errno(UNIT(m), r, "Failed to create mount point '%s', ignoring: %m", m->where);
|
||||
|
||||
/* If we are asked to create an OverlayFS, create the upper/work directories if they are missing */
|
||||
if (p && streq_ptr(p->fstype, "overlay")) {
|
||||
if (streq_ptr(p->fstype, "overlay")) {
|
||||
_cleanup_strv_free_ char **dirs = NULL;
|
||||
|
||||
r = fstab_filter_options(
|
||||
@ -1223,13 +1244,9 @@ static void mount_enter_mounting(Mount *m) {
|
||||
|
||||
if (source_is_dir)
|
||||
unit_warn_if_dir_nonempty(UNIT(m), m->where);
|
||||
unit_warn_leftover_processes(UNIT(m), /* start = */ true);
|
||||
|
||||
m->control_command_id = MOUNT_EXEC_MOUNT;
|
||||
m->control_command = m->exec_command + MOUNT_EXEC_MOUNT;
|
||||
|
||||
/* Create the source directory for bind-mounts if needed */
|
||||
if (p && mount_is_bind(p)) {
|
||||
if (mount_is_bind(p)) {
|
||||
r = mkdir_p_label(p->what, m->directory_mode);
|
||||
/* mkdir_p_label() can return -EEXIST if the target path exists and is not a directory - which is
|
||||
* totally OK, in case the user wants us to overmount a non-directory inode. Also -EROFS can be
|
||||
@ -1241,19 +1258,18 @@ static void mount_enter_mounting(Mount *m) {
|
||||
r, "Failed to make bind mount source '%s', ignoring: %m", p->what);
|
||||
}
|
||||
|
||||
if (p) {
|
||||
r = mount_set_mount_command(m, m->control_command, p);
|
||||
if (r < 0) {
|
||||
log_unit_warning_errno(UNIT(m), r, "Failed to prepare mount command line: %m");
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
r = log_unit_warning_errno(UNIT(m), SYNTHETIC_ERRNO(ENOENT), "No mount parameters to operate on.");
|
||||
mount_unwatch_control_pid(m);
|
||||
unit_warn_leftover_processes(UNIT(m), /* start = */ true);
|
||||
|
||||
m->control_command_id = MOUNT_EXEC_MOUNT;
|
||||
m->control_command = m->exec_command + MOUNT_EXEC_MOUNT;
|
||||
|
||||
r = mount_set_mount_command(m, m->control_command, p, /* remount = */ false);
|
||||
if (r < 0) {
|
||||
log_unit_error_errno(UNIT(m), r, "Failed to prepare mount command line: %m");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
mount_unwatch_control_pid(m);
|
||||
|
||||
r = mount_spawn(m, m->control_command, mount_exec_flags(MOUNT_MOUNTING), &m->control_pid);
|
||||
if (r < 0) {
|
||||
log_unit_warning_errno(UNIT(m), r, "Failed to spawn 'mount' task: %m");
|
||||
@ -1283,41 +1299,23 @@ static void mount_enter_remounting(Mount *m) {
|
||||
|
||||
assert(m);
|
||||
|
||||
/* Reset reload result when we are about to start a new remount operation */
|
||||
m->reload_result = MOUNT_SUCCESS;
|
||||
|
||||
m->control_command_id = MOUNT_EXEC_REMOUNT;
|
||||
m->control_command = m->exec_command + MOUNT_EXEC_REMOUNT;
|
||||
|
||||
p = get_mount_parameters_fragment(m);
|
||||
if (p) {
|
||||
const char *o;
|
||||
|
||||
if (p->options)
|
||||
o = strjoina("remount,", p->options);
|
||||
else
|
||||
o = "remount";
|
||||
|
||||
r = exec_command_set(m->control_command, MOUNT_PATH,
|
||||
p->what, m->where,
|
||||
"-o", o, NULL);
|
||||
if (r >= 0 && m->sloppy_options)
|
||||
r = exec_command_append(m->control_command, "-s", NULL);
|
||||
if (r >= 0 && m->read_write_only)
|
||||
r = exec_command_append(m->control_command, "-w", NULL);
|
||||
if (r >= 0 && p->fstype)
|
||||
r = exec_command_append(m->control_command, "-t", p->fstype, NULL);
|
||||
if (r < 0) {
|
||||
log_unit_warning_errno(UNIT(m), r, "Failed to prepare remount command line: %m");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (!p) {
|
||||
r = log_unit_warning_errno(UNIT(m), SYNTHETIC_ERRNO(ENOENT), "No mount parameters to operate on.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
mount_unwatch_control_pid(m);
|
||||
m->reload_result = MOUNT_SUCCESS;
|
||||
|
||||
m->control_command_id = MOUNT_EXEC_REMOUNT;
|
||||
m->control_command = m->exec_command + MOUNT_EXEC_REMOUNT;
|
||||
|
||||
r = mount_set_mount_command(m, m->control_command, p, /* remount = */ true);
|
||||
if (r < 0) {
|
||||
log_unit_error_errno(UNIT(m), r, "Failed to prepare remount command line: %m");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r = mount_spawn(m, m->control_command, mount_exec_flags(MOUNT_REMOUNTING), &m->control_pid);
|
||||
if (r < 0) {
|
||||
@ -1427,6 +1425,12 @@ static int mount_reload(Unit *u) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool mount_can_reload(Unit *u) {
|
||||
Mount *m = ASSERT_PTR(MOUNT(u));
|
||||
|
||||
return get_mount_parameters_fragment(m);
|
||||
}
|
||||
|
||||
static int mount_serialize(Unit *u, FILE *f, FDSet *fds) {
|
||||
Mount *m = ASSERT_PTR(MOUNT(u));
|
||||
|
||||
@ -2364,6 +2368,9 @@ static int mount_can_start(Unit *u) {
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!get_mount_parameters_fragment(m))
|
||||
return -ENOENT;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -2478,7 +2485,9 @@ const UnitVTable mount_vtable = {
|
||||
|
||||
.start = mount_start,
|
||||
.stop = mount_stop,
|
||||
|
||||
.reload = mount_reload,
|
||||
.can_reload = mount_can_reload,
|
||||
|
||||
.clean = mount_clean,
|
||||
.can_clean = mount_can_clean,
|
||||
|
@ -81,15 +81,13 @@ struct Mount {
|
||||
|
||||
MountState state, deserialized_state;
|
||||
|
||||
ExecCommand* control_command;
|
||||
ExecCommand *control_command;
|
||||
MountExecCommand control_command_id;
|
||||
PidRef control_pid;
|
||||
|
||||
sd_event_source *timer_event_source;
|
||||
|
||||
unsigned n_retry_umount;
|
||||
|
||||
char **graceful_options;
|
||||
};
|
||||
|
||||
extern const UnitVTable mount_vtable;
|
||||
|
@ -148,9 +148,11 @@ static int bus_append_string(sd_bus_message *m, const char *field, const char *e
|
||||
}
|
||||
|
||||
static int bus_append_strv(sd_bus_message *m, const char *field, const char *eq, const char *separator, ExtractFlags flags) {
|
||||
const char *p;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(field);
|
||||
|
||||
r = sd_bus_message_open_container(m, 'r', "sv");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
@ -167,16 +169,16 @@ static int bus_append_strv(sd_bus_message *m, const char *field, const char *eq,
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
for (p = eq;;) {
|
||||
for (const char *p = eq;;) {
|
||||
_cleanup_free_ char *word = NULL;
|
||||
|
||||
r = extract_first_word(&p, &word, separator, flags);
|
||||
if (r == 0)
|
||||
break;
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Invalid syntax: %s", eq);
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
r = sd_bus_message_append_basic(m, 's', word);
|
||||
if (r < 0)
|
||||
@ -2333,9 +2335,6 @@ static int bus_append_mount_property(sd_bus_message *m, const char *field, const
|
||||
"ReadwriteOnly"))
|
||||
return bus_append_parse_boolean(m, field, eq);
|
||||
|
||||
if (streq(field, "GracefulOptions"))
|
||||
return bus_append_strv(m, field, eq, /* separator= */ ",", 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -181,9 +181,9 @@ touch "$WORK_DIR/mnt/hello"
|
||||
[[ "$(stat -c "%U:%G" "$WORK_DIR/mnt/hello")" == "testuser:testuser" ]]
|
||||
systemd-umount LABEL=owner-vfat
|
||||
|
||||
# Mkae sure that graceful mount options work
|
||||
# Make sure that graceful mount options work
|
||||
GRACEFULTEST="/tmp/graceful/$RANDOM"
|
||||
systemd-mount --tmpfs -p GracefulOptions=idefinitelydontexist,nr_inodes=4711,idonexisteither "$GRACEFULTEST"
|
||||
systemd-mount --tmpfs --options="x-systemd.graceful-option=idefinitelydontexist,x-systemd.graceful-option=nr_inodes=4711,x-systemd.graceful-option=idonexisteither" "$GRACEFULTEST"
|
||||
findmnt -n -o options "$GRACEFULTEST"
|
||||
findmnt -n -o options "$GRACEFULTEST" | grep -q nr_inodes=4711
|
||||
umount "$GRACEFULTEST"
|
||||
|
@ -22,5 +22,4 @@ After=swap.target
|
||||
What=tmpfs
|
||||
Where=/tmp
|
||||
Type=tmpfs
|
||||
Options=mode=1777,strictatime,nosuid,nodev,size=50%%,nr_inodes=1m
|
||||
GracefulOptions=usrquota
|
||||
Options=mode=1777,strictatime,nosuid,nodev,size=50%%,nr_inodes=1m,x-systemd.graceful-option=usrquota
|
||||
|
Loading…
x
Reference in New Issue
Block a user