]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super-intel.c
imsm: fix num_domains
[thirdparty/mdadm.git] / super-intel.c
index 9b8cea21957fabf44048c85cee242365fc71b7fd..35c43f4e40a388560ff8b8fc660067a4a4a98d8a 100644 (file)
@@ -53,6 +53,7 @@
 
 #define MPB_SECTOR_CNT 418
 #define IMSM_RESERVED_SECTORS 4096
+#define SECT_PER_MB_SHIFT 11
 
 /* Disk configuration info. */
 #define IMSM_MAX_DEVICES 255
@@ -88,7 +89,7 @@ struct imsm_map {
        __u8  num_members;      /* number of member disks */
        __u8  num_domains;      /* number of parity domains */
        __u8  failed_disk_num;  /* valid only when state is degraded */
-       __u8  reserved[1];
+       __u8  ddf;
        __u32 filler[7];        /* expansion area */
 #define IMSM_ORD_REBUILD (1 << 24)
        __u32 disk_ord_tbl[1];  /* disk_ord_tbl[num_members],
@@ -105,6 +106,7 @@ struct imsm_vol {
 #define MIGR_VERIFY 2 /* analagous to echo check > sync_action */
 #define MIGR_GEN_MIGR 3
 #define MIGR_STATE_CHANGE 4
+#define MIGR_REPAIR 5
        __u8  migr_type;        /* Initializing, Rebuilding, ... */
        __u8  dirty;
        __u8  fs_state;         /* fast-sync state for CnG (0xff == disabled) */
@@ -193,6 +195,29 @@ struct bbm_log {
 static char *map_state_str[] = { "normal", "uninitialized", "degraded", "failed" };
 #endif
 
+static __u8 migr_type(struct imsm_dev *dev)
+{
+       if (dev->vol.migr_type == MIGR_VERIFY &&
+           dev->status & DEV_VERIFY_AND_FIX)
+               return MIGR_REPAIR;
+       else
+               return dev->vol.migr_type;
+}
+
+static void set_migr_type(struct imsm_dev *dev, __u8 migr_type)
+{
+       /* for compatibility with older oroms convert MIGR_REPAIR, into
+        * MIGR_VERIFY w/ DEV_VERIFY_AND_FIX status
+        */
+       if (migr_type == MIGR_REPAIR) {
+               dev->vol.migr_type = MIGR_VERIFY;
+               dev->status |= DEV_VERIFY_AND_FIX;
+       } else {
+               dev->vol.migr_type = migr_type;
+               dev->status &= ~DEV_VERIFY_AND_FIX;
+       }
+}
+
 static unsigned int sector_count(__u32 bytes)
 {
        return ((bytes + (512-1)) & (~(512-1))) / 512;
@@ -621,10 +646,23 @@ static void print_imsm_dev(struct imsm_dev *dev, char *uuid, int disk_idx)
        printf("     Chunk Size : %u KiB\n",
                __le16_to_cpu(map->blocks_per_strip) / 2);
        printf("       Reserved : %d\n", __le32_to_cpu(dev->reserved_blocks));
-       printf("  Migrate State : %s", dev->vol.migr_state ? "migrating" : "idle");
-       if (dev->vol.migr_state)
-               printf(": %s", dev->vol.migr_type ? "rebuilding" : "initializing");
-       printf("\n");
+       printf("  Migrate State : %s", dev->vol.migr_state ? "migrating" : "idle\n");
+       if (dev->vol.migr_state) {
+               if (migr_type(dev) == MIGR_INIT)
+                       printf(": initializing\n");
+               else if (migr_type(dev) == MIGR_REBUILD)
+                       printf(": rebuilding\n");
+               else if (migr_type(dev) == MIGR_VERIFY)
+                       printf(": check\n");
+               else if (migr_type(dev) == MIGR_GEN_MIGR)
+                       printf(": general migration\n");
+               else if (migr_type(dev) == MIGR_STATE_CHANGE)
+                       printf(": state change\n");
+               else if (migr_type(dev) == MIGR_REPAIR)
+                       printf(": repair\n");
+               else
+                       printf(": <unknown:%d>\n", migr_type(dev));
+       }
        printf("      Map State : %s", map_state_str[map->map_state]);
        if (dev->vol.migr_state) {
                struct imsm_map *map = get_imsm_map(dev, 1);
@@ -697,7 +735,8 @@ static void examine_super_imsm(struct supertype *st, char *homehost)
                printf("      Signature : %x\n", __le32_to_cpu(log->signature));
                printf("    Entry Count : %d\n", __le32_to_cpu(log->entry_count));
                printf("   Spare Blocks : %d\n",  __le32_to_cpu(log->reserved_spare_block_count));
-               printf("    First Spare : %llx\n", __le64_to_cpu(log->first_spare_lba));
+               printf("    First Spare : %llx\n",
+                      (unsigned long long) __le64_to_cpu(log->first_spare_lba));
        }
        for (i = 0; i < mpb->num_raid_devs; i++) {
                struct mdinfo info;
@@ -715,7 +754,7 @@ static void examine_super_imsm(struct supertype *st, char *homehost)
        }
 }
 
-static void brief_examine_super_imsm(struct supertype *st)
+static void brief_examine_super_imsm(struct supertype *st, int verbose)
 {
        /* We just write a generic IMSM ARRAY entry */
        struct mdinfo info;
@@ -1166,6 +1205,9 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info)
        info->array.utime         = 0;
        info->array.chunk_size    = __le16_to_cpu(map->blocks_per_strip) << 9;
        info->array.state         = !dev->vol.dirty;
+       info->custom_array_size   = __le32_to_cpu(dev->size_high);
+       info->custom_array_size   <<= 32;
+       info->custom_array_size   |= __le32_to_cpu(dev->size_low);
 
        info->disk.major = 0;
        info->disk.minor = 0;
@@ -1181,7 +1223,8 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info)
        if (map->map_state == IMSM_T_STATE_UNINITIALIZED || dev->vol.dirty)
                info->resync_start = 0;
        else if (dev->vol.migr_state)
-               info->resync_start = __le32_to_cpu(dev->vol.curr_migr_unit);
+               /* FIXME add curr_migr_unit to resync_start conversion */
+               info->resync_start = 0;
        else
                info->resync_start = ~0ULL;
 
@@ -1653,7 +1696,7 @@ load_imsm_disk(int fd, struct intel_super *super, char *devname, int keep_fd)
  * 1/ Idle (migr_state=0 map0state=normal||unitialized||degraded||failed)
  * 2/ Initialize (migr_state=1 migr_type=MIGR_INIT map0state=normal
  *    map1state=unitialized)
- * 3/ Verify (Resync) (migr_state=1 migr_type=MIGR_REBUILD map0state=normal
+ * 3/ Repair (Resync) (migr_state=1 migr_type=MIGR_REPAIR  map0state=normal
  *    map1state=normal)
  * 4/ Rebuild (migr_state=1 migr_type=MIGR_REBUILD map0state=normal
  *    map1state=degraded)
@@ -1664,7 +1707,7 @@ static void migrate(struct imsm_dev *dev, __u8 to_state, int migr_type)
        struct imsm_map *src = get_imsm_map(dev, 0);
 
        dev->vol.migr_state = 1;
-       dev->vol.migr_type = migr_type;
+       set_migr_type(dev, migr_type);
        dev->vol.curr_migr_unit = 0;
        dest = get_imsm_map(dev, 1);
 
@@ -2336,13 +2379,16 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
                array_blocks = calc_array_size(info->level, info->raid_disks,
                                               info->layout, info->chunk_size,
                                               info->size*2);
+       /* round array size down to closest MB */
+       array_blocks = (array_blocks >> SECT_PER_MB_SHIFT) << SECT_PER_MB_SHIFT;
+
        dev->size_low = __cpu_to_le32((__u32) array_blocks);
        dev->size_high = __cpu_to_le32((__u32) (array_blocks >> 32));
        dev->status = __cpu_to_le32(0);
        dev->reserved_blocks = __cpu_to_le32(0);
        vol = &dev->vol;
        vol->migr_state = 0;
-       vol->migr_type = MIGR_INIT;
+       set_migr_type(dev, MIGR_INIT);
        vol->dirty = 0;
        vol->curr_migr_unit = 0;
        map = get_imsm_map(dev, 0);
@@ -2352,19 +2398,23 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
        map->failed_disk_num = ~0;
        map->map_state = info->level ? IMSM_T_STATE_UNINITIALIZED :
                                       IMSM_T_STATE_NORMAL;
+       map->ddf = 1;
 
        if (info->level == 1 && info->raid_disks > 2) {
                fprintf(stderr, Name": imsm does not support more than 2 disks"
                                "in a raid1 volume\n");
                return 0;
        }
+
+       map->raid_level = info->level;
        if (info->level == 10) {
                map->raid_level = 1;
                map->num_domains = info->raid_disks / 2;
-       } else {
-               map->raid_level = info->level;
+       } else if (info->level == 1)
+               map->num_domains = info->raid_disks;
+       else
                map->num_domains = 1;
-       }
+
        num_data_stripes = info_to_num_data_stripes(info, map->num_domains);
        map->num_data_stripes = __cpu_to_le32(num_data_stripes);
 
@@ -3318,6 +3368,18 @@ static struct mdinfo *container_content_imsm(struct supertype *st)
                struct mdinfo *this;
                int slot;
 
+               /* do not publish arrays that are in the middle of an
+                * unsupported migration
+                */
+               if (dev->vol.migr_state &&
+                   (migr_type(dev) == MIGR_GEN_MIGR ||
+                    migr_type(dev) == MIGR_STATE_CHANGE)) {
+                       fprintf(stderr, Name ": cannot assemble volume '%.16s':"
+                               " unsupported migration in progress\n",
+                               dev->volume);
+                       continue;
+               }
+
                this = malloc(sizeof(*this));
                memset(this, 0, sizeof(*this));
                this->next = rest;
@@ -3364,7 +3426,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st)
                        info_d = malloc(sizeof(*info_d));
                        if (!info_d) {
                                fprintf(stderr, Name ": failed to allocate disk"
-                                       " for volume %s\n", (char *) dev->volume);
+                                       " for volume %.16s\n", dev->volume);
                                free(this);
                                this = rest;
                                break;
@@ -3518,7 +3580,8 @@ static int is_resyncing(struct imsm_dev *dev)
        if (!dev->vol.migr_state)
                return 0;
 
-       if (dev->vol.migr_type == MIGR_INIT)
+       if (migr_type(dev) == MIGR_INIT ||
+           migr_type(dev) == MIGR_REPAIR)
                return 1;
 
        migr_map = get_imsm_map(dev, 1);
@@ -3536,7 +3599,7 @@ static int is_rebuilding(struct imsm_dev *dev)
        if (!dev->vol.migr_state)
                return 0;
 
-       if (dev->vol.migr_type != MIGR_REBUILD)
+       if (migr_type(dev) != MIGR_REBUILD)
                return 0;
 
        migr_map = get_imsm_map(dev, 1);
@@ -3627,20 +3690,14 @@ static int imsm_set_array_state(struct active_array *a, int consistent)
        } else if (!is_resyncing(dev) && !failed) {
                /* mark the start of the init process if nothing is failed */
                dprintf("imsm: mark resync start (%llu)\n", a->resync_start);
-               if (map->map_state == IMSM_T_STATE_NORMAL)
-                       migrate(dev, IMSM_T_STATE_NORMAL, MIGR_REBUILD);
-               else
+               if (map->map_state == IMSM_T_STATE_UNINITIALIZED)
                        migrate(dev, IMSM_T_STATE_NORMAL, MIGR_INIT);
+               else
+                       migrate(dev, IMSM_T_STATE_NORMAL, MIGR_REPAIR);
                super->updates_pending++;
        }
 
-       /* check if we can update the migration checkpoint */
-       if (dev->vol.migr_state &&
-           __le32_to_cpu(dev->vol.curr_migr_unit) != a->resync_start) {
-               dprintf("imsm: checkpoint migration (%llu)\n", a->resync_start);
-               dev->vol.curr_migr_unit = __cpu_to_le32(a->resync_start);
-               super->updates_pending++;
-       }
+        /* FIXME check if we can update curr_migr_unit from resync_start */
 
        /* mark dirty / clean */
        if (dev->vol.dirty != !consistent) {