]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Detail: fix for an imsm container with a spare
authorDan Williams <dan.j.williams@intel.com>
Tue, 15 Sep 2009 18:34:20 +0000 (11:34 -0700)
committerDan Williams <dan.j.williams@intel.com>
Tue, 15 Sep 2009 18:34:20 +0000 (11:34 -0700)
Spares for imsm arrays do not have any info about the container in their
metadata records.  If Detail() inadvertantly picks such a device for
->get_array_info() it will end up with less than useful info for the
container.  So, continue to read from the disks until a non-spare device
is found.

This bug was found by timeouts waiting for udev to create the
user-friendly container name.  To detect future UUID reporting problems
and a debug print to the timeout case in wait_for().

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Detail.c
util.c

index ab01cfb4b59092cfbd84c19808135ed995aa681a..001012a211cb38e85c8499222a0a0756f8f880ee 100644 (file)
--- a/Detail.c
+++ b/Detail.c
@@ -122,12 +122,25 @@ int Detail(char *dev, int brief, int export, int test, char *homehost)
                    disk.minor == 0)
                        continue;
                if ((dv=map_dev(disk.major, disk.minor, 1))) {
                    disk.minor == 0)
                        continue;
                if ((dv=map_dev(disk.major, disk.minor, 1))) {
-                       if ((!st || !st->sb) &&
+                       /* some formats (imsm) have free-floating-spares
+                        * with a uuid of uuid_match_any, they don't
+                        * have very good info about the rest of the
+                        * container, so keep searching when
+                        * encountering such a device.  Otherwise, stop
+                        * after the first successful call to
+                        * ->load_super.
+                        */
+                       int free_spare = memcmp(uuid_match_any,
+                                               info.uuid,
+                                               sizeof(uuid_match_any)) == 0;
+                       if ((!st || !st->sb || free_spare) &&
                            (array.raid_disks == 0 || 
                             (disk.state & (1<<MD_DISK_ACTIVE)))) {
                                /* try to read the superblock from this device
                                 * to get more info
                                 */
                            (array.raid_disks == 0 || 
                             (disk.state & (1<<MD_DISK_ACTIVE)))) {
                                /* try to read the superblock from this device
                                 * to get more info
                                 */
+                               if (free_spare)
+                                       st->ss->free_super(st);
                                int fd2 = dev_open(dv, O_RDONLY);
                                if (fd2 >=0 && st &&
                                    st->ss->load_super(st, fd2, NULL) == 0) {
                                int fd2 = dev_open(dv, O_RDONLY);
                                if (fd2 >=0 && st &&
                                    st->ss->load_super(st, fd2, NULL) == 0) {
diff --git a/util.c b/util.c
index 2543971026656ac8afca07c30d3d2f983a4a55a0..4ccb1bbf9f07e122a99f1c349ad546516dea9c0e 100644 (file)
--- a/util.c
+++ b/util.c
@@ -863,6 +863,8 @@ void wait_for(char *dev, int fd)
                        return;
                usleep(200000);
        }
                        return;
                usleep(200000);
        }
+       if (i == 25)
+               dprintf("%s: timeout waiting for %s\n", __func__, dev);
 }
 
 struct superswitch *superlist[] = { &super0, &super1, &super_ddf, &super_imsm, NULL };
 }
 
 struct superswitch *superlist[] = { &super0, &super1, &super_ddf, &super_imsm, NULL };