swap: replace Discard= setting by a more generic Options= setting

For now, it's systemd itself that parses the options string, but as soon
as util-linux' swapon can take the option string directly with -o we
should pass it on unmodified.
This commit is contained in:
Lennart Poettering 2014-10-28 14:24:46 +01:00
parent 33488f1979
commit 47cb901e38
6 changed files with 102 additions and 76 deletions

View File

@ -171,14 +171,14 @@
</varlistentry>
<varlistentry>
<term><varname>Discard=</varname></term>
<term><varname>Options=</varname></term>
<listitem><para>Enable discards, if the swap
backing device supports the discard or trim
operation. Can be one of <literal>none</literal>,
<literal>once</literal>, <literal>pages</literal>
or <literal>all</literal>. Defaults to
<literal>none</literal>. (See
<listitem><para>May contain an option
string for the swap device. This may
be used for controlling discard
options among other functionality, if
the swap backing device supports the
discard or trim operation. (See
<citerefentry><refentrytitle>swapon</refentrytitle><manvolnum>8</manvolnum></citerefentry>
for more information.)
</para></listitem>

View File

@ -55,7 +55,7 @@ static int property_get_priority(
return sd_bus_message_append(reply, "i", p);
}
static int property_get_discard(
static int property_get_options(
sd_bus *bus,
const char *path,
const char *interface,
@ -65,17 +65,16 @@ static int property_get_discard(
sd_bus_error *error) {
Swap *s = SWAP(userdata);
const char *p;
const char *options = NULL;
assert(bus);
assert(reply);
assert(s);
if (s->from_fragment)
p = s->parameters_fragment.discard ?: "none";
else
p = "none";
return sd_bus_message_append(reply, "s", p);
options = s->parameters_fragment.options;
return sd_bus_message_append(reply, "s", options);
}
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, swap_result, SwapResult);
@ -84,7 +83,7 @@ const sd_bus_vtable bus_swap_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("What", "s", NULL, offsetof(Swap, what), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("Priority", "i", property_get_priority, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("Discard", "s", property_get_discard, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("Options", "s", property_get_options, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("TimeoutUSec", "t", bus_property_get_usec, offsetof(Swap, timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Swap, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Swap, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),

View File

@ -299,7 +299,7 @@ Automount.DirectoryMode, config_parse_mode, 0,
m4_dnl
Swap.What, config_parse_path, 0, offsetof(Swap, parameters_fragment.what)
Swap.Priority, config_parse_int, 0, offsetof(Swap, parameters_fragment.priority)
Swap.Discard, config_parse_string, 0, offsetof(Swap, parameters_fragment.discard)
Swap.Options, config_parse_string, 0, offsetof(Swap, parameters_fragment.options)
Swap.TimeoutSec, config_parse_sec, 0, offsetof(Swap, timeout_usec)
EXEC_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl
CGROUP_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl

View File

@ -152,8 +152,8 @@ static void swap_done(Unit *u) {
free(s->parameters_fragment.what);
s->parameters_fragment.what = NULL;
free(s->parameters_fragment.discard);
s->parameters_fragment.discard = NULL;
free(s->parameters_fragment.options);
s->parameters_fragment.options = NULL;
s->exec_runtime = exec_runtime_unref(s->exec_runtime);
exec_command_done_array(s->exec_command, _SWAP_EXEC_COMMAND_MAX);
@ -608,11 +608,11 @@ static void swap_dump(Unit *u, FILE *f, const char *prefix) {
"%sPriority: %i\n"
"%sNoAuto: %s\n"
"%sNoFail: %s\n"
"%sDiscard: %s\n",
"%sOptions: %s\n",
prefix, p->priority,
prefix, yes_no(p->noauto),
prefix, yes_no(p->nofail),
prefix, p->discard ?: "none");
prefix, strempty(p->options));
if (s->control_pid > 0)
fprintf(f,
@ -739,9 +739,74 @@ fail:
swap_enter_dead(s, SWAP_FAILURE_RESOURCES);
}
static int mount_find_pri(const char *options, int *ret) {
const char *opt;
char *end;
unsigned long r;
assert(ret);
if (!options)
return 0;
opt = mount_test_option(options, "pri");
if (!opt)
return 0;
opt += strlen("pri");
if (*opt != '=')
return -EINVAL;
errno = 0;
r = strtoul(opt + 1, &end, 10);
if (errno > 0)
return -errno;
if (end == opt + 1 || (*end != ',' && *end != 0))
return -EINVAL;
*ret = (int) r;
return 1;
}
static int mount_find_discard(const char *options, char **ret) {
const char *opt;
char *ans;
size_t len;
assert(ret);
if (!options)
return 0;
opt = mount_test_option(options, "discard");
if (!opt)
return 0;
opt += strlen("discard");
if (*opt == ',' || *opt == '\0')
ans = strdup("all");
else {
if (*opt != '=')
return -EINVAL;
len = strcspn(opt + 1, ",");
if (len == 0)
return -EINVAL;
ans = strndup(opt + 1, len);
}
if (!ans)
return -ENOMEM;
*ret = ans;
return 1;
}
static void swap_enter_activating(Swap *s) {
int r, priority;
char *discard;
_cleanup_free_ char *discard = NULL;
int r, priority = -1;
assert(s);
@ -749,11 +814,11 @@ static void swap_enter_activating(Swap *s) {
s->control_command = s->exec_command + SWAP_EXEC_ACTIVATE;
if (s->from_fragment) {
mount_find_discard(s->parameters_fragment.options, &discard);
priority = s->parameters_fragment.priority;
discard = s->parameters_fragment.discard;
} else {
priority = -1;
discard = NULL;
if (priority < 0)
mount_find_pri(s->parameters_fragment.options, &priority);
}
r = exec_command_set(s->control_command, "/sbin/swapon", NULL);
@ -770,9 +835,11 @@ static void swap_enter_activating(Swap *s) {
}
if (discard && !streq(discard, "none")) {
const char *discard_arg = "--discard";
const char *discard_arg;
if (!streq(discard, "all"))
if (streq(discard, "all"))
discard_arg = "--discard";
else
discard_arg = strappenda("--discard=", discard);
r = exec_command_append(s->control_command, discard_arg, NULL);

View File

@ -63,7 +63,7 @@ typedef enum SwapResult {
typedef struct SwapParameters {
char *what;
char *discard;
char *options;
int priority;
bool noauto:1;
bool nofail:1;

View File

@ -47,7 +47,6 @@ static char *arg_usr_what = NULL;
static char *arg_usr_fstype = NULL;
static char *arg_usr_options = NULL;
static int mount_find_pri(struct mntent *me, int *ret) {
char *end, *opt;
unsigned long r;
@ -60,7 +59,6 @@ static int mount_find_pri(struct mntent *me, int *ret) {
return 0;
opt += strlen("pri");
if (*opt != '=')
return -EINVAL;
@ -76,43 +74,9 @@ static int mount_find_pri(struct mntent *me, int *ret) {
return 1;
}
static int mount_find_discard(struct mntent *me, char **ret) {
char *opt, *ans;
size_t len;
assert(me);
assert(ret);
opt = hasmntopt(me, "discard");
if (!opt)
return 0;
opt += strlen("discard");
if (*opt == ',' || *opt == '\0')
ans = strdup("all");
else {
if (*opt != '=')
return -EINVAL;
len = strcspn(opt + 1, ",");
if (len == 0)
return -EINVAL;
ans = strndup(opt + 1, len);
}
if (!ans)
return -ENOMEM;
*ret = ans;
return 1;
}
static int add_swap(const char *what, struct mntent *me) {
_cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL;
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *discard = NULL;
bool noauto;
int r, pri = -1;
@ -131,12 +95,6 @@ static int add_swap(const char *what, struct mntent *me) {
return r;
}
r = mount_find_discard(me, &discard);
if (r < 0) {
log_error("Failed to parse discard");
return r;
}
noauto = !!hasmntopt(me, "noauto");
name = unit_name_from_path(what, ".swap");
@ -165,16 +123,18 @@ static int add_swap(const char *what, struct mntent *me) {
"What=%s\n",
what);
/* Note that we currently pass the priority field twice, once
* in Priority=, and once in Options= */
if (pri >= 0)
fprintf(f, "Priority=%i\n", pri);
if (discard)
fprintf(f, "Discard=%s\n", discard);
if (!isempty(me->mnt_opts) && !streq(me->mnt_opts, "defaults"))
fprintf(f, "Options=%s\n", me->mnt_opts);
fflush(f);
if (ferror(f)) {
log_error("Failed to write unit file %s: %m", unit);
return -errno;
r = fflush_and_check(f);
if (r < 0) {
log_error("Failed to write unit file %s: %s", unit, strerror(-r));
return r;
}
/* use what as where, to have a nicer error message */