Express RAID member state as an array of strings, instead of just a string
authorDavid Zeuthen <zeuthen@gmail.com>
Wed, 19 Sep 2012 16:21:55 +0000 (12:21 -0400)
committerDavid Zeuthen <zeuthen@gmail.com>
Wed, 19 Sep 2012 16:21:55 +0000 (12:21 -0400)
The sysfs file /sys/block/md0/md/dev-sda/state is a comma-separated
list of states, not just one state.

Signed-off-by: David Zeuthen <zeuthen@gmail.com>
data/org.freedesktop.UDisks2.xml
src/udiskslinuxmdraid.c

index 2e57a82..482c4bb 100644 (file)
          <listitem><para>The object path for the underlying block device (guaranteed to implement the #org.freedesktop.UDisks2.Block interface)</para></listitem></varlistentry>
          <varlistentry><term>slot (type 'i')</term>
          <listitem><para>-1 if the device is not currently part of the array (ie. <literal>spare</literal> or <literal>faulty</literal>), otherwise the slot number the device currently fills (between 0 and #org.freedesktop.UDisks2.MDRaid:NumDevices)</para></listitem></varlistentry>
-         <varlistentry><term>state (type 's')</term>
-         <listitem><para>The state of the device - known values include <literal>faulty</literal>, <literal>in_sync</literal>, <literal>writemostly</literal>, <literal>blocked</literal> and <literal>spare</literal></para></listitem></varlistentry>
+         <varlistentry><term>state (type 'as')</term>
+         <listitem><para>The state of the device - known elements include <literal>faulty</literal>, <literal>in_sync</literal>, <literal>write_mostly</literal>, <literal>blocked</literal> and <literal>spare</literal></para></listitem></varlistentry>
          <varlistentry><term>num_read_errors (type 't')</term>
          <listitem><para>An ongoing count of read errors that have been detected on this device but have not caused the device to be evicted from the array</para></listitem></varlistentry>
          <varlistentry><term>expansion (type 'a{sv}')</term>
          <filename><ulink url="http://www.kernel.org/doc/Documentation/md.txt">Documentation/md.txt</ulink></filename>
          file shipped with the kernel sources.
     -->
-    <property name="ActiveDevices" type="a(oista{sv})" access="read"/>
+    <property name="ActiveDevices" type="a(oiasta{sv})" access="read"/>
 
     <!--
         Start:
index fd0a5cb..7a5fb85 100644 (file)
@@ -239,8 +239,8 @@ member_cmpfunc (GVariant **a,
   g_return_val_if_fail (a != NULL, 0);
   g_return_val_if_fail (b != NULL, 0);
 
-  g_variant_get (*a, "(&oista{sv})", &objpath_a, &slot_a, NULL, NULL, NULL);
-  g_variant_get (*b, "(&oista{sv})", &objpath_b, &slot_b, NULL, NULL, NULL);
+  g_variant_get (*a, "(&oiasta{sv})", &objpath_a, &slot_a, NULL, NULL, NULL);
+  g_variant_get (*b, "(&oiasta{sv})", &objpath_b, &slot_b, NULL, NULL, NULL);
 
   if (slot_a == slot_b)
     return g_strcmp0 (objpath_a, objpath_b);
@@ -386,7 +386,7 @@ udisks_linux_mdraid_update (UDisksLinuxMDRaid       *mdraid,
     }
 
   /* figure out active devices */
-  g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(oista{sv})"));
+  g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(oiasta{sv})"));
   if (raid_device != NULL)
     {
       gchar *md_dir_name = NULL;
@@ -412,6 +412,7 @@ udisks_linux_mdraid_update (UDisksLinuxMDRaid       *mdraid,
               gchar *block_sysfs_path = NULL;
               UDisksObject *member_object = NULL;
               gchar *member_state = NULL;
+              gchar **member_state_elements = NULL;
               gchar *member_slot = NULL;
               gint member_slot_as_int = -1;
               guint64 member_errors = 0;
@@ -438,7 +439,10 @@ udisks_linux_mdraid_update (UDisksLinuxMDRaid       *mdraid,
               snprintf (buf, sizeof (buf), "md/%s/state", name);
               member_state = read_sysfs_attr (raid_device, buf);
               if (member_state != NULL)
-                g_strstrip (member_state);
+                {
+                  g_strstrip (member_state);
+                  member_state_elements = g_strsplit (member_state, ",", 0);
+                }
 
               snprintf (buf, sizeof (buf), "md/%s/slot", name);
               member_slot = read_sysfs_attr (raid_device, buf);
@@ -453,16 +457,17 @@ udisks_linux_mdraid_update (UDisksLinuxMDRaid       *mdraid,
               member_errors = read_sysfs_attr_as_uint64 (raid_device, buf);
 
               g_ptr_array_add (p,
-                               g_variant_new ("(oista{sv})",
+                               g_variant_new ("(oi^asta{sv})",
                                               g_dbus_object_get_object_path (G_DBUS_OBJECT (member_object)),
                                               member_slot_as_int,
-                                              member_state,
+                                              member_state_elements,
                                               member_errors,
                                               NULL)); /* expansion, unused for now */
 
             member_done:
               g_free (member_slot);
               g_free (member_state);
+              g_strfreev (member_state_elements);
               g_clear_object (&member_object);
               g_free (block_sysfs_path);
 
@@ -755,28 +760,36 @@ handle_stop (UDisksMDRaid           *_mdraid,
 
 /* ---------------------------------------------------------------------------------------------------- */
 
-static gchar *
-find_member_state (UDisksLinuxMDRaid *mdraid,
-                   const gchar       *member_device_objpath)
+static gchar **
+find_member_states (UDisksLinuxMDRaid *mdraid,
+                    const gchar       *member_device_objpath)
 {
   GVariantIter iter;
   GVariant *active_devices = NULL;
   const gchar *iter_objpath;
-  const gchar *iter_state;
-  gchar *ret = NULL;
+  const gchar **iter_state;
+  gchar **ret = NULL;
 
   active_devices = udisks_mdraid_dup_active_devices (UDISKS_MDRAID (mdraid));
   if (active_devices == NULL)
     goto out;
 
   g_variant_iter_init (&iter, active_devices);
-  while (g_variant_iter_next (&iter, "(&oi&sta{sv})", &iter_objpath, NULL, &iter_state, NULL, NULL))
+  while (g_variant_iter_next (&iter, "(&oi^a&sta{sv})", &iter_objpath, NULL, &iter_state, NULL, NULL))
     {
       if (g_strcmp0 (iter_objpath, member_device_objpath) == 0)
         {
-          ret = g_strdup (iter_state);
+          guint n;
+          /* we only own the container, so need to dup the values */
+          ret = (gchar **) iter_state;
+          for (n = 0; ret[n] != NULL; n++)
+            ret[n] = g_strdup (ret[n]);
           goto out;
         }
+      else
+        {
+          g_free (iter_state);
+        }
     }
 
  out:
@@ -786,6 +799,27 @@ find_member_state (UDisksLinuxMDRaid *mdraid,
 }
 
 static gboolean
+has_state (gchar **states, const gchar *state)
+{
+  gboolean ret = FALSE;
+  guint n;
+
+  if (states == NULL)
+    goto out;
+
+  for (n = 0; states[n] != NULL; n++)
+    {
+      if (g_strcmp0 (states[n], state) == 0)
+        {
+          ret = TRUE;
+          goto out;
+        }
+    }
+ out:
+  return ret;
+}
+
+static gboolean
 handle_remove_device (UDisksMDRaid           *_mdraid,
                       GDBusMethodInvocation  *invocation,
                       const gchar            *member_device_objpath,
@@ -807,7 +841,7 @@ handle_remove_device (UDisksMDRaid           *_mdraid,
   gchar *error_message = NULL;
   UDisksObject *member_device_object = NULL;
   UDisksBlock *member_device = NULL;
-  gchar *member_state = NULL;
+  gchar **member_states = NULL;
   gboolean opt_wipe = FALSE;
 
   object = udisks_daemon_util_dup_object (mdraid, &error);
@@ -859,8 +893,8 @@ handle_remove_device (UDisksMDRaid           *_mdraid,
       goto out;
     }
 
-  member_state = find_member_state (mdraid, member_device_objpath);
-  if (member_state == NULL)
+  member_states = find_member_states (mdraid, member_device_objpath);
+  if (member_states == NULL)
     {
       g_dbus_method_invocation_return_error (invocation, UDISKS_ERROR, UDISKS_ERROR_FAILED,
                                              "Cannot determine member state of given object");
@@ -888,7 +922,7 @@ handle_remove_device (UDisksMDRaid           *_mdraid,
   escaped_member_device_file = udisks_daemon_util_escape_and_quote (member_device_file);
 
   /* if necessary, mark as faulty first */
-  if (g_strcmp0 (member_state, "in_sync") == 0 || g_strcmp0 (member_state, "writemostly") == 0)
+  if (has_state (member_states, "in_sync"))
     {
       if (!udisks_daemon_launch_spawned_job_sync (daemon,
                                                   UDISKS_OBJECT (object),
@@ -968,7 +1002,7 @@ handle_remove_device (UDisksMDRaid           *_mdraid,
   g_free (error_message);
   g_free (escaped_device_file);
   g_free (escaped_member_device_file);
-  g_free (member_state);
+  g_free (member_states);
   g_clear_object (&member_device_object);
   g_clear_object (&member_device);
   g_clear_object (&raid_device);