Merging upstream version 4.3+20240723.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
9d4f96bc70
commit
aa881a3626
70 changed files with 1465 additions and 1206 deletions
491
super-intel.c
491
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;
|
||||
if ((attributes & (MPB_ATTRIB_SUPPORTED | MPB_ATTRIB_IGNORED)) == attributes)
|
||||
return true;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue