]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super-intel.c
FIX: Raid0 expansion cannot be restarted
[thirdparty/mdadm.git] / super-intel.c
index 44c100b5e97bf22a375cf687fcd5b1b5fe19f435..dc5e34e35f0d09a6c498dcd957b360b4fb5d9873 100644 (file)
@@ -383,7 +383,6 @@ const char *get_sys_dev_type(enum sys_dev_type type)
        return _sys_dev_type[type];
 }
 
-#ifndef MDASSEMBLE
 static struct intel_hba * alloc_intel_hba(struct sys_dev *device)
 {
        struct intel_hba *result = malloc(sizeof(*result));
@@ -407,7 +406,6 @@ static struct intel_hba * find_intel_hba(struct intel_hba *hba, struct sys_dev *
        return result;
 }
 
-
 static int attach_hba_to_super(struct intel_super *super, struct sys_dev *device)
 {
        struct intel_hba *hba;
@@ -473,7 +471,6 @@ static struct sys_dev* find_disk_attached_hba(int fd, const char *devname)
 
        return NULL;
 }
-#endif /* MDASSEMBLE */
 
 
 static int find_intel_hba_capability(int fd, struct intel_super *super,
@@ -1748,6 +1745,7 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info,
        struct imsm_map *map_to_analyse = map;
        struct dl *dl;
        char *devname;
+       unsigned int component_size_alligment;
        int map_disks = info->array.raid_disks;
 
        if (prev_map)
@@ -1827,6 +1825,21 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info,
        info->data_offset         = __le32_to_cpu(map_to_analyse->pba_of_lba0);
        info->component_size      =
                __le32_to_cpu(map_to_analyse->blocks_per_member);
+
+       /* check component size aligment
+        */
+       component_size_alligment =
+               info->component_size % (info->array.chunk_size/512);
+
+       if (component_size_alligment &&
+           (info->array.level != 1) && (info->array.level != UnSet)) {
+               dprintf("imsm: reported component size alligned from %llu ",
+                       info->component_size);
+               info->component_size -= component_size_alligment;
+               dprintf("to %llu (%i).\n",
+                       info->component_size, component_size_alligment);
+       }
+
        memset(info->uuid, 0, sizeof(info->uuid));
        info->recovery_start = MaxSector;
 
@@ -2218,11 +2231,12 @@ static int compare_super_imsm(struct supertype *st, struct supertype *tst)
         * use the same Intel hba
         */
        if (!check_env("IMSM_NO_PLATFORM")) {
-               if (first->hba->type != sec->hba->type)  {
+               if (!first->hba || !sec->hba ||
+                   (first->hba->type != sec->hba->type))  {
                        fprintf(stderr,
                                "HBAs of devices does not match %s != %s\n",
-                               get_sys_dev_type(first->hba->type),
-                               get_sys_dev_type(sec->hba->type));
+                               first->hba ? get_sys_dev_type(first->hba->type) : NULL,
+                               sec->hba ? get_sys_dev_type(sec->hba->type) : NULL);
                        return 3;
                }
        }
@@ -3386,16 +3400,19 @@ static int load_super_imsm(struct supertype *st, int fd, char *devname)
                        sizeof(*super));
                return 1;
        }
+       /* Load hba and capabilities if they exist.
+        * But do not preclude loading metadata in case capabilities or hba are
+        * non-compliant and ignore_hw_compat is set.
+        */
        rv = find_intel_hba_capability(fd, super, devname);
        /* no orom/efi or non-intel hba of the disk */
-       if (rv != 0) {
+       if ((rv != 0) && (st->ignore_hw_compat == 0)) {
                if (devname)
                        fprintf(stderr,
                                Name ": No OROM/EFI properties for %s\n", devname);
                free_imsm(super);
                return 2;
        }
-
        rv = load_and_parse_mpb(fd, super, devname, 0);
 
        if (rv) {
@@ -3838,6 +3855,7 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
        } else {
                dd->next = super->disks;
                super->disks = dd;
+               super->updates_pending++;
        }
 
        return 0;
@@ -4957,6 +4975,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
                 */
 
                chunk = __le16_to_cpu(map->blocks_per_strip) >> 1;
+#ifndef MDASSEMBLE
                if (!validate_geometry_imsm_orom(super,
                                                 get_imsm_raid_level(map), /* RAID level */
                                                 imsm_level_to_layout(get_imsm_raid_level(map)),
@@ -4967,6 +4986,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
                                "Cannot proceed with the action(s).\n");
                        continue;
                }
+#endif /* MDASSEMBLE */
                this = malloc(sizeof(*this));
                if (!this) {
                        fprintf(stderr, Name ": failed to allocate %zu bytes\n",
@@ -5213,8 +5233,6 @@ static int mark_failure(struct imsm_dev *dev, struct imsm_disk *disk, int idx)
        __u32 ord;
        int slot;
        struct imsm_map *map;
-       char buf[MAX_RAID_SERIAL_LEN+3];
-       unsigned int len, shift = 0;
 
        /* new failures are always set in map[0] */
        map = get_imsm_map(dev, 0);
@@ -5227,11 +5245,6 @@ static int mark_failure(struct imsm_dev *dev, struct imsm_disk *disk, int idx)
        if (is_failed(disk) && (ord & IMSM_ORD_REBUILD))
                return 0;
 
-       sprintf(buf, "%s:0", disk->serial);
-       if ((len = strlen(buf)) >= MAX_RAID_SERIAL_LEN)
-               shift = len - MAX_RAID_SERIAL_LEN + 1;
-       strncpy((char *)disk->serial, &buf[shift], MAX_RAID_SERIAL_LEN);
-
        disk->status |= FAILED_DISK;
        set_imsm_ord_tbl_ent(map, slot, idx | IMSM_ORD_REBUILD);
        if (map->failed_disk_num == 0xff)
@@ -6949,6 +6962,14 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st,
                                         geo->raid_disks > 1 ? "s" : "");
                                break;
                        }
+                       /* check if component size is aligned to chunk size
+                        */
+                       if (info->component_size %
+                           (info->array.chunk_size/512)) {
+                               dprintf("Component size is not aligned to "
+                                       "chunk size\n");
+                               break;
+                       }
                }
 
                if (*old_raid_disks &&
@@ -7254,6 +7275,30 @@ int imsm_takeover(struct supertype *st, struct geo_params *geo)
        return 0;
 }
 
+static int warn_user_about_risk(void)
+{
+       int rv = 0;
+
+       fprintf(stderr,
+               "\nThis is an experimental feature. Data on the RAID volume(s) "
+               "can be lost!!!\n\n"
+               "To continue command execution please make sure that\n"
+               "the grow process will not be interrupted. Use safe power\n"
+               "supply to avoid unexpected system reboot. Make sure that\n"
+               "reshaped container is not assembled automatically during\n"
+               "system boot.\n"
+               "If reshape is interrupted, assemble array manually\n"
+               "using e.g. '-Ac' option and up to date mdadm.conf file.\n"
+               "Assembly in scan mode is not possible in such case.\n"
+               "Growing container with boot array is not possible.\n"
+               "If boot array reshape is interrupted, whole file system\n"
+               "can be lost.\n\n");
+       rv = ask("Do you want to continue? ");
+       fprintf(stderr, "\n");
+
+       return rv;
+}
+
 static int imsm_reshape_super(struct supertype *st, long long size, int level,
                              int layout, int chunksize, int raid_disks,
                              int delta_disks, char *backup, char *dev,
@@ -7286,6 +7331,14 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level,
                /* On container level we can only increase number of devices. */
                dprintf("imsm: info: Container operation\n");
                int old_raid_disks = 0;
+
+               /* this warning will be removed when imsm checkpointing
+                * will be implemented, and restoring from check-point
+                * operation will be transparent for reboot process
+                */
+               if (warn_user_about_risk() == 0)
+                       return ret_val;
+
                if (imsm_reshape_is_allowed_on_container(
                            st, &geo, &old_raid_disks)) {
                        struct imsm_update_reshape *u = NULL;