]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super1.c
Allow test to detect 'resync=DELAYED' state
[thirdparty/mdadm.git] / super1.c
index 24c18c0ee3ea57f55eb321db031edd662bf57710..50a5f48779ca035432a9e4d8f4bd01b77c7fd97c 100644 (file)
--- a/super1.c
+++ b/super1.c
@@ -558,12 +558,13 @@ static void uuid_from_super1(struct supertype *st, int uuid[4])
                cuuid[i] = super->set_uuid[i];
 }
 
-static void getinfo_super1(struct supertype *st, struct mdinfo *info)
+static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map)
 {
        struct mdp_superblock_1 *sb = st->sb;
        int working = 0;
        unsigned int i;
-       int role;
+       unsigned int role;
+       unsigned int map_disks = info->array.raid_disks;
 
        info->array.major_version = 1;
        info->array.minor_version = st->minor_version;
@@ -629,22 +630,41 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info)
        } else
                info->reshape_active = 0;
 
+       if (map)
+               for (i=0; i<map_disks; i++)
+                       map[i] = 0;
        for (i = 0; i < __le32_to_cpu(sb->max_dev); i++) {
                role = __le16_to_cpu(sb->dev_roles[i]);
-               if (/*role == 0xFFFF || */role < info->array.raid_disks)
+               if (/*role == 0xFFFF || */role < (unsigned) info->array.raid_disks) {
                        working++;
+                       if (map && role < map_disks)
+                               map[role] = 1;
+               }
        }
 
        info->array.working_disks = working;
 }
 
+static struct mdinfo *container_content1(struct supertype *st, char *subarray)
+{
+       struct mdinfo *info;
+
+       if (subarray)
+               return NULL;
+
+       info = malloc(sizeof(*info));
+       getinfo_super1(st, info, NULL);
+       return info;
+}
+
 static int update_super1(struct supertype *st, struct mdinfo *info,
                         char *update,
                         char *devname, int verbose,
                         int uuid_set, char *homehost)
 {
-       /* NOTE: for 'assemble' and 'force' we need to return non-zero if any change was made.
-        * For others, the return value is ignored.
+       /* NOTE: for 'assemble' and 'force' we need to return non-zero
+        * if any change was made.  For others, the return value is
+        * ignored.
         */
        int rv = 0;
        struct mdp_superblock_1 *sb = st->sb;
@@ -671,11 +691,11 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
                int d = info->disk.number;
                int want;
                if (info->disk.state == 6)
-                       want = __cpu_to_le32(info->disk.raid_disk);
+                       want = info->disk.raid_disk;
                else
                        want = 0xFFFF;
-               if (sb->dev_roles[d] != want) {
-                       sb->dev_roles[d] = want;
+               if (sb->dev_roles[d] != __cpu_to_le16(want)) {
+                       sb->dev_roles[d] = __cpu_to_le16(want);
                        rv = 1;
                }
        } else if (strcmp(update, "linear-grow-new") == 0) {
@@ -735,6 +755,8 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
                        bm = (struct bitmap_super_s*)(st->sb+1024);
                        memcpy(bm->uuid, sb->set_uuid, 16);
                }
+       } else if (strcmp(update, "no-bitmap") == 0) {
+               sb->feature_map &= ~__cpu_to_le32(MD_FEATURE_BITMAP_OFFSET);
        } else if (strcmp(update, "homehost") == 0 &&
            homehost) {
                char *c;
@@ -997,11 +1019,13 @@ static unsigned long choose_bm_space(unsigned long devsize)
        return 4*2;
 }
 
+static void free_super1(struct supertype *st);
+
 #ifndef MDASSEMBLE
 static int write_init_super1(struct supertype *st)
 {
        struct mdp_superblock_1 *sb = st->sb;
-       struct supertype refst;
+       struct supertype *refst;
        int rfd;
        int rv = 0;
        unsigned long long bm_space;
@@ -1033,10 +1057,9 @@ static int write_init_super1(struct supertype *st)
 
                sb->events = 0;
 
-               refst =*st;
-               refst.sb = NULL;
-               if (load_super1(&refst, di->fd, NULL)==0) {
-                       struct mdp_superblock_1 *refsb = refst.sb;
+               refst = dup_super(st);
+               if (load_super1(refst, di->fd, NULL)==0) {
+                       struct mdp_superblock_1 *refsb = refst->sb;
 
                        memcpy(sb->device_uuid, refsb->device_uuid, 16);
                        if (memcmp(sb->set_uuid, refsb->set_uuid, 16)==0) {
@@ -1049,8 +1072,9 @@ static int write_init_super1(struct supertype *st)
                                if (get_linux_version() >= 2006018)
                                        sb->dev_number = refsb->dev_number;
                        }
-                       free(refsb);
+                       free_super1(refst);
                }
+               free(refst);
 
                if (!get_dev_size(di->fd, NULL, &dsize))
                        return 1;
@@ -1185,8 +1209,6 @@ static int compare_super1(struct supertype *st, struct supertype *tst)
        return 0;
 }
 
-static void free_super1(struct supertype *st);
-
 static int load_super1(struct supertype *st, int fd, char *devname)
 {
        unsigned long long dsize;
@@ -1198,9 +1220,6 @@ static int load_super1(struct supertype *st, int fd, char *devname)
 
        free_super1(st);
 
-       if (st->subarray[0])
-               return 1;
-
        if (st->ss == NULL || st->minor_version == -1) {
                int bestvers = -1;
                struct supertype tst;
@@ -1355,6 +1374,7 @@ static struct supertype *match_metadata_desc1(char *arg)
        if (!st) return st;
 
        memset(st, 0, sizeof(*st));
+       st->container_dev = NoMdDev;
        st->ss = &super1;
        st->max_devs = 384;
        st->sb = NULL;
@@ -1621,6 +1641,13 @@ static void free_super1(struct supertype *st)
 {
        if (st->sb)
                free(st->sb);
+       while (st->info) {
+               struct devinfo *di = st->info;
+               st->info = di->next;
+               if (di->fd >= 0)
+                       close(di->fd);
+               free(di);
+       }
        st->sb = NULL;
 }
 
@@ -1676,6 +1703,7 @@ struct superswitch super1 = {
        .match_home = match_home1,
        .uuid_from_super = uuid_from_super1,
        .getinfo_super = getinfo_super1,
+       .container_content = container_content1,
        .update_super = update_super1,
        .init_super = init_super1,
        .store_super = store_super1,