- Add checks for Intel metadata version and attributes. Ignore disks with

unsupported metadata types like Intel Smart Response to not corrupt them.
 - Improve setting of these things during metadata writing to protect from
incapable BIOS'es and other implementations.
This commit is contained in:
Alexander Motin 2013-01-13 23:00:40 +00:00
parent 233af52df2
commit f9462b9bbe
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=245398

View File

@ -165,6 +165,11 @@ struct intel_raid_conf {
#define INTEL_ATTR_RAID1E 0x00000008
#define INTEL_ATTR_RAID5 0x00000010
#define INTEL_ATTR_RAIDCNG 0x00000020
#define INTEL_ATTR_EXT_STRIP 0x00000040
#define INTEL_ATTR_NVM_CACHE 0x02000000
#define INTEL_ATTR_2TB_DISK 0x04000000
#define INTEL_ATTR_BBM 0x08000000
#define INTEL_ATTR_NVM_CACHE2 0x10000000
#define INTEL_ATTR_2TB 0x20000000
#define INTEL_ATTR_PM 0x40000000
#define INTEL_ATTR_CHECKSUM 0x80000000
@ -182,6 +187,11 @@ struct intel_raid_conf {
/* Here goes total_volumes of struct intel_raid_vol. */
} __packed;
#define INTEL_ATTR_SUPPORTED ( INTEL_ATTR_RAID0 | INTEL_ATTR_RAID1 | \
INTEL_ATTR_RAID10 | INTEL_ATTR_RAID1E | INTEL_ATTR_RAID5 | \
INTEL_ATTR_RAIDCNG | INTEL_ATTR_EXT_STRIP | INTEL_ATTR_2TB_DISK | \
INTEL_ATTR_2TB | INTEL_ATTR_PM | INTEL_ATTR_CHECKSUM )
#define INTEL_MAX_MD_SIZE(ndisks) \
(sizeof(struct intel_raid_conf) + \
sizeof(struct intel_raid_disk) * (ndisks - 1) + \
@ -554,6 +564,21 @@ intel_meta_read(struct g_consumer *cp)
g_raid_md_intel_print(meta);
if (strncmp(meta->version, INTEL_VERSION_1300, 6) > 0) {
G_RAID_DEBUG(1, "Intel unsupported version: '%.6s'",
meta->version);
free(meta, M_MD_INTEL);
return (NULL);
}
if (strncmp(meta->version, INTEL_VERSION_1300, 6) >= 0 &&
(meta->attributes & ~INTEL_ATTR_SUPPORTED) != 0) {
G_RAID_DEBUG(1, "Intel unsupported attributes: 0x%08x",
meta->attributes & ~INTEL_ATTR_SUPPORTED);
free(meta, M_MD_INTEL);
return (NULL);
}
/* Validate disk indexes. */
for (i = 0; i < meta->total_volumes; i++) {
mvol = intel_get_volume(meta, i);
@ -2268,6 +2293,8 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol,
if (pd->pd_disk_pos < 0)
continue;
meta->disk[pd->pd_disk_pos] = pd->pd_disk_meta;
if (pd->pd_disk_meta.sectors_hi != 0)
meta->attributes |= INTEL_ATTR_2TB_DISK;
}
/* Fill volumes and maps. */
@ -2297,12 +2324,16 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol,
meta->attributes |= INTEL_ATTR_RAID1;
else if (vol->v_raid_level == G_RAID_VOLUME_RL_RAID5)
meta->attributes |= INTEL_ATTR_RAID5;
else
else if ((vol->v_disks_count & 1) == 0)
meta->attributes |= INTEL_ATTR_RAID10;
else
meta->attributes |= INTEL_ATTR_RAID1E;
if (pv->pv_cng)
meta->attributes |= INTEL_ATTR_RAIDCNG;
if (vol->v_strip_size > 131072)
meta->attributes |= INTEL_ATTR_EXT_STRIP;
if (meta->attributes & INTEL_ATTR_2TB)
cv = INTEL_VERSION_1300;
else if (pv->pv_cng)
if (pv->pv_cng)
cv = INTEL_VERSION_1206;
else if (vol->v_disks_count > 4)
cv = INTEL_VERSION_1204;
@ -2310,8 +2341,6 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol,
cv = INTEL_VERSION_1202;
else if (vol->v_disks_count > 2)
cv = INTEL_VERSION_1201;
else if (vi > 0)
cv = INTEL_VERSION_1200;
else if (vol->v_raid_level == G_RAID_VOLUME_RL_RAID1)
cv = INTEL_VERSION_1100;
else
@ -2321,6 +2350,8 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol,
strlcpy(&mvol->name[0], vol->v_name, sizeof(mvol->name));
mvol->total_sectors = vol->v_mediasize / sectorsize;
mvol->state = (INTEL_ST_READ_COALESCING |
INTEL_ST_WRITE_COALESCING);
if (pv->pv_cng) {
mvol->state |= INTEL_ST_CLONE_N_GO;
if (pv->pv_cng_man_sync)
@ -2437,7 +2468,10 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol,
vi++;
}
meta->total_volumes = vi;
if (strcmp(version, INTEL_VERSION_1300) != 0)
if (vi > 1 || meta->attributes &
(INTEL_ATTR_EXT_STRIP | INTEL_ATTR_2TB_DISK | INTEL_ATTR_2TB))
version = INTEL_VERSION_1300;
if (strcmp(version, INTEL_VERSION_1300) < 0)
meta->attributes &= INTEL_ATTR_CHECKSUM;
memcpy(&meta->version[0], version, sizeof(INTEL_VERSION_1000) - 1);