diff options
Diffstat (limited to 'super-intel.c')
-rw-r--r-- | super-intel.c | 489 |
1 files changed, 239 insertions, 250 deletions
diff --git a/super-intel.c b/super-intel.c index 1faab60..713bfcc 100644 --- a/super-intel.c +++ b/super-intel.c @@ -32,14 +32,19 @@ /* MPB == Metadata Parameter Block */ #define MPB_SIGNATURE "Intel Raid ISM Cfg Sig. " #define MPB_SIG_LEN (strlen(MPB_SIGNATURE)) -#define MPB_VERSION_RAID0 "1.0.00" -#define MPB_VERSION_RAID1 "1.1.00" -#define MPB_VERSION_MANY_VOLUMES_PER_ARRAY "1.2.00" -#define MPB_VERSION_3OR4_DISK_ARRAY "1.2.01" -#define MPB_VERSION_RAID5 "1.2.02" -#define MPB_VERSION_5OR6_DISK_ARRAY "1.2.04" -#define MPB_VERSION_CNG "1.2.06" + +/* Legacy IMSM versions: + * MPB_VERSION_RAID0 1.0.00 + * MPB_VERSION_RAID1 1.1.00 + * MPB_VERSION_MANY_VOLUMES_PER_ARRAY 1.2.00 + * MPB_VERSION_3OR4_DISK_ARRAY 1.2.01 + * MPB_VERSION_RAID5 1.2.02 + * MPB_VERSION_5OR6_DISK_ARRAY 1.2.04 + * MPB_VERSION_CNG 1.2.06 + */ + #define MPB_VERSION_ATTRIBS "1.3.00" +#define MPB_VERSION_ATTRIBS_JD "2.0.00" #define MAX_SIGNATURE_LENGTH 32 #define MAX_RAID_SERIAL_LEN 16 @@ -57,6 +62,8 @@ #define MPB_ATTRIB_RAIDCNG __cpu_to_le32(0x00000020) /* supports expanded stripe sizes of 256K, 512K and 1MB */ #define MPB_ATTRIB_EXP_STRIPE_SIZE __cpu_to_le32(0x00000040) +/* supports RAID10 with more than 4 drives */ +#define MPB_ATTRIB_RAID10_EXT __cpu_to_le32(0x00000080) /* The OROM Support RST Caching of Volumes */ #define MPB_ATTRIB_NVM __cpu_to_le32(0x02000000) @@ -84,6 +91,7 @@ MPB_ATTRIB_RAID10 | \ MPB_ATTRIB_RAID5 | \ MPB_ATTRIB_EXP_STRIPE_SIZE | \ + MPB_ATTRIB_RAID10_EXT | \ MPB_ATTRIB_BBM) /* Define attributes that are unused but not harmful */ @@ -166,7 +174,8 @@ struct imsm_map { __u8 raid_level; #define IMSM_T_RAID0 0 #define IMSM_T_RAID1 1 -#define IMSM_T_RAID5 5 /* since metadata version 1.2.02 ? */ +#define IMSM_T_RAID5 5 +#define IMSM_T_RAID10 10 __u8 num_members; /* number of member disks */ __u8 num_domains; /* number of parity domains */ __u8 failed_disk_num; /* valid only when state is degraded */ @@ -514,6 +523,7 @@ enum imsm_reshape_type { CH_TAKEOVER, CH_MIGRATION, CH_ARRAY_SIZE, + CH_ABORT }; /* definition of messages passed to imsm_process_update */ @@ -1259,14 +1269,42 @@ static int get_imsm_disk_slot(struct imsm_map *map, const unsigned int idx) return IMSM_STATUS_ERROR; } +/** + * update_imsm_raid_level() - update raid level appropriately in &imsm_map. + * @map: &imsm_map pointer. + * @new_level: MD style level. + * + * For backward compatibility reasons we need to differentiate RAID10. + * In the past IMSM RAID10 was presented as RAID1. + * Keep compatibility unless it is not explicitly updated by UEFI driver. + * + * Routine needs num_members to be set and (optionally) raid_level. + */ +static void update_imsm_raid_level(struct imsm_map *map, int new_level) +{ + if (new_level != IMSM_T_RAID10) { + map->raid_level = new_level; + return; + } + + if (map->num_members == 4) { + if (map->raid_level == IMSM_T_RAID10 || map->raid_level == IMSM_T_RAID1) + return; + + map->raid_level = IMSM_T_RAID1; + return; + } + + map->raid_level = IMSM_T_RAID10; +} static int get_imsm_raid_level(struct imsm_map *map) { - if (map->raid_level == 1) { + if (map->raid_level == IMSM_T_RAID1) { if (map->num_members == 2) - return 1; + return IMSM_T_RAID1; else - return 10; + return IMSM_T_RAID10; } return map->raid_level; @@ -2098,91 +2136,18 @@ void convert_from_4k(struct intel_super *super) mpb->check_sum = __gen_imsm_checksum(mpb); } -/******************************************************************************* - * function: imsm_check_attributes - * Description: Function checks if features represented by attributes flags - * are supported by mdadm. - * Parameters: - * attributes - Attributes read from metadata - * Returns: - * 0 - passed attributes contains unsupported features flags - * 1 - all features are supported - ******************************************************************************/ -static int imsm_check_attributes(__u32 attributes) +/** + * imsm_check_attributes() - Check if features represented by attributes flags are supported. + * + * @attributes: attributes read from metadata. + * Returns: true if all features are supported, false otherwise. + */ +static bool imsm_check_attributes(__u32 attributes) { - int ret_val = 1; - __u32 not_supported = MPB_ATTRIB_SUPPORTED^0xffffffff; - - not_supported &= ~MPB_ATTRIB_IGNORED; - - not_supported &= attributes; - if (not_supported) { - pr_err("(IMSM): Unsupported attributes : %x\n", - (unsigned)__le32_to_cpu(not_supported)); - if (not_supported & MPB_ATTRIB_CHECKSUM_VERIFY) { - dprintf("\t\tMPB_ATTRIB_CHECKSUM_VERIFY \n"); - not_supported ^= MPB_ATTRIB_CHECKSUM_VERIFY; - } - if (not_supported & MPB_ATTRIB_2TB) { - dprintf("\t\tMPB_ATTRIB_2TB\n"); - not_supported ^= MPB_ATTRIB_2TB; - } - if (not_supported & MPB_ATTRIB_RAID0) { - dprintf("\t\tMPB_ATTRIB_RAID0\n"); - not_supported ^= MPB_ATTRIB_RAID0; - } - if (not_supported & MPB_ATTRIB_RAID1) { - dprintf("\t\tMPB_ATTRIB_RAID1\n"); - not_supported ^= MPB_ATTRIB_RAID1; - } - if (not_supported & MPB_ATTRIB_RAID10) { - dprintf("\t\tMPB_ATTRIB_RAID10\n"); - not_supported ^= MPB_ATTRIB_RAID10; - } - if (not_supported & MPB_ATTRIB_RAID1E) { - dprintf("\t\tMPB_ATTRIB_RAID1E\n"); - not_supported ^= MPB_ATTRIB_RAID1E; - } - if (not_supported & MPB_ATTRIB_RAID5) { - dprintf("\t\tMPB_ATTRIB_RAID5\n"); - not_supported ^= MPB_ATTRIB_RAID5; - } - if (not_supported & MPB_ATTRIB_RAIDCNG) { - dprintf("\t\tMPB_ATTRIB_RAIDCNG\n"); - not_supported ^= MPB_ATTRIB_RAIDCNG; - } - if (not_supported & MPB_ATTRIB_BBM) { - dprintf("\t\tMPB_ATTRIB_BBM\n"); - not_supported ^= MPB_ATTRIB_BBM; - } - if (not_supported & MPB_ATTRIB_CHECKSUM_VERIFY) { - dprintf("\t\tMPB_ATTRIB_CHECKSUM_VERIFY (== MPB_ATTRIB_LEGACY)\n"); - not_supported ^= MPB_ATTRIB_CHECKSUM_VERIFY; - } - if (not_supported & MPB_ATTRIB_EXP_STRIPE_SIZE) { - dprintf("\t\tMPB_ATTRIB_EXP_STRIP_SIZE\n"); - not_supported ^= MPB_ATTRIB_EXP_STRIPE_SIZE; - } - if (not_supported & MPB_ATTRIB_2TB_DISK) { - dprintf("\t\tMPB_ATTRIB_2TB_DISK\n"); - not_supported ^= MPB_ATTRIB_2TB_DISK; - } - if (not_supported & MPB_ATTRIB_NEVER_USE2) { - dprintf("\t\tMPB_ATTRIB_NEVER_USE2\n"); - not_supported ^= MPB_ATTRIB_NEVER_USE2; - } - if (not_supported & MPB_ATTRIB_NEVER_USE) { - dprintf("\t\tMPB_ATTRIB_NEVER_USE\n"); - not_supported ^= MPB_ATTRIB_NEVER_USE; - } - - if (not_supported) - dprintf("(IMSM): Unknown attributes : %x\n", not_supported); - - ret_val = 0; - } + if ((attributes & (MPB_ATTRIB_SUPPORTED | MPB_ATTRIB_IGNORED)) == attributes) + return true; - return ret_val; + return false; } static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *map); @@ -2210,11 +2175,10 @@ static void examine_super_imsm(struct supertype *st, char *homehost) creation_time = __le64_to_cpu(mpb->creation_time); printf(" Creation Time : %.24s\n", creation_time ? ctime(&creation_time) : "Unknown"); - printf(" Attributes : "); - if (imsm_check_attributes(mpb->attributes)) - printf("All supported\n"); - else - printf("not supported\n"); + + printf(" Attributes : %08x (%s)\n", mpb->attributes, + imsm_check_attributes(mpb->attributes) ? "supported" : "not supported"); + getinfo_super_imsm(st, &info, NULL); fname_from_uuid(&info, nbuf); printf(" UUID : %s\n", nbuf + 5); @@ -2354,7 +2318,7 @@ void print_encryption_information(int disk_fd, enum sys_dev_type hba_type) { struct encryption_information information = {0}; mdadm_status_t status = MDADM_STATUS_SUCCESS; - const char *indent = " "; + const char *indent = " "; switch (hba_type) { case SYS_DEV_VMD: @@ -2379,7 +2343,8 @@ void print_encryption_information(int disk_fd, enum sys_dev_type hba_type) get_encryption_status_string(information.status)); } -static int ahci_enumerate_ports(struct sys_dev *hba, int port_count, int host_base, int verbose) +static int ahci_enumerate_ports(struct sys_dev *hba, unsigned long port_count, int host_base, + int verbose) { /* dump an unsorted list of devices attached to AHCI Intel storage * controller, as well as non-connected ports @@ -2393,7 +2358,7 @@ static int ahci_enumerate_ports(struct sys_dev *hba, int port_count, int host_ba if (port_count > (int)sizeof(port_mask) * 8) { if (verbose > 0) - pr_err("port_count %d out of range\n", port_count); + pr_err("port_count %ld out of range\n", port_count); return 2; } @@ -2535,11 +2500,11 @@ static int ahci_enumerate_ports(struct sys_dev *hba, int port_count, int host_ba if (dir) closedir(dir); if (err == 0) { - int i; + unsigned long i; for (i = 0; i < port_count; i++) - if (port_mask & (1 << i)) - printf(" Port%d : - no device attached -\n", i); + if (port_mask & (1L << i)) + printf(" Port%ld : - no device attached -\n", i); } return err; @@ -2652,6 +2617,15 @@ static int ahci_get_port_count(const char *hba_path, int *port_count) return host_base; } +static void print_imsm_level_capability(const struct imsm_orom *orom) +{ + int idx; + + for (idx = 0; imsm_level_ops[idx].name; idx++) + if (imsm_level_ops[idx].is_level_supported(orom)) + printf("%s ", imsm_level_ops[idx].name); +} + static void print_imsm_capability(const struct imsm_orom *orom) { printf(" Platform : Intel(R) "); @@ -2670,12 +2644,11 @@ static void print_imsm_capability(const struct imsm_orom *orom) printf(" Version : %d.%d.%d.%d\n", orom->major_ver, orom->minor_ver, orom->hotfix_ver, orom->build); } - printf(" RAID Levels :%s%s%s%s%s\n", - imsm_orom_has_raid0(orom) ? " raid0" : "", - imsm_orom_has_raid1(orom) ? " raid1" : "", - imsm_orom_has_raid1e(orom) ? " raid1e" : "", - imsm_orom_has_raid10(orom) ? " raid10" : "", - imsm_orom_has_raid5(orom) ? " raid5" : ""); + + printf(" RAID Levels : "); + print_imsm_level_capability(orom); + printf("\n"); + printf(" Chunk Sizes :%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", imsm_orom_has_chunk(orom, 2) ? " 2k" : "", imsm_orom_has_chunk(orom, 4) ? " 4k" : "", @@ -2710,12 +2683,11 @@ static void print_imsm_capability_export(const struct imsm_orom *orom) if (orom->major_ver || orom->minor_ver || orom->hotfix_ver || orom->build) printf("IMSM_VERSION=%d.%d.%d.%d\n", orom->major_ver, orom->minor_ver, orom->hotfix_ver, orom->build); - printf("IMSM_SUPPORTED_RAID_LEVELS=%s%s%s%s%s\n", - imsm_orom_has_raid0(orom) ? "raid0 " : "", - imsm_orom_has_raid1(orom) ? "raid1 " : "", - imsm_orom_has_raid1e(orom) ? "raid1e " : "", - imsm_orom_has_raid5(orom) ? "raid10 " : "", - imsm_orom_has_raid10(orom) ? "raid5 " : ""); + + printf("IMSM_SUPPORTED_RAID_LEVELS="); + print_imsm_level_capability(orom); + printf("\n"); + printf("IMSM_SUPPORTED_CHUNK_SIZES=%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", imsm_orom_has_chunk(orom, 2) ? "2k " : "", imsm_orom_has_chunk(orom, 4) ? "4k " : "", @@ -4268,7 +4240,10 @@ load_imsm_disk(int fd, struct intel_super *super, char *devname, int keep_fd) dl = xcalloc(1, sizeof(*dl)); - fstat(fd, &stb); + if (fstat(fd, &stb) != 0) { + free(dl); + return 1; + } dl->major = major(stb.st_rdev); dl->minor = minor(stb.st_rdev); dl->next = super->disks; @@ -5476,51 +5451,48 @@ static unsigned long long info_to_blocks_per_member(mdu_array_info_t *info, return (size * 2) & ~(info_to_blocks_per_strip(info) - 1); } +static void imsm_write_signature(struct imsm_super *mpb) +{ + /* It is safer to eventually truncate version rather than left it not NULL ended */ + snprintf((char *) mpb->sig, MAX_SIGNATURE_LENGTH, MPB_SIGNATURE MPB_VERSION_ATTRIBS); +} + static void imsm_update_version_info(struct intel_super *super) { /* update the version and attributes */ struct imsm_super *mpb = super->anchor; - char *version; struct imsm_dev *dev; struct imsm_map *map; int i; + mpb->attributes |= MPB_ATTRIB_CHECKSUM_VERIFY; + for (i = 0; i < mpb->num_raid_devs; i++) { dev = get_imsm_dev(super, i); map = get_imsm_map(dev, MAP_0); + if (__le32_to_cpu(dev->size_high) > 0) mpb->attributes |= MPB_ATTRIB_2TB; - /* FIXME detect when an array spans a port multiplier */ - #if 0 - mpb->attributes |= MPB_ATTRIB_PM; - #endif - - if (mpb->num_raid_devs > 1 || - mpb->attributes != MPB_ATTRIB_CHECKSUM_VERIFY) { - version = MPB_VERSION_ATTRIBS; - switch (get_imsm_raid_level(map)) { - case 0: mpb->attributes |= MPB_ATTRIB_RAID0; break; - case 1: mpb->attributes |= MPB_ATTRIB_RAID1; break; - case 10: mpb->attributes |= MPB_ATTRIB_RAID10; break; - case 5: mpb->attributes |= MPB_ATTRIB_RAID5; break; - } - } else { - if (map->num_members >= 5) - version = MPB_VERSION_5OR6_DISK_ARRAY; - else if (dev->status == DEV_CLONE_N_GO) - version = MPB_VERSION_CNG; - else if (get_imsm_raid_level(map) == 5) - version = MPB_VERSION_RAID5; - else if (map->num_members >= 3) - version = MPB_VERSION_3OR4_DISK_ARRAY; - else if (get_imsm_raid_level(map) == 1) - version = MPB_VERSION_RAID1; - else - version = MPB_VERSION_RAID0; + switch (get_imsm_raid_level(map)) { + case IMSM_T_RAID0: + mpb->attributes |= MPB_ATTRIB_RAID0; + break; + case IMSM_T_RAID1: + mpb->attributes |= MPB_ATTRIB_RAID1; + break; + case IMSM_T_RAID5: + mpb->attributes |= MPB_ATTRIB_RAID5; + break; + case IMSM_T_RAID10: + mpb->attributes |= MPB_ATTRIB_RAID10; + if (map->num_members > 4) + mpb->attributes |= MPB_ATTRIB_RAID10_EXT; + break; } - strcpy(((char *) mpb->sig) + strlen(MPB_SIGNATURE), version); } + + imsm_write_signature(mpb); } /** @@ -5678,7 +5650,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, set_pba_of_lba0(map, super->create_offset); map->blocks_per_strip = __cpu_to_le16(info_to_blocks_per_strip(info)); map->failed_disk_num = ~0; - if (info->level > 0) + if (info->level > IMSM_T_RAID0) map->map_state = (info->state ? IMSM_T_STATE_NORMAL : IMSM_T_STATE_UNINITIALIZED); else @@ -5686,16 +5658,15 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, IMSM_T_STATE_NORMAL; map->ddf = 1; - if (info->level == 1 && info->raid_disks > 2) { + if (info->level == IMSM_T_RAID1 && info->raid_disks > 2) { free(dev); free(dv); - pr_err("imsm does not support more than 2 disksin a raid1 volume\n"); + pr_err("imsm does not support more than 2 disks in a raid1 volume\n"); return 0; } + map->num_members = info->raid_disks; - map->raid_level = info->level; - if (info->level == 10) - map->raid_level = 1; + update_imsm_raid_level(map, info->level); set_num_domains(map); size_per_member += NUM_BLOCKS_DIRTY_STRIPE_REGION; @@ -5703,7 +5674,6 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, size_per_member / BLOCKS_PER_KB)); - map->num_members = info->raid_disks; update_num_data_stripes(map, array_blocks); for (i = 0; i < map->num_members; i++) { /* initialized in add_to_super */ @@ -5751,7 +5721,6 @@ static int init_super_imsm(struct supertype *st, mdu_array_info_t *info, struct intel_super *super; struct imsm_super *mpb; size_t mpb_size; - char *version; if (data_offset != INVALID_SECTORS) { pr_err("data-offset not supported by imsm\n"); @@ -5794,13 +5763,7 @@ static int init_super_imsm(struct supertype *st, mdu_array_info_t *info, return 0; } - mpb->attributes = MPB_ATTRIB_CHECKSUM_VERIFY; - - version = (char *) mpb->sig; - strcpy(version, MPB_SIGNATURE); - version += strlen(MPB_SIGNATURE); - strcpy(version, MPB_VERSION_RAID0); - + imsm_update_version_info(super); return 1; } @@ -6022,7 +5985,8 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk, if (super->current_vol >= 0) return add_to_super_imsm_volume(st, dk, fd, devname); - fstat(fd, &stb); + if (fstat(fd, &stb) != 0) + return 1; dd = xcalloc(sizeof(*dd), 1); dd->major = major(stb.st_rdev); dd->minor = minor(stb.st_rdev); @@ -6174,7 +6138,6 @@ static union { static int write_super_imsm_spare(struct intel_super *super, struct dl *d) { - struct imsm_super *mpb = super->anchor; struct imsm_super *spare = &spare_record.anchor; __u32 sum; @@ -6183,14 +6146,11 @@ static int write_super_imsm_spare(struct intel_super *super, struct dl *d) spare->mpb_size = __cpu_to_le32(sizeof(struct imsm_super)); spare->generation_num = __cpu_to_le32(1UL); - spare->attributes = MPB_ATTRIB_CHECKSUM_VERIFY; spare->num_disks = 1; spare->num_raid_devs = 0; - spare->cache_size = mpb->cache_size; spare->pwr_cycle_count = __cpu_to_le32(1); - snprintf((char *) spare->sig, MAX_SIGNATURE_LENGTH, - MPB_SIGNATURE MPB_VERSION_RAID0); + imsm_write_signature(spare); spare->disk[0] = d->disk; if (__le32_to_cpu(d->disk.total_blocks_hi) > 0) @@ -6965,26 +6925,41 @@ static unsigned long long merge_extents(struct intel_super *super, const bool ex return free_size - reservation_size; } -static int is_raid_level_supported(const struct imsm_orom *orom, int level, int raiddisks) +/** + * is_raid_level_supported() - check if this count of drives and level is supported by platform. + * @orom: hardware properties, could be NULL. + * @level: requested raid level. + * @raiddisks: requested disk count. + * + * IMSM UEFI/OROM does not provide information about supported count of raid disks + * for particular level. That is why it is hardcoded. + * It is recommended to not allow of usage other levels than supported, + * IMSM code is not tested against different level implementations. + * + * Return: true if supported, false otherwise. + */ +static bool is_raid_level_supported(const struct imsm_orom *orom, int level, int raiddisks) { - if (level < 0 || level == 6 || level == 4) - return 0; + int idx; - /* if we have an orom prevent invalid raid levels */ - if (orom) - switch (level) { - case 0: return imsm_orom_has_raid0(orom); - case 1: - if (raiddisks > 2) - return imsm_orom_has_raid1e(orom); - return imsm_orom_has_raid1(orom) && raiddisks == 2; - case 10: return imsm_orom_has_raid10(orom) && raiddisks == 4; - case 5: return imsm_orom_has_raid5(orom) && raiddisks > 2; - } - else - return 1; /* not on an Intel RAID platform so anything goes */ + for (idx = 0; imsm_level_ops[idx].name; idx++) { + if (imsm_level_ops[idx].level == level) + break; + } - return 0; + if (!imsm_level_ops[idx].name) + return false; + + if (!imsm_level_ops[idx].is_raiddisks_count_supported(raiddisks)) + return false; + + if (!orom) + return true; + + if (imsm_level_ops[idx].is_level_supported(orom)) + return true; + + return false; } static int @@ -7072,7 +7047,6 @@ get_devices(const char *hba_path) struct md_list *dv; struct dirent *ent; DIR *dir; - int err = 0; #if DEBUG_LOOP devlist = get_loop_devices(); @@ -7114,14 +7088,6 @@ get_devices(const char *hba_path) dv->next = devlist; devlist = dv; } - if (err) { - while(devlist) { - dv = devlist; - devlist = devlist->next; - free(dv->devname); - free(dv); - } - } closedir(dir); return devlist; } @@ -7740,9 +7706,11 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, char *dev, unsigned long long *freesize, int consistency_policy, int verbose) { - int fd, cfd; + struct intel_super *super = st->sb; struct mdinfo *sra; int is_member = 0; + imsm_status_t rv; + int fd, cfd; /* load capability * if given unused devices create a container @@ -7767,11 +7735,10 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, } if (!dev) { - struct intel_super *super = st->sb; - /* * Autolayout mode, st->sb must be set. */ + if (!super) { pr_vrb("superblock must be set for autolayout, aborting\n"); return 0; @@ -7782,21 +7749,22 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, verbose)) return 0; - if (super->orom && freesize) { - imsm_status_t rv; - int count = count_volumes(super->hba, super->orom->dpa, - verbose); + if (super->orom) { + int count = count_volumes(super->hba, super->orom->dpa, verbose); + if (super->orom->vphba <= count) { pr_vrb("platform does not support more than %d raid volumes.\n", super->orom->vphba); return 0; } + } - rv = autolayout_imsm(super, raiddisks, size, *chunk, - freesize); - if (rv != IMSM_STATUS_OK) - return 0; + if (freesize) { + rv = autolayout_imsm(super, raiddisks, size, *chunk, freesize); + if (rv != IMSM_STATUS_OK) + return 0; } + return 1; } if (st->sb) { @@ -8139,9 +8107,9 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra int current_vol = super->current_vol; /* do not assemble arrays when not all attributes are supported */ - if (imsm_check_attributes(mpb->attributes) == 0) { + if (imsm_check_attributes(mpb->attributes) == false) { sb_errors = 1; - pr_err("Unsupported attributes in IMSM metadata.Arrays activation is blocked.\n"); + pr_err("Unsupported attributes in IMSM metadata. Arrays activation is blocked.\n"); } /* count spare devices, not used in maps @@ -8275,7 +8243,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra info_d->data_offset = pba_of_lba0(map); info_d->component_size = calc_component_size(map, dev); - if (map->raid_level == 5) { + if (map->raid_level == IMSM_T_RAID5) { info_d->ppl_sector = this->ppl_sector; info_d->ppl_size = this->ppl_size; if (this->consistency_policy == CONSISTENCY_POLICY_PPL && @@ -9533,7 +9501,7 @@ static int apply_reshape_migration_update(struct imsm_update_reshape_migration * } to_state = map->map_state; - if ((u->new_level == 5) && (map->raid_level == 0)) { + if ((u->new_level == IMSM_T_RAID5) && (map->raid_level == IMSM_T_RAID0)) { map->num_members++; /* this should not happen */ if (u->new_disks[0] < 0) { @@ -9544,11 +9512,13 @@ static int apply_reshape_migration_update(struct imsm_update_reshape_migration * to_state = IMSM_T_STATE_NORMAL; } migrate(new_dev, super, to_state, MIGR_GEN_MIGR); + if (u->new_level > -1) - map->raid_level = u->new_level; + update_imsm_raid_level(map, u->new_level); + migr_map = get_imsm_map(new_dev, MAP_1); - if ((u->new_level == 5) && - (migr_map->raid_level == 0)) { + if ((u->new_level == IMSM_T_RAID5) && + (migr_map->raid_level == IMSM_T_RAID0)) { int ord = map->num_members - 1; migr_map->num_members--; if (u->new_disks[0] < 0) @@ -9584,7 +9554,7 @@ static int apply_reshape_migration_update(struct imsm_update_reshape_migration * /* add disk */ - if (u->new_level != 5 || migr_map->raid_level != 0 || + if (u->new_level != IMSM_T_RAID5 || migr_map->raid_level != IMSM_T_RAID0 || migr_map->raid_level == map->raid_level) goto skip_disk_add; @@ -9963,7 +9933,7 @@ static int apply_takeover_update(struct imsm_update_takeover *u, /* update map */ map->num_members /= map->num_domains; map->map_state = IMSM_T_STATE_NORMAL; - map->raid_level = 0; + update_imsm_raid_level(map, IMSM_T_RAID0); set_num_domains(map); update_num_data_stripes(map, imsm_dev_size(dev)); map->failed_disk_num = -1; @@ -10007,7 +9977,7 @@ static int apply_takeover_update(struct imsm_update_takeover *u, map = get_imsm_map(dev_new, MAP_0); map->map_state = IMSM_T_STATE_DEGRADED; - map->raid_level = 1; + update_imsm_raid_level(map, IMSM_T_RAID10); set_num_domains(map); map->num_members = map->num_members * map->num_domains; update_num_data_stripes(map, imsm_dev_size(dev)); @@ -11352,7 +11322,7 @@ check_policy: return MDADM_STATUS_SUCCESS; fd2devname(disk_fd, devname); - pr_vrb("Encryption status \"%s\" detected for disk %s, but \"%s\" status was detected eariler.\n", + pr_vrb("Encryption status \"%s\" detected for disk %s, but \"%s\" status was detected earlier.\n", encryption_state, devname, expected_policy->value); pr_vrb("Disks with different encryption status cannot be used.\n"); return MDADM_STATUS_ERROR; @@ -11927,24 +11897,23 @@ success: ****************************************************************************/ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, struct geo_params *geo, - int direction) + int direction, struct context *c) { struct mdinfo info; int change = -1; int check_devs = 0; int chunk; - /* number of added/removed disks in operation result */ - int devNumChange = 0; /* imsm compatible layout value for array geometry verification */ int imsm_layout = -1; + int raid_disks = geo->raid_disks; imsm_status_t rv; getinfo_super_imsm_volume(st, &info, NULL); - if (geo->level != info.array.level && geo->level >= 0 && + if (geo->level != info.array.level && geo->level >= IMSM_T_RAID0 && geo->level != UnSet) { switch (info.array.level) { - case 0: - if (geo->level == 5) { + case IMSM_T_RAID0: + if (geo->level == IMSM_T_RAID5) { change = CH_MIGRATION; if (geo->layout != ALGORITHM_LEFT_ASYMMETRIC) { pr_err("Error. Requested Layout not supported (left-asymmetric layout is supported only)!\n"); @@ -11953,20 +11922,28 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, } imsm_layout = geo->layout; check_devs = 1; - devNumChange = 1; /* parity disk added */ - } else if (geo->level == 10) { + raid_disks += 1; /* parity disk added */ + } else if (geo->level == IMSM_T_RAID10) { + if (geo->level == IMSM_T_RAID10 && geo->raid_disks > 2 && + !c->force) { + pr_err("Warning! VROC UEFI driver does not support RAID10 in requested layout.\n"); + pr_err("Array won't be suitable as boot device.\n"); + pr_err("Note: You can omit this check with \"--force\"\n"); + if (ask("Do you want to continue") < 1) + return CH_ABORT; + } change = CH_TAKEOVER; check_devs = 1; - devNumChange = 2; /* two mirrors added */ + raid_disks *= 2; /* mirrors added */ imsm_layout = 0x102; /* imsm supported layout */ } break; - case 1: - case 10: + case IMSM_T_RAID1: + case IMSM_T_RAID10: if (geo->level == 0) { change = CH_TAKEOVER; check_devs = 1; - devNumChange = -(geo->raid_disks/2); + raid_disks /= 2; imsm_layout = 0; /* imsm raid0 layout */ } break; @@ -11982,10 +11959,10 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, if (geo->layout != info.array.layout && (geo->layout != UnSet && geo->layout != -1)) { change = CH_MIGRATION; - if (info.array.layout == 0 && info.array.level == 5 && + if (info.array.layout == 0 && info.array.level == IMSM_T_RAID5 && geo->layout == 5) { /* reshape 5 -> 4 */ - } else if (info.array.layout == 5 && info.array.level == 5 && + } else if (info.array.layout == 5 && info.array.level == IMSM_T_RAID5 && geo->layout == 0) { /* reshape 4 -> 5 */ geo->layout = 0; @@ -12004,7 +11981,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, if (geo->chunksize > 0 && geo->chunksize != UnSet && geo->chunksize != info.array.chunk_size) { - if (info.array.level == 10) { + if (info.array.level == IMSM_T_RAID10) { pr_err("Error. Chunk size change for RAID 10 is not supported.\n"); change = -1; goto analyse_change_exit; @@ -12029,14 +12006,16 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, rv = imsm_analyze_expand(st, geo, &info, direction); if (rv != IMSM_STATUS_OK) goto analyse_change_exit; + raid_disks = geo->raid_disks; change = CH_ARRAY_SIZE; } chunk = geo->chunksize / 1024; + if (!validate_geometry_imsm(st, geo->level, imsm_layout, - geo->raid_disks + devNumChange, + raid_disks, &chunk, geo->size, INVALID_SECTORS, 0, 0, info.consistency_policy, 1)) @@ -12152,28 +12131,37 @@ exit: return ret_val; } -static int imsm_reshape_super(struct supertype *st, unsigned long long size, - int level, - int layout, int chunksize, int raid_disks, - int delta_disks, char *backup, char *dev, - int direction, int verbose) +/** + * shape_to_geo() - fill geo_params from shape. + * + * @shape: array details. + * @geo: new geometry params. + * Returns: 0 on success, 1 otherwise. + */ +static void shape_to_geo(struct shape *shape, struct geo_params *geo) +{ + assert(shape); + assert(geo); + + geo->dev_name = shape->dev; + geo->size = shape->size; + geo->level = shape->level; + geo->layout = shape->layout; + geo->chunksize = shape->chunk; + geo->raid_disks = shape->raiddisks; +} + +static int imsm_reshape_super(struct supertype *st, struct shape *shape, struct context *c) { int ret_val = 1; - struct geo_params geo; + struct geo_params geo = {0}; dprintf("(enter)\n"); - memset(&geo, 0, sizeof(struct geo_params)); - - geo.dev_name = dev; + shape_to_geo(shape, &geo); strcpy(geo.devnm, st->devnm); - geo.size = size; - geo.level = level; - geo.layout = layout; - geo.chunksize = chunksize; - geo.raid_disks = raid_disks; - if (delta_disks != UnSet) - geo.raid_disks += delta_disks; + if (shape->delta_disks != UnSet) + geo.raid_disks += shape->delta_disks; dprintf("for level : %i\n", geo.level); dprintf("for raid_disks : %i\n", geo.raid_disks); @@ -12184,7 +12172,7 @@ static int imsm_reshape_super(struct supertype *st, unsigned long long size, int old_raid_disks = 0; if (imsm_reshape_is_allowed_on_container( - st, &geo, &old_raid_disks, direction)) { + st, &geo, &old_raid_disks, shape->direction)) { struct imsm_update_reshape *u = NULL; int len; @@ -12238,7 +12226,7 @@ static int imsm_reshape_super(struct supertype *st, unsigned long long size, goto exit_imsm_reshape_super; } super->current_vol = dev->index; - change = imsm_analyze_change(st, &geo, direction); + change = imsm_analyze_change(st, &geo, shape->direction, c); switch (change) { case CH_TAKEOVER: ret_val = imsm_takeover(st, &geo); @@ -12281,6 +12269,7 @@ static int imsm_reshape_super(struct supertype *st, unsigned long long size, free(u); } break; + case CH_ABORT: default: ret_val = 1; } |