diff options
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | dbus-swap.c | 47 | ||||
-rw-r--r-- | dbus-swap.h | 32 | ||||
-rw-r--r-- | load-fragment.c | 7 | ||||
-rw-r--r-- | manager.h | 4 | ||||
-rw-r--r-- | mount.c | 112 | ||||
-rw-r--r-- | mount.h | 2 | ||||
-rw-r--r-- | swap.c | 424 | ||||
-rw-r--r-- | swap.h | 60 | ||||
-rw-r--r-- | unit.c | 6 | ||||
-rw-r--r-- | unit.h | 4 |
11 files changed, 659 insertions, 43 deletions
diff --git a/Makefile.am b/Makefile.am index c38c7d575c..115cd0530f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -112,6 +112,8 @@ COMMON_SOURCES = \ automount.h \ mount.c \ mount.h \ + swap.c \ + swap.h \ device.c \ device.h \ target.c \ @@ -144,6 +146,8 @@ COMMON_SOURCES = \ dbus-mount.h \ dbus-automount.c \ dbus-autpmount.h \ + dbus-swap.c \ + dbus-swap.h \ dbus-snapshot.c \ dbus-snapshot.h \ dbus-device.c \ diff --git a/dbus-swap.c b/dbus-swap.c new file mode 100644 index 0000000000..6939ae29c7 --- /dev/null +++ b/dbus-swap.c @@ -0,0 +1,47 @@ +/*-*- Mode: C; c-basic-offset: 8 -*-*/ + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + Copyright 2010 Maarten Lankhorst + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include "dbus-unit.h" +#include "dbus-swap.h" + +static const char introspection[] = + DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE + "<node>" + BUS_UNIT_INTERFACE + BUS_PROPERTIES_INTERFACE + " <interface name=\"org.freedesktop.systemd1.Swap\">" + " <property name=\"What\" type=\"s\" access=\"read\"/>" + " <property name=\"Priority\" type=\"i\" access=\"read\"/>" + " </interface>" + BUS_INTROSPECTABLE_INTERFACE + "</node>"; + +DBusHandlerResult bus_swap_message_handler(Unit *u, DBusMessage *message) { + const BusProperty properties[] = { + BUS_UNIT_PROPERTIES, + { "org.freedesktop.systemd1.Swap", "What", bus_property_append_string, "s", u->swap.what }, + { "org.freedesktop.systemd1.Swap", "Priority", bus_property_append_int32, "i", &u->swap.priority }, + { NULL, NULL, NULL, NULL, NULL } + }; + + return bus_default_message_handler(u->meta.manager, message, introspection, properties); +} diff --git a/dbus-swap.h b/dbus-swap.h new file mode 100644 index 0000000000..3bef6ad621 --- /dev/null +++ b/dbus-swap.h @@ -0,0 +1,32 @@ +/*-*- Mode: C; c-basic-offset: 8 -*-*/ + +#ifndef foodbusswaphfoo +#define foodbusswaphfoo + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + Copyright 2010 Maarten Lankhorst + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <dbus/dbus.h> + +#include "unit.h" + +DBusHandlerResult bus_swap_message_handler(Unit *u, DBusMessage *message); + +#endif diff --git a/load-fragment.c b/load-fragment.c index 0dfb49f113..b4e0c76009 100644 --- a/load-fragment.c +++ b/load-fragment.c @@ -1171,7 +1171,8 @@ static int load_from_path(Unit *u, const char *path) { [UNIT_DEVICE] = "Device", [UNIT_MOUNT] = "Mount", [UNIT_AUTOMOUNT] = "Automount", - [UNIT_SNAPSHOT] = "Snapshot" + [UNIT_SNAPSHOT] = "Snapshot", + [UNIT_SWAP] = "Swap" }; #define EXEC_CONTEXT_CONFIG_ITEMS(context, section) \ @@ -1286,6 +1287,10 @@ static int load_from_path(Unit *u, const char *path) { { "Where", config_parse_path, &u->automount.where, "Automount" }, + { "What", config_parse_path, &u->swap.what, "Swap" }, + { "Priority", config_parse_unsigned, &u->swap.priority, "Swap" }, + { "NoAuto", config_parse_bool, &u->swap.no_auto, "Swap" }, + { NULL, NULL, NULL, NULL } }; @@ -99,6 +99,7 @@ struct Watch { #define SPECIAL_LOCAL_FS_TARGET "local-fs.target" #define SPECIAL_REMOTE_FS_TARGET "remote-fs.target" +#define SPECIAL_SWAP_TARGET "swap.target" #define SPECIAL_NETWORK_TARGET "network.target" #define SPECIAL_NSS_LOOKUP_TARGET "nss-lookup.target" /* LSB's $named */ #define SPECIAL_RPCBIND_TARGET "rpcbind.target" /* LSB's $portmap */ @@ -187,6 +188,9 @@ struct Manager { FILE *proc_self_mountinfo; Watch mount_watch; + /* Data specific to the swap filesystem */ + FILE *proc_swaps; + /* Data specific to the D-Bus subsystem */ DBusConnection *api_bus, *system_bus; Set *subscribed; @@ -113,87 +113,82 @@ static void mount_done(Unit *u) { unit_unwatch_timer(u, &m->timer_watch); } -static int mount_add_node_links(Mount *m) { +int mount_add_node_links(Unit *u, const char *what) { Unit *device; char *e; int r; - const char *what; - assert(m); - - /* Adds in links to the device that this node is based on */ + assert(u); - if (m->parameters_fragment.what) - what = m->parameters_fragment.what; - else if (m->parameters_etc_fstab.what) - what = m->parameters_etc_fstab.what; - else + if (!what) /* We observe kernel mounts only while they are live, * hence don't create any links for them */ return 0; + /* Adds in links to the device that this node is based on */ + if (!path_startswith(what, "/dev/")) return 0; if (!(e = unit_name_build_escape(what+1, NULL, ".device"))) return -ENOMEM; - r = manager_load_unit(UNIT(m)->meta.manager, e, NULL, &device); + r = manager_load_unit(u->meta.manager, e, NULL, &device); free(e); if (r < 0) return r; - if ((r = unit_add_dependency(UNIT(m), UNIT_AFTER, device, true)) < 0) + if ((r = unit_add_dependency(u, UNIT_AFTER, device, true)) < 0) return r; - if ((r = unit_add_dependency(UNIT(m), UNIT_REQUIRES, device, true)) < 0) + if ((r = unit_add_dependency(u, UNIT_REQUIRES, device, true)) < 0) return r; - if (UNIT(m)->meta.manager->running_as == MANAGER_INIT || - UNIT(m)->meta.manager->running_as == MANAGER_SYSTEM) - if ((r = unit_add_dependency(device, UNIT_WANTS, UNIT(m), false)) < 0) + if (u->meta.manager->running_as == MANAGER_INIT || + u->meta.manager->running_as == MANAGER_SYSTEM) + if ((r = unit_add_dependency(device, UNIT_WANTS, u, false)) < 0) return r; return 0; } -static int mount_add_path_links(Mount *m) { +int mount_add_path_links(Unit *u, const char *where, bool requires) { Meta *other; int r; - assert(m); + assert(u); /* Adds in link to other mount points, that might lie below or * above us in the hierarchy */ - LIST_FOREACH(units_per_type, other, UNIT(m)->meta.manager->units_per_type[UNIT_MOUNT]) { + LIST_FOREACH(units_per_type, other, u->meta.manager->units_per_type[UNIT_MOUNT]) { Mount *n; n = (Mount*) other; - if (n == m) + if (UNIT(n) == u) continue; - if (m->meta.load_state != UNIT_LOADED) + if (u->meta.load_state != UNIT_LOADED) continue; - if (path_startswith(m->where, n->where)) { + if (path_startswith(where, n->where)) { - if ((r = unit_add_dependency(UNIT(m), UNIT_AFTER, UNIT(other), true)) < 0) + if ((r = unit_add_dependency(u, UNIT_AFTER, UNIT(other), true)) < 0) return r; - if (n->from_etc_fstab || n->from_fragment) - if ((r = unit_add_dependency(UNIT(m), UNIT_REQUIRES, UNIT(other), true)) < 0) + if (requires) + if ((r = unit_add_dependency(u, UNIT_REQUIRES, UNIT(other), true)) < 0) return r; - } else if (path_startswith(n->where, m->where)) { + } else if (path_startswith(n->where, where)) { - if ((r = unit_add_dependency(UNIT(m), UNIT_BEFORE, UNIT(other), true)) < 0) + if ((r = unit_add_dependency(u, UNIT_BEFORE, UNIT(other), true)) < 0) return r; - if (m->from_etc_fstab || m->from_fragment) - if ((r = unit_add_dependency(UNIT(other), UNIT_REQUIRES, UNIT(m), true)) < 0) + if (requires) + if ((r = unit_add_dependency(UNIT(other), UNIT_REQUIRES, u, true)) < 0) return r; } } @@ -201,7 +196,7 @@ static int mount_add_path_links(Mount *m) { return 0; } -static bool mount_test_option(const char *haystack, const char *needle) { +static char* mount_test_option(const char *haystack, const char *needle) { struct mntent me; assert(needle); @@ -215,7 +210,7 @@ static bool mount_test_option(const char *haystack, const char *needle) { zero(me); me.mnt_opts = (char*) haystack; - return !!hasmntopt(&me, needle); + return hasmntopt(&me, needle); } static int mount_add_target_links(Mount *m) { @@ -234,9 +229,9 @@ static int mount_add_target_links(Mount *m) { else return 0; - noauto = mount_test_option(p->options, MNTOPT_NOAUTO); - handle = mount_test_option(p->options, "comment=systemd.mount"); - automount = mount_test_option(p->options, "comment=systemd.automount"); + noauto = !!mount_test_option(p->options, MNTOPT_NOAUTO); + handle = !!mount_test_option(p->options, "comment=systemd.mount"); + automount = !!mount_test_option(p->options, "comment=systemd.automount"); if (noauto && !handle && !automount) return 0; @@ -305,6 +300,9 @@ static int mount_load(Unit *u) { /* This is a new unit? Then let's add in some extras */ if (u->meta.load_state == UNIT_LOADED) { + const char *what = m->parameters_fragment.what; + if (!what) + what = m->parameters_etc_fstab.what; if (!m->where) if (!(m->where = unit_name_to_path(u->meta.id))) @@ -319,10 +317,10 @@ static int mount_load(Unit *u) { if (m->parameters_fragment.what) m->from_fragment = true; - if ((r = mount_add_node_links(MOUNT(u))) < 0) + if ((r = mount_add_node_links(u, what)) < 0) return r; - if ((r = mount_add_path_links(MOUNT(u))) < 0) + if ((r = mount_add_path_links(u, m->where, m->from_etc_fstab || m->from_fragment)) < 0) return r; if ((r = mount_add_target_links(MOUNT(u))) < 0) @@ -1049,9 +1047,9 @@ static int mount_add_one( goto fail; if (!(MOUNT(u)->where = strdup(where))) { - r = -ENOMEM; - goto fail; - } + r = -ENOMEM; + goto fail; + } if ((r = unit_set_description(u, where)) < 0) goto fail; @@ -1148,6 +1146,27 @@ static char *fstab_node_to_udev_node(char *p) { return strdup(p); } +static int mount_find_pri(char *options) { + char *end, *pri; + unsigned long r; + + if (!(pri = mount_test_option(options, "pri="))) + return 0; + + pri += 4; + + errno = 0; + r = strtoul(pri, &end, 10); + + if (errno != 0) + return -errno; + + if (end == pri || (*end != ',' && *end != 0)) + return -EINVAL; + + return (int) r; +} + static int mount_load_etc_fstab(Manager *m) { FILE *f; int r; @@ -1179,7 +1198,20 @@ static int mount_load_etc_fstab(Manager *m) { if (where[0] == '/') path_kill_slashes(where); - r = mount_add_one(m, what, where, me->mnt_opts, me->mnt_type, false, false); + if (streq(me->mnt_type, "swap")) { + int pri; + + if ((pri = mount_find_pri(me->mnt_opts)) < 0) + r = pri; + else + r = swap_add_one(m, + what, + !!mount_test_option(me->mnt_opts, MNTOPT_NOAUTO), + pri, + false); + } else + r = mount_add_one(m, what, where, me->mnt_opts, me->mnt_type, false, false); + free(what); free(where); @@ -100,6 +100,8 @@ extern const UnitVTable mount_vtable; void mount_fd_event(Manager *m, int events); int mount_path_is_mounted(Manager *m, const char* path); +int mount_add_node_links(Unit *m, const char *what); +int mount_add_path_links(Unit *m, const char *where, bool requires); const char* mount_state_to_string(MountState i); MountState mount_state_from_string(const char *s); diff --git a/swap.c b/swap.c new file mode 100644 index 0000000000..aacf0e8d55 --- /dev/null +++ b/swap.c @@ -0,0 +1,424 @@ +/*-*- Mode: C; c-basic-offset: 8 -*-*/ + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#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 "unit.h" +#include "swap.h" +#include "load-fragment.h" +#include "load-dropin.h" +#include "unit-name.h" +#include "dbus-swap.h" + +static const UnitActiveState state_translation_table[_SWAP_STATE_MAX] = { + [SWAP_DEAD] = UNIT_INACTIVE, + [SWAP_ACTIVE] = UNIT_ACTIVE, + [SWAP_MAINTAINANCE] = UNIT_INACTIVE +}; + +static int swap_verify(Swap *s) { + bool b; + char *e; + + if (UNIT(s)->meta.load_state != UNIT_LOADED) + return 0; + + if (!(e = unit_name_from_path(s->what, ".swap"))) + return -ENOMEM; + + b = unit_has_name(UNIT(s), e); + free(e); + + if (!b) { + log_error("%s: Value of \"What\" and unit name do not match, not loading.\n", UNIT(s)->meta.id); + return -EINVAL; + } + return 0; +} + +static int swap_add_target_links(Swap *s) { + Manager *m = s->meta.manager; + Unit *tu; + int r; + + r = manager_load_unit(m, SPECIAL_SWAP_TARGET, NULL, &tu); + if (r < 0) + return r; + + if (!s->no_auto && (r = unit_add_dependency(tu, UNIT_WANTS, UNIT(s), true)) < 0) + return r; + + return unit_add_dependency(UNIT(s), UNIT_BEFORE, tu, true); +} + +static int swap_load(Unit *u) { + int r; + Swap *s = SWAP(u); + + assert(s); + assert(u->meta.load_state == UNIT_STUB); + + /* Load a .swap file */ + if ((r = unit_load_fragment_and_dropin_optional(u)) < 0) + return r; + + if (u->meta.load_state == UNIT_LOADED) { + if (!s->what) + if (!(s->what = unit_name_to_path(u->meta.id))) + return -ENOMEM; + + path_kill_slashes(s->what); + + if ((r = mount_add_node_links(u, s->what)) < 0) + return r; + + if (!path_startswith(s->what, "/dev/")) + if ((r = mount_add_path_links(u, s->what, true)) < 0) + return r; + + if ((r = swap_add_target_links(s)) < 0) + return r; + } + + return swap_verify(s); +} + +int swap_add_one(Manager *m, const char *what, bool no_auto, int prio, bool from_proc_swaps) { + Unit *u; + char *e; + bool delete; + int r; + + if (!(e = unit_name_from_path(what, ".swap"))) + return -ENOMEM; + + if (!(u = manager_get_unit(m, e))) { + delete = true; + + if (!(u = unit_new(m))) { + free(e); + return -ENOMEM; + } + + r = unit_add_name(u, e); + free(e); + + if (r < 0) + goto fail; + + if (!(SWAP(u)->what = strdup(what))) { + r = -ENOMEM; + goto fail; + } + + if ((r = unit_set_description(u, what)) < 0) + goto fail; + + unit_add_to_load_queue(u); + + SWAP(u)->from_proc_swaps_only = from_proc_swaps; + } else { + if (SWAP(u)->from_proc_swaps_only && !from_proc_swaps) + SWAP(u)->from_proc_swaps_only = false; + + delete = false; + free(e); + } + + if (!from_proc_swaps) + SWAP(u)->no_auto = no_auto; + else + SWAP(u)->found_in_proc_swaps = true; + + SWAP(u)->priority = prio; + + return 0; + +fail: + if (delete) + unit_free(u); + + return 0; +} + +static void swap_set_state(Swap *s, SwapState state) { + SwapState old_state; + assert(s); + + old_state = s->state; + s->state = state; + + if (state != old_state) + log_debug("%s changed %s -> %s", + UNIT(s)->meta.id, + swap_state_to_string(old_state), + swap_state_to_string(state)); + + unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state]); +} + +static int swap_coldplug(Unit *u) { + Swap *s = SWAP(u); + SwapState new_state = SWAP_DEAD; + + assert(s); + assert(s->state == SWAP_DEAD); + + if (s->deserialized_state != s->state) + new_state = s->deserialized_state; + else if (s->found_in_proc_swaps) + new_state = SWAP_ACTIVE; + + if (new_state != s->state) + swap_set_state(s, s->deserialized_state); + + return 0; +} + +static void swap_dump(Unit *u, FILE *f, const char *prefix) { + Swap *s = SWAP(u); + + assert(s); + + fprintf(f, + "%sAutomount State: %s\n" + "%sWhat: %s\n" + "%sPriority: %i\n" + "%sNoAuto: %s\n", + prefix, swap_state_to_string(s->state), + prefix, s->what, + prefix, s->priority, + prefix, yes_no(s->no_auto)); +} + +static void swap_enter_dead(Swap *s, bool success) { + assert(s); + + swap_set_state(s, success ? SWAP_MAINTAINANCE : SWAP_DEAD); +} + +static int swap_start(Unit *u) { + Swap *s = SWAP(u); + int r; + + assert(s); + + assert(s->state == SWAP_DEAD || s->state == SWAP_MAINTAINANCE); + + r = swapon(s->what, (s->priority << SWAP_FLAG_PRIO_SHIFT) & SWAP_FLAG_PRIO_MASK); + + if (r < 0 && errno != EBUSY) { + r = -errno; + swap_enter_dead(s, false); + return r; + } + + swap_set_state(s, SWAP_ACTIVE); + return 0; +} + +static int swap_stop(Unit *u) { + Swap *s = SWAP(u); + int r; + + assert(s); + + assert(s->state == SWAP_ACTIVE); + + r = swapoff(s->what); + swap_enter_dead(s, r >= 0 || errno == EINVAL); + + return 0; +} + +static int swap_serialize(Unit *u, FILE *f, FDSet *fds) { + Swap *s = SWAP(u); + + assert(s); + assert(f); + assert(fds); + + unit_serialize_item(u, f, "state", swap_state_to_string(s->state)); + + return 0; +} + +static int swap_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { + Swap *s = SWAP(u); + + assert(s); + assert(fds); + + if (streq(key, "state")) { + SwapState state; + + if ((state = swap_state_from_string(value)) < 0) + log_debug("Failed to parse state value %s", value); + else + s->deserialized_state = state; + } else + log_debug("Unknown serialization key '%s'", key); + + return 0; +} + +static UnitActiveState swap_active_state(Unit *u) { + assert(u); + + return state_translation_table[SWAP(u)->state]; +} + +static const char *swap_sub_state_to_string(Unit *u) { + assert(u); + + return swap_state_to_string(SWAP(u)->state); +} + +static bool swap_check_gc(Unit *u) { + Swap *s = SWAP(u); + + assert(s); + + return !s->from_proc_swaps_only || s->found_in_proc_swaps; +} + +static int swap_load_proc_swaps(Manager *m) { + Meta *meta; + + rewind(m->proc_swaps); + fscanf(m->proc_self_mountinfo, "%*s %*s %*s %*s %*s\n"); + + for (;;) { + char *dev = NULL, *d; + int prio = 0, k; + + k = fscanf(m->proc_self_mountinfo, + "%ms " /* device/file */ + "%*s " /* type of swap */ + "%*s " /* swap size */ + "%*s " /* used */ + "%d\n", /* priority */ + &dev, &prio); + + if (k != 2) { + if (k == EOF) + k = 0; + + free(dev); + return -EBADMSG; + } + if (!(d = cunescape(dev))) { + free(dev); + k = -ENOMEM; + return k; + } + + k = swap_add_one(m, d, false, prio, true); + free(dev); + free(d); + + if (k < 0) + return k; + } + + LIST_FOREACH(units_per_type, meta, m->units_per_type[UNIT_SWAP]) { + Swap *s = (Swap*) meta; + + if (s->state != SWAP_DEAD && s->state != SWAP_ACTIVE) + continue; + + if ((s->state == SWAP_DEAD && !s->found_in_proc_swaps) || + (s->state == SWAP_ACTIVE && s->found_in_proc_swaps)) + continue; + + swap_set_state(s, s->found_in_proc_swaps ? SWAP_ACTIVE : SWAP_DEAD); + + /* Reset the flags for later calls */ + s->found_in_proc_swaps = false; + } +} + +static void swap_shutdown(Manager *m) { + assert(m); + + if (m->proc_swaps) { + fclose(m->proc_swaps); + m->proc_swaps = NULL; + } +} + +static const char* const swap_state_table[_SWAP_STATE_MAX] = { + [SWAP_DEAD] = "dead", + [SWAP_ACTIVE] = "active", + [SWAP_MAINTAINANCE] = "maintainance" +}; + +DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState); + +static int swap_enumerate(Manager *m) { + int r; + assert(m); + + if (!m->proc_swaps && + !(m->proc_swaps = fopen("/proc/swaps", "er"))) + return -errno; + + if ((r = swap_load_proc_swaps(m)) < 0) + swap_shutdown(m); + + return r; +} + +const UnitVTable swap_vtable = { + .suffix = ".swap", + + .no_alias = true, + .no_instances = true, + + .load = swap_load, + + .coldplug = swap_coldplug, + + .dump = swap_dump, + + .start = swap_start, + .stop = swap_stop, + + .serialize = swap_serialize, + .deserialize_item = swap_deserialize_item, + + .active_state = swap_active_state, + .sub_state_to_string = swap_sub_state_to_string, + + .check_gc = swap_check_gc, + + .bus_message_handler = bus_swap_message_handler, + + .shutdown = swap_shutdown, + + .enumerate = swap_enumerate +}; diff --git a/swap.h b/swap.h new file mode 100644 index 0000000000..d8692509b6 --- /dev/null +++ b/swap.h @@ -0,0 +1,60 @@ +/*-*- Mode: C; c-basic-offset: 8 -*-*/ + +#ifndef fooswaphfoo +#define fooswaphfoo + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + Copyright 2010 Maarten Lankhorst + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +typedef struct Swap Swap; + +#include "unit.h" + +typedef enum SwapState { + SWAP_DEAD, + SWAP_ACTIVE, + SWAP_MAINTAINANCE, + _SWAP_STATE_MAX, + _SWAP_STATE_INVALID = -1 +} SwapState; + +struct Swap { + Meta meta; + + char *what; + + int priority; + + bool no_auto; + + bool from_proc_swaps_only:1; + bool found_in_proc_swaps:1; + + MountState state, deserialized_state; +}; + +extern const UnitVTable swap_vtable; + +const char* swap_state_to_string(SwapState i); +SwapState swap_state_from_string(const char *s); + +extern int swap_add_one(Manager *m, const char *what, bool no_auto, int prio, bool from_proc_swap); + +#endif @@ -47,7 +47,8 @@ const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = { [UNIT_DEVICE] = &device_vtable, [UNIT_MOUNT] = &mount_vtable, [UNIT_AUTOMOUNT] = &automount_vtable, - [UNIT_SNAPSHOT] = &snapshot_vtable + [UNIT_SNAPSHOT] = &snapshot_vtable, + [UNIT_SWAP] = &swap_vtable }; Unit *unit_new(Manager *m) { @@ -1839,7 +1840,8 @@ static const char* const unit_type_table[_UNIT_TYPE_MAX] = { [UNIT_DEVICE] = "device", [UNIT_MOUNT] = "mount", [UNIT_AUTOMOUNT] = "automount", - [UNIT_SNAPSHOT] = "snapshot" + [UNIT_SNAPSHOT] = "snapshot", + [UNIT_SWAP] = "swap" }; DEFINE_STRING_TABLE_LOOKUP(unit_type, UnitType); @@ -61,6 +61,7 @@ enum UnitType { UNIT_AUTOMOUNT, UNIT_SNAPSHOT, UNIT_TIMER, + UNIT_SWAP, _UNIT_TYPE_MAX, _UNIT_TYPE_INVALID = -1 }; @@ -194,6 +195,7 @@ struct Meta { #include "mount.h" #include "automount.h" #include "snapshot.h" +#include "swap.h" union Unit { Meta meta; @@ -205,6 +207,7 @@ union Unit { Mount mount; Automount automount; Snapshot snapshot; + Swap swap; }; struct UnitVTable { @@ -335,6 +338,7 @@ DEFINE_CAST(DEVICE, Device); DEFINE_CAST(MOUNT, Mount); DEFINE_CAST(AUTOMOUNT, Automount); DEFINE_CAST(SNAPSHOT, Snapshot); +DEFINE_CAST(SWAP, Swap); Unit *unit_new(Manager *m); void unit_free(Unit *u); |