Blob Blame History Raw
From 5bcb348b17935328a2344d811ddba9847ab3c846 Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Mon, 16 Oct 2017 12:33:14 +0200
Subject: [PATCH 1/5] Move some useful mdraid functions to a helper file

Related: rhbz#1400056
Signed-off-by: Vratislav Podzimek <vpodzime@redhat.com>
---
 src/Makefile.am                |   1 +
 src/udiskslinuxmdraid.c        |  83 ++------------------------------
 src/udiskslinuxmdraidhelpers.c | 104 +++++++++++++++++++++++++++++++++++++++++
 src/udiskslinuxmdraidhelpers.h |  41 ++++++++++++++++
 4 files changed, 149 insertions(+), 80 deletions(-)
 create mode 100644 src/udiskslinuxmdraidhelpers.c
 create mode 100644 src/udiskslinuxmdraidhelpers.h

diff --git a/src/Makefile.am b/src/Makefile.am
index 396ab4e..9cca8cd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -66,6 +66,7 @@ libudisks_daemon_la_SOURCES =                                                  \
 	udiskslinuxdrive.h             udiskslinuxdrive.c                      \
 	udiskslinuxdriveata.h          udiskslinuxdriveata.c                   \
 	udiskslinuxmdraidobject.h      udiskslinuxmdraidobject.c               \
+	udiskslinuxmdraidhelpers.h     udiskslinuxmdraidhelpers.c              \
 	udiskslinuxmdraid.h            udiskslinuxmdraid.c                     \
 	udiskslinuxmanager.h           udiskslinuxmanager.c                    \
 	udiskslinuxfsinfo.h            udiskslinuxfsinfo.c                     \
diff --git a/src/udiskslinuxmdraid.c b/src/udiskslinuxmdraid.c
index 9bf6ae9..2dcf0ff 100644
--- a/src/udiskslinuxmdraid.c
+++ b/src/udiskslinuxmdraid.c
@@ -38,6 +38,7 @@
 #include "udiskslinuxprovider.h"
 #include "udiskslinuxmdraidobject.h"
 #include "udiskslinuxmdraid.h"
+#include "udiskslinuxmdraidhelpers.h"
 #include "udiskslinuxblockobject.h"
 #include "udisksdaemon.h"
 #include "udisksstate.h"
@@ -128,68 +129,6 @@ udisks_linux_mdraid_new (void)
 
 /* ---------------------------------------------------------------------------------------------------- */
 
-static gchar *
-read_sysfs_attr (GUdevDevice *device,
-                 const gchar *attr)
-{
-  gchar *ret = NULL;
-  gchar *path = NULL;
-  GError *error = NULL;
-
-  g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL);
-
-  path = g_strdup_printf ("%s/%s", g_udev_device_get_sysfs_path (device), attr);
-  if (!g_file_get_contents (path, &ret, NULL /* size */, &error))
-    {
-      udisks_warning ("Error reading sysfs attr `%s': %s (%s, %d)",
-                      path, error->message, g_quark_to_string (error->domain), error->code);
-      g_clear_error (&error);
-      goto out;
-    }
-
- out:
-  g_free (path);
-  return ret;
-}
-
-static gint
-read_sysfs_attr_as_int (GUdevDevice *device,
-                        const gchar *attr)
-{
-  gint ret = 0;
-  gchar *str = NULL;
-
-  str = read_sysfs_attr (device, attr);
-  if (str == NULL)
-    goto out;
-
-  ret = atoi (str);
-  g_free (str);
-
- out:
-  return ret;
-}
-
-static guint64
-read_sysfs_attr_as_uint64 (GUdevDevice *device,
-                           const gchar *attr)
-{
-  guint64 ret = 0;
-  gchar *str = NULL;
-
-  str = read_sysfs_attr (device, attr);
-  if (str == NULL)
-    goto out;
-
-  ret = atoll (str);
-  g_free (str);
-
- out:
-  return ret;
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
 static gboolean
 on_polling_timout (gpointer user_data)
 {
@@ -306,8 +245,6 @@ udisks_linux_mdraid_update (UDisksLinuxMDRaid       *mdraid,
   guint64 sync_remaining_time = 0;
   GVariantBuilder builder;
   UDisksDaemon *daemon = NULL;
-  gboolean has_redundancy = FALSE;
-  gboolean has_stripes = FALSE;
   UDisksBaseJob *job = NULL;
 
   daemon = udisks_linux_mdraid_object_get_daemon (object);
@@ -377,23 +314,9 @@ udisks_linux_mdraid_update (UDisksLinuxMDRaid       *mdraid,
 
   udisks_mdraid_set_running (iface, raid_device != NULL);
 
-  if (g_strcmp0 (level, "raid1") == 0 ||
-      g_strcmp0 (level, "raid4") == 0 ||
-      g_strcmp0 (level, "raid5") == 0 ||
-      g_strcmp0 (level, "raid6") == 0 ||
-      g_strcmp0 (level, "raid10") == 0)
-    has_redundancy = TRUE;
-
-  if (g_strcmp0 (level, "raid0") == 0 ||
-      g_strcmp0 (level, "raid4") == 0 ||
-      g_strcmp0 (level, "raid5") == 0 ||
-      g_strcmp0 (level, "raid6") == 0 ||
-      g_strcmp0 (level, "raid10") == 0)
-    has_stripes = TRUE;
-
   if (raid_device != NULL)
     {
-      if (has_redundancy)
+      if (mdraid_has_redundancy (level))
         {
           /* Can't use GUdevDevice methods as they cache the result and these variables vary */
           degraded = read_sysfs_attr_as_int (raid_device->udev_device, "md/degraded");
@@ -408,7 +331,7 @@ udisks_linux_mdraid_update (UDisksLinuxMDRaid       *mdraid,
             g_strstrip (bitmap_location);
         }
 
-      if (has_stripes)
+      if (mdraid_has_stripes (level))
         {
           chunk_size = read_sysfs_attr_as_uint64 (raid_device->udev_device, "md/chunk_size");
         }
diff --git a/src/udiskslinuxmdraidhelpers.c b/src/udiskslinuxmdraidhelpers.c
new file mode 100644
index 0000000..dafdddf
--- /dev/null
+++ b/src/udiskslinuxmdraidhelpers.c
@@ -0,0 +1,104 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: Vojtech Trefny <vtrefny@redhat.com>
+ *
+ */
+
+#include <glib.h>
+#include <gudev/gudev.h>
+#include <stdlib.h>
+
+#include "udiskslinuxmdraidhelpers.h"
+#include "udiskslogging.h"
+
+gboolean
+mdraid_has_redundancy (const gchar *raid_level)
+{
+  return raid_level != NULL &&
+         g_str_has_prefix (raid_level, "raid") &&
+         g_strcmp0 (raid_level, "raid0") != 0;
+}
+
+gboolean
+mdraid_has_stripes (const gchar *raid_level)
+{
+  return raid_level != NULL &&
+         g_str_has_prefix (raid_level, "raid") &&
+         g_strcmp0 (raid_level, "raid1") != 0;
+}
+
+gchar *
+read_sysfs_attr (GUdevDevice *device,
+                 const gchar *attr)
+{
+  gchar *ret = NULL;
+  gchar *path = NULL;
+  GError *error = NULL;
+
+  g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL);
+
+  path = g_strdup_printf ("%s/%s", g_udev_device_get_sysfs_path (device), attr);
+  if (!g_file_get_contents (path, &ret, NULL /* size */, &error))
+    {
+      udisks_warning ("Error reading sysfs attr `%s': %s (%s, %d)",
+                      path, error->message, g_quark_to_string (error->domain), error->code);
+      g_clear_error (&error);
+      goto out;
+    }
+
+ out:
+  g_free (path);
+  return ret;
+}
+
+gint
+read_sysfs_attr_as_int (GUdevDevice *device,
+                        const gchar *attr)
+{
+  gint ret = 0;
+  gchar *str = NULL;
+
+  str = read_sysfs_attr (device, attr);
+  if (str == NULL)
+    goto out;
+
+  ret = atoi (str);
+  g_free (str);
+
+ out:
+  return ret;
+}
+
+guint64
+read_sysfs_attr_as_uint64 (GUdevDevice *device,
+                           const gchar *attr)
+{
+  guint64 ret = 0;
+  gchar *str = NULL;
+
+  str = read_sysfs_attr (device, attr);
+  if (str == NULL)
+    goto out;
+
+  ret = atoll (str);
+  g_free (str);
+
+ out:
+  return ret;
+}
diff --git a/src/udiskslinuxmdraidhelpers.h b/src/udiskslinuxmdraidhelpers.h
new file mode 100644
index 0000000..6d2b714
--- /dev/null
+++ b/src/udiskslinuxmdraidhelpers.h
@@ -0,0 +1,41 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: Vojtech Trefny <vtrefny@redhat.com>
+ *
+ */
+
+#ifndef __UDISKS_LINUX_MDRAID_HELPERS_H__
+#define __UDISKS_LINUX_MDRAID_HEPLERS_H__
+
+#include <glib.h>
+#include <gudev/gudev.h>
+
+
+G_BEGIN_DECLS
+
+gboolean mdraid_has_redundancy (const gchar *raid_level);
+gboolean mdraid_has_stripes (const gchar *raid_level);
+gchar   *read_sysfs_attr (GUdevDevice *device, const gchar *attr);
+gint     read_sysfs_attr_as_int (GUdevDevice *device, const gchar *attr);
+guint64  read_sysfs_attr_as_uint64 (GUdevDevice *device, const gchar *attr);
+
+G_END_DECLS
+
+
+#endif /* __UDISKS_LINUX_MDRAID_HEPLERS_H__ */
-- 
2.9.5

From 61ff342139f21663958bcc2972a3efa37cf7bc83 Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Mon, 16 Oct 2017 12:41:22 +0200
Subject: [PATCH 2/5] Remove leading/trailing white space in 'read_sysfs_attr'

So we don't have to call 'g_strstrip' after using it.

Related: rhbz#1400056
Signed-off-by: Vratislav Podzimek <vpodzime@redhat.com>
---
 src/udiskslinuxmdraid.c        | 8 --------
 src/udiskslinuxmdraidhelpers.c | 4 ++++
 2 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/src/udiskslinuxmdraid.c b/src/udiskslinuxmdraid.c
index 2dcf0ff..22b4ee4 100644
--- a/src/udiskslinuxmdraid.c
+++ b/src/udiskslinuxmdraid.c
@@ -321,14 +321,8 @@ udisks_linux_mdraid_update (UDisksLinuxMDRaid       *mdraid,
           /* Can't use GUdevDevice methods as they cache the result and these variables vary */
           degraded = read_sysfs_attr_as_int (raid_device->udev_device, "md/degraded");
           sync_action = read_sysfs_attr (raid_device->udev_device, "md/sync_action");
-          if (sync_action != NULL)
-            g_strstrip (sync_action);
           sync_completed = read_sysfs_attr (raid_device->udev_device, "md/sync_completed");
-          if (sync_completed != NULL)
-            g_strstrip (sync_completed);
           bitmap_location = read_sysfs_attr (raid_device->udev_device, "md/bitmap/location");
-          if (bitmap_location != NULL)
-            g_strstrip (bitmap_location);
         }
 
       if (mdraid_has_stripes (level))
@@ -472,7 +466,6 @@ udisks_linux_mdraid_update (UDisksLinuxMDRaid       *mdraid,
               member_state = read_sysfs_attr (raid_device->udev_device, buf);
               if (member_state != NULL)
                 {
-                  g_strstrip (member_state);
                   member_state_elements = g_strsplit (member_state, ",", 0);
                 }
               else
@@ -486,7 +479,6 @@ udisks_linux_mdraid_update (UDisksLinuxMDRaid       *mdraid,
               member_slot = read_sysfs_attr (raid_device->udev_device, buf);
               if (member_slot != NULL)
                 {
-                  g_strstrip (member_slot);
                   if (g_strcmp0 (member_slot, "none") != 0)
                     member_slot_as_int = atoi (member_slot);
                 }
diff --git a/src/udiskslinuxmdraidhelpers.c b/src/udiskslinuxmdraidhelpers.c
index dafdddf..297b1fa 100644
--- a/src/udiskslinuxmdraidhelpers.c
+++ b/src/udiskslinuxmdraidhelpers.c
@@ -62,6 +62,10 @@ read_sysfs_attr (GUdevDevice *device,
       goto out;
     }
 
+  /* remove newline from the attribute */
+  if (ret != NULL)
+    g_strstrip (ret);
+
  out:
   g_free (path);
   return ret;
-- 
2.9.5

From 756571efc1b0d602bca2dd4ff761dca686dc08bd Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Mon, 16 Oct 2017 12:42:42 +0200
Subject: [PATCH 3/5] Do not try to create file watchers for RAIDs without
 redundancy

We are trying to watch 'md/degraded' and 'md/sync_action' sysfs
files for all RAIDs but these files exist only for RAIDs with
redundancy -- we shouldn't do this for raid0, containers and linear
RAIDs.

Resolves: rhbz#1400056
Signed-off-by: Vratislav Podzimek <vpodzime@redhat.com>
---
 src/udiskslinuxmdraidobject.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/src/udiskslinuxmdraidobject.c b/src/udiskslinuxmdraidobject.c
index 493145e..1d2f07a 100644
--- a/src/udiskslinuxmdraidobject.c
+++ b/src/udiskslinuxmdraidobject.c
@@ -30,6 +30,7 @@
 #include "udisksdaemonutil.h"
 #include "udiskslinuxprovider.h"
 #include "udiskslinuxmdraidobject.h"
+#include "udiskslinuxmdraidhelpers.h"
 #include "udiskslinuxmdraid.h"
 #include "udiskslinuxblockobject.h"
 #include "udiskslinuxdevice.h"
@@ -552,9 +553,18 @@ static void
 raid_device_added (UDisksLinuxMDRaidObject *object,
                    UDisksLinuxDevice       *device)
 {
+  gchar *level = NULL;
+
   g_assert (object->sync_action_source == NULL);
   g_assert (object->degraded_source == NULL);
 
+  if (!UDISKS_IS_LINUX_DEVICE (device))
+    goto out;
+
+  level = read_sysfs_attr (device->udev_device, "md/level");
+  if (level == NULL || !mdraid_has_redundancy (level))
+    goto out;
+
   /* udisks_debug ("start watching %s", g_udev_device_get_sysfs_path (device->udev_device)); */
   object->sync_action_source = watch_attr (device,
                                            "md/sync_action",
@@ -564,6 +574,9 @@ raid_device_added (UDisksLinuxMDRaidObject *object,
                                         "md/degraded",
                                         (GSourceFunc) attr_changed,
                                         object);
+
+ out:
+  g_free (level);
 }
 
 static void
@@ -684,6 +697,12 @@ udisks_linux_mdraid_object_uevent (UDisksLinuxMDRaidObject *object,
                   object->raid_device = g_object_ref (device);
                   raid_device_added (object, object->raid_device);
                 }
+              else if (object->sync_action_source == NULL && object->degraded_source == NULL)
+                {
+                  /* we don't have file watchers, adding them may failed because
+                     we were unable to get raid level, let's try again */
+                  raid_device_added (object, object->raid_device);
+                }
             }
         }
     }
-- 
2.9.5

From ab6ee79abac6a75eddd0ecfba7fc5111663bc50f Mon Sep 17 00:00:00 2001
From: Vojtech Trefny <vtrefny@redhat.com>
Date: Mon, 16 Oct 2017 15:26:16 +0200
Subject: [PATCH 5/5] Try to use libblockdev to get RAID array size

If reading size from sysfs fails, try to use libblockdev to read
it from mdadm --examine data.

Signed-off-by: Vratislav Podzimek <vpodzime@redhat.com>
---
 src/udiskslinuxmdraid.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/src/udiskslinuxmdraid.c b/src/udiskslinuxmdraid.c
index 22b4ee4..6c94a2b 100644
--- a/src/udiskslinuxmdraid.c
+++ b/src/udiskslinuxmdraid.c
@@ -246,6 +246,8 @@ udisks_linux_mdraid_update (UDisksLinuxMDRaid       *mdraid,
   GVariantBuilder builder;
   UDisksDaemon *daemon = NULL;
   UDisksBaseJob *job = NULL;
+  GError *error = NULL;
+  BDMDExamineData *raid_data = NULL;
 
   daemon = udisks_linux_mdraid_object_get_daemon (object);
 
@@ -303,7 +305,15 @@ udisks_linux_mdraid_update (UDisksLinuxMDRaid       *mdraid,
     }
   else
     {
-      /* TODO: need MD_ARRAY_SIZE, see https://bugs.freedesktop.org/show_bug.cgi?id=53239#c5 */
+      raid_data = bd_md_examine (g_udev_device_get_device_file (device->udev_device),
+                                 &error);
+      if (raid_data == NULL)
+        {
+          udisks_debug ("Failed to read array size: %s", error->message);
+          g_clear_error (&error);
+        }
+      else
+          size = raid_data->size;
     }
 
   udisks_mdraid_set_uuid (iface, uuid);
@@ -523,11 +533,14 @@ udisks_linux_mdraid_update (UDisksLinuxMDRaid       *mdraid,
                                                                                 uuid));
 
  out:
+  if (raid_data)
+      bd_md_examine_data_free (raid_data);
   g_free (sync_completed);
   g_free (sync_action);
   g_free (bitmap_location);
   g_list_free_full (member_devices, g_object_unref);
   g_clear_object (&raid_device);
+  g_clear_error (&error);
   return ret;
 }
 
-- 
2.9.5