***/
#include <errno.h>
-#include <limits.h>
#include <unistd.h>
-#include <fcntl.h>
#include <sys/epoll.h>
#include <sys/stat.h>
-#include <sys/swap.h>
#include <libudev.h>
#include "unit.h"
#include "swap.h"
-#include "load-fragment.h"
-#include "load-dropin.h"
#include "unit-name.h"
#include "dbus-swap.h"
#include "special.h"
-#include "bus-common-errors.h"
#include "exit-status.h"
-#include "def.h"
#include "path-util.h"
#include "virt.h"
#include "udev-util.h"
return swap_verify(s);
}
-static int swap_add_one(
+static int swap_setup_unit(
Manager *m,
const char *what,
const char *what_proc_swaps,
if (u &&
SWAP(u)->from_proc_swaps &&
- !path_equal(SWAP(u)->parameters_proc_swaps.what, what_proc_swaps))
+ !path_equal(SWAP(u)->parameters_proc_swaps.what, what_proc_swaps)) {
+ log_error("Swap %s appeared twice with different device paths %s and %s", e, SWAP(u)->parameters_proc_swaps.what, what_proc_swaps);
return -EEXIST;
+ }
if (!u) {
delete = true;
SWAP(u)->what = strdup(what);
if (!SWAP(u)->what) {
- r = log_oom();
+ r = -ENOMEM;
goto fail;
}
p->priority = priority;
unit_add_to_dbus_queue(u);
-
return 0;
fail:
return r;
}
-static int swap_process_new_swap(Manager *m, const char *device, int prio, bool set_flags) {
+static int swap_process_new(Manager *m, const char *device, int prio, bool set_flags) {
_cleanup_udev_device_unref_ struct udev_device *d = NULL;
struct udev_list_entry *item = NULL, *first = NULL;
const char *dn;
assert(m);
- r = swap_add_one(m, device, device, prio, set_flags);
+ r = swap_setup_unit(m, device, device, prio, set_flags);
if (r < 0)
return r;
/* Add the main device node */
dn = udev_device_get_devnode(d);
if (dn && !streq(dn, device))
- swap_add_one(m, dn, device, prio, set_flags);
+ swap_setup_unit(m, dn, device, prio, set_flags);
/* Add additional units for all symlinks */
first = udev_device_get_devlinks_list_entry(d);
st.st_rdev != udev_device_get_devnum(d))
continue;
- swap_add_one(m, p, device, prio, set_flags);
+ swap_setup_unit(m, p, device, prio, set_flags);
}
return r;
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) {
+static int swap_coldplug(Unit *u, Hashmap *deferred_work) {
Swap *s = SWAP(u);
SwapState new_state = SWAP_DEAD;
int r;
assert(c);
assert(_pid);
- unit_realize_cgroup(UNIT(s));
+ (void) unit_realize_cgroup(UNIT(s));
+ if (s->reset_cpu_usage) {
+ (void) unit_reset_cpu_usage(UNIT(s));
+ s->reset_cpu_usage = false;
+ }
r = unit_setup_exec_runtime(UNIT(s));
if (r < 0)
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;
+ s->reset_cpu_usage = true;
+
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 (k == EOF)
break;
- log_warning("Failed to parse /proc/swaps:%u", i);
+ log_warning("Failed to parse /proc/swaps:%u.", i);
continue;
}
d = cunescape(dev);
if (!d)
- return -ENOMEM;
+ return log_oom();
+
+ device_found_node(m, d, true, DEVICE_FOUND_SWAP, set_flags);
- k = swap_process_new_swap(m, d, prio, set_flags);
+ k = swap_process_new(m, d, prio, set_flags);
if (k < 0)
r = k;
}
break;
}
+ if (swap->what)
+ device_found_node(m, swap->what, false, DEVICE_FOUND_SWAP, true);
+
} else if (swap->just_activated) {
/* New swap entry */
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;
return r;
}
-int swap_process_new_device(Manager *m, struct udev_device *dev) {
+int swap_process_device_new(Manager *m, struct udev_device *dev) {
struct udev_list_entry *item = NULL, *first = NULL;
_cleanup_free_ char *e = NULL;
const char *dn;
return r;
}
-int swap_process_removed_device(Manager *m, struct udev_device *dev) {
+int swap_process_device_remove(Manager *m, struct udev_device *dev) {
const char *dn;
int r = 0;
Swap *s;