pid1: add GracefulOptions= setting to .mount units
This new setting can be used to specify mount options that shall only be added to the mount option string if the kernel supports them. This shall be used for adding "usrquota" to tmp.mount without breaking compat, but is generally be useful.
This commit is contained in:
@@ -75,6 +75,7 @@ const sd_bus_vtable bus_mount_vtable[] = {
|
||||
SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Mount, 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),
|
||||
@@ -150,6 +151,30 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -548,6 +548,7 @@ 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') }}
|
||||
|
||||
@@ -6123,6 +6123,51 @@ 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,6 +165,7 @@ 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);
|
||||
|
||||
@@ -231,6 +231,8 @@ 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(
|
||||
@@ -1079,6 +1081,44 @@ 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) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(p);
|
||||
assert(opts);
|
||||
|
||||
if (strv_isempty(m->graceful_options))
|
||||
return 0;
|
||||
|
||||
if (!p->fstype) {
|
||||
log_unit_warning(UNIT(m), "GracefulOptions= used but file system type not known, suppressing all graceful options.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
STRV_FOREACH(o, m->graceful_options) {
|
||||
_cleanup_free_ char *k = NULL, *v = NULL;
|
||||
|
||||
r = split_pair(*o, "=", &k, &v);
|
||||
if (r < 0 && r != -EINVAL) /* EINVAL → not a key/value pair */
|
||||
return r;
|
||||
|
||||
r = mount_option_supported(p->fstype, k ?: *o, v);
|
||||
if (r < 0)
|
||||
log_unit_warning_errno(UNIT(m), r, "GracefulOptions=%s specified, but cannot determine availability, suppressing.", *o);
|
||||
else if (r == 0)
|
||||
log_unit_info(UNIT(m), "GracefulOptions=%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);
|
||||
|
||||
if (!strextend_with_separator(opts, ",", *o))
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mount_set_mount_command(Mount *m, ExecCommand *c, const MountParameters *p) {
|
||||
int r;
|
||||
|
||||
@@ -1113,6 +1153,10 @@ static int mount_set_mount_command(Mount *m, ExecCommand *c, const MountParamete
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = mount_append_graceful_options(m, p, &opts);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!isempty(opts)) {
|
||||
r = exec_command_append(c, "-o", opts, NULL);
|
||||
if (r < 0)
|
||||
|
||||
@@ -88,6 +88,8 @@ struct Mount {
|
||||
sd_event_source *timer_event_source;
|
||||
|
||||
unsigned n_retry_umount;
|
||||
|
||||
char **graceful_options;
|
||||
};
|
||||
|
||||
extern const UnitVTable mount_vtable;
|
||||
|
||||
Reference in New Issue
Block a user