Blob Blame History Raw
From 673422da37ce9f96b44a182addd1aa922a9b047f Mon Sep 17 00:00:00 2001
From: Adam Williamson <awilliam@redhat.com>
Date: Mon, 24 Oct 2016 14:41:47 -0700
Subject: [PATCH] Handle mdadm --examine output during migration

If a RAID set is undergoing any operation considered to be a
'migration' - which includes initialization of a new set at any
RAID level that includes redundancy - mdadm --examine will have
lines like this:

     RAID Level : 5 <-- 5
        Members : 3 <-- 3
      Map State : normal <-- uninitialized

At present we don't understand this at all. This is a fairly
minimal fix which just has parse_mdadm_vars notice such lines,
split the 'value' on "<--", and stuff the first value (the one
being migrated *to*, which is usually what we care about, I
think) into the table. We could do something more elaborate
like store both values and make `get_examine_data_from_table`
understand that, but it's more complicated and this should be
all we truly need for now.

(cherry picked from commit 07aec87385e2fdbe3f0855d697facf04b9ea6521)
Signed-off-by: Vratislav Podzimek <vpodzime@redhat.com>
---
 src/plugins/mdraid.c                      | 13 +++++-
 tests/md_test.py                          |  8 ++++
 tests/mdadm_fw_RAID_examine_migrate/mdadm | 69 +++++++++++++++++++++++++++++++
 3 files changed, 88 insertions(+), 2 deletions(-)
 create mode 100755 tests/mdadm_fw_RAID_examine_migrate/mdadm

diff --git a/src/plugins/mdraid.c b/src/plugins/mdraid.c
index 9cb0cc7..c4780eb 100644
--- a/src/plugins/mdraid.c
+++ b/src/plugins/mdraid.c
@@ -155,6 +155,7 @@ static GHashTable* parse_mdadm_vars (gchar *str, gchar *item_sep, gchar *key_val
     gchar **items = NULL;
     gchar **item_p = NULL;
     gchar **key_val = NULL;
+    gchar **vals = NULL;
 
     table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
     *num_items = 0;
@@ -165,8 +166,16 @@ static GHashTable* parse_mdadm_vars (gchar *str, gchar *item_sep, gchar *key_val
         if (g_strv_length (key_val) == 2) {
             /* we only want to process valid lines (with the separator) */
             /* only use the first value for the given key */
-            if (!g_hash_table_contains (table, g_strstrip (key_val[0])))
-                g_hash_table_insert (table, g_strstrip (key_val[0]), g_strstrip (key_val[1]));
+            if (!g_hash_table_contains (table, g_strstrip (key_val[0]))) {
+                if (strstr (key_val[1], "<--")) {
+                    /* mdadm --examine output for a set being migrated */
+                    vals = g_strsplit (key_val[1], "<--", 2);
+                    g_hash_table_insert (table, g_strstrip (key_val[0]), g_strstrip (vals[0]));
+                    g_free (vals[1]);
+                } else {
+                    g_hash_table_insert (table, g_strstrip (key_val[0]), g_strstrip (key_val[1]));
+                }
+            }
             (*num_items)++;
         } else
             /* invalid line, just free key_val */
diff --git a/tests/md_test.py b/tests/md_test.py
index d7e007a..926d0c5 100644
--- a/tests/md_test.py
+++ b/tests/md_test.py
@@ -415,6 +415,14 @@ class FakeMDADMutilTest(unittest.TestCase):
 
         self.assertIs(ex_data.metadata, None)
 
+    def test_fw_raid_migrating(self):
+        """Verify that md_examine works when array is migrating ("foo <-- bar" values in output) """
+
+        with fake_utils("tests/mdadm_fw_RAID_examine_migrate"):
+            ex_data = BlockDev.md_examine("fake_dev")
+
+        self.assertEqual(ex_data.chunk_size, 128 * 1024)
+
 
 class MDUnloadTest(unittest.TestCase):
     def setUp(self):
diff --git a/tests/mdadm_fw_RAID_examine_migrate/mdadm b/tests/mdadm_fw_RAID_examine_migrate/mdadm
new file mode 100755
index 0000000..36ab0ca
--- /dev/null
+++ b/tests/mdadm_fw_RAID_examine_migrate/mdadm
@@ -0,0 +1,69 @@
+#!/bin/bash
+
+echo "$@"|grep -- "--brief" &>/dev/null
+is_brief=$?
+
+echo "$@"|grep -- "--export" &>/dev/null
+is_export=$?
+
+if [ $is_brief -eq 0 ]; then
+    cat <<EOF
+ARRAY metadata=imsm UUID=83c77249:90fb26a2:882bfb52:87f71b59
+ARRAY /dev/md/Volume0 container=83c77249:90fb26a2:882bfb52:87f71b59 member=0 UUID=76508998:aea211a0:b4fa4eda:78e41fbb
+EOF
+elif [ $is_export -eq 0 ]; then
+    cat <<EOF
+MD_METADATA=imsm
+MD_LEVEL=container
+MD_UUID=83c77249:90fb26a2:882bfb52:87f71b59
+MD_DEVICES=3
+EOF
+else
+    cat <<EOF
+/dev/sda:
+          Magic : Intel Raid ISM Cfg Sig.
+        Version : 1.2.02
+    Orig Family : 56330de5
+         Family : 56330de5
+     Generation : 00000005
+     Attributes : All supported
+           UUID : 83c77249:90fb26a2:882bfb52:87f71b59
+       Checksum : 359f2642 correct
+    MPB Sectors : 2
+          Disks : 3
+   RAID Devices : 1
+
+  Disk00 Serial : 50026B723702E422
+          State : active
+             Id : 00000000
+    Usable Size : 234436872 (111.79 GiB 120.03 GB)
+
+[Volume0]:
+           UUID : 76508998:aea211a0:b4fa4eda:78e41fbb
+     RAID Level : 5 <-- 5
+        Members : 3 <-- 3
+          Slots : [UUU] <-- [UUU]
+    Failed disk : none
+      This Slot : 0
+     Array Size : 468873216 (223.58 GiB 240.06 GB)
+   Per Dev Size : 234436872 (111.79 GiB 120.03 GB)
+  Sector Offset : 0
+    Num Stripes : 915768
+     Chunk Size : 128 KiB <-- 128 KiB
+       Reserved : 0
+  Migrate State : initialize
+      Map State : normal <-- uninitialized
+     Checkpoint : 0 (768)
+    Dirty State : clean
+
+  Disk01 Serial : 2327B37FS
+          State : active
+             Id : 00000002
+    Usable Size : 976768392 (465.76 GiB 500.11 GB)
+
+  Disk02 Serial : 232K7DDFS
+          State : active
+             Id : 00000003
+    Usable Size : 976768392 (465.76 GiB 500.11 GB)
+EOF
+fi
-- 
2.7.4