Fix corner-cases for detecting RAID arrays
authorDavid Zeuthen <zeuthen@gmail.com>
Thu, 13 Sep 2012 18:24:11 +0000 (14:24 -0400)
committerDavid Zeuthen <zeuthen@gmail.com>
Thu, 13 Sep 2012 18:24:11 +0000 (14:24 -0400)
If the array device was detected before any of the components we would
fail to detect the array. Fix that.

Signed-off-by: David Zeuthen <zeuthen@gmail.com>
src/udiskslinuxmdraid.c
src/udiskslinuxmdraidobject.c

index 85ace3f..bdebec6 100644 (file)
@@ -179,20 +179,32 @@ udisks_linux_mdraid_update (UDisksLinuxMDRaid       *mdraid,
   guint64 size = 0;
   GUdevDevice *raid_device = NULL;
   GList *member_devices = NULL;
-  GUdevDevice *member_device = NULL;
+  GUdevDevice *device = NULL;
   const gchar *level = NULL;
   gchar *sync_action = NULL;
   guint degraded = 0;
 
   member_devices = udisks_linux_mdraid_object_get_members (object);
-  if (member_devices == NULL)
-    goto out;
-
   raid_device = udisks_linux_mdraid_object_get_device (object);
-  member_device = G_UDEV_DEVICE (member_devices->data);
 
-  num_devices = g_udev_device_get_property_as_int (member_device, "MD_DEVICES");
-  level = g_udev_device_get_property (member_device, "MD_LEVEL");
+  if (member_devices == NULL && raid_device == NULL)
+    {
+      /* this should never happen */
+      udisks_warning ("No members and no RAID device - bailing");
+      goto out;
+    }
+
+  /* it doesn't matter where we get the MD_ properties from - it can be
+   * either a member device or the raid device (/dev/md*) - prefer the
+   * former, if available
+   */
+  if (member_devices != NULL)
+    device = G_UDEV_DEVICE (member_devices->data);
+  else
+    device = G_UDEV_DEVICE (raid_device);
+
+  num_devices = g_udev_device_get_property_as_int (device, "MD_DEVICES");
+  level = g_udev_device_get_property (device, "MD_LEVEL");
 
   /* figure out size */
   if (raid_device != NULL)
@@ -204,8 +216,8 @@ udisks_linux_mdraid_update (UDisksLinuxMDRaid       *mdraid,
       /* TODO: need MD_ARRAY_SIZE, see https://bugs.freedesktop.org/show_bug.cgi?id=53239#c5 */
     }
 
-  udisks_mdraid_set_uuid (iface, g_udev_device_get_property (member_device, "MD_UUID"));
-  udisks_mdraid_set_name (iface, g_udev_device_get_property (member_device, "MD_NAME"));
+  udisks_mdraid_set_uuid (iface, g_udev_device_get_property (device, "MD_UUID"));
+  udisks_mdraid_set_name (iface, g_udev_device_get_property (device, "MD_NAME"));
   udisks_mdraid_set_level (iface, level);
   udisks_mdraid_set_num_devices (iface, num_devices);
   udisks_mdraid_set_size (iface, size);
index c8db978..4c0775a 100644 (file)
@@ -151,8 +151,13 @@ udisks_linux_mdraid_object_set_property (GObject      *__object,
       break;
 
     case PROP_DEVICE:
-      g_assert (object->devices == NULL);
-      object->devices = g_list_prepend (NULL, g_value_dup_object (value));
+      /* initial coldplug */
+      {
+        GUdevDevice *device;
+        g_assert (object->devices == NULL);
+        device = G_UDEV_DEVICE (g_value_get_object (value));
+        udisks_linux_mdraid_object_uevent (object, "add", device);
+      }
       break;
 
     default:
@@ -194,9 +199,6 @@ udisks_linux_mdraid_object_constructed (GObject *_object)
   gchar *uuid;
   gchar *s;
 
-  /* initial coldplug */
-  udisks_linux_mdraid_object_uevent (object, "add", object->devices->data);
-
   /* compute the object path */
   uuid = udisks_mdraid_dup_uuid (object->iface_mdraid);
   strip_and_replace_with_uscore (uuid);
@@ -518,6 +520,7 @@ attr_changed (GIOChannel   *channel,
       g_clear_error (&error);
       goto out;
     }
+
   if (g_io_channel_read_to_end (channel, &str, &len, &error) != G_IO_STATUS_NORMAL)
     {
       udisks_warning ("Error reading: %s (%s, %d)",
@@ -526,6 +529,8 @@ attr_changed (GIOChannel   *channel,
       goto out;
     }
 
+  g_free (str);
+
   /* synthesize uevent */
   udisks_linux_mdraid_object_uevent (object, "change", NULL);
 
@@ -551,6 +556,7 @@ md_device_added (UDisksLinuxMDRaidObject *object,
   g_assert (object->sync_action_source == NULL);
   g_assert (object->degraded_source == NULL);
 
+  /* udisks_debug ("start watching %s", g_udev_device_get_sysfs_path (device)); */
   object->sync_action_source = watch_attr (device,
                                            "md/sync_action",
                                            (GSourceFunc) attr_changed,
@@ -565,6 +571,7 @@ static void
 md_device_removed (UDisksLinuxMDRaidObject *object,
                    GUdevDevice             *device)
 {
+  /* udisks_debug ("stop watching %s", g_udev_device_get_sysfs_path (device)); */
   remove_watches (object);
 }