diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:49:52 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:49:52 +0000 |
commit | 55944e5e40b1be2afc4855d8d2baf4b73d1876b5 (patch) | |
tree | 33f869f55a1b149e9b7c2b7e201867ca5dd52992 /src/shutdown/detach-swap.c | |
parent | Initial commit. (diff) | |
download | systemd-55944e5e40b1be2afc4855d8d2baf4b73d1876b5.tar.xz systemd-55944e5e40b1be2afc4855d8d2baf4b73d1876b5.zip |
Adding upstream version 255.4.upstream/255.4
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/shutdown/detach-swap.c')
-rw-r--r-- | src/shutdown/detach-swap.c | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/src/shutdown/detach-swap.c b/src/shutdown/detach-swap.c new file mode 100644 index 0000000..fd7dcdf --- /dev/null +++ b/src/shutdown/detach-swap.c @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/*** + Copyright © 2010 ProFUSION embedded systems +***/ + +#include <sys/swap.h> + +#include "alloc-util.h" +#include "detach-swap.h" +#include "libmount-util.h" + +static void swap_device_free(SwapDevice **head, SwapDevice *m) { + assert(head); + assert(m); + + LIST_REMOVE(swap_device, *head, m); + + free(m->path); + free(m); +} + +void swap_devices_list_free(SwapDevice **head) { + assert(head); + + while (*head) + swap_device_free(head, *head); +} + +int swap_list_get(const char *swaps, SwapDevice **head) { + _cleanup_(mnt_free_tablep) struct libmnt_table *t = NULL; + _cleanup_(mnt_free_iterp) struct libmnt_iter *i = NULL; + int r; + + assert(head); + + t = mnt_new_table(); + i = mnt_new_iter(MNT_ITER_FORWARD); + if (!t || !i) + return log_oom(); + + r = mnt_table_parse_swaps(t, swaps); + if (r == -ENOENT) /* no /proc/swaps is fine */ + return 0; + if (r < 0) + return log_error_errno(r, "Failed to parse %s: %m", swaps ?: "/proc/swaps"); + + for (;;) { + struct libmnt_fs *fs; + _cleanup_free_ SwapDevice *swap = NULL; + const char *source; + + r = mnt_table_next_fs(t, i, &fs); + if (r == 1) /* EOF */ + break; + if (r < 0) + return log_error_errno(r, "Failed to get next entry from %s: %m", swaps ?: "/proc/swaps"); + + source = mnt_fs_get_source(fs); + if (!source) + continue; + + swap = new0(SwapDevice, 1); + if (!swap) + return log_oom(); + + swap->path = strdup(source); + if (!swap->path) + return log_oom(); + + LIST_PREPEND(swap_device, *head, TAKE_PTR(swap)); + } + + return 0; +} + +static int swap_points_list_off(SwapDevice **head, bool *changed) { + int n_failed = 0; + + assert(head); + assert(changed); + + LIST_FOREACH(swap_device, m, *head) { + log_info("Deactivating swap %s.", m->path); + if (swapoff(m->path) < 0) { + log_warning_errno(errno, "Could not deactivate swap %s: %m", m->path); + n_failed++; + continue; + } + + *changed = true; + swap_device_free(head, m); + } + + return n_failed; +} + +int swapoff_all(bool *changed) { + _cleanup_(swap_devices_list_free) LIST_HEAD(SwapDevice, swap_list_head); + int r; + + assert(changed); + + LIST_HEAD_INIT(swap_list_head); + + r = swap_list_get(NULL, &swap_list_head); + if (r < 0) + return r; + + return swap_points_list_off(&swap_list_head, changed); +} |