2ee3d8
From 3f9f1fa90a087186dcc96060537543d2685616d8 Mon Sep 17 00:00:00 2001
2ee3d8
From: Vojtech Trefny <vtrefny@redhat.com>
2ee3d8
Date: Mon, 1 Oct 2018 16:06:42 +0200
2ee3d8
Subject: [PATCH 1/2] Use libblkid to check swap status before swapon
2ee3d8
2ee3d8
libblkid probe is more reliable than our custom check.
2ee3d8
---
2ee3d8
 configure.ac            |   2 +-
2ee3d8
 src/plugins/Makefile.am |   4 +-
2ee3d8
 src/plugins/swap.c      | 149 ++++++++++++++++++++++++++++++++--------
2ee3d8
 3 files changed, 124 insertions(+), 31 deletions(-)
2ee3d8
2ee3d8
diff --git a/configure.ac b/configure.ac
2ee3d8
index 6285a48..7ac5089 100644
2ee3d8
--- a/configure.ac
2ee3d8
+++ b/configure.ac
2ee3d8
@@ -227,7 +227,7 @@ AS_IF([test "x$with_fs" != "xno"],
2ee3d8
               AC_SUBST([PARTED_FS_CFLAGS], [])])],
2ee3d8
       [])
2ee3d8
 
2ee3d8
-AS_IF([test "x$with_fs" != "xno" -o "x$with_crypto" != "xno"],
2ee3d8
+AS_IF([test "x$with_fs" != "xno" -o "x$with_crypto" != "xno" -o "x$with_swap" != "xno"],
2ee3d8
       [LIBBLOCKDEV_PKG_CHECK_MODULES([BLKID], [blkid >= 2.23.0])
2ee3d8
       # older versions of libblkid don't support BLKID_SUBLKS_BADCSUM so let's just
2ee3d8
       # define it as 0 (neutral value for bit combinations of flags)
2ee3d8
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
2ee3d8
index e7b4bf0..6219a40 100644
2ee3d8
--- a/src/plugins/Makefile.am
2ee3d8
+++ b/src/plugins/Makefile.am
2ee3d8
@@ -149,8 +149,8 @@ libbd_nvdimm_la_SOURCES = nvdimm.c nvdimm.h check_deps.c check_deps.h
2ee3d8
 endif
2ee3d8
 
2ee3d8
 if WITH_SWAP
2ee3d8
-libbd_swap_la_CFLAGS = $(GLIB_CFLAGS) -Wall -Wextra -Werror
2ee3d8
-libbd_swap_la_LIBADD = $(GLIB_LIBS) ${builddir}/../utils/libbd_utils.la
2ee3d8
+libbd_swap_la_CFLAGS = $(GLIB_CFLAGS) $(BLKID_CFLAGS) -Wall -Wextra -Werror
2ee3d8
+libbd_swap_la_LIBADD = $(GLIB_LIBS) $(BLKID_LIBS) ${builddir}/../utils/libbd_utils.la
2ee3d8
 libbd_swap_la_LDFLAGS = -L${srcdir}/../utils/ -version-info 2:0:0 -Wl,--no-undefined
2ee3d8
 libbd_swap_la_CPPFLAGS = -I${builddir}/../../include/
2ee3d8
 libbd_swap_la_SOURCES = swap.c swap.h check_deps.c check_deps.h
2ee3d8
diff --git a/src/plugins/swap.c b/src/plugins/swap.c
2ee3d8
index bc52637..bfe653f 100644
2ee3d8
--- a/src/plugins/swap.c
2ee3d8
+++ b/src/plugins/swap.c
2ee3d8
@@ -21,6 +21,8 @@
2ee3d8
 #include <string.h>
2ee3d8
 #include <unistd.h>
2ee3d8
 #include <sys/swap.h>
2ee3d8
+#include <fcntl.h>
2ee3d8
+#include <blkid.h>
2ee3d8
 #include <blockdev/utils.h>
2ee3d8
 
2ee3d8
 #include "swap.h"
2ee3d8
@@ -179,13 +181,14 @@ gboolean bd_swap_mkswap (const gchar *device, const gchar *label, const BDExtraA
2ee3d8
  * Tech category: %BD_SWAP_TECH_SWAP-%BD_SWAP_TECH_MODE_ACTIVATE_DEACTIVATE
2ee3d8
  */
2ee3d8
 gboolean bd_swap_swapon (const gchar *device, gint priority, GError **error) {
2ee3d8
-    GIOChannel *dev_file = NULL;
2ee3d8
-    GIOStatus io_status = G_IO_STATUS_ERROR;
2ee3d8
-    GError *tmp_error = NULL;
2ee3d8
-    gsize num_read = 0;
2ee3d8
-    gchar dev_status[11];
2ee3d8
-    dev_status[10] = '\0';
2ee3d8
-    gint page_size;
2ee3d8
+    blkid_probe probe = NULL;
2ee3d8
+    gint fd = 0;
2ee3d8
+    gint status = 0;
2ee3d8
+    guint n_try = 0;
2ee3d8
+    const gchar *value = NULL;
2ee3d8
+    gint64 status_len = 0;
2ee3d8
+    gint64 swap_pagesize = 0;
2ee3d8
+    gint64 sys_pagesize = 0;
2ee3d8
     gint flags = 0;
2ee3d8
     gint ret = 0;
2ee3d8
     guint64 progress_id = 0;
2ee3d8
@@ -198,53 +201,143 @@ gboolean bd_swap_swapon (const gchar *device, gint priority, GError **error) {
2ee3d8
 
2ee3d8
     bd_utils_report_progress (progress_id, 0, "Analysing the swap device");
2ee3d8
     /* check the device if it is an activatable swap */
2ee3d8
-    dev_file = g_io_channel_new_file (device, "r", error);
2ee3d8
-    if (!dev_file) {
2ee3d8
-        /* error is already populated */
2ee3d8
+    probe = blkid_new_probe ();
2ee3d8
+    if (!probe) {
2ee3d8
+        g_set_error (error, BD_SWAP_ERROR, BD_SWAP_ERROR_UNKNOWN_STATE,
2ee3d8
+                     "Failed to create a new probe");
2ee3d8
         bd_utils_report_finished (progress_id, (*error)->message);
2ee3d8
         return FALSE;
2ee3d8
     }
2ee3d8
 
2ee3d8
-    page_size = getpagesize ();
2ee3d8
-    page_size = MAX (2048, page_size);
2ee3d8
-    io_status = g_io_channel_seek_position (dev_file, page_size - 10, G_SEEK_SET, &tmp_error);
2ee3d8
-    if (io_status != G_IO_STATUS_NORMAL) {
2ee3d8
+    fd = open (device, O_RDONLY|O_CLOEXEC);
2ee3d8
+    if (fd == -1) {
2ee3d8
         g_set_error (error, BD_SWAP_ERROR, BD_SWAP_ERROR_UNKNOWN_STATE,
2ee3d8
-                     "Failed to determine device's state: %s", tmp_error->message);
2ee3d8
-        g_clear_error (&tmp_error);
2ee3d8
-        g_io_channel_shutdown (dev_file, FALSE, &tmp_error);
2ee3d8
+                     "Failed to open the device '%s'", device);
2ee3d8
         bd_utils_report_finished (progress_id, (*error)->message);
2ee3d8
+        blkid_free_probe (probe);
2ee3d8
         return FALSE;
2ee3d8
     }
2ee3d8
 
2ee3d8
-    io_status = g_io_channel_read_chars (dev_file, dev_status, 10, &num_read, &tmp_error);
2ee3d8
-    if ((io_status != G_IO_STATUS_NORMAL) || (num_read != 10)) {
2ee3d8
+    /* we may need to try mutliple times with some delays in case the device is
2ee3d8
+       busy at the very moment */
2ee3d8
+    for (n_try=5, status=-1; (status != 0) && (n_try > 0); n_try--) {
2ee3d8
+        status = blkid_probe_set_device (probe, fd, 0, 0);
2ee3d8
+        if (status != 0)
2ee3d8
+            g_usleep (100 * 1000); /* microseconds */
2ee3d8
+    }
2ee3d8
+    if (status != 0) {
2ee3d8
         g_set_error (error, BD_SWAP_ERROR, BD_SWAP_ERROR_UNKNOWN_STATE,
2ee3d8
-                     "Failed to determine device's state: %s", tmp_error->message);
2ee3d8
-        g_clear_error (&tmp_error);
2ee3d8
-        g_io_channel_shutdown (dev_file, FALSE, &tmp_error);
2ee3d8
-        g_clear_error (&tmp_error);
2ee3d8
+                     "Failed to create a probe for the device '%s'", device);
2ee3d8
         bd_utils_report_finished (progress_id, (*error)->message);
2ee3d8
+        blkid_free_probe (probe);
2ee3d8
+        close (fd);
2ee3d8
         return FALSE;
2ee3d8
     }
2ee3d8
 
2ee3d8
-    g_io_channel_shutdown (dev_file, FALSE, &tmp_error);
2ee3d8
-    g_clear_error (&tmp_error);
2ee3d8
+    blkid_probe_enable_superblocks (probe, 1);
2ee3d8
+    blkid_probe_set_superblocks_flags (probe, BLKID_SUBLKS_TYPE | BLKID_SUBLKS_MAGIC);
2ee3d8
 
2ee3d8
-    if (g_str_has_prefix (dev_status, "SWAP-SPACE")) {
2ee3d8
+    /* we may need to try mutliple times with some delays in case the device is
2ee3d8
+       busy at the very moment */
2ee3d8
+    for (n_try=5, status=-1; !(status == 0 || status == 1) && (n_try > 0); n_try--) {
2ee3d8
+        status = blkid_do_safeprobe (probe);
2ee3d8
+        if (status < 0)
2ee3d8
+            g_usleep (100 * 1000); /* microseconds */
2ee3d8
+    }
2ee3d8
+    if (status < 0) {
2ee3d8
+        /* -1 or -2 = error during probing*/
2ee3d8
+        g_set_error (error, BD_SWAP_ERROR, BD_SWAP_ERROR_UNKNOWN_STATE,
2ee3d8
+                     "Failed to probe the device '%s'", device);
2ee3d8
+        bd_utils_report_finished (progress_id, (*error)->message);
2ee3d8
+        blkid_free_probe (probe);
2ee3d8
+        close (fd);
2ee3d8
+        return FALSE;
2ee3d8
+    } else if (status == 1) {
2ee3d8
+        /* 1 = nothing detected */
2ee3d8
+        g_set_error (error, BD_SWAP_ERROR, BD_SWAP_ERROR_UNKNOWN_STATE,
2ee3d8
+                     "No superblock detected on the device '%s'", device);
2ee3d8
+        bd_utils_report_finished (progress_id, (*error)->message);
2ee3d8
+        blkid_free_probe (probe);
2ee3d8
+        close (fd);
2ee3d8
+        return FALSE;
2ee3d8
+    }
2ee3d8
+
2ee3d8
+    status = blkid_probe_lookup_value (probe, "TYPE", &value, NULL);
2ee3d8
+    if (status != 0) {
2ee3d8
+        g_set_error (error, BD_SWAP_ERROR, BD_SWAP_ERROR_UNKNOWN_STATE,
2ee3d8
+                     "Failed to get format type for the device '%s'", device);
2ee3d8
+        bd_utils_report_finished (progress_id, (*error)->message);
2ee3d8
+        blkid_free_probe (probe);
2ee3d8
+        close (fd);
2ee3d8
+        return FALSE;
2ee3d8
+    }
2ee3d8
+
2ee3d8
+    if (g_strcmp0 (value, "swap") != 0) {
2ee3d8
+        g_set_error (error, BD_SWAP_ERROR, BD_SWAP_ERROR_UNKNOWN_STATE,
2ee3d8
+                     "Device '%s' is not formatted as swap", device);
2ee3d8
+        bd_utils_report_finished (progress_id, (*error)->message);
2ee3d8
+        blkid_free_probe (probe);
2ee3d8
+        close (fd);
2ee3d8
+        return FALSE;
2ee3d8
+    }
2ee3d8
+
2ee3d8
+    status = blkid_probe_lookup_value (probe, "SBMAGIC", &value, NULL);
2ee3d8
+    if (status != 0) {
2ee3d8
+        g_set_error (error, BD_SWAP_ERROR, BD_SWAP_ERROR_UNKNOWN_STATE,
2ee3d8
+                     "Failed to get swap status on the device '%s'", device);
2ee3d8
+        bd_utils_report_finished (progress_id, (*error)->message);
2ee3d8
+        blkid_free_probe (probe);
2ee3d8
+        close (fd);
2ee3d8
+        return FALSE;
2ee3d8
+    }
2ee3d8
+
2ee3d8
+    if (g_strcmp0 (value, "SWAP-SPACE") == 0) {
2ee3d8
         g_set_error (error, BD_SWAP_ERROR, BD_SWAP_ERROR_ACTIVATE,
2ee3d8
                      "Old swap format, cannot activate.");
2ee3d8
         bd_utils_report_finished (progress_id, (*error)->message);
2ee3d8
+        blkid_free_probe (probe);
2ee3d8
+        close (fd);
2ee3d8
         return FALSE;
2ee3d8
-    } else if (g_str_has_prefix (dev_status, "S1SUSPEND") || g_str_has_prefix (dev_status, "S2SUSPEND")) {
2ee3d8
+    } else if (g_strcmp0 (value, "S1SUSPEND") == 0 || g_strcmp0 (value, "S2SUSPEND") == 0) {
2ee3d8
         g_set_error (error, BD_SWAP_ERROR, BD_SWAP_ERROR_ACTIVATE,
2ee3d8
                      "Suspended system on the swap device, cannot activate.");
2ee3d8
         bd_utils_report_finished (progress_id, (*error)->message);
2ee3d8
+        blkid_free_probe (probe);
2ee3d8
+        close (fd);
2ee3d8
         return FALSE;
2ee3d8
-    } else if (!g_str_has_prefix (dev_status, "SWAPSPACE2")) {
2ee3d8
+    } else if (g_strcmp0 (value, "SWAPSPACE2") != 0) {
2ee3d8
         g_set_error (error, BD_SWAP_ERROR, BD_SWAP_ERROR_ACTIVATE,
2ee3d8
                      "Unknown swap space format, cannot activate.");
2ee3d8
         bd_utils_report_finished (progress_id, (*error)->message);
2ee3d8
+        blkid_free_probe (probe);
2ee3d8
+        close (fd);
2ee3d8
+        return FALSE;
2ee3d8
+    }
2ee3d8
+
2ee3d8
+    status_len = (gint64) strlen (value);
2ee3d8
+
2ee3d8
+    status = blkid_probe_lookup_value (probe, "SBMAGIC_OFFSET", &value, NULL);
2ee3d8
+    if (status != 0 || !value) {
2ee3d8
+        g_set_error (error, BD_SWAP_ERROR, BD_SWAP_ERROR_UNKNOWN_STATE,
2ee3d8
+                     "Failed to get swap status on the device '%s'", device);
2ee3d8
+        bd_utils_report_finished (progress_id, (*error)->message);
2ee3d8
+        blkid_free_probe (probe);
2ee3d8
+        close (fd);
2ee3d8
+        return FALSE;
2ee3d8
+    }
2ee3d8
+
2ee3d8
+    swap_pagesize = status_len + g_ascii_strtoll (value, (char **)NULL, 10);
2ee3d8
+
2ee3d8
+    blkid_free_probe (probe);
2ee3d8
+    close (fd);
2ee3d8
+
2ee3d8
+    sys_pagesize = getpagesize ();
2ee3d8
+
2ee3d8
+    if (swap_pagesize != sys_pagesize) {
2ee3d8
+        g_set_error (error, BD_SWAP_ERROR, BD_SWAP_ERROR_UNKNOWN_STATE,
2ee3d8
+                     "Swap format pagesize (%"G_GINT64_FORMAT") and system pagesize (%"G_GINT64_FORMAT") don't match",
2ee3d8
+                     swap_pagesize, sys_pagesize);
2ee3d8
+        bd_utils_report_finished (progress_id, (*error)->message);
2ee3d8
         return FALSE;
2ee3d8
     }
2ee3d8
 
2ee3d8
-- 
2ee3d8
2.17.1
2ee3d8
2ee3d8
2ee3d8
From f6508829e7cac138e4961a1c3ef6170d6f67bfd9 Mon Sep 17 00:00:00 2001
2ee3d8
From: Vojtech Trefny <vtrefny@redhat.com>
2ee3d8
Date: Thu, 4 Oct 2018 08:07:55 +0200
2ee3d8
Subject: [PATCH 2/2] Add error codes and Python exceptions for swapon fails
2ee3d8
2ee3d8
We need to be able to tell why swapon failed so our users can
2ee3d8
decide what to do.
2ee3d8
---
2ee3d8
 src/lib/plugin_apis/swap.api        |  4 ++++
2ee3d8
 src/plugins/swap.c                  | 10 +++++-----
2ee3d8
 src/plugins/swap.h                  |  4 ++++
2ee3d8
 src/python/gi/overrides/BlockDev.py | 19 +++++++++++++++++--
2ee3d8
 tests/swap_test.py                  | 13 +++++++++++++
2ee3d8
 5 files changed, 43 insertions(+), 7 deletions(-)
2ee3d8
2ee3d8
diff --git a/src/lib/plugin_apis/swap.api b/src/lib/plugin_apis/swap.api
2ee3d8
index d0906fe..3fcc0e5 100644
2ee3d8
--- a/src/lib/plugin_apis/swap.api
2ee3d8
+++ b/src/lib/plugin_apis/swap.api
2ee3d8
@@ -10,6 +10,10 @@ typedef enum {
2ee3d8
     BD_SWAP_ERROR_UNKNOWN_STATE,
2ee3d8
     BD_SWAP_ERROR_ACTIVATE,
2ee3d8
     BD_SWAP_ERROR_TECH_UNAVAIL,
2ee3d8
+    BD_SWAP_ERROR_ACTIVATE_OLD,
2ee3d8
+    BD_SWAP_ERROR_ACTIVATE_SUSPEND,
2ee3d8
+    BD_SWAP_ERROR_ACTIVATE_UNKNOWN,
2ee3d8
+    BD_SWAP_ERROR_ACTIVATE_PAGESIZE,
2ee3d8
 } BDSwapError;
2ee3d8
 
2ee3d8
 typedef enum {
2ee3d8
diff --git a/src/plugins/swap.c b/src/plugins/swap.c
2ee3d8
index bfe653f..28db6f3 100644
2ee3d8
--- a/src/plugins/swap.c
2ee3d8
+++ b/src/plugins/swap.c
2ee3d8
@@ -292,21 +292,21 @@ gboolean bd_swap_swapon (const gchar *device, gint priority, GError **error) {
2ee3d8
     }
2ee3d8
 
2ee3d8
     if (g_strcmp0 (value, "SWAP-SPACE") == 0) {
2ee3d8
-        g_set_error (error, BD_SWAP_ERROR, BD_SWAP_ERROR_ACTIVATE,
2ee3d8
+        g_set_error (error, BD_SWAP_ERROR, BD_SWAP_ERROR_ACTIVATE_OLD,
2ee3d8
                      "Old swap format, cannot activate.");
2ee3d8
         bd_utils_report_finished (progress_id, (*error)->message);
2ee3d8
         blkid_free_probe (probe);
2ee3d8
         close (fd);
2ee3d8
         return FALSE;
2ee3d8
     } else if (g_strcmp0 (value, "S1SUSPEND") == 0 || g_strcmp0 (value, "S2SUSPEND") == 0) {
2ee3d8
-        g_set_error (error, BD_SWAP_ERROR, BD_SWAP_ERROR_ACTIVATE,
2ee3d8
+        g_set_error (error, BD_SWAP_ERROR, BD_SWAP_ERROR_ACTIVATE_SUSPEND,
2ee3d8
                      "Suspended system on the swap device, cannot activate.");
2ee3d8
         bd_utils_report_finished (progress_id, (*error)->message);
2ee3d8
         blkid_free_probe (probe);
2ee3d8
         close (fd);
2ee3d8
         return FALSE;
2ee3d8
     } else if (g_strcmp0 (value, "SWAPSPACE2") != 0) {
2ee3d8
-        g_set_error (error, BD_SWAP_ERROR, BD_SWAP_ERROR_ACTIVATE,
2ee3d8
+        g_set_error (error, BD_SWAP_ERROR, BD_SWAP_ERROR_ACTIVATE_UNKNOWN,
2ee3d8
                      "Unknown swap space format, cannot activate.");
2ee3d8
         bd_utils_report_finished (progress_id, (*error)->message);
2ee3d8
         blkid_free_probe (probe);
2ee3d8
@@ -318,7 +318,7 @@ gboolean bd_swap_swapon (const gchar *device, gint priority, GError **error) {
2ee3d8
 
2ee3d8
     status = blkid_probe_lookup_value (probe, "SBMAGIC_OFFSET", &value, NULL);
2ee3d8
     if (status != 0 || !value) {
2ee3d8
-        g_set_error (error, BD_SWAP_ERROR, BD_SWAP_ERROR_UNKNOWN_STATE,
2ee3d8
+        g_set_error (error, BD_SWAP_ERROR, BD_SWAP_ERROR_ACTIVATE_PAGESIZE,
2ee3d8
                      "Failed to get swap status on the device '%s'", device);
2ee3d8
         bd_utils_report_finished (progress_id, (*error)->message);
2ee3d8
         blkid_free_probe (probe);
2ee3d8
@@ -334,7 +334,7 @@ gboolean bd_swap_swapon (const gchar *device, gint priority, GError **error) {
2ee3d8
     sys_pagesize = getpagesize ();
2ee3d8
 
2ee3d8
     if (swap_pagesize != sys_pagesize) {
2ee3d8
-        g_set_error (error, BD_SWAP_ERROR, BD_SWAP_ERROR_UNKNOWN_STATE,
2ee3d8
+        g_set_error (error, BD_SWAP_ERROR, BD_SWAP_ERROR_ACTIVATE_PAGESIZE,
2ee3d8
                      "Swap format pagesize (%"G_GINT64_FORMAT") and system pagesize (%"G_GINT64_FORMAT") don't match",
2ee3d8
                      swap_pagesize, sys_pagesize);
2ee3d8
         bd_utils_report_finished (progress_id, (*error)->message);
2ee3d8
diff --git a/src/plugins/swap.h b/src/plugins/swap.h
2ee3d8
index a01c873..9947bad 100644
2ee3d8
--- a/src/plugins/swap.h
2ee3d8
+++ b/src/plugins/swap.h
2ee3d8
@@ -12,6 +12,10 @@ typedef enum {
2ee3d8
     BD_SWAP_ERROR_UNKNOWN_STATE,
2ee3d8
     BD_SWAP_ERROR_ACTIVATE,
2ee3d8
     BD_SWAP_ERROR_TECH_UNAVAIL,
2ee3d8
+    BD_SWAP_ERROR_ACTIVATE_OLD,
2ee3d8
+    BD_SWAP_ERROR_ACTIVATE_SUSPEND,
2ee3d8
+    BD_SWAP_ERROR_ACTIVATE_UNKNOWN,
2ee3d8
+    BD_SWAP_ERROR_ACTIVATE_PAGESIZE,
2ee3d8
 } BDSwapError;
2ee3d8
 
2ee3d8
 typedef enum {
2ee3d8
diff --git a/src/python/gi/overrides/BlockDev.py b/src/python/gi/overrides/BlockDev.py
2ee3d8
index c2ef2f4..e608887 100644
2ee3d8
--- a/src/python/gi/overrides/BlockDev.py
2ee3d8
+++ b/src/python/gi/overrides/BlockDev.py
2ee3d8
@@ -1031,7 +1031,17 @@ __all__.append("MpathError")
2ee3d8
 
2ee3d8
 class SwapError(BlockDevError):
2ee3d8
     pass
2ee3d8
-__all__.append("SwapError")
2ee3d8
+class SwapActivateError(SwapError):
2ee3d8
+    pass
2ee3d8
+class SwapOldError(SwapActivateError):
2ee3d8
+    pass
2ee3d8
+class SwapSuspendError(SwapActivateError):
2ee3d8
+    pass
2ee3d8
+class SwapUnknownError(SwapActivateError):
2ee3d8
+    pass
2ee3d8
+class SwapPagesizeError(SwapActivateError):
2ee3d8
+    pass
2ee3d8
+__all__.extend(("SwapError", "SwapActivateError", "SwapOldError", "SwapSuspendError", "SwapUnknownError", "SwapPagesizeError"))
2ee3d8
 
2ee3d8
 class KbdError(BlockDevError):
2ee3d8
     pass
2ee3d8
@@ -1070,6 +1080,11 @@ __all__.append("BlockDevNotImplementedError")
2ee3d8
 not_implemented_rule = XRule(GLib.Error, re.compile(r".*The function '.*' called, but not implemented!"), None, BlockDevNotImplementedError)
2ee3d8
 
2ee3d8
 fs_nofs_rule = XRule(GLib.Error, None, 3, FSNoFSError)
2ee3d8
+swap_activate_rule = XRule(GLib.Error, None, 1, SwapActivateError)
2ee3d8
+swap_old_rule = XRule(GLib.Error, None, 3, SwapOldError)
2ee3d8
+swap_suspend_rule = XRule(GLib.Error, None, 4, SwapSuspendError)
2ee3d8
+swap_unknown_rule = XRule(GLib.Error, None, 5, SwapUnknownError)
2ee3d8
+swap_pagesize_rule = XRule(GLib.Error, None, 6, SwapPagesizeError)
2ee3d8
 
2ee3d8
 btrfs = ErrorProxy("btrfs", BlockDev, [(GLib.Error, BtrfsError)], [not_implemented_rule])
2ee3d8
 __all__.append("btrfs")
2ee3d8
@@ -1092,7 +1107,7 @@ __all__.append("md")
2ee3d8
 mpath = ErrorProxy("mpath", BlockDev, [(GLib.Error, MpathError)], [not_implemented_rule])
2ee3d8
 __all__.append("mpath")
2ee3d8
 
2ee3d8
-swap = ErrorProxy("swap", BlockDev, [(GLib.Error, SwapError)], [not_implemented_rule])
2ee3d8
+swap = ErrorProxy("swap", BlockDev, [(GLib.Error, SwapError)], [not_implemented_rule, swap_activate_rule, swap_old_rule, swap_suspend_rule, swap_unknown_rule, swap_pagesize_rule])
2ee3d8
 __all__.append("swap")
2ee3d8
 
2ee3d8
 kbd = ErrorProxy("kbd", BlockDev, [(GLib.Error, KbdError)], [not_implemented_rule])
2ee3d8
diff --git a/tests/swap_test.py b/tests/swap_test.py
2ee3d8
index 05d0c19..395fdf5 100644
2ee3d8
--- a/tests/swap_test.py
2ee3d8
+++ b/tests/swap_test.py
2ee3d8
@@ -97,6 +97,19 @@ class SwapTestCase(SwapTest):
2ee3d8
         _ret, out, _err = run_command("blkid -ovalue -sLABEL -p %s" % self.loop_dev)
2ee3d8
         self.assertEqual(out, "BlockDevSwap")
2ee3d8
 
2ee3d8
+    def test_swapon_pagesize(self):
2ee3d8
+        """Verify that activating swap with different pagesize fails"""
2ee3d8
+
2ee3d8
+        # create swap with 64k pagesize
2ee3d8
+        ret, out, err = run_command("mkswap --pagesize 65536 %s" % self.loop_dev)
2ee3d8
+        if ret != 0:
2ee3d8
+            self.fail("Failed to prepare swap for pagesize test: %s %s" % (out, err))
2ee3d8
+
2ee3d8
+        # activation should fail because swap has different pagesize
2ee3d8
+        with self.assertRaises(BlockDev.SwapPagesizeError):
2ee3d8
+            BlockDev.swap.swapon(self.loop_dev)
2ee3d8
+
2ee3d8
+
2ee3d8
 class SwapUnloadTest(SwapTest):
2ee3d8
     def setUp(self):
2ee3d8
         # make sure the library is initialized with all plugins loaded for other
2ee3d8
-- 
2ee3d8
2.17.1
2ee3d8