[systemd-devel] [PATCH] Make swap unit follow device node when swap is off

Olivier Brunel i.am.jack.mail at gmail.com
Mon Oct 29 11:16:58 PDT 2012


Swap units will now be following the unit of the devnode when the swap is off
(and usual following therefore not in place), thus allowing things to work
even in cases such as:
    systemctl start 'dev-disk-by\x2dlabel-SWAP.swap' dev-sda3.swap

This first will load and redirect the request to the unit for sda3, the second
will :
- if /dev/sda3 is what appears on /proc/swaps, be starting/started already
- else if swap is started, it'll follow the unit from /proc/swaps
- else it'll still be following dev-sda3.swap (which is starting)
---

I was thinking about this, and it seems this could solve the problem.

I have tested this and it seems to work as expected, but I always have in
/proc/swaps the devnode (i.e. never a symlink), so I can't test that case. I
think it should work as well though, as described above.

I'd be happy to hear what you think about it.

 src/core/swap.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/src/core/swap.c b/src/core/swap.c
index 97145a9..cbd6182 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -1176,6 +1176,7 @@ int swap_fd_event(Manager *m, int events) {
 static Unit *swap_following(Unit *u) {
         Swap *s = SWAP(u);
         Swap *other, *first = NULL;
+        struct udev_device *d = NULL;
 
         assert(s);
 
@@ -1196,6 +1197,49 @@ static Unit *swap_following(Unit *u) {
                 first = other;
         }
 
+        /* if we have nothing, let's try to follow the unit of the actual
+         * device and not any symlink */
+        if (!first) {
+            Manager *m = u->manager;
+            struct stat st;
+            const char *dn;
+
+            if (stat(s->what, &st) >= 0 && S_ISBLK(st.st_mode)) {
+                d = udev_device_new_from_devnum(m->udev, 'b', st.st_rdev);
+                if (!d)
+                    goto bail;
+
+                dn = udev_device_get_devnode(d);
+                if (dn && !streq(dn, s->what)) {
+                    Unit *f = NULL;
+                    int r;
+                    char *e;
+
+                    r = swap_add_one(m, dn, dn, s->parameters_proc_swaps.priority, false, false, false);
+                    if (r < 0)
+                        goto bail;
+
+                    e = unit_name_from_path(dn, ".swap");
+                    if (!e)
+                        goto bail;
+
+                    f = manager_get_unit(m, e);
+                    free(e);
+                    if (!f)
+                        goto bail;
+
+                    udev_device_unref(d);
+
+                    /* we need to load it now, else starting will fail */
+                    unit_load(f);
+                    return f;
+                }
+            }
+        }
+
+bail:
+        if (d)
+            udev_device_unref(d);
         return UNIT(first);
 }
 
-- 
1.8.0



More information about the systemd-devel mailing list