static void swap_set_state(Swap *s, SwapState state) {
SwapState old_state;
+ Swap *other;
assert(s);
swap_state_to_string(state));
unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], true);
+
+ /* If there other units for the same device node have a job
+ queued it might be worth checking again if it is runnable
+ now. This is necessary, since swap_start() refuses
+ operation with EAGAIN if there's already another job for
+ the same device node queued. */
+ LIST_FOREACH_OTHERS(same_devnode, other, s)
+ if (UNIT(other)->job)
+ job_add_to_run_queue(UNIT(other)->job);
}
static int swap_coldplug(Unit *u) {
if (streq(discard, "all"))
discard_arg = "--discard";
else
- discard_arg = strappenda("--discard=", discard);
+ discard_arg = strjoina("--discard=", discard);
r = exec_command_append(s->control_command, discard_arg, NULL);
if (r < 0)
}
static int swap_start(Unit *u) {
- Swap *s = SWAP(u);
+ Swap *s = SWAP(u), *other;
assert(s);
if (detect_container(NULL) > 0)
return -EPERM;
+ /* If there's a job for another swap unit for the same node
+ * running, then let's not dispatch this one for now, and wait
+ * until that other job has finished. */
+ LIST_FOREACH_OTHERS(same_devnode, other, s)
+ if (UNIT(other)->job && UNIT(other)->job->state == JOB_RUNNING)
+ return -EAGAIN;
+
s->result = SWAP_SUCCESS;
swap_enter_activating(s);
- return 0;
+ return 1;
}
static int swap_stop(Unit *u) {
return -EPERM;
swap_enter_deactivating(s);
- return 0;
+ return 1;
}
static int swap_serialize(Unit *u, FILE *f, FDSet *fds) {
if (s->from_fragment)
return NULL;
- LIST_FOREACH_AFTER(same_devnode, other, s)
- if (other->from_fragment)
- return UNIT(other);
-
- LIST_FOREACH_BEFORE(same_devnode, other, s)
+ LIST_FOREACH_OTHERS(same_devnode, other, s)
if (other->from_fragment)
return UNIT(other);
if (!set)
return -ENOMEM;
- LIST_FOREACH_AFTER(same_devnode, other, s) {
- r = set_put(set, other);
- if (r < 0)
- goto fail;
- }
-
- LIST_FOREACH_BEFORE(same_devnode, other, s) {
+ LIST_FOREACH_OTHERS(same_devnode, other, s) {
r = set_put(set, other);
if (r < 0)
goto fail;